Skip to content

Commit c61c893

Browse files
committed
DCE fixes
1 parent 009ce6c commit c61c893

2 files changed

Lines changed: 54 additions & 1 deletion

File tree

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

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,22 @@ private List<ImExpr> collectSideEffects(ImExpr expr, SideEffectAnalyzer analyzer
213213
}
214214

215215
private boolean mayTrapAtRuntime(Element elem) {
216+
return mayTrapAtRuntime(elem, new HashMap<>(), new LinkedHashSet<>());
217+
}
218+
219+
private boolean mayTrapAtRuntime(Element elem, Map<ImFunction, Boolean> functionCache, Set<ImFunction> inProgress) {
220+
if (elem instanceof ImFunctionCall) {
221+
ImFunction calledFunc = ((ImFunctionCall) elem).getFunc();
222+
if (functionMayTrapAtRuntime(calledFunc, functionCache, inProgress)) {
223+
return true;
224+
}
225+
} else if (elem instanceof ImMethodCall) {
226+
ImFunction calledFunc = ((ImMethodCall) elem).getMethod().getImplementation();
227+
if (calledFunc == null || functionMayTrapAtRuntime(calledFunc, functionCache, inProgress)) {
228+
return true;
229+
}
230+
}
231+
216232
if (elem instanceof ImOperatorCall) {
217233
ImOperatorCall opCall = (ImOperatorCall) elem;
218234
WurstOperator op = opCall.getOp();
@@ -226,10 +242,31 @@ private boolean mayTrapAtRuntime(Element elem) {
226242
}
227243
for (int i = 0; i < elem.size(); i++) {
228244
Element child = elem.get(i);
229-
if (mayTrapAtRuntime(child)) {
245+
if (mayTrapAtRuntime(child, functionCache, inProgress)) {
230246
return true;
231247
}
232248
}
233249
return false;
234250
}
251+
252+
private boolean functionMayTrapAtRuntime(ImFunction function, Map<ImFunction, Boolean> functionCache, Set<ImFunction> inProgress) {
253+
if (function.isNative()) {
254+
return false;
255+
}
256+
257+
Boolean cachedResult = functionCache.get(function);
258+
if (cachedResult != null) {
259+
return cachedResult;
260+
}
261+
262+
if (!inProgress.add(function)) {
263+
// Recursive cycles are conservatively treated as potentially trapping.
264+
return true;
265+
}
266+
267+
boolean mayTrap = mayTrapAtRuntime(function.getBody(), functionCache, inProgress);
268+
inProgress.remove(function);
269+
functionCache.put(function, mayTrap);
270+
return mayTrap;
271+
}
235272
}

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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,22 @@ public void deadStoreKeepsPotentialDivisionTrap() throws IOException {
613613
assertTrue(compiledNoOpt.contains("1 /"), "potential division trap should be preserved");
614614
}
615615

616+
@Test
617+
public void deadStoreKeepsPotentialDivisionTrapInCallee() throws IOException {
618+
test().executeProg(false).lines(
619+
"package test",
620+
" @extern native I2S(int i) returns string",
621+
" native getY() returns int",
622+
" function wrap(int y) returns int",
623+
" return 1 div y",
624+
" init",
625+
" int y = getY()",
626+
" string x = I2S(wrap(y))",
627+
"endpackage");
628+
String compiledNoOpt = Files.toString(new File("test-output/OptimizerTests_deadStoreKeepsPotentialDivisionTrapInCallee_no_opts.j"), Charsets.UTF_8);
629+
assertTrue(compiledNoOpt.contains("1 /"), "potential division trap in callee should be preserved");
630+
}
631+
616632
@Test
617633
public void test_unreachableCodeRemover() throws IOException {
618634
test().withStdLib().lines(

0 commit comments

Comments
 (0)