Further work on incremental phi updater

This commit is contained in:
Alexey Andreev 2016-05-23 22:35:55 +03:00
parent 5ac195df5a
commit ca521f74f0
6 changed files with 205 additions and 101 deletions

View File

@ -19,10 +19,6 @@ import java.util.*;
import org.teavm.common.MutableGraphNode;
import org.teavm.model.*;
/**
*
* @author Alexey Andreev
*/
class InterferenceGraphBuilder {
public List<MutableGraphNode> build(Program program, int paramCount, LivenessAnalyzer liveness) {
List<MutableGraphNode> nodes = new ArrayList<>();
@ -32,7 +28,7 @@ class InterferenceGraphBuilder {
UsageExtractor useExtractor = new UsageExtractor();
DefinitionExtractor defExtractor = new DefinitionExtractor();
InstructionTransitionExtractor succExtractor = new InstructionTransitionExtractor();
List<List<Incoming>> outgoings = getOutgoings(program);
List<List<Incoming>> outgoings = ProgramUtils.getPhiOutputs(program);
Set<MutableGraphNode> live = new HashSet<>(128);
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
@ -98,20 +94,4 @@ class InterferenceGraphBuilder {
}
return nodes;
}
private List<List<Incoming>> getOutgoings(Program program) {
List<List<Incoming>> outgoings = new ArrayList<>(program.basicBlockCount());
for (int i = 0; i < program.basicBlockCount(); ++i) {
outgoings.add(new ArrayList<Incoming>());
}
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
for (Phi phi : block.getPhis()) {
for (Incoming incoming : phi.getIncomings()) {
outgoings.get(incoming.getSource().getIndex()).add(incoming);
}
}
}
return outgoings;
}
}

View File

@ -15,12 +15,57 @@
*/
package org.teavm.model.util;
import java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.teavm.common.DominatorTree;
import org.teavm.common.Graph;
import org.teavm.common.GraphUtils;
import org.teavm.model.*;
import org.teavm.model.instructions.*;
import org.teavm.model.BasicBlock;
import org.teavm.model.Incoming;
import org.teavm.model.Instruction;
import org.teavm.model.InvokeDynamicInstruction;
import org.teavm.model.Phi;
import org.teavm.model.Program;
import org.teavm.model.TryCatchBlock;
import org.teavm.model.Variable;
import org.teavm.model.instructions.ArrayLengthInstruction;
import org.teavm.model.instructions.AssignInstruction;
import org.teavm.model.instructions.BinaryBranchingInstruction;
import org.teavm.model.instructions.BinaryInstruction;
import org.teavm.model.instructions.BranchingInstruction;
import org.teavm.model.instructions.CastInstruction;
import org.teavm.model.instructions.CastIntegerInstruction;
import org.teavm.model.instructions.CastNumberInstruction;
import org.teavm.model.instructions.ClassConstantInstruction;
import org.teavm.model.instructions.CloneArrayInstruction;
import org.teavm.model.instructions.ConstructArrayInstruction;
import org.teavm.model.instructions.ConstructInstruction;
import org.teavm.model.instructions.ConstructMultiArrayInstruction;
import org.teavm.model.instructions.DoubleConstantInstruction;
import org.teavm.model.instructions.EmptyInstruction;
import org.teavm.model.instructions.ExitInstruction;
import org.teavm.model.instructions.FloatConstantInstruction;
import org.teavm.model.instructions.GetElementInstruction;
import org.teavm.model.instructions.GetFieldInstruction;
import org.teavm.model.instructions.InitClassInstruction;
import org.teavm.model.instructions.InstructionVisitor;
import org.teavm.model.instructions.IntegerConstantInstruction;
import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.model.instructions.IsInstanceInstruction;
import org.teavm.model.instructions.JumpInstruction;
import org.teavm.model.instructions.LongConstantInstruction;
import org.teavm.model.instructions.MonitorEnterInstruction;
import org.teavm.model.instructions.MonitorExitInstruction;
import org.teavm.model.instructions.NegateInstruction;
import org.teavm.model.instructions.NullCheckInstruction;
import org.teavm.model.instructions.NullConstantInstruction;
import org.teavm.model.instructions.PutElementInstruction;
import org.teavm.model.instructions.PutFieldInstruction;
import org.teavm.model.instructions.RaiseInstruction;
import org.teavm.model.instructions.StringConstantInstruction;
import org.teavm.model.instructions.SwitchInstruction;
import org.teavm.model.instructions.UnwrapArrayInstruction;
public class PhiUpdater {
private Program program;
@ -30,13 +75,15 @@ public class PhiUpdater {
private BasicBlock currentBlock;
private Phi[][] phiMap;
private int[][] phiIndexMap;
private List<List<Phi>> synthesizedPhis = new ArrayList<>();
private boolean[] usedDefinitions;
public void updatePhis(Program program, Variable[] arguments) {
if (program.basicBlockCount() == 0) {
return;
}
this.program = program;
cfg = ProgramUtils.buildControlFlowGraphWithTryCatch(program);
cfg = ProgramUtils.buildControlFlowGraph(program);
DominatorTree domTree = GraphUtils.buildDominatorTree(cfg);
domFrontiers = new int[cfg.size()][];
variableMap = new Variable[program.variableCount()];
@ -50,6 +97,12 @@ public class PhiUpdater {
phiIndexMap[i] = new int[program.variableCount()];
}
domFrontiers = GraphUtils.findDominanceFrontiers(cfg, domTree);
synthesizedPhis.clear();
for (int i = 0; i < program.basicBlockCount(); ++i) {
synthesizedPhis.add(new ArrayList<>());
}
usedDefinitions = new boolean[program.variableCount()];
estimatePhis();
renameVariables();
}
@ -89,61 +142,54 @@ public class PhiUpdater {
}
}
List<List<TryCatchBlock>> caughtBlocks = new ArrayList<>();
List<List<Phi>> specialPhis = new ArrayList<>();
for (int i = 0; i < program.basicBlockCount(); ++i) {
caughtBlocks.add(new ArrayList<>());
specialPhis.add(new ArrayList<>());
}
for (int i = 0; i < program.basicBlockCount(); ++i) {
for (TryCatchBlock tryCatch : program.basicBlockAt(i).getTryCatchBlocks()) {
caughtBlocks.get(tryCatch.getHandler().getIndex()).add(tryCatch);
}
}
List<List<Incoming>> phiOutputs = ProgramUtils.getPhiOutputs(program);
boolean[] processed = new boolean[program.basicBlockCount()];
while (head > 0) {
Task task = stack[--head];
currentBlock = task.block;
if (processed[currentBlock.getIndex()]) {
int index = currentBlock.getIndex();
if (processed[index]) {
continue;
}
processed[currentBlock.getIndex()] = true;
processed[index] = true;
variableMap = Arrays.copyOf(task.variables, task.variables.length);
for (Phi phi : currentBlock.getPhis()) {
for (Phi phi : synthesizedPhis.get(index)) {
Variable var = program.createVariable();
var.getDebugNames().addAll(phi.getReceiver().getDebugNames());
variableMap[phi.getReceiver().getIndex()] = var;
phi.setReceiver(var);
}
if (!caughtBlocks.get(currentBlock.getIndex()).isEmpty()) {
Phi phi = new Phi();
phi.setReceiver(program.createVariable());
for (TryCatchBlock tryCatch : caughtBlocks.get(currentBlock.getIndex())) {
variableMap[tryCatch.getExceptionVariable().getIndex()] = phi.getReceiver();
Set<String> debugNames = tryCatch.getExceptionVariable().getDebugNames();
tryCatch.setExceptionVariable(program.createVariable());
tryCatch.getExceptionVariable().getDebugNames().addAll(debugNames);
Incoming incoming = new Incoming();
incoming.setSource(tryCatch.getProtectedBlock());
incoming.setValue(tryCatch.getExceptionVariable());
phi.getIncomings().add(incoming);
}
specialPhis.get(currentBlock.getIndex()).add(phi);
for (Phi phi : currentBlock.getPhis()) {
phi.setReceiver(define(phi.getReceiver()));
}
for (Instruction insn : currentBlock.getInstructions()) {
insn.acceptVisitor(consumer);
}
int[] successors = domGraph.outgoingEdges(currentBlock.getIndex());
for (TryCatchBlock tryCatch : currentBlock.getTryCatchBlocks()) {
Variable var = tryCatch.getExceptionVariable();
if (var != null) {
tryCatch.setExceptionVariable(define(var));
}
}
for (Incoming output : phiOutputs.get(index)) {
output.setValue(use(output.getValue()));
}
int[] successors = domGraph.outgoingEdges(index);
for (int successor : successors) {
Task next = new Task();
next.variables = Arrays.copyOf(variableMap, variableMap.length);
next.block = program.basicBlockAt(successor);
stack[head++] = next;
}
successors = cfg.outgoingEdges(currentBlock.getIndex());
successors = cfg.outgoingEdges(index);
for (int successor : successors) {
int[] phiIndexes = phiIndexMap[successor];
List<Phi> phis = program.basicBlockAt(successor).getPhis();
List<Phi> phis = synthesizedPhis.get(successor);
for (int j = 0; j < phis.size(); ++j) {
Phi phi = phis.get(j);
Variable var = variableMap[phiIndexes[j]];
@ -156,9 +202,8 @@ public class PhiUpdater {
}
}
}
}
for (int i = 0; i < specialPhis.size(); ++i) {
program.basicBlockAt(i).getPhis().addAll(specialPhis.get(i));
program.basicBlockAt(index).getPhis().addAll(synthesizedPhis.get(index));
}
}
@ -174,13 +219,12 @@ public class PhiUpdater {
}
for (int frontier : frontiers) {
BasicBlock frontierBlock = program.basicBlockAt(frontier);
frontierBlock.getPhis();
Phi phi = phiMap[frontier][var.getIndex()];
if (phi == null) {
phi = new Phi();
phi.setReceiver(var);
phiIndexMap[frontier][frontierBlock.getPhis().size()] = var.getIndex();
frontierBlock.getPhis().add(phi);
phiIndexMap[frontier][synthesizedPhis.get(frontier).size()] = var.getIndex();
synthesizedPhis.get(frontier).add(phi);
phiMap[frontier][var.getIndex()] = phi;
worklist[head++] = frontierBlock;
}
@ -189,7 +233,14 @@ public class PhiUpdater {
}
private Variable define(Variable var) {
Variable result = program.createVariable();
Variable result;
if (!usedDefinitions[var.getIndex()]) {
usedDefinitions[var.getIndex()] = true;
result = var;
} else {
result = program.createVariable();
}
variableMap[var.getIndex()] = result;
return result;
}

View File

@ -59,30 +59,6 @@ public final class ProgramUtils {
return graphBuilder.build();
}
public static Graph buildControlFlowGraphWithTryCatch(Program program) {
GraphBuilder graphBuilder = new GraphBuilder(program.basicBlockCount());
InstructionTransitionExtractor transitionExtractor = new InstructionTransitionExtractor();
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
Instruction insn = block.getLastInstruction();
if (insn != null) {
insn.acceptVisitor(transitionExtractor);
if (transitionExtractor.getTargets() != null) {
for (BasicBlock successor : transitionExtractor.getTargets()) {
graphBuilder.addEdge(i, successor.getIndex());
for (TryCatchBlock succTryCatch : successor.getTryCatchBlocks()) {
graphBuilder.addEdge(i, succTryCatch.getHandler().getIndex());
}
}
}
}
for (TryCatchBlock tryCatch : block.getTryCatchBlocks()) {
graphBuilder.addEdge(i, tryCatch.getHandler().getIndex());
}
}
return graphBuilder.build();
}
public static Map<InstructionLocation, InstructionLocation[]> getLocationCFG(Program program) {
return new LocationGraphBuilder().build(program);
}
@ -149,4 +125,22 @@ public final class ProgramUtils {
}
return result;
}
public static List<List<Incoming>> getPhiOutputs(Program program) {
List<List<Incoming>> outputs = new ArrayList<>(program.basicBlockCount());
for (int i = 0; i < program.basicBlockCount(); ++i) {
outputs.add(new ArrayList<>());
}
for (int i = 0; i < program.basicBlockCount(); ++i) {
BasicBlock block = program.basicBlockAt(i);
for (Phi phi : block.getPhis()) {
for (Incoming incoming : phi.getIncomings()) {
outputs.get(incoming.getSource().getIndex()).add(incoming);
}
}
}
return outputs;
}
}

View File

@ -15,12 +15,13 @@
*/
package org.teavm.optimization;
import org.teavm.model.ElementModifier;
import org.teavm.model.MethodReader;
import org.teavm.model.Program;
public class LoopInversion implements MethodOptimization {
@Override
public void optimize(MethodReader method, Program program) {
new LoopInversionImpl(program).apply();
new LoopInversionImpl(program, method.parameterCount() + 1).apply();
}
}

View File

@ -38,8 +38,10 @@ import org.teavm.model.Instruction;
import org.teavm.model.Phi;
import org.teavm.model.Program;
import org.teavm.model.TryCatchBlock;
import org.teavm.model.Variable;
import org.teavm.model.util.BasicBlockMapper;
import org.teavm.model.util.InstructionCopyReader;
import org.teavm.model.util.PhiUpdater;
import org.teavm.model.util.ProgramUtils;
/**
@ -74,12 +76,15 @@ import org.teavm.model.util.ProgramUtils;
*/
class LoopInversionImpl {
private final Program program;
private final int parameterCount;
private Graph cfg;
private DominatorTree dom;
private boolean postponed;
private boolean changed;
LoopInversionImpl(Program program) {
LoopInversionImpl(Program program, int parameterCount) {
this.program = program;
this.parameterCount = parameterCount;
}
void apply() {
@ -90,8 +95,17 @@ class LoopInversionImpl {
List<LoopWithExits> loops = getLoopsWithExits(loopGraph);
postponed = false;
for (LoopWithExits loop : loops) {
loop.invert();
if (!loops.isEmpty()) {
for (LoopWithExits loop : loops) {
loop.invert();
}
if (changed) {
Variable[] inputs = new Variable[parameterCount];
for (int i = 0; i < inputs.length; ++i) {
inputs[i] = program.variableAt(i);
}
new PhiUpdater().updatePhis(program, inputs);
}
}
} while (postponed);
}
@ -185,6 +199,7 @@ class LoopInversionImpl {
removeInternalPhiInputsFromCondition();
removeExternalPhiInputsFromConditionCopy();
changed = true;
return true;
}

View File

@ -15,26 +15,89 @@
*/
package org.teavm.vm;
import java.io.*;
import java.util.*;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.Set;
import org.teavm.cache.NoCache;
import org.teavm.codegen.*;
import org.teavm.codegen.AliasProvider;
import org.teavm.codegen.DefaultAliasProvider;
import org.teavm.codegen.DefaultNamingStrategy;
import org.teavm.codegen.MinifyingAliasProvider;
import org.teavm.codegen.SourceWriter;
import org.teavm.codegen.SourceWriterBuilder;
import org.teavm.common.ServiceRepository;
import org.teavm.debugging.information.DebugInformationEmitter;
import org.teavm.debugging.information.SourceLocation;
import org.teavm.dependency.*;
import org.teavm.dependency.BootstrapMethodSubstitutor;
import org.teavm.dependency.DependencyChecker;
import org.teavm.dependency.DependencyInfo;
import org.teavm.dependency.DependencyListener;
import org.teavm.dependency.Linker;
import org.teavm.dependency.MethodDependency;
import org.teavm.diagnostics.AccumulationDiagnostics;
import org.teavm.diagnostics.ProblemProvider;
import org.teavm.javascript.*;
import org.teavm.javascript.Decompiler;
import org.teavm.javascript.EmptyRegularMethodNodeCache;
import org.teavm.javascript.MethodNodeCache;
import org.teavm.javascript.Renderer;
import org.teavm.javascript.RenderingException;
import org.teavm.javascript.ast.ClassNode;
import org.teavm.javascript.spi.GeneratedBy;
import org.teavm.javascript.spi.Generator;
import org.teavm.javascript.spi.InjectedBy;
import org.teavm.javascript.spi.Injector;
import org.teavm.model.*;
import org.teavm.model.instructions.*;
import org.teavm.model.util.*;
import org.teavm.optimization.*;
import org.teavm.model.BasicBlock;
import org.teavm.model.CallLocation;
import org.teavm.model.ClassHolder;
import org.teavm.model.ClassHolderSource;
import org.teavm.model.ClassHolderTransformer;
import org.teavm.model.ClassReader;
import org.teavm.model.ClassReaderSource;
import org.teavm.model.ElementHolder;
import org.teavm.model.ElementModifier;
import org.teavm.model.InstructionLocation;
import org.teavm.model.ListableClassHolderSource;
import org.teavm.model.ListableClassReaderSource;
import org.teavm.model.MethodHolder;
import org.teavm.model.MethodReference;
import org.teavm.model.MutableClassHolderSource;
import org.teavm.model.Program;
import org.teavm.model.ProgramCache;
import org.teavm.model.ValueType;
import org.teavm.model.Variable;
import org.teavm.model.instructions.ConstructInstruction;
import org.teavm.model.instructions.InvocationType;
import org.teavm.model.instructions.InvokeInstruction;
import org.teavm.model.instructions.RaiseInstruction;
import org.teavm.model.instructions.StringConstantInstruction;
import org.teavm.model.util.AsyncMethodFinder;
import org.teavm.model.util.ListingBuilder;
import org.teavm.model.util.MissingItemsProcessor;
import org.teavm.model.util.ModelUtils;
import org.teavm.model.util.ProgramUtils;
import org.teavm.model.util.RegisterAllocator;
import org.teavm.optimization.ArrayUnwrapMotion;
import org.teavm.optimization.Devirtualization;
import org.teavm.optimization.GlobalValueNumbering;
import org.teavm.optimization.LoopInvariantMotion;
import org.teavm.optimization.LoopInversion;
import org.teavm.optimization.MethodOptimization;
import org.teavm.optimization.UnusedVariableElimination;
import org.teavm.vm.spi.RendererListener;
import org.teavm.vm.spi.TeaVMHost;
import org.teavm.vm.spi.TeaVMPlugin;
@ -649,7 +712,7 @@ public class TeaVM implements TeaVMHost, ServiceRepository {
}
private List<MethodOptimization> getOptimizations() {
return Arrays.asList(new ArrayUnwrapMotion(), /*new LoopInversion(),*/ new LoopInvariantMotion(),
return Arrays.asList(new ArrayUnwrapMotion(), new LoopInversion(), new LoopInvariantMotion(),
new GlobalValueNumbering(), new UnusedVariableElimination());
}