Fix bug in liveness analysis

This commit is contained in:
Alexey Andreev 2019-06-26 13:41:21 +03:00
parent b6cfbe7f5b
commit a2b6c2be58

View File

@ -17,10 +17,11 @@ 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 java.util.ArrayDeque; import com.carrotsearch.hppc.IntStack;
import java.util.BitSet; import java.util.BitSet;
import java.util.Deque; import org.teavm.common.DominatorTree;
import org.teavm.common.Graph; import org.teavm.common.Graph;
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;
@ -46,6 +47,7 @@ public class LivenessAnalyzer {
public void analyze(Program program) { public void analyze(Program program) {
Graph cfg = ProgramUtils.buildControlFlowGraph(program); Graph cfg = ProgramUtils.buildControlFlowGraph(program);
DominatorTree dominatorTree = GraphUtils.buildDominatorTree(cfg);
liveVars = new BitSet[cfg.size()]; liveVars = new BitSet[cfg.size()];
liveOutVars = new BitSet[cfg.size()]; liveOutVars = new BitSet[cfg.size()];
for (int i = 0; i < liveVars.length; ++i) { for (int i = 0; i < liveVars.length; ++i) {
@ -55,7 +57,7 @@ public class LivenessAnalyzer {
UsageExtractor usageExtractor = new UsageExtractor(); UsageExtractor usageExtractor = new UsageExtractor();
DefinitionExtractor defExtractor = new DefinitionExtractor(); DefinitionExtractor defExtractor = new DefinitionExtractor();
Deque<Task> stack = new ArrayDeque<>(); IntStack stack = new IntStack();
int[] definitions = new int[program.variableCount()]; int[] definitions = new int[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);
@ -68,10 +70,8 @@ public class LivenessAnalyzer {
insn.acceptVisitor(usageExtractor); insn.acceptVisitor(usageExtractor);
IntSet usedVars = new IntHashSet(); IntSet usedVars = new IntHashSet();
for (Variable var : usageExtractor.getUsedVariables()) { for (Variable var : usageExtractor.getUsedVariables()) {
Task task = new Task(); stack.push(i);
task.block = i; stack.push(var.getIndex());
task.var = var.getIndex();
stack.push(task);
usedVars.add(var.getIndex()); usedVars.add(var.getIndex());
} }
insn.acceptVisitor(defExtractor); insn.acceptVisitor(defExtractor);
@ -85,25 +85,24 @@ public class LivenessAnalyzer {
for (Phi phi : block.getPhis()) { for (Phi phi : block.getPhis()) {
definitions[phi.getReceiver().getIndex()] = i; definitions[phi.getReceiver().getIndex()] = i;
for (Incoming incoming : phi.getIncomings()) { for (Incoming incoming : phi.getIncomings()) {
Task task = new Task(); stack.push(incoming.getSource().getIndex());
task.block = incoming.getSource().getIndex(); stack.push(incoming.getValue().getIndex());
task.var = incoming.getValue().getIndex();
stack.push(task);
} }
} }
} }
while (!stack.isEmpty()) { while (!stack.isEmpty()) {
Task task = stack.pop(); int variable = stack.pop();
if (liveVars[task.block].get(task.var) || definitions[task.var] == task.block) { int block = stack.pop();
BitSet blockLiveVars = liveVars[block];
if (blockLiveVars.get(variable) || definitions[variable] == block
|| !dominatorTree.dominates(definitions[variable], block)) {
continue; continue;
} }
liveVars[task.block].set(task.var, true); liveVars[block].set(variable, true);
for (int pred : cfg.incomingEdges(task.block)) { for (int pred : cfg.incomingEdges(block)) {
Task nextTask = new Task(); stack.push(pred);
nextTask.block = pred; stack.push(variable);
nextTask.var = task.var;
stack.push(nextTask);
} }
} }
@ -119,9 +118,4 @@ public class LivenessAnalyzer {
} }
} }
} }
private static class Task {
int block;
int var;
}
} }