mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Refactor phi updater
This commit is contained in:
parent
a5eb9ac800
commit
9532f9a32b
|
@ -228,6 +228,7 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
||||||
@Override
|
@Override
|
||||||
public InstructionIterator iterateInstructions() {
|
public InstructionIterator iterateInstructions() {
|
||||||
return new InstructionIterator() {
|
return new InstructionIterator() {
|
||||||
|
TextLocation location;
|
||||||
Instruction instruction = firstInstruction;
|
Instruction instruction = firstInstruction;
|
||||||
Instruction readInstruction;
|
Instruction readInstruction;
|
||||||
InstructionReadVisitor visitor = new InstructionReadVisitor(null);
|
InstructionReadVisitor visitor = new InstructionReadVisitor(null);
|
||||||
|
@ -257,6 +258,10 @@ public class BasicBlock implements BasicBlockReader, Iterable<Instruction> {
|
||||||
@Override
|
@Override
|
||||||
public void read(InstructionReader reader) {
|
public void read(InstructionReader reader) {
|
||||||
visitor.reader = reader;
|
visitor.reader = reader;
|
||||||
|
if (!Objects.equals(readInstruction.getLocation(), location)) {
|
||||||
|
location = readInstruction.getLocation();
|
||||||
|
reader.location(location);
|
||||||
|
}
|
||||||
readInstruction.acceptVisitor(visitor);
|
readInstruction.acceptVisitor(visitor);
|
||||||
visitor.reader = null;
|
visitor.reader = null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,6 +136,7 @@ public class Inlining {
|
||||||
ExitInstruction exit = (ExitInstruction) lastInsn;
|
ExitInstruction exit = (ExitInstruction) lastInsn;
|
||||||
JumpInstruction exitReplacement = new JumpInstruction();
|
JumpInstruction exitReplacement = new JumpInstruction();
|
||||||
exitReplacement.setTarget(splitBlock);
|
exitReplacement.setTarget(splitBlock);
|
||||||
|
exitReplacement.setLocation(exit.getLocation());
|
||||||
exit.replace(exitReplacement);
|
exit.replace(exitReplacement);
|
||||||
if (exit.getValueToReturn() != null) {
|
if (exit.getValueToReturn() != null) {
|
||||||
Incoming resultIncoming = new Incoming();
|
Incoming resultIncoming = new Incoming();
|
||||||
|
|
|
@ -21,9 +21,12 @@ import com.carrotsearch.hppc.IntObjectMap;
|
||||||
import com.carrotsearch.hppc.IntObjectOpenHashMap;
|
import com.carrotsearch.hppc.IntObjectOpenHashMap;
|
||||||
import com.carrotsearch.hppc.IntOpenHashSet;
|
import com.carrotsearch.hppc.IntOpenHashSet;
|
||||||
import com.carrotsearch.hppc.IntSet;
|
import com.carrotsearch.hppc.IntSet;
|
||||||
|
import java.util.ArrayDeque;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Deque;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -84,9 +87,13 @@ import org.teavm.model.instructions.UnwrapArrayInstruction;
|
||||||
public class PhiUpdater {
|
public class PhiUpdater {
|
||||||
private Program program;
|
private Program program;
|
||||||
private Graph cfg;
|
private Graph cfg;
|
||||||
|
private DominatorTree domTree;
|
||||||
|
private Graph domGraph;
|
||||||
private int[][] domFrontiers;
|
private int[][] domFrontiers;
|
||||||
private Variable[] variableMap;
|
private Variable[] variableMap;
|
||||||
|
private boolean[] variableDefined;
|
||||||
private BasicBlock currentBlock;
|
private BasicBlock currentBlock;
|
||||||
|
private TryCatchBlock currentTryCatch;
|
||||||
private Phi[][] phiMap;
|
private Phi[][] phiMap;
|
||||||
private int[][] phiIndexMap;
|
private int[][] phiIndexMap;
|
||||||
private Map<TryCatchBlock, Map<Variable, TryCatchJoint>> jointMap = new HashMap<>();
|
private Map<TryCatchBlock, Map<Variable, TryCatchJoint>> jointMap = new HashMap<>();
|
||||||
|
@ -124,8 +131,10 @@ public class PhiUpdater {
|
||||||
phisByReceiver.clear();
|
phisByReceiver.clear();
|
||||||
jointsByReceiver.clear();
|
jointsByReceiver.clear();
|
||||||
cfg = ProgramUtils.buildControlFlowGraph(program);
|
cfg = ProgramUtils.buildControlFlowGraph(program);
|
||||||
DominatorTree domTree = GraphUtils.buildDominatorTree(cfg);
|
domTree = GraphUtils.buildDominatorTree(cfg);
|
||||||
domFrontiers = new int[cfg.size()][];
|
domFrontiers = new int[cfg.size()][];
|
||||||
|
domGraph = GraphUtils.buildDominatorGraph(domTree, program.basicBlockCount());
|
||||||
|
|
||||||
variableMap = new Variable[program.variableCount()];
|
variableMap = new Variable[program.variableCount()];
|
||||||
usedDefinitions = new boolean[program.variableCount()];
|
usedDefinitions = new boolean[program.variableCount()];
|
||||||
for (int i = 0; i < arguments.length; ++i) {
|
for (int i = 0; i < arguments.length; ++i) {
|
||||||
|
@ -167,13 +176,23 @@ public class PhiUpdater {
|
||||||
|
|
||||||
private void estimatePhis() {
|
private void estimatePhis() {
|
||||||
DefinitionExtractor definitionExtractor = new DefinitionExtractor();
|
DefinitionExtractor definitionExtractor = new DefinitionExtractor();
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
List<List<TryCatchJoint>> inputJoints = getInputJoints(program);
|
||||||
|
variableDefined = new boolean[program.variableCount()];
|
||||||
|
|
||||||
|
IntDeque stack = new IntArrayDeque();
|
||||||
|
stack.addLast(0);
|
||||||
|
while (!stack.isEmpty()) {
|
||||||
|
int i = stack.removeLast();
|
||||||
currentBlock = program.basicBlockAt(i);
|
currentBlock = program.basicBlockAt(i);
|
||||||
|
|
||||||
if (currentBlock.getExceptionVariable() != null) {
|
if (currentBlock.getExceptionVariable() != null) {
|
||||||
markAssignment(currentBlock.getExceptionVariable());
|
markAssignment(currentBlock.getExceptionVariable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (TryCatchJoint joint : inputJoints.get(currentBlock.getIndex())) {
|
||||||
|
markAssignment(joint.getReceiver());
|
||||||
|
}
|
||||||
|
|
||||||
for (Phi phi : currentBlock.getPhis()) {
|
for (Phi phi : currentBlock.getPhis()) {
|
||||||
markAssignment(phi.getReceiver());
|
markAssignment(phi.getReceiver());
|
||||||
}
|
}
|
||||||
|
@ -197,37 +216,42 @@ public class PhiUpdater {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (int successor : domGraph.outgoingEdges(i)) {
|
||||||
|
stack.addLast(successor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class Task {
|
private static class Task {
|
||||||
Variable[] variables;
|
Variable[] variables;
|
||||||
BasicBlock block;
|
BasicBlock block;
|
||||||
|
TryCatchBlock tryCatch;
|
||||||
|
int tryCatchIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void renameVariables() {
|
private void renameVariables() {
|
||||||
DominatorTree domTree = GraphUtils.buildDominatorTree(ProgramUtils.buildControlFlowGraph(program));
|
Deque<Task> stack = new ArrayDeque<>();
|
||||||
Graph domGraph = GraphUtils.buildDominatorGraph(domTree, program.basicBlockCount());
|
|
||||||
Task[] stack = new Task[cfg.size() * 2];
|
|
||||||
int head = 0;
|
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
if (domGraph.incomingEdgesCount(i) == 0) {
|
if (domGraph.incomingEdgesCount(i) == 0) {
|
||||||
Task task = new Task();
|
Task task = new Task();
|
||||||
task.block = program.basicBlockAt(i);
|
task.block = program.basicBlockAt(i);
|
||||||
task.variables = variableMap.clone();
|
task.variables = variableMap.clone();
|
||||||
stack[head++] = task;
|
stack.push(task);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<List<Incoming>> phiOutputs = ProgramUtils.getPhiOutputs(program);
|
List<List<Incoming>> phiOutputs = ProgramUtils.getPhiOutputs(program);
|
||||||
|
|
||||||
while (head > 0) {
|
while (!stack.isEmpty()) {
|
||||||
Task task = stack[--head];
|
Task task = stack.pop();
|
||||||
|
|
||||||
currentBlock = task.block;
|
currentBlock = task.block;
|
||||||
|
currentTryCatch = task.tryCatch;
|
||||||
int index = currentBlock.getIndex();
|
int index = currentBlock.getIndex();
|
||||||
variableMap = task.variables.clone();
|
variableMap = task.variables.clone();
|
||||||
|
|
||||||
|
if (currentTryCatch == null) {
|
||||||
if (currentBlock.getExceptionVariable() != null) {
|
if (currentBlock.getExceptionVariable() != null) {
|
||||||
currentBlock.setExceptionVariable(define(currentBlock.getExceptionVariable()));
|
currentBlock.setExceptionVariable(define(currentBlock.getExceptionVariable()));
|
||||||
}
|
}
|
||||||
|
@ -247,35 +271,16 @@ public class PhiUpdater {
|
||||||
for (Instruction insn : currentBlock) {
|
for (Instruction insn : currentBlock) {
|
||||||
insn.acceptVisitor(consumer);
|
insn.acceptVisitor(consumer);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
for (TryCatchJoint joint : currentTryCatch.getJoints()) {
|
||||||
for (TryCatchJoint joint : tryCatch.getJoints()) {
|
joint.setReceiver(define(joint.getReceiver()));
|
||||||
for (int i = 0; i < joint.getSourceVariables().size(); ++i) {
|
|
||||||
joint.getSourceVariables().set(i, use(joint.getSourceVariables().get(i)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
IntSet catchSuccessors = new IntOpenHashSet();
|
|
||||||
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
|
|
||||||
catchSuccessors.add(tryCatch.getHandler().getIndex());
|
|
||||||
}
|
|
||||||
|
|
||||||
for (Incoming output : phiOutputs.get(index)) {
|
|
||||||
if (!catchSuccessors.contains(output.getPhi().getBasicBlock().getIndex())) {
|
|
||||||
Variable var = output.getValue();
|
|
||||||
output.setValue(use(var));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Variable[] regularVariableMap = variableMap;
|
boolean tryCatchIsSuccessor = currentTryCatch != null
|
||||||
Variable[] catchVariableMap = variableMap.clone();
|
&& domTree.immediateDominatorOf(currentTryCatch.getHandler().getIndex()) == index;
|
||||||
|
if (currentTryCatch != null) {
|
||||||
variableMap = catchVariableMap;
|
for (TryCatchJoint joint : synthesizedJointsByBlock.get(index).get(task.tryCatchIndex)) {
|
||||||
for (int i = 0; i < currentBlock.getTryCatchBlocks().size(); ++i) {
|
|
||||||
TryCatchBlock tryCatch = currentBlock.getTryCatchBlocks().get(i);
|
|
||||||
catchSuccessors.add(tryCatch.getHandler().getIndex());
|
|
||||||
for (TryCatchJoint joint : synthesizedJointsByBlock.get(index).get(i)) {
|
|
||||||
Variable var = program.createVariable();
|
Variable var = program.createVariable();
|
||||||
var.setDebugName(joint.getReceiver().getDebugName());
|
var.setDebugName(joint.getReceiver().getDebugName());
|
||||||
var.setLabel(joint.getReceiver().getLabel());
|
var.setLabel(joint.getReceiver().getLabel());
|
||||||
|
@ -284,23 +289,67 @@ public class PhiUpdater {
|
||||||
jointsByReceiver.put(var.getIndex(), joint);
|
jointsByReceiver.put(var.getIndex(), joint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
variableMap = regularVariableMap;
|
|
||||||
|
|
||||||
int[] successors = domGraph.outgoingEdges(index);
|
int[] successors;
|
||||||
|
List<TryCatchBlock> tryCatchBlockSuccessors = new ArrayList<>();
|
||||||
|
IntSet tryCatchSuccessors = new IntOpenHashSet();
|
||||||
|
if (currentTryCatch != null) {
|
||||||
|
successors = tryCatchIsSuccessor ? new int[] { currentTryCatch.getHandler().getIndex() } : new int[0];
|
||||||
|
} else {
|
||||||
|
List<TryCatchBlock> tryCatchBlocks = currentBlock.getTryCatchBlocks();
|
||||||
|
for (int i = 0; i < tryCatchBlocks.size(); i++) {
|
||||||
|
TryCatchBlock tryCatch = tryCatchBlocks.get(i);
|
||||||
|
tryCatchSuccessors.add(tryCatch.getHandler().getIndex());
|
||||||
|
tryCatchBlockSuccessors.add(tryCatch);
|
||||||
|
}
|
||||||
|
successors = Arrays.stream(domGraph.outgoingEdges(index))
|
||||||
|
.filter(successor -> !tryCatchSuccessors.contains(successor))
|
||||||
|
.toArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
IntSet successorSet = IntOpenHashSet.from(successors);
|
||||||
|
for (Incoming output : phiOutputs.get(index)) {
|
||||||
|
if (successorSet.contains(output.getPhi().getBasicBlock().getIndex())) {
|
||||||
|
Variable var = output.getValue();
|
||||||
|
output.setValue(use(var));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (tryCatchIsSuccessor) {
|
||||||
|
for (TryCatchJoint joint : currentTryCatch.getJoints()) {
|
||||||
|
for (int i = 0; i < joint.getSourceVariables().size(); ++i) {
|
||||||
|
joint.getSourceVariables().set(i, use(joint.getSourceVariables().get(i)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (int j = successors.length - 1; j >= 0; --j) {
|
for (int j = successors.length - 1; j >= 0; --j) {
|
||||||
int successor = successors[j];
|
int successor = successors[j];
|
||||||
Task next = new Task();
|
Task next = new Task();
|
||||||
next.variables = (catchSuccessors.contains(successor) ? catchVariableMap : variableMap).clone();
|
next.variables = variableMap.clone();
|
||||||
next.block = program.basicBlockAt(successor);
|
next.block = program.basicBlockAt(successor);
|
||||||
stack[head++] = next;
|
stack.push(next);
|
||||||
}
|
}
|
||||||
|
|
||||||
successors = cfg.outgoingEdges(index);
|
for (int j = tryCatchBlockSuccessors.size() - 1; j >= 0; --j) {
|
||||||
for (int successor : successors) {
|
TryCatchBlock tryCatch = tryCatchBlockSuccessors.get(j);
|
||||||
variableMap = catchSuccessors.contains(successor) ? catchVariableMap : regularVariableMap;
|
Task next = new Task();
|
||||||
|
next.variables = variableMap.clone();
|
||||||
|
next.block = currentBlock;
|
||||||
|
next.tryCatch = tryCatch;
|
||||||
|
next.tryCatchIndex = j;
|
||||||
|
stack.push(next);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTryCatch == null) {
|
||||||
|
for (int successor : cfg.outgoingEdges(index)) {
|
||||||
|
if (!tryCatchSuccessors.contains(successor)) {
|
||||||
renameOutgoingPhis(successor);
|
renameOutgoingPhis(successor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
renameOutgoingPhis(currentTryCatch.getHandler().getIndex());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addSynthesizedPhis() {
|
private void addSynthesizedPhis() {
|
||||||
|
@ -395,6 +444,7 @@ public class PhiUpdater {
|
||||||
int head = 0;
|
int head = 0;
|
||||||
worklist[head++] = currentBlock;
|
worklist[head++] = currentBlock;
|
||||||
|
|
||||||
|
if (variableDefined[var.getIndex()]) {
|
||||||
BasicBlock startBlock = currentBlock;
|
BasicBlock startBlock = currentBlock;
|
||||||
List<TryCatchBlock> tryCatchBlocks = startBlock.getTryCatchBlocks();
|
List<TryCatchBlock> tryCatchBlocks = startBlock.getTryCatchBlocks();
|
||||||
for (int i = 0; i < tryCatchBlocks.size(); i++) {
|
for (int i = 0; i < tryCatchBlocks.size(); i++) {
|
||||||
|
@ -408,6 +458,9 @@ public class PhiUpdater {
|
||||||
worklist[head++] = tryCatch.getHandler();
|
worklist[head++] = tryCatch.getHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
variableDefined[var.getIndex()] = true;
|
||||||
|
}
|
||||||
|
|
||||||
while (head > 0) {
|
while (head > 0) {
|
||||||
BasicBlock block = worklist[--head];
|
BasicBlock block = worklist[--head];
|
||||||
|
@ -504,6 +557,19 @@ public class PhiUpdater {
|
||||||
return mappedVar;
|
return mappedVar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<List<TryCatchJoint>> getInputJoints(Program program) {
|
||||||
|
List<List<TryCatchJoint>> inputJoints = new ArrayList<>(Collections.nCopies(program.basicBlockCount(), null));
|
||||||
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
|
inputJoints.set(i, new ArrayList<>());
|
||||||
|
}
|
||||||
|
for (BasicBlock block : program.getBasicBlocks()) {
|
||||||
|
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
|
||||||
|
inputJoints.get(tryCatch.getHandler().getIndex()).addAll(tryCatch.getJoints());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inputJoints;
|
||||||
|
}
|
||||||
|
|
||||||
private InstructionVisitor consumer = new InstructionVisitor() {
|
private InstructionVisitor consumer = new InstructionVisitor() {
|
||||||
@Override
|
@Override
|
||||||
public void visit(EmptyInstruction insn) {
|
public void visit(EmptyInstruction insn) {
|
||||||
|
|
|
@ -6,8 +6,8 @@ $start
|
||||||
@a_2 := ephi @a, @a_1
|
@a_2 := ephi @a, @a_1
|
||||||
$catch
|
$catch
|
||||||
@b := 1
|
@b := 1
|
||||||
@a_4 := @a_2 + @b as int
|
@a_3 := @a_2 + @b as int
|
||||||
goto $end
|
goto $end
|
||||||
$end
|
$end
|
||||||
@a_3 := phi @a_1 from $start, @a_4 from $catch
|
@a_4 := phi @a_1 from $start, @a_3 from $catch
|
||||||
return @a_3
|
return @a_4
|
|
@ -5,15 +5,15 @@ $start
|
||||||
catch java.lang.RuntimeException goto $catch
|
catch java.lang.RuntimeException goto $catch
|
||||||
@a_2 := ephi @a, @a_1
|
@a_2 := ephi @a, @a_1
|
||||||
$second
|
$second
|
||||||
@a_3 := invokeStatic `Foo.boo()I`
|
@a_5 := invokeStatic `Foo.boo()I`
|
||||||
goto $end
|
goto $end
|
||||||
catch java.lang.RuntimeException goto $catch
|
catch java.lang.RuntimeException goto $catch
|
||||||
@a_4 := ephi @a_1, @a_3
|
@a_6 := ephi @a_1, @a_5
|
||||||
$catch
|
$catch
|
||||||
@a_5 := phi @a_2 from $start, @a_4 from $second
|
@a_3 := phi @a_2 from $start, @a_6 from $second
|
||||||
@b := 1
|
@b := 1
|
||||||
@a_6 := @a_5 + @b as int
|
@a_4 := @a_3 + @b as int
|
||||||
goto $end
|
goto $end
|
||||||
$end
|
$end
|
||||||
@a_7 := phi @a_3 from $second, @a_6 from $catch
|
@a_7 := phi @a_4 from $catch, @a_5 from $second
|
||||||
return @a_7
|
return @a_7
|
|
@ -34,7 +34,7 @@ interface TeaVMTestConfiguration {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void apply(TeaVM vm) {
|
public void apply(TeaVM vm) {
|
||||||
vm.setOptimizationLevel(TeaVMOptimizationLevel.FULL);
|
vm.setOptimizationLevel(TeaVMOptimizationLevel.SIMPLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
Loading…
Reference in New Issue
Block a user