diff --git a/core/src/main/java/org/teavm/model/analysis/NullnessChecker.java b/core/src/main/java/org/teavm/model/analysis/NullnessChecker.java index 09397bd06..152c2ef29 100644 --- a/core/src/main/java/org/teavm/model/analysis/NullnessChecker.java +++ b/core/src/main/java/org/teavm/model/analysis/NullnessChecker.java @@ -51,7 +51,7 @@ public class NullnessChecker { notNullIncomings = new HashSet<>(); notNull = new boolean[program.variableCount()]; nullLiteral = new boolean[program.variableCount()]; - phiOutputs = ProgramUtils.getPhiOutputs(program); + phiOutputs = ProgramUtils.getPhiOutputsByVariable(program); graphBuilder = new GraphBuilder(program.variableCount()); Graph cfg = ProgramUtils.buildControlFlowGraph(program); diff --git a/core/src/main/java/org/teavm/model/optimization/LoopInvariantAnalyzer.java b/core/src/main/java/org/teavm/model/optimization/LoopInvariantAnalyzer.java index 4fd6846fc..2b757b8cb 100644 --- a/core/src/main/java/org/teavm/model/optimization/LoopInvariantAnalyzer.java +++ b/core/src/main/java/org/teavm/model/optimization/LoopInvariantAnalyzer.java @@ -57,10 +57,15 @@ import org.teavm.model.instructions.SwitchInstruction; import org.teavm.model.instructions.UnwrapArrayInstruction; public class LoopInvariantAnalyzer implements InstructionVisitor { + private boolean[] notNull; public boolean canMove; public boolean constant; public boolean sideEffect; + public LoopInvariantAnalyzer(boolean[] notNull) { + this.notNull = notNull; + } + public void reset() { canMove = false; constant = false; @@ -187,7 +192,9 @@ public class LoopInvariantAnalyzer implements InstructionVisitor { @Override public void visit(ArrayLengthInstruction insn) { canMove = true; - sideEffect = true; + if (!notNull[insn.getArray().getIndex()]) { + sideEffect = true; + } } @Override @@ -197,7 +204,9 @@ public class LoopInvariantAnalyzer implements InstructionVisitor { @Override public void visit(UnwrapArrayInstruction insn) { canMove = true; - sideEffect = true; + if (!notNull[insn.getArray().getIndex()]) { + sideEffect = true; + } } @Override @@ -228,16 +237,16 @@ public class LoopInvariantAnalyzer implements InstructionVisitor { @Override public void visit(NullCheckInstruction insn) { canMove = true; - sideEffect = true; + if (!notNull[insn.getValue().getIndex()]) { + sideEffect = true; + } } @Override public void visit(MonitorEnterInstruction insn) { - } @Override public void visit(MonitorExitInstruction insn) { - } } diff --git a/core/src/main/java/org/teavm/model/optimization/LoopInvariantMotion.java b/core/src/main/java/org/teavm/model/optimization/LoopInvariantMotion.java index ef2465a51..e6ce37134 100644 --- a/core/src/main/java/org/teavm/model/optimization/LoopInvariantMotion.java +++ b/core/src/main/java/org/teavm/model/optimization/LoopInvariantMotion.java @@ -20,6 +20,7 @@ import java.util.Arrays; import java.util.List; import org.teavm.common.*; import org.teavm.model.*; +import org.teavm.model.analysis.NullnessChecker; import org.teavm.model.instructions.*; import org.teavm.model.util.*; @@ -53,7 +54,7 @@ public class LoopInvariantMotion implements MethodOptimization { DefinitionExtractor defExtractor = new DefinitionExtractor(); UsageExtractor useExtractor = new UsageExtractor(); - LoopInvariantAnalyzer analyzer = new LoopInvariantAnalyzer(); + LoopInvariantAnalyzer analyzer = new LoopInvariantAnalyzer(new NullnessChecker().check(program)); CopyConstantVisitor constantCopier = new CopyConstantVisitor(); int[][] loopExits = ControlFlowUtils.findLoopExits(graph); diff --git a/core/src/main/java/org/teavm/model/optimization/LoopInversionImpl.java b/core/src/main/java/org/teavm/model/optimization/LoopInversionImpl.java index d3404c6f9..cc2878753 100644 --- a/core/src/main/java/org/teavm/model/optimization/LoopInversionImpl.java +++ b/core/src/main/java/org/teavm/model/optimization/LoopInversionImpl.java @@ -41,6 +41,7 @@ import org.teavm.model.Program; import org.teavm.model.TryCatchBlock; import org.teavm.model.TryCatchJoint; import org.teavm.model.Variable; +import org.teavm.model.analysis.NullnessChecker; import org.teavm.model.util.BasicBlockMapper; import org.teavm.model.util.DefinitionExtractor; import org.teavm.model.util.InstructionCopyReader; @@ -222,7 +223,8 @@ class LoopInversionImpl { private boolean isInversionProfitable(IntSet nodesToCopy) { UsageExtractor useExtractor = new UsageExtractor(); DefinitionExtractor defExtractor = new DefinitionExtractor(); - LoopInvariantAnalyzer invariantAnalyzer = new LoopInvariantAnalyzer(); + boolean[] notNull = new NullnessChecker().check(program); + LoopInvariantAnalyzer invariantAnalyzer = new LoopInvariantAnalyzer(notNull); for (int node : nodes.toArray()) { if (nodesToCopy.contains(node)) { continue; 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 c7cfb237e..d8ae03473 100644 --- a/core/src/main/java/org/teavm/model/util/ProgramUtils.java +++ b/core/src/main/java/org/teavm/model/util/ProgramUtils.java @@ -163,6 +163,23 @@ public final class ProgramUtils { return outputs; } + public static List> getPhiOutputsByVariable(Program program) { + List> outputs = new ArrayList<>(program.variableCount()); + for (int i = 0; i < program.variableCount(); ++i) { + outputs.add(new ArrayList<>()); + } + + for (BasicBlock block : program.getBasicBlocks()) { + for (Phi phi : block.getPhis()) { + for (Incoming incoming : phi.getIncomings()) { + outputs.get(incoming.getValue().getIndex()).add(incoming); + } + } + } + + return outputs; + } + public static BasicBlock[] getVariableDefinitionPlaces(Program program) { BasicBlock[] places = new BasicBlock[program.variableCount()]; DefinitionExtractor defExtractor = new DefinitionExtractor();