mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -08:00
Fix bug in liveness analysis when running on non-SSA IR
This commit is contained in:
parent
1d19562c49
commit
67c86b089f
|
@ -68,12 +68,15 @@ public class Optimizer {
|
||||||
|
|
||||||
public void optimize(AsyncMethodNode method, AsyncProgramSplitter splitter, boolean friendlyToDebugger) {
|
public void optimize(AsyncMethodNode method, AsyncProgramSplitter splitter, boolean friendlyToDebugger) {
|
||||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||||
liveness.analyze(splitter.getOriginalProgram());
|
liveness.analyze(splitter.getOriginalProgram(), method.getReference().getDescriptor());
|
||||||
|
|
||||||
Graph cfg = ProgramUtils.buildControlFlowGraph(splitter.getOriginalProgram());
|
Graph cfg = ProgramUtils.buildControlFlowGraph(splitter.getOriginalProgram());
|
||||||
|
boolean[] preservedVars = new boolean[method.getVariables().size()];
|
||||||
|
for (int i = 0; i < splitter.size(); ++i) {
|
||||||
|
findEscapingLiveVars(liveness, cfg, splitter, i, preservedVars);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 0; i < splitter.size(); ++i) {
|
for (int i = 0; i < splitter.size(); ++i) {
|
||||||
boolean[] preservedVars = new boolean[method.getVariables().size()];
|
|
||||||
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
ReadWriteStatsBuilder stats = new ReadWriteStatsBuilder(method.getVariables().size());
|
||||||
stats.analyze(splitter.getProgram(i));
|
stats.analyze(splitter.getProgram(i));
|
||||||
applyParametersToWriteStats(stats, method.getReference());
|
applyParametersToWriteStats(stats, method.getReference());
|
||||||
|
@ -81,7 +84,6 @@ public class Optimizer {
|
||||||
AsyncMethodPart part = method.getBody().get(i);
|
AsyncMethodPart part = method.getBody().get(i);
|
||||||
BreakEliminator breakEliminator = new BreakEliminator();
|
BreakEliminator breakEliminator = new BreakEliminator();
|
||||||
breakEliminator.eliminate(part.getStatement());
|
breakEliminator.eliminate(part.getStatement());
|
||||||
findEscapingLiveVars(liveness, cfg, splitter, i, preservedVars);
|
|
||||||
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads,
|
OptimizingVisitor optimizer = new OptimizingVisitor(preservedVars, stats.writes, stats.reads,
|
||||||
stats.constants, friendlyToDebugger);
|
stats.constants, friendlyToDebugger);
|
||||||
part.getStatement().acceptVisitor(optimizer);
|
part.getStatement().acceptVisitor(optimizer);
|
||||||
|
|
|
@ -112,7 +112,7 @@ public class CoroutineTransformation {
|
||||||
parameterCount = methodReference.parameterCount();
|
parameterCount = methodReference.parameterCount();
|
||||||
returnType = methodReference.getReturnType();
|
returnType = methodReference.getReturnType();
|
||||||
variableTypes.inferTypes(program, methodReference);
|
variableTypes.inferTypes(program, methodReference);
|
||||||
livenessAnalysis.analyze(program);
|
livenessAnalysis.analyze(program, methodReference.getDescriptor());
|
||||||
splitter = new BasicBlockSplitter(program);
|
splitter = new BasicBlockSplitter(program);
|
||||||
int basicBlockCount = program.basicBlockCount();
|
int basicBlockCount = program.basicBlockCount();
|
||||||
createSplitPrologue();
|
createSplitPrologue();
|
||||||
|
|
|
@ -36,6 +36,7 @@ import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.FieldReference;
|
import org.teavm.model.FieldReference;
|
||||||
import org.teavm.model.Incoming;
|
import org.teavm.model.Incoming;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.MethodReference;
|
import org.teavm.model.MethodReference;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
|
@ -95,7 +96,7 @@ public class EscapeAnalysis {
|
||||||
escapingVars[definitionClasses[i]] = true;
|
escapingVars[definitionClasses[i]] = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
analyzePhis(program);
|
analyzePhis(program, methodReference.getDescriptor());
|
||||||
|
|
||||||
propagateFields(program, visitor.fields);
|
propagateFields(program, visitor.fields);
|
||||||
fields = packFields(visitor.fields);
|
fields = packFields(visitor.fields);
|
||||||
|
@ -114,9 +115,9 @@ public class EscapeAnalysis {
|
||||||
return varFields != null ? varFields.clone() : null;
|
return varFields != null ? varFields.clone() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void analyzePhis(Program program) {
|
private void analyzePhis(Program program, MethodDescriptor methodDescriptor) {
|
||||||
LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
|
LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
|
||||||
livenessAnalyzer.analyze(program);
|
livenessAnalyzer.analyze(program, methodDescriptor);
|
||||||
|
|
||||||
GraphBuilder graphBuilder = new GraphBuilder(program.variableCount());
|
GraphBuilder graphBuilder = new GraphBuilder(program.variableCount());
|
||||||
IntDeque queue = new IntArrayDeque();
|
IntDeque queue = new IntArrayDeque();
|
||||||
|
|
|
@ -134,7 +134,7 @@ public class GCShadowStackContributor {
|
||||||
List<Map<Instruction, BitSet>> liveInInformation = new ArrayList<>();
|
List<Map<Instruction, BitSet>> liveInInformation = new ArrayList<>();
|
||||||
|
|
||||||
LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
|
LivenessAnalyzer livenessAnalyzer = new LivenessAnalyzer();
|
||||||
livenessAnalyzer.analyze(program);
|
livenessAnalyzer.analyze(program, method.getDescriptor());
|
||||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||||
UsageExtractor useExtractor = new UsageExtractor();
|
UsageExtractor useExtractor = new UsageExtractor();
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,7 @@ package org.teavm.model.util;
|
||||||
import com.carrotsearch.hppc.IntHashSet;
|
import com.carrotsearch.hppc.IntHashSet;
|
||||||
import com.carrotsearch.hppc.IntSet;
|
import com.carrotsearch.hppc.IntSet;
|
||||||
import com.carrotsearch.hppc.IntStack;
|
import com.carrotsearch.hppc.IntStack;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.BitSet;
|
import java.util.BitSet;
|
||||||
import org.teavm.common.DominatorTree;
|
import org.teavm.common.DominatorTree;
|
||||||
import org.teavm.common.Graph;
|
import org.teavm.common.Graph;
|
||||||
|
@ -25,6 +26,7 @@ import org.teavm.common.GraphUtils;
|
||||||
import org.teavm.model.BasicBlock;
|
import org.teavm.model.BasicBlock;
|
||||||
import org.teavm.model.Incoming;
|
import org.teavm.model.Incoming;
|
||||||
import org.teavm.model.Instruction;
|
import org.teavm.model.Instruction;
|
||||||
|
import org.teavm.model.MethodDescriptor;
|
||||||
import org.teavm.model.Phi;
|
import org.teavm.model.Phi;
|
||||||
import org.teavm.model.Program;
|
import org.teavm.model.Program;
|
||||||
import org.teavm.model.Variable;
|
import org.teavm.model.Variable;
|
||||||
|
@ -45,7 +47,11 @@ public class LivenessAnalyzer {
|
||||||
return (BitSet) liveOutVars[block].clone();
|
return (BitSet) liveOutVars[block].clone();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void analyze(Program program) {
|
public void analyze(Program program, MethodDescriptor descriptor) {
|
||||||
|
analyze(program, descriptor.parameterCount() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void analyze(Program program, int parameterCount) {
|
||||||
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
|
Graph cfg = ProgramUtils.buildControlFlowGraph(program);
|
||||||
DominatorTree dominatorTree = GraphUtils.buildDominatorTree(cfg);
|
DominatorTree dominatorTree = GraphUtils.buildDominatorTree(cfg);
|
||||||
liveVars = new BitSet[program.basicBlockCount()];
|
liveVars = new BitSet[program.basicBlockCount()];
|
||||||
|
@ -58,32 +64,28 @@ public class LivenessAnalyzer {
|
||||||
UsageExtractor usageExtractor = new UsageExtractor();
|
UsageExtractor usageExtractor = new UsageExtractor();
|
||||||
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
DefinitionExtractor defExtractor = new DefinitionExtractor();
|
||||||
IntStack stack = new IntStack();
|
IntStack stack = new IntStack();
|
||||||
int[] definitions = new int[program.variableCount()];
|
IntSet[] definitionsBuilder = new IntSet[program.variableCount()];
|
||||||
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
for (int i = 0; i < program.basicBlockCount(); ++i) {
|
||||||
BasicBlock block = program.basicBlockAt(i);
|
BasicBlock block = program.basicBlockAt(i);
|
||||||
|
|
||||||
if (block.getExceptionVariable() != null) {
|
if (block.getExceptionVariable() != null) {
|
||||||
definitions[block.getExceptionVariable().getIndex()] = i;
|
addDefinition(definitionsBuilder, block.getExceptionVariable().getIndex(), i);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Instruction insn : block) {
|
for (Instruction insn : block) {
|
||||||
insn.acceptVisitor(usageExtractor);
|
insn.acceptVisitor(usageExtractor);
|
||||||
IntSet usedVars = new IntHashSet();
|
|
||||||
for (Variable var : usageExtractor.getUsedVariables()) {
|
for (Variable var : usageExtractor.getUsedVariables()) {
|
||||||
stack.push(i);
|
stack.push(i);
|
||||||
stack.push(var.getIndex());
|
stack.push(var.getIndex());
|
||||||
usedVars.add(var.getIndex());
|
|
||||||
}
|
}
|
||||||
insn.acceptVisitor(defExtractor);
|
insn.acceptVisitor(defExtractor);
|
||||||
for (Variable var : defExtractor.getDefinedVariables()) {
|
for (Variable var : defExtractor.getDefinedVariables()) {
|
||||||
if (!usedVars.contains(var.getIndex())) {
|
addDefinition(definitionsBuilder, var.getIndex(), i);
|
||||||
definitions[var.getIndex()] = i;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Phi phi : block.getPhis()) {
|
for (Phi phi : block.getPhis()) {
|
||||||
definitions[phi.getReceiver().getIndex()] = i;
|
addDefinition(definitionsBuilder, phi.getReceiver().getIndex(), i);
|
||||||
for (Incoming incoming : phi.getIncomings()) {
|
for (Incoming incoming : phi.getIncomings()) {
|
||||||
stack.push(incoming.getSource().getIndex());
|
stack.push(incoming.getSource().getIndex());
|
||||||
stack.push(incoming.getValue().getIndex());
|
stack.push(incoming.getValue().getIndex());
|
||||||
|
@ -91,15 +93,39 @@ public class LivenessAnalyzer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!stack.isEmpty()) {
|
int[][] definitions = new int[program.variableCount()][];
|
||||||
|
for (int i = 0; i < definitions.length; ++i) {
|
||||||
|
IntSet definitionsByVar = definitionsBuilder[i];
|
||||||
|
if (definitionsByVar == null) {
|
||||||
|
definitions[i] = new int[0];
|
||||||
|
} else {
|
||||||
|
definitions[i] = definitionsByVar.toArray();
|
||||||
|
Arrays.sort(definitions[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
worklist: while (!stack.isEmpty()) {
|
||||||
int variable = stack.pop();
|
int variable = stack.pop();
|
||||||
int block = stack.pop();
|
int block = stack.pop();
|
||||||
BitSet blockLiveVars = liveVars[block];
|
BitSet blockLiveVars = liveVars[block];
|
||||||
if (blockLiveVars.get(variable) || definitions[variable] == block
|
if (blockLiveVars.get(variable)) {
|
||||||
|| !dominatorTree.dominates(definitions[variable], block)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
liveVars[block].set(variable, true);
|
|
||||||
|
boolean hasDominatingDefinition = variable < parameterCount;
|
||||||
|
for (int definedAt : definitions[variable]) {
|
||||||
|
if (definedAt == block) {
|
||||||
|
continue worklist;
|
||||||
|
}
|
||||||
|
if (!hasDominatingDefinition && dominatorTree.dominates(definedAt, block)) {
|
||||||
|
hasDominatingDefinition = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!hasDominatingDefinition) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockLiveVars.set(variable, true);
|
||||||
for (int pred : cfg.incomingEdges(block)) {
|
for (int pred : cfg.incomingEdges(block)) {
|
||||||
stack.push(pred);
|
stack.push(pred);
|
||||||
stack.push(variable);
|
stack.push(variable);
|
||||||
|
@ -118,4 +144,13 @@ public class LivenessAnalyzer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void addDefinition(IntSet[] definitions, int v, int block) {
|
||||||
|
IntSet definitionsByVar = definitions[v];
|
||||||
|
if (definitionsByVar == null) {
|
||||||
|
definitionsByVar = new IntHashSet();
|
||||||
|
definitions[v] = definitionsByVar;
|
||||||
|
}
|
||||||
|
definitionsByVar.add(block);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -42,7 +42,7 @@ public class RegisterAllocator {
|
||||||
insertPhiArgumentsCopies(program);
|
insertPhiArgumentsCopies(program);
|
||||||
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder();
|
||||||
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
LivenessAnalyzer liveness = new LivenessAnalyzer();
|
||||||
liveness.analyze(program);
|
liveness.analyze(program, method.getDescriptor());
|
||||||
List<MutableGraphNode> interferenceGraph = interferenceBuilder.build(
|
List<MutableGraphNode> interferenceGraph = interferenceBuilder.build(
|
||||||
program, method.parameterCount(), liveness);
|
program, method.parameterCount(), liveness);
|
||||||
DisjointSet congruenceClasses = buildPhiCongruenceClasses(program);
|
DisjointSet congruenceClasses = buildPhiCongruenceClasses(program);
|
||||||
|
|
Loading…
Reference in New Issue
Block a user