diff --git a/teavm-core/src/main/java/org/teavm/common/GraphBuilder.java b/teavm-core/src/main/java/org/teavm/common/GraphBuilder.java index 7a072a96a..4f6bfdd03 100644 --- a/teavm-core/src/main/java/org/teavm/common/GraphBuilder.java +++ b/teavm-core/src/main/java/org/teavm/common/GraphBuilder.java @@ -43,6 +43,9 @@ public class GraphBuilder { } public void addEdge(int from, int to) { + if (to < 0) { + throw new IllegalArgumentException("To is negative: " + to); + } sz = Math.max(sz, Math.max(from, to) + 1); builtGraph = null; if (addedEdges.size() == from) { diff --git a/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java b/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java new file mode 100644 index 000000000..064c668b9 --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/model/util/BasicBlockMapper.java @@ -0,0 +1,183 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.model.util; + +import org.teavm.model.BasicBlock; +import org.teavm.model.Incoming; +import org.teavm.model.Phi; +import org.teavm.model.Program; +import org.teavm.model.instructions.*; + +/** + * + * @author Alexey Andreev + */ +public abstract class BasicBlockMapper implements InstructionVisitor { + protected abstract BasicBlock map(BasicBlock block); + + public void transform(Program program) { + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlock block = program.basicBlockAt(i); + block.getLastInstruction().acceptVisitor(this); + for (Phi phi : block.getPhis()) { + for (Incoming incoming : phi.getIncomings()) { + incoming.setSource(map(incoming.getSource())); + } + } + } + } + + @Override + public void visit(EmptyInstruction insn) { + } + + @Override + public void visit(ClassConstantInstruction insn) { + } + + @Override + public void visit(NullConstantInstruction insn) { + } + + @Override + public void visit(IntegerConstantInstruction insn) { + } + + @Override + public void visit(LongConstantInstruction insn) { + } + + @Override + public void visit(FloatConstantInstruction insn) { + } + + @Override + public void visit(DoubleConstantInstruction insn) { + } + + @Override + public void visit(StringConstantInstruction insn) { + } + + @Override + public void visit(BinaryInstruction insn) { + } + + @Override + public void visit(NegateInstruction insn) { + } + + @Override + public void visit(AssignInstruction insn) { + } + + @Override + public void visit(CastInstruction insn) { + } + + @Override + public void visit(CastNumberInstruction insn) { + } + + @Override + public void visit(CastIntegerInstruction insn) { + } + + @Override + public void visit(BranchingInstruction insn) { + insn.setConsequent(map(insn.getConsequent())); + insn.setAlternative(map(insn.getAlternative())); + } + + @Override + public void visit(BinaryBranchingInstruction insn) { + insn.setConsequent(map(insn.getConsequent())); + insn.setAlternative(map(insn.getAlternative())); + } + + @Override + public void visit(JumpInstruction insn) { + insn.setTarget(map(insn.getTarget())); + } + + @Override + public void visit(SwitchInstruction insn) { + for (SwitchTableEntry entry : insn.getEntries()) { + entry.setTarget(map(entry.getTarget())); + } + insn.setDefaultTarget(map(insn.getDefaultTarget())); + } + + @Override + public void visit(ExitInstruction insn) { + } + + @Override + public void visit(RaiseInstruction insn) { + } + + @Override + public void visit(ConstructArrayInstruction insn) { + } + + @Override + public void visit(ConstructInstruction insn) { + } + + @Override + public void visit(ConstructMultiArrayInstruction insn) { + } + + @Override + public void visit(GetFieldInstruction insn) { + } + + @Override + public void visit(PutFieldInstruction insn) { + } + + @Override + public void visit(ArrayLengthInstruction insn) { + } + + @Override + public void visit(CloneArrayInstruction insn) { + } + + @Override + public void visit(UnwrapArrayInstruction insn) { + } + + @Override + public void visit(GetElementInstruction insn) { + } + + @Override + public void visit(PutElementInstruction insn) { + } + + @Override + public void visit(InvokeInstruction insn) { + } + + @Override + public void visit(IsInstanceInstruction insn) { + } + + @Override + public void visit(InitClassInstruction insn) { + } +} diff --git a/teavm-core/src/main/java/org/teavm/model/util/DefinitionExtractor.java b/teavm-core/src/main/java/org/teavm/model/util/DefinitionExtractor.java index 79fcda1ba..16ea86fc9 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/DefinitionExtractor.java +++ b/teavm-core/src/main/java/org/teavm/model/util/DefinitionExtractor.java @@ -195,5 +195,6 @@ public class DefinitionExtractor implements InstructionVisitor { @Override public void visit(InitClassInstruction insn) { + definedVariables = new Variable[0]; } } diff --git a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java index 027010f1a..1e4ce4cf5 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java +++ b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java @@ -37,10 +37,9 @@ public class RegisterAllocator { for (int i = 0; i < method.parameterCount(); ++i) { colors[i] = i; } - List> involvedIncomings = getInvolvedIncomings(method.getProgram()); GraphBuilder graphBuilder = new GraphBuilder(); Program program = method.getProgram(); - for (int v = 0; v < program.variableCount(); ++v) { + for (int v = 0; v < interferenceGraph.size(); ++v) { for (int w : interferenceGraph.outgoingEdges(v)) { if (w <= v) { continue; @@ -55,20 +54,21 @@ public class RegisterAllocator { return colors; } - private List> getInvolvedIncomings(Program program) { - List> involvedIncomings = new ArrayList<>(); - for (int i = 0; i < program.variableCount(); ++i) { - involvedIncomings.add(new ArrayList()); - } + private static class PhiArgumentCopy { + Incoming incoming; + int original; + } + + private List insertPhiArgumentsCopies(Program program) { + List copies = new ArrayList<>(); for (int i = 0; i < program.basicBlockCount(); ++i) { - BasicBlock block = program.basicBlockAt(i); - for (Phi phi : block.getPhis()) { + for (Phi phi : program.basicBlockAt(i).getPhis()) { for (Incoming incoming : phi.getIncomings()) { - involvedIncomings.get(incoming.getValue().getIndex()).add(incoming); + } } } - return involvedIncomings; + return copies; } private int[] buildPhiCongruenceClasses(Program program) { diff --git a/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java b/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java index e1b3999b4..ece03aea7 100644 --- a/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java +++ b/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java @@ -27,7 +27,8 @@ import org.teavm.model.MethodHolder; */ public class ClassSetOptimizer { private List optimizations = Arrays.asList( - new CommonSubexpressionElimination(), new UnusedVariableElimination()); + new CommonSubexpressionElimination(), new UnusedVariableElimination(), + new EmptyBlockElimination()); public void optimizeAll(ListableClassHolderSource classSource) { for (String className : classSource.getClassNames()) { diff --git a/teavm-core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java b/teavm-core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java new file mode 100644 index 000000000..24cd7656e --- /dev/null +++ b/teavm-core/src/main/java/org/teavm/optimization/EmptyBlockElimination.java @@ -0,0 +1,60 @@ +/* + * Copyright 2014 Alexey Andreev. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.teavm.optimization; + +import org.teavm.model.BasicBlock; +import org.teavm.model.MethodHolder; +import org.teavm.model.Program; +import org.teavm.model.instructions.JumpInstruction; +import org.teavm.model.util.BasicBlockMapper; + +/** + * + * @author Alexey Andreev + */ +public class EmptyBlockElimination implements MethodOptimization { + @Override + public void optimize(MethodHolder method) { + final Program program = method.getProgram(); + final int[] blockMapping = new int[program.basicBlockCount()]; + for (int i = 0; i < blockMapping.length; ++i) { + blockMapping[i] = i; + } + int lastNonEmpty = program.basicBlockCount() - 1; + for (int i = program.basicBlockCount() - 2; i > 0; --i) { + BasicBlock block = program.basicBlockAt(i); + if (block.getPhis().isEmpty() && block.getInstructions().size() == 1 && + block.getLastInstruction() instanceof JumpInstruction) { + JumpInstruction insn = (JumpInstruction)block.getLastInstruction(); + if (insn.getTarget().getIndex() == i + 1) { + blockMapping[i] = lastNonEmpty; + } + } + lastNonEmpty = blockMapping[i]; + } + new BasicBlockMapper() { + @Override protected BasicBlock map(BasicBlock block) { + return program.basicBlockAt(blockMapping[block.getIndex()]); + } + }.transform(program); + for (int i = 0; i < program.basicBlockCount(); ++i) { + if (blockMapping[i] != i) { + program.deleteBasicBlock(i); + } + } + program.pack(); + } +}