mirror of
https://github.com/konsoletyper/teavm.git
synced 2025-02-23 11:29:56 +08:00
Avoid creating of unnecessary phi functions
This commit is contained in:
parent
7ca6a4d64e
commit
973231752f
@ -22,6 +22,6 @@ public class LoopInversion implements MethodOptimization {
|
||||
@Override
|
||||
public boolean optimize(MethodOptimizationContext context, Program program) {
|
||||
MethodReader method = context.getMethod();
|
||||
return new LoopInversionImpl(method, program, method.parameterCount() + 1).apply();
|
||||
return new LoopInversionImpl(program, method.parameterCount() + 1).apply();
|
||||
}
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ import org.teavm.common.LoopGraph;
|
||||
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;
|
||||
@ -80,7 +79,6 @@ import org.teavm.model.util.UsageExtractor;
|
||||
* all remaining nodes are *condition*.
|
||||
*/
|
||||
class LoopInversionImpl {
|
||||
private final MethodReader method;
|
||||
private final Program program;
|
||||
private final int parameterCount;
|
||||
private Graph cfg;
|
||||
@ -90,8 +88,7 @@ class LoopInversionImpl {
|
||||
private BasicBlock[] definitionPlaces;
|
||||
private boolean affected;
|
||||
|
||||
LoopInversionImpl(MethodReader method, Program program, int parameterCount) {
|
||||
this.method = method;
|
||||
LoopInversionImpl(Program program, int parameterCount) {
|
||||
this.program = program;
|
||||
this.parameterCount = parameterCount;
|
||||
definitionPlaces = ProgramUtils.getVariableDefinitionPlaces(program);
|
||||
@ -116,7 +113,6 @@ class LoopInversionImpl {
|
||||
inputs[i] = program.variableAt(i);
|
||||
}
|
||||
new PhiUpdater().updatePhis(program, inputs);
|
||||
new UnusedVariableElimination().optimize(method, program);
|
||||
}
|
||||
}
|
||||
} while (postponed);
|
||||
|
@ -15,10 +15,15 @@
|
||||
*/
|
||||
package org.teavm.model.util;
|
||||
|
||||
import com.carrotsearch.hppc.IntArrayDeque;
|
||||
import com.carrotsearch.hppc.IntDeque;
|
||||
import com.carrotsearch.hppc.IntObjectMap;
|
||||
import com.carrotsearch.hppc.IntObjectOpenHashMap;
|
||||
import com.carrotsearch.hppc.IntOpenHashSet;
|
||||
import com.carrotsearch.hppc.IntSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
@ -86,6 +91,9 @@ public class PhiUpdater {
|
||||
private int[][] phiIndexMap;
|
||||
private Map<TryCatchBlock, Map<Variable, TryCatchJoint>> jointMap = new HashMap<>();
|
||||
private List<List<Phi>> synthesizedPhis = new ArrayList<>();
|
||||
private IntObjectMap<Phi> phisByReceiver = new IntObjectOpenHashMap<>();
|
||||
private IntObjectMap<TryCatchJoint> jointsByReceiver = new IntObjectOpenHashMap<>();
|
||||
private BitSet usedPhis = new BitSet();
|
||||
private List<List<List<TryCatchJoint>>> synthesizedJoints = new ArrayList<>();
|
||||
private Variable[] originalExceptionVariables;
|
||||
private boolean[] usedDefinitions;
|
||||
@ -100,6 +108,8 @@ public class PhiUpdater {
|
||||
return;
|
||||
}
|
||||
this.program = program;
|
||||
phisByReceiver.clear();
|
||||
jointsByReceiver.clear();
|
||||
cfg = ProgramUtils.buildControlFlowGraph(program);
|
||||
DominatorTree domTree = GraphUtils.buildDominatorTree(cfg);
|
||||
domFrontiers = new int[cfg.size()][];
|
||||
@ -138,6 +148,8 @@ public class PhiUpdater {
|
||||
|
||||
estimatePhis();
|
||||
renameVariables();
|
||||
propagatePhiUsageInformation();
|
||||
addSynthesizedPhis();
|
||||
}
|
||||
|
||||
private void estimatePhis() {
|
||||
@ -211,6 +223,7 @@ public class PhiUpdater {
|
||||
Variable var = program.createVariable();
|
||||
var.setDebugName(phi.getReceiver().getDebugName());
|
||||
mapVariable(phi.getReceiver().getIndex(), var);
|
||||
phisByReceiver.put(var.getIndex(), phi);
|
||||
phi.setReceiver(var);
|
||||
}
|
||||
for (Phi phi : currentBlock.getPhis()) {
|
||||
@ -244,7 +257,11 @@ public class PhiUpdater {
|
||||
TryCatchBlock tryCatch = currentBlock.getTryCatchBlocks().get(i);
|
||||
catchSuccessors.add(tryCatch.getHandler().getIndex());
|
||||
for (TryCatchJoint joint : synthesizedJoints.get(index).get(i)) {
|
||||
joint.setReceiver(defineForExceptionPhi(joint.getReceiver()));
|
||||
Variable var = program.createVariable();
|
||||
var.setDebugName(joint.getReceiver().getDebugName());
|
||||
mapVariable(joint.getReceiver().getIndex(), var);
|
||||
joint.setReceiver(var);
|
||||
jointsByReceiver.put(var.getIndex(), joint);
|
||||
}
|
||||
}
|
||||
variableMap = regularVariableMap;
|
||||
@ -263,9 +280,14 @@ public class PhiUpdater {
|
||||
renameOutgoingPhis(successor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addSynthesizedPhis() {
|
||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||
for (Phi phi : synthesizedPhis.get(i)) {
|
||||
if (!usedPhis.get(phi.getReceiver().getIndex())) {
|
||||
continue;
|
||||
}
|
||||
if (!phi.getIncomings().isEmpty()) {
|
||||
program.basicBlockAt(i).getPhis().add(phi);
|
||||
}
|
||||
@ -276,6 +298,9 @@ public class PhiUpdater {
|
||||
List<TryCatchJoint> jointList = joints.get(j);
|
||||
TryCatchBlock targetTryCatch = program.basicBlockAt(i).getTryCatchBlocks().get(j);
|
||||
for (TryCatchJoint joint : jointList) {
|
||||
if (!usedPhis.get(joint.getReceiver().getIndex())) {
|
||||
continue;
|
||||
}
|
||||
if (!joint.getSourceVariables().isEmpty()) {
|
||||
targetTryCatch.getJoints().add(joint);
|
||||
}
|
||||
@ -284,6 +309,47 @@ public class PhiUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
private void propagatePhiUsageInformation() {
|
||||
IntDeque worklist = new IntArrayDeque();
|
||||
for (int receiverIndex : phisByReceiver.keys().toArray()) {
|
||||
if (usedPhis.get(receiverIndex)) {
|
||||
worklist.addLast(receiverIndex);
|
||||
}
|
||||
}
|
||||
for (int receiverIndex : jointsByReceiver.keys().toArray()) {
|
||||
if (usedPhis.get(receiverIndex)) {
|
||||
worklist.addLast(receiverIndex);
|
||||
}
|
||||
}
|
||||
|
||||
IntSet visited = new IntOpenHashSet();
|
||||
while (!worklist.isEmpty()) {
|
||||
int varIndex = worklist.removeFirst();
|
||||
if (!visited.add(varIndex)) {
|
||||
continue;
|
||||
}
|
||||
usedPhis.set(varIndex);
|
||||
|
||||
Phi phi = phisByReceiver.get(varIndex);
|
||||
if (phi != null) {
|
||||
for (Incoming incoming : phi.getIncomings()) {
|
||||
if (!visited.contains(incoming.getValue().getIndex())) {
|
||||
worklist.addLast(incoming.getValue().getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
TryCatchJoint joint = jointsByReceiver.get(varIndex);
|
||||
if (joint != null) {
|
||||
for (Variable sourceVar : joint.getSourceVariables()) {
|
||||
if (!visited.contains(sourceVar.getIndex())) {
|
||||
worklist.addLast(sourceVar.getIndex());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void renameOutgoingPhis(int successor) {
|
||||
int[] phiIndexes = phiIndexMap[successor];
|
||||
List<Phi> phis = synthesizedPhis.get(successor);
|
||||
@ -350,13 +416,6 @@ public class PhiUpdater {
|
||||
}
|
||||
}
|
||||
|
||||
private Variable defineForExceptionPhi(Variable var) {
|
||||
Variable original = var;
|
||||
var = introduce(var);
|
||||
mapVariable(original.getIndex(), var);
|
||||
return var;
|
||||
}
|
||||
|
||||
private Variable define(Variable var) {
|
||||
Variable old = variableMap[var.getIndex()];
|
||||
Variable original = var;
|
||||
@ -413,6 +472,7 @@ public class PhiUpdater {
|
||||
if (mappedVar == null) {
|
||||
throw new AssertionError("Variable used before definition: " + var.getIndex());
|
||||
}
|
||||
usedPhis.set(mappedVar.getIndex());
|
||||
return mappedVar;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user