mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2025-01-08 07:54:11 -08:00
Adds loop invariant code motion optimization
This commit is contained in:
parent
2f2985bb10
commit
b96c5038ce
|
@ -213,9 +213,6 @@ public class Decompiler {
|
|||
if (node >= 0) {
|
||||
generator.currentBlock = program.basicBlockAt(node);
|
||||
int tmp = indexer.nodeAt(next);
|
||||
if (tmp < 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
generator.nextBlock = next < indexer.size() ? program.basicBlockAt(tmp) : null;
|
||||
generator.statements.clear();
|
||||
for (Instruction insn : generator.currentBlock.getInstructions()) {
|
||||
|
|
|
@ -36,7 +36,8 @@ public class ClassSetOptimizer {
|
|||
}
|
||||
|
||||
private List<MethodOptimization> getOptimizations() {
|
||||
return Arrays.<MethodOptimization>asList(new GlobalValueNumbering(), new UnusedVariableElimination());
|
||||
return Arrays.<MethodOptimization>asList(new LoopInvariantMotion(), new GlobalValueNumbering(),
|
||||
new UnusedVariableElimination());
|
||||
}
|
||||
|
||||
public void optimizeAll(ListableClassHolderSource classSource) {
|
||||
|
|
|
@ -0,0 +1,319 @@
|
|||
/*
|
||||
* 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 java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.teavm.common.*;
|
||||
import org.teavm.model.*;
|
||||
import org.teavm.model.instructions.*;
|
||||
import org.teavm.model.util.DefinitionExtractor;
|
||||
import org.teavm.model.util.ProgramUtils;
|
||||
import org.teavm.model.util.UsageExtractor;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class LoopInvariantMotion implements MethodOptimization {
|
||||
private int[] preheaders;
|
||||
private LoopGraph graph;
|
||||
private DominatorTree dom;
|
||||
private Program program;
|
||||
|
||||
@Override
|
||||
public void optimize(MethodReader method, Program program) {
|
||||
this.program = program;
|
||||
graph = new LoopGraph(ProgramUtils.buildControlFlowGraph(program));
|
||||
dom = GraphUtils.buildDominatorTree(graph);
|
||||
Graph domGraph = GraphUtils.buildDominatorGraph(dom, graph.size());
|
||||
preheaders = new int[graph.size()];
|
||||
Arrays.fill(preheaders, -1);
|
||||
IntegerStack stack = new IntegerStack(graph.size());
|
||||
int[] defLocation = new int[program.variableCount()];
|
||||
Arrays.fill(defLocation, -1);
|
||||
for (int i = 0; i < domGraph.size(); ++i) {
|
||||
if (dom.immediateDominatorOf(i) < 0) {
|
||||
stack.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||
UsageExtractor useExtractor = new UsageExtractor();
|
||||
InstructionAnalyzer analyzer = new InstructionAnalyzer();
|
||||
while (!stack.isEmpty()) {
|
||||
int v = stack.pop();
|
||||
BasicBlock block = program.basicBlockAt(v);
|
||||
insnLoop: for (int i = 0; i < block.getInstructions().size(); ++i) {
|
||||
Instruction insn = block.getInstructions().get(i);
|
||||
insn.acceptVisitor(defExtractor);
|
||||
Variable[] defs = defExtractor.getDefinedVariables();
|
||||
for (Variable def : defs) {
|
||||
defLocation[def.getIndex()] = v;
|
||||
}
|
||||
analyzer.canMove = false;
|
||||
insn.acceptVisitor(analyzer);
|
||||
if (!analyzer.canMove) {
|
||||
continue;
|
||||
}
|
||||
Loop defLoop = graph.loopAt(v);
|
||||
if (defLoop == null) {
|
||||
continue;
|
||||
}
|
||||
insn.acceptVisitor(useExtractor);
|
||||
Loop commonUseLoop = null;
|
||||
for (Variable use : useExtractor.getUsedVariables()) {
|
||||
int useLoc = defLocation[use.getIndex()];
|
||||
if (useLoc == -1) {
|
||||
continue insnLoop;
|
||||
}
|
||||
Loop useLoop = graph.loopAt(useLoc);
|
||||
if (useLoop == defLoop) {
|
||||
continue insnLoop;
|
||||
}
|
||||
if (useLoop != null && useLoop.isChildOf(commonUseLoop)) {
|
||||
commonUseLoop = useLoop;
|
||||
}
|
||||
}
|
||||
block.getInstructions().set(i, new EmptyInstruction());
|
||||
while (defLoop.getParent() != commonUseLoop) {
|
||||
defLoop = defLoop.getParent();
|
||||
}
|
||||
int preheader = getPreheader(defLoop.getHead());
|
||||
List<Instruction> preheaderInstructions = program.basicBlockAt(preheader).getInstructions();
|
||||
preheaderInstructions.add(preheaderInstructions.size() - 1, insn);
|
||||
defLocation[defs[0].getIndex()] = commonUseLoop != null ? commonUseLoop.getHead() : 0;
|
||||
}
|
||||
for (int succ : domGraph.outgoingEdges(v)) {
|
||||
stack.push(succ);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int getPreheader(int header) {
|
||||
int preheader = preheaders[header];
|
||||
if (preheader < 0) {
|
||||
int[] entries = getLoopEntries(header);
|
||||
if (entries.length == 1) {
|
||||
preheader = graph.incomingEdges(header)[0];
|
||||
} else {
|
||||
preheader = insertPreheader(header);
|
||||
}
|
||||
preheaders[header] = preheader;
|
||||
}
|
||||
return preheader;
|
||||
}
|
||||
|
||||
private int[] getLoopEntries(int header) {
|
||||
int[] predecessors = graph.incomingEdges(header);
|
||||
int j = 0;
|
||||
for (int i = 0; i < predecessors.length; ++i) {
|
||||
int pred = predecessors[i];
|
||||
if (!dom.dominates(header, pred)) {
|
||||
predecessors[j++] = pred;
|
||||
}
|
||||
}
|
||||
return Arrays.copyOf(predecessors, j);
|
||||
}
|
||||
|
||||
private int insertPreheader(int headerIndex) {
|
||||
BasicBlock preheader = program.createBasicBlock();
|
||||
JumpInstruction escapeInsn = new JumpInstruction();
|
||||
BasicBlock header = program.basicBlockAt(headerIndex);
|
||||
escapeInsn.setTarget(header);
|
||||
preheader.getInstructions().add(escapeInsn);
|
||||
for (int i = 0; i < header.getPhis().size(); ++i) {
|
||||
Phi phi = header.getPhis().get(i);
|
||||
Phi preheaderPhi = null;
|
||||
for (int j = 0; j < phi.getIncomings().size(); ++j) {
|
||||
Incoming incoming = phi.getIncomings().get(j);
|
||||
if (!dom.dominates(headerIndex, incoming.getSource().getIndex())) {
|
||||
phi.getIncomings().remove(j--);
|
||||
if (preheaderPhi == null) {
|
||||
preheaderPhi = new Phi();
|
||||
preheaderPhi.setReceiver(program.createVariable());
|
||||
preheader.getPhis().add(preheaderPhi);
|
||||
}
|
||||
preheaderPhi.getIncomings().add(incoming);
|
||||
}
|
||||
}
|
||||
if (preheaderPhi != null) {
|
||||
Incoming incoming = new Incoming();
|
||||
incoming.setSource(preheader);
|
||||
incoming.setValue(phi.getReceiver());
|
||||
phi.getIncomings().add(incoming);
|
||||
}
|
||||
}
|
||||
return preheader.getIndex();
|
||||
}
|
||||
|
||||
private static class InstructionAnalyzer implements InstructionVisitor {
|
||||
public boolean canMove;
|
||||
|
||||
@Override
|
||||
public void visit(EmptyInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(ClassConstantInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullConstantInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IntegerConstantInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(LongConstantInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(FloatConstantInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(DoubleConstantInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(StringConstantInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BinaryInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NegateInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(AssignInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CastInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CastNumberInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CastIntegerInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BranchingInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(BinaryBranchingInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(JumpInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(SwitchInstruction insn) {
|
||||
}
|
||||
|
||||
@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) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(CloneArrayInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(UnwrapArrayInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(GetElementInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(PutElementInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InvokeInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(IsInstanceInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(InitClassInstruction insn) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(NullCheckInstruction insn) {
|
||||
canMove = true;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user