Skip to content

Commit a0d3839

Browse files
committed
Bound Lua inlining without local allocation
1 parent 45c8ef0 commit a0d3839

4 files changed

Lines changed: 51 additions & 5 deletions

File tree

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstio/WurstCompilerJassImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -946,10 +946,10 @@ public LuaCompilationUnit transformProgToLua() {
946946
timeTaker.endPhase();
947947
}
948948

949-
if (runArgs.isInline()) {
949+
if (runArgs.isInline() && runArgs.isLocalOptimizations()) {
950950
beginPhase(10, "inline Lua arithmetic helpers within allocated local budget");
951951
int arithmeticHelpersInlined = optimizer.inlineLuaDivModHelpersWithinLocalBudget();
952-
if (arithmeticHelpersInlined > 0 && runArgs.isLocalOptimizations()) {
952+
if (arithmeticHelpersInlined > 0) {
953953
optimizer.localOptimizations();
954954
}
955955
timeTaker.endPhase();

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imoptimizer/ImInliner.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@ private final class LuaRegisterBudget {
555555
private Map<ImStmt, io.vavr.collection.Set<ImVar>> liveness;
556556
private LuaPressure peakPressure;
557557
private int backendLocals;
558+
private int declarationsWithoutAllocation;
558559

559560
private LuaRegisterBudget(ImFunction function) {
560561
this.function = function;
@@ -566,16 +567,31 @@ private LuaRegisterBudget(ImFunction function) {
566567
}
567568
peakPressure = cachedPressure.copy();
568569
backendLocals = backendGeneratedLuaLocals(function);
570+
declarationsWithoutAllocation = function.getParameters().size() + function.getLocals().size()
571+
+ backendLocals;
569572
}
570573

571574
private boolean fits(ImFunctionCall call, ImFunction callee) {
575+
if (!translator.getRunArgs().isLocalOptimizations()) {
576+
return declarationsWithoutAllocation + declarationsAddedByInline(callee)
577+
<= LUA_INLINE_REGISTER_BUDGET;
578+
}
572579
return projectedPressure(call, callee) <= LUA_INLINE_REGISTER_BUDGET
573580
- backendLocals - backendGeneratedLuaLocals(callee);
574581
}
575582

583+
private int declarationsAddedByInline(ImFunction callee) {
584+
int controlLocals = maxOneReturn(callee)
585+
? 0
586+
: 1 + (callee.getReturnType() instanceof ImVoid ? 0 : 1);
587+
return callee.getParameters().size() + callee.getLocals().size() + controlLocals
588+
+ backendGeneratedLuaLocals(callee);
589+
}
590+
576591
private void recordInline(ImFunctionCall call, ImFunction callee) {
577592
peakPressure.keepMaximums(pressureDuringInline(call, callee));
578593
backendLocals += backendGeneratedLuaLocals(callee);
594+
declarationsWithoutAllocation += declarationsAddedByInline(callee);
579595
// Callers are processed after their callees. Publish the expanded pressure so a
580596
// later caller budgets the body it will actually copy, not the pre-inline callee.
581597
luaRegisterPressure.put(function, peakPressure.copy());

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/LuaTranslationTests.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2208,6 +2208,33 @@ public void luaInlinerKeepsCallWhenLiveValuesWouldExceedRegisterBudget() {
22082208
callerBody.contains("__wurst_locals"));
22092209
}
22102210

2211+
@Test
2212+
public void luaInliningWithoutLocalAllocationUsesDeclarationBudget() {
2213+
List<String> lines = new ArrayList<>();
2214+
lines.add("package Test");
2215+
lines.add("native takesInt(int i)");
2216+
lines.add("@noinline function caller(int value)");
2217+
for (int i = 0; i < 70; i++) {
2218+
lines.add(" takesInt((value + " + i + ") mod 3)");
2219+
}
2220+
lines.add("init");
2221+
lines.add(" caller(7)");
2222+
2223+
String compiled = compileLuaWithCUs(
2224+
"LuaTranslationTests_luaInliningWithoutLocalAllocationUsesDeclarationBudget",
2225+
false, Collections.emptyList(), new RunArgs().with("-lua", "-inline"),
2226+
lines.toArray(new String[0]));
2227+
int callerStart = compiled.indexOf("function caller(");
2228+
assertTrue("caller function not found", callerStart >= 0);
2229+
int callerEnd = compiled.indexOf("\nend", callerStart);
2230+
assertTrue("caller function end not found", callerEnd > callerStart);
2231+
String body = compiled.substring(callerStart, callerEnd);
2232+
assertFalse("inlining without allocation must not cross into whole-function spill mode:\n" + body,
2233+
body.contains("__wurst_locals"));
2234+
assertTrue("the exact declaration budget must retain residual helper calls near the limit:\n" + body,
2235+
body.contains("__wurst_modInt("));
2236+
}
2237+
22112238
@Test
22122239
public void luaInlinerReusesRegistersAcrossSequentialInlineSites() {
22132240
List<String> lines = new ArrayList<>();
@@ -2354,7 +2381,8 @@ public void luaInlinerDoesNotTreatSequentialVarargLoopTempsAsConcurrent() {
23542381

23552382
String compiled = compileLuaWithCUs(
23562383
"LuaTranslationTests_luaInlinerDoesNotTreatSequentialVarargLoopTempsAsConcurrent",
2357-
false, Collections.emptyList(), new RunArgs().with("-lua", "-inline"),
2384+
false, Collections.emptyList(),
2385+
new RunArgs().with("-lua", "-inline", "-localOptimizations"),
23582386
lines.toArray(new String[0]));
23592387
assertFalse("sequential loop temporaries must not consume concurrent register budget:\n" + compiled,
23602388
compiled.contains("small("));

de.peeeq.wurstscript/src/test/java/tests/wurstscript/tests/OptimizerTests.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1600,7 +1600,8 @@ public void repeatedLocalOptimizationStartsANewIteration() {
16001600
@Test
16011601
public void luaArithmeticHelperRetryRespectsFunctionLocalBudget() {
16021602
WurstModel model = Ast.WurstModel();
1603-
ImTranslator translator = new ImTranslator(model, false, new RunArgs().with("-lua"));
1603+
ImTranslator translator = new ImTranslator(model, false,
1604+
new RunArgs().with("-lua", "-localOptimizations"));
16041605
ImProg prog = translator.getImProg();
16051606

16061607
ImVar helperA = JassIm.ImVar(model, TypesHelper.imInt(), "a", false);
@@ -1654,7 +1655,8 @@ public void luaArithmeticHelperRetryRespectsFunctionLocalBudget() {
16541655
@Test
16551656
public void luaArithmeticHelperRetryReusesSequentialSlots() {
16561657
WurstModel model = Ast.WurstModel();
1657-
ImTranslator translator = new ImTranslator(model, false, new RunArgs().with("-lua"));
1658+
ImTranslator translator = new ImTranslator(model, false,
1659+
new RunArgs().with("-lua", "-localOptimizations"));
16581660
ImProg prog = translator.getImProg();
16591661
ImVar helperA = JassIm.ImVar(model, TypesHelper.imInt(), "a", false);
16601662
ImVar helperB = JassIm.ImVar(model, TypesHelper.imInt(), "b", false);

0 commit comments

Comments
 (0)