Add redundant jump elimination

This commit is contained in:
Alexey Andreev 2016-06-18 23:32:23 +03:00 committed by Alexey Andreev
parent 0d6d4e7e41
commit 920a17ff63
8 changed files with 138 additions and 26 deletions

View File

@ -23,28 +23,18 @@ import org.teavm.model.Variable;
* @author shannah * @author shannah
*/ */
public class MonitorEnterInstruction extends Instruction { public class MonitorEnterInstruction extends Instruction {
private Variable objectRef; private Variable objectRef;
@Override @Override
public void acceptVisitor(InstructionVisitor visitor) { public void acceptVisitor(InstructionVisitor visitor) {
visitor.visit(this); visitor.visit(this);
} }
/**
* @return the objectRef
*/
public Variable getObjectRef() { public Variable getObjectRef() {
return objectRef; return objectRef;
} }
/**
* @param objectRef the objectRef to set
*/
public void setObjectRef(Variable objectRef) { public void setObjectRef(Variable objectRef) {
this.objectRef = objectRef; this.objectRef = objectRef;
} }
} }

View File

@ -23,7 +23,6 @@ import org.teavm.model.Variable;
* @author shannah * @author shannah
*/ */
public class MonitorExitInstruction extends Instruction { public class MonitorExitInstruction extends Instruction {
private Variable objectRef; private Variable objectRef;
@Override @Override
@ -31,18 +30,11 @@ public class MonitorExitInstruction extends Instruction {
visitor.visit(this); visitor.visit(this);
} }
/**
* @return the objectRef
*/
public Variable getObjectRef() { public Variable getObjectRef() {
return objectRef; return objectRef;
} }
/**
* @param objectRef the objectRef to set
*/
public void setObjectRef(Variable objectRef) { public void setObjectRef(Variable objectRef) {
this.objectRef = objectRef; this.objectRef = objectRef;
} }
} }

View File

@ -38,12 +38,15 @@ public class ArrayUnwrapMotion implements MethodOptimization {
Instruction insn = instructions.get(i); Instruction insn = instructions.get(i);
if (insn instanceof UnwrapArrayInstruction) { if (insn instanceof UnwrapArrayInstruction) {
UnwrapArrayInstruction unwrap = (UnwrapArrayInstruction) insn; UnwrapArrayInstruction unwrap = (UnwrapArrayInstruction) insn;
instructions.set(i, new EmptyInstruction()); EmptyInstruction empty = new EmptyInstruction();
empty.setLocation(unwrap.getLocation());
instructions.set(i, empty);
int def = whereDefined(instructions, i, unwrap.getArray()); int def = whereDefined(instructions, i, unwrap.getArray());
if (def < 0) { if (def < 0) {
newInstructions.add(unwrap); newInstructions.add(unwrap);
} else { } else {
instructions.add(def + 1, unwrap); instructions.add(def + 1, unwrap);
unwrap.setLocation(instructions.get(def).getLocation());
++i; ++i;
} }
} }

View File

@ -55,7 +55,9 @@ public class ClassInitElimination implements MethodOptimization {
if (insn instanceof InitClassInstruction) { if (insn instanceof InitClassInstruction) {
InitClassInstruction initClass = (InitClassInstruction) insn; InitClassInstruction initClass = (InitClassInstruction) insn;
if (!step.initializedClasses.add(initClass.getClassName())) { if (!step.initializedClasses.add(initClass.getClassName())) {
instructions.set(i, new EmptyInstruction()); EmptyInstruction empty = new EmptyInstruction();
empty.setLocation(initClass.getLocation());
instructions.set(i, empty);
} }
continue; continue;
} }

View File

@ -95,28 +95,34 @@ public class GlobalValueNumbering implements MethodOptimization {
currentInsn.acceptVisitor(optimizer); currentInsn.acceptVisitor(optimizer);
if (eliminate) { if (eliminate) {
affected = true; affected = true;
block.getInstructions().set(i, new EmptyInstruction()); EmptyInstruction empty = new EmptyInstruction();
empty.setLocation(currentInsn.getLocation());
block.getInstructions().set(i, empty);
eliminate = false; eliminate = false;
} else if (evaluatedConstant != null) { } else if (evaluatedConstant != null) {
if (evaluatedConstant instanceof Integer) { if (evaluatedConstant instanceof Integer) {
IntegerConstantInstruction newInsn = new IntegerConstantInstruction(); IntegerConstantInstruction newInsn = new IntegerConstantInstruction();
newInsn.setConstant((Integer) evaluatedConstant); newInsn.setConstant((Integer) evaluatedConstant);
newInsn.setReceiver(program.variableAt(receiver)); newInsn.setReceiver(program.variableAt(receiver));
newInsn.setLocation(currentInsn.getLocation());
block.getInstructions().set(i, newInsn); block.getInstructions().set(i, newInsn);
} else if (evaluatedConstant instanceof Long) { } else if (evaluatedConstant instanceof Long) {
LongConstantInstruction newInsn = new LongConstantInstruction(); LongConstantInstruction newInsn = new LongConstantInstruction();
newInsn.setConstant((Long) evaluatedConstant); newInsn.setConstant((Long) evaluatedConstant);
newInsn.setReceiver(program.variableAt(receiver)); newInsn.setReceiver(program.variableAt(receiver));
newInsn.setLocation(currentInsn.getLocation());
block.getInstructions().set(i, newInsn); block.getInstructions().set(i, newInsn);
} else if (evaluatedConstant instanceof Float) { } else if (evaluatedConstant instanceof Float) {
FloatConstantInstruction newInsn = new FloatConstantInstruction(); FloatConstantInstruction newInsn = new FloatConstantInstruction();
newInsn.setConstant((Float) evaluatedConstant); newInsn.setConstant((Float) evaluatedConstant);
newInsn.setReceiver(program.variableAt(receiver)); newInsn.setReceiver(program.variableAt(receiver));
newInsn.setLocation(currentInsn.getLocation());
block.getInstructions().set(i, newInsn); block.getInstructions().set(i, newInsn);
} else if (evaluatedConstant instanceof Double) { } else if (evaluatedConstant instanceof Double) {
DoubleConstantInstruction newInsn = new DoubleConstantInstruction(); DoubleConstantInstruction newInsn = new DoubleConstantInstruction();
newInsn.setConstant((Double) evaluatedConstant); newInsn.setConstant((Double) evaluatedConstant);
newInsn.setReceiver(program.variableAt(receiver)); newInsn.setReceiver(program.variableAt(receiver));
newInsn.setLocation(currentInsn.getLocation());
block.getInstructions().set(i, newInsn); block.getInstructions().set(i, newInsn);
} }
} }

View File

@ -109,7 +109,10 @@ public class LoopInvariantMotion implements MethodOptimization {
continue insnLoop; continue insnLoop;
} }
} }
block.getInstructions().set(i, new EmptyInstruction());
EmptyInstruction empty = new EmptyInstruction();
empty.setLocation(insn.getLocation());
block.getInstructions().set(i, empty);
int preheader = getPreheader(defLoop.getHead()); int preheader = getPreheader(defLoop.getHead());
List<Instruction> preheaderInstructions = program.basicBlockAt(preheader).getInstructions(); List<Instruction> preheaderInstructions = program.basicBlockAt(preheader).getInstructions();
List<Instruction> newInstructions = new ArrayList<>(); List<Instruction> newInstructions = new ArrayList<>();

View File

@ -0,0 +1,108 @@
/*
* Copyright 2016 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.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.teavm.common.Graph;
import org.teavm.model.BasicBlock;
import org.teavm.model.Incoming;
import org.teavm.model.Instruction;
import org.teavm.model.MethodReader;
import org.teavm.model.Phi;
import org.teavm.model.Program;
import org.teavm.model.TryCatchBlock;
import org.teavm.model.instructions.AssignInstruction;
import org.teavm.model.instructions.JumpInstruction;
import org.teavm.model.util.InstructionTransitionExtractor;
import org.teavm.model.util.ProgramUtils;
public class RedundantJumpElimination implements MethodOptimization {
@Override
public boolean optimize(MethodReader method, Program program) {
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
int[] incomingCount = new int[cfg.size()];
Arrays.setAll(incomingCount, cfg::incomingEdgesCount);
boolean changed = false;
InstructionTransitionExtractor transitionExtractor = new InstructionTransitionExtractor();
for (int i = 1; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
if (block == null) {
continue;
}
Instruction insn = block.getLastInstruction();
if (!(insn instanceof JumpInstruction)) {
continue;
}
BasicBlock target = ((JumpInstruction) insn).getTarget();
if (incomingCount[target.getIndex()] > 1) {
continue;
}
if (!block.getTryCatchBlocks().isEmpty() || !target.getTryCatchBlocks().isEmpty()) {
continue;
}
block.getInstructions().remove(block.getInstructions().size() - 1);
for (Phi phi : target.getPhis()) {
if (phi.getIncomings().isEmpty()) {
continue;
}
Incoming incoming = phi.getIncomings().get(0);
AssignInstruction assign = new AssignInstruction();
assign.setReceiver(phi.getReceiver());
assign.setAssignee(incoming.getValue());
block.getInstructions().add(assign);
}
List<Instruction> instructionsToTransfer = new ArrayList<>(target.getInstructions());
target.getInstructions().clear();
block.getInstructions().addAll(instructionsToTransfer);
Instruction lastInsn = block.getLastInstruction();
if (lastInsn != null) {
lastInsn.acceptVisitor(transitionExtractor);
BasicBlock[] successors = transitionExtractor.getTargets();
if (successors != null) {
for (BasicBlock successor : successors) {
successor.getPhis().stream()
.flatMap(phi -> phi.getIncomings().stream())
.filter(incoming -> incoming.getSource() == target)
.forEach(incoming -> incoming.setSource(block));
}
}
}
for (TryCatchBlock tryCatch : target.getTryCatchBlocks()) {
for (Phi phi : tryCatch.getHandler().getPhis()) {
phi.getIncomings().removeIf(incoming -> incoming.getSource() == target);
}
}
incomingCount[target.getIndex()] = 2;
program.deleteBasicBlock(target.getIndex());
--i;
changed = true;
}
if (changed) {
program.pack();
}
return changed;
}
}

View File

@ -100,6 +100,7 @@ import org.teavm.optimization.Inlining;
import org.teavm.optimization.LoopInvariantMotion; import org.teavm.optimization.LoopInvariantMotion;
import org.teavm.optimization.LoopInversion; import org.teavm.optimization.LoopInversion;
import org.teavm.optimization.MethodOptimization; import org.teavm.optimization.MethodOptimization;
import org.teavm.optimization.RedundantJumpElimination;
import org.teavm.optimization.UnreachableBasicBlockElimination; import org.teavm.optimization.UnreachableBasicBlockElimination;
import org.teavm.optimization.UnusedVariableElimination; import org.teavm.optimization.UnusedVariableElimination;
import org.teavm.vm.spi.RendererListener; import org.teavm.vm.spi.RendererListener;
@ -735,9 +736,16 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
} }
private List<MethodOptimization> getOptimizations() { private List<MethodOptimization> getOptimizations() {
return Arrays.asList(new ArrayUnwrapMotion(), new LoopInversion(), new LoopInvariantMotion(), return Arrays.asList(
new GlobalValueNumbering(), new ConstantConditionElimination(), new UnusedVariableElimination(), new ArrayUnwrapMotion(),
new ClassInitElimination(), new UnreachableBasicBlockElimination()); new LoopInversion(),
new LoopInvariantMotion(),
new GlobalValueNumbering(),
new ConstantConditionElimination(),
new RedundantJumpElimination(),
new UnusedVariableElimination(),
new ClassInitElimination(),
new UnreachableBasicBlockElimination());
} }
private void logMethodBytecode(PrintWriter writer, MethodHolder method) { private void logMethodBytecode(PrintWriter writer, MethodHolder method) {