From 1d81b7004f236f7953f6046488189e753ff851ba Mon Sep 17 00:00:00 2001 From: Alexey Andreev Date: Thu, 26 Sep 2024 20:39:29 +0200 Subject: [PATCH] Fix possible bug with exceptions in GVN --- .../optimization/GlobalValueNumbering.java | 91 ++++++++++--------- .../org/teavm/model/util/ProgramUtils.java | 23 +++++ tests/build.gradle.kts | 1 + 3 files changed, 71 insertions(+), 44 deletions(-) diff --git a/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java b/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java index 86cf03e2a..c048c8b79 100644 --- a/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java +++ b/core/src/main/java/org/teavm/model/optimization/GlobalValueNumbering.java @@ -100,7 +100,7 @@ public class GlobalValueNumbering implements MethodOptimization { boolean affected = false; this.program = program; knownValues.clear(); - Graph cfg = ProgramUtils.buildControlFlowGraph(program); + Graph cfg = ProgramUtils.buildControlFlowGraph2(program); domTree = GraphUtils.buildDominatorTree(cfg); Graph dom = GraphUtils.buildDominatorGraph(domTree, cfg.size()); map = new int[program.variableCount()]; @@ -123,52 +123,55 @@ public class GlobalValueNumbering implements MethodOptimization { } while (top > 0) { int v = stack[--top]; - currentBlockIndex = v; - BasicBlock block = program.basicBlockAt(v); + if (v % 2 == 0) { + var blockIndex = v / 2; + currentBlockIndex = blockIndex; + BasicBlock block = program.basicBlockAt(blockIndex); - if (block.getExceptionVariable() != null) { - int var = map[block.getExceptionVariable().getIndex()]; - block.setExceptionVariable(program.variableAt(var)); - } + if (block.getExceptionVariable() != null) { + int var = map[block.getExceptionVariable().getIndex()]; + block.setExceptionVariable(program.variableAt(var)); + } - for (Instruction currentInsn : block) { - evaluatedConstant = null; - currentInsn.acceptVisitor(optimizer); - if (eliminate) { - affected = true; - currentInsn.delete(); - eliminate = false; - } else if (evaluatedConstant != null) { - if (evaluatedConstant instanceof Integer) { - IntegerConstantInstruction newInsn = new IntegerConstantInstruction(); - newInsn.setConstant((Integer) evaluatedConstant); - newInsn.setReceiver(program.variableAt(receiver)); - newInsn.setLocation(currentInsn.getLocation()); - currentInsn.replace(newInsn); - } else if (evaluatedConstant instanceof Long) { - LongConstantInstruction newInsn = new LongConstantInstruction(); - newInsn.setConstant((Long) evaluatedConstant); - newInsn.setReceiver(program.variableAt(receiver)); - newInsn.setLocation(currentInsn.getLocation()); - currentInsn.replace(newInsn); - } else if (evaluatedConstant instanceof Float) { - FloatConstantInstruction newInsn = new FloatConstantInstruction(); - newInsn.setConstant((Float) evaluatedConstant); - newInsn.setReceiver(program.variableAt(receiver)); - newInsn.setLocation(currentInsn.getLocation()); - currentInsn.replace(newInsn); - } else if (evaluatedConstant instanceof Double) { - DoubleConstantInstruction newInsn = new DoubleConstantInstruction(); - newInsn.setConstant((Double) evaluatedConstant); - newInsn.setReceiver(program.variableAt(receiver)); - newInsn.setLocation(currentInsn.getLocation()); - currentInsn.replace(newInsn); + for (Instruction currentInsn : block) { + evaluatedConstant = null; + currentInsn.acceptVisitor(optimizer); + if (eliminate) { + affected = true; + currentInsn.delete(); + eliminate = false; + } else if (evaluatedConstant != null) { + if (evaluatedConstant instanceof Integer) { + IntegerConstantInstruction newInsn = new IntegerConstantInstruction(); + newInsn.setConstant((Integer) evaluatedConstant); + newInsn.setReceiver(program.variableAt(receiver)); + newInsn.setLocation(currentInsn.getLocation()); + currentInsn.replace(newInsn); + } else if (evaluatedConstant instanceof Long) { + LongConstantInstruction newInsn = new LongConstantInstruction(); + newInsn.setConstant((Long) evaluatedConstant); + newInsn.setReceiver(program.variableAt(receiver)); + newInsn.setLocation(currentInsn.getLocation()); + currentInsn.replace(newInsn); + } else if (evaluatedConstant instanceof Float) { + FloatConstantInstruction newInsn = new FloatConstantInstruction(); + newInsn.setConstant((Float) evaluatedConstant); + newInsn.setReceiver(program.variableAt(receiver)); + newInsn.setLocation(currentInsn.getLocation()); + currentInsn.replace(newInsn); + } else if (evaluatedConstant instanceof Double) { + DoubleConstantInstruction newInsn = new DoubleConstantInstruction(); + newInsn.setConstant((Double) evaluatedConstant); + newInsn.setReceiver(program.variableAt(receiver)); + newInsn.setLocation(currentInsn.getLocation()); + currentInsn.replace(newInsn); + } } } - } - for (Incoming incoming : outgoings.get(v)) { - int value = replaceMap[incoming.getValue().getIndex()]; - incoming.setValue(program.variableAt(value)); + for (Incoming incoming : outgoings.get(blockIndex)) { + int value = replaceMap[incoming.getValue().getIndex()]; + incoming.setValue(program.variableAt(value)); + } } for (int succ : dom.outgoingEdges(v)) { @@ -216,7 +219,7 @@ public class GlobalValueNumbering implements MethodOptimization { } namesCompatible = knownName.isEmpty() || name.isEmpty() || knownName.equals(name); } - if (known != null && domTree.dominates(known.location, currentBlockIndex) && known.value != var + if (known != null && domTree.dominates(known.location * 2 + 1, currentBlockIndex * 2) && known.value != var && namesCompatible) { map[var] = known.value; if (!noReplace) { diff --git a/core/src/main/java/org/teavm/model/util/ProgramUtils.java b/core/src/main/java/org/teavm/model/util/ProgramUtils.java index a57b772bb..ce2e409ce 100644 --- a/core/src/main/java/org/teavm/model/util/ProgramUtils.java +++ b/core/src/main/java/org/teavm/model/util/ProgramUtils.java @@ -73,6 +73,29 @@ public final class ProgramUtils { return graphBuilder.build(); } + + public static Graph buildControlFlowGraph2(Program program) { + var graphBuilder = new GraphBuilder(program.basicBlockCount()); + TransitionExtractor transitionExtractor = new TransitionExtractor(); + for (int i = 0; i < program.basicBlockCount(); ++i) { + graphBuilder.addEdge(i * 2, i * 2 + 1); + BasicBlock block = program.basicBlockAt(i); + Instruction insn = block.getLastInstruction(); + if (insn != null) { + insn.acceptVisitor(transitionExtractor); + if (transitionExtractor.getTargets() != null) { + for (BasicBlock successor : transitionExtractor.getTargets()) { + graphBuilder.addEdge(i * 2 + 1, successor.getIndex() * 2); + } + } + } + for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) { + graphBuilder.addEdge(i * 2, tryCatch.getHandler().getIndex() * 2); + } + } + return graphBuilder.build(); + } + public static ControlFlowEntry[] getLocationCFG(Program program) { return new LocationGraphBuilder().build(program); } diff --git a/tests/build.gradle.kts b/tests/build.gradle.kts index 621c012bb..0328a9f9a 100644 --- a/tests/build.gradle.kts +++ b/tests/build.gradle.kts @@ -93,4 +93,5 @@ tasks.test { .joinToString(File.pathSeparator)) maxParallelForks = (Runtime.getRuntime().availableProcessors() / 2).coerceAtLeast(1) + maxHeapSize = "800m" } \ No newline at end of file