From 5c03e7547f96da77ccf7f31da422010a56ebf8e5 Mon Sep 17 00:00:00 2001 From: konsoletyper Date: Sat, 22 Feb 2014 23:20:30 +0400 Subject: [PATCH] Avoids swap problem when eliminating phi functions and therefore gets back global value numbering optimization --- .../org/teavm/model/util/GraphColorer.java | 34 +-- .../teavm/model/util/MutableGraphEdge.java | 5 + .../teavm/model/util/RegisterAllocator.java | 200 +++++++++++------- .../teavm/optimization/ClassSetOptimizer.java | 3 +- 4 files changed, 130 insertions(+), 112 deletions(-) diff --git a/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java b/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java index d03e4db90..2277129e9 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java +++ b/teavm-core/src/main/java/org/teavm/model/util/GraphColorer.java @@ -15,9 +15,7 @@ */ package org.teavm.model.util; -import java.util.ArrayList; import java.util.BitSet; -import java.util.List; import org.teavm.common.Graph; /** @@ -25,42 +23,20 @@ import org.teavm.common.Graph; * @author Alexey Andreev */ class GraphColorer { - public void colorize(Graph graph, int[] classes, int[] colors) { - List> classMembers = new ArrayList<>(); - for (int i = 0; i < classes.length; ++i) { - int cls = classes[i]; - while (cls >= classMembers.size()) { - classMembers.add(new ArrayList()); - } - classMembers.get(cls).add(i); - } - for (int i = 0; i < colors.length; ++i) { - if (colors[i] >= 0) { - int cls = classes[i]; - for (int member : classMembers.get(cls)) { - colors[member] = colors[i]; - } - } - } + public void colorize(Graph graph, int[] colors) { BitSet usedColors = new BitSet(); for (int v : getOrdering(graph)) { if (colors[v] >= 0) { continue; } - int cls = classes[v]; usedColors.clear(); usedColors.set(0); - for (int member : classMembers.get(cls)) { - for (int succ : graph.outgoingEdges(member)) { - if (colors[succ] >= 0) { - usedColors.set(colors[succ]); - } + for (int succ : graph.outgoingEdges(v)) { + if (colors[succ] >= 0) { + usedColors.set(colors[succ]); } } - int color = usedColors.nextClearBit(0); - for (int member : classMembers.get(cls)) { - colors[member] = color; - } + colors[v] = usedColors.nextClearBit(0); } } diff --git a/teavm-core/src/main/java/org/teavm/model/util/MutableGraphEdge.java b/teavm-core/src/main/java/org/teavm/model/util/MutableGraphEdge.java index 3c844c43f..3a38ddac2 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/MutableGraphEdge.java +++ b/teavm-core/src/main/java/org/teavm/model/util/MutableGraphEdge.java @@ -57,4 +57,9 @@ class MutableGraphEdge { public MutableGraphEdge getBack() { return back; } + + @Override + public String toString() { + return String.valueOf(second.getTag()); + } } diff --git a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java index 78d2fd03c..fb431144b 100644 --- a/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java +++ b/teavm-core/src/main/java/org/teavm/model/util/RegisterAllocator.java @@ -18,6 +18,7 @@ package org.teavm.model.util; import java.util.*; import org.teavm.common.DisjointSet; import org.teavm.common.Graph; +import org.teavm.common.GraphBuilder; import org.teavm.model.*; import org.teavm.model.instructions.AssignInstruction; import org.teavm.model.instructions.EmptyInstruction; @@ -29,35 +30,28 @@ import org.teavm.model.instructions.JumpInstruction; */ public class RegisterAllocator { public void allocateRegisters(MethodReader method, Program program) { - List phiArgsCopies = insertPhiArgumentsCopies(program); + insertPhiArgumentsCopies(program); InterferenceGraphBuilder interferenceBuilder = new InterferenceGraphBuilder(); LivenessAnalyzer liveness = new LivenessAnalyzer(); liveness.analyze(program); Graph interferenceGraph = interferenceBuilder.build(program, method.parameterCount(), liveness); DisjointSet congruenceClasses = buildPhiCongruenceClasses(program); List classInterferenceGraph = makeMutableGraph(interferenceGraph, congruenceClasses); - removeRedundantCopies(program, phiArgsCopies, classInterferenceGraph, congruenceClasses); + removeRedundantCopies(program, classInterferenceGraph, congruenceClasses); int[] classArray = congruenceClasses.pack(program.variableCount()); + renameVariables(program, classArray); int[] colors = new int[program.variableCount()]; Arrays.fill(colors, -1); for (int i = 0; i <= method.parameterCount(); ++i) { colors[i] = i; } GraphColorer colorer = new GraphColorer(); - colorer.colorize(interferenceGraph, classArray, colors); + colorer.colorize(renameInterferenceGraph(interferenceGraph, classArray), colors); for (int i = 0; i < colors.length; ++i) { program.variableAt(i).setRegister(colors[i]); } } - private static class PhiArgumentCopy { - Incoming incoming; - int original; - int index; - BasicBlock block; - int var; - } - private static List makeMutableGraph(Graph graph, DisjointSet classes) { List mutableGraph = new ArrayList<>(); for (int i = 0; i < graph.size(); ++i) { @@ -77,93 +71,135 @@ public class RegisterAllocator { return mutableGraph; } - private List insertPhiArgumentsCopies(Program program) { - List copies = new ArrayList<>(); + private void insertPhiArgumentsCopies(Program program) { for (int i = 0; i < program.basicBlockCount(); ++i) { Map blockMap = new HashMap<>(); - for (final Phi phi : program.basicBlockAt(i).getPhis()) { + for (Phi phi : program.basicBlockAt(i).getPhis()) { for (Incoming incoming : phi.getIncomings()) { - PhiArgumentCopy copy = new PhiArgumentCopy(); - copy.incoming = incoming; - copy.original = incoming.getValue().getIndex(); - AssignInstruction copyInstruction = new AssignInstruction(); - copyInstruction.setReceiver(program.createVariable()); - copyInstruction.setAssignee(incoming.getValue()); - copy.var = copyInstruction.getReceiver().getIndex(); - BasicBlock source = blockMap.get(incoming.getSource()); - if (source == null) { - source = incoming.getSource(); - } else { - incoming.setSource(source); - } - if (incoming.getSource().getLastInstruction() instanceof JumpInstruction) { - copy.index = incoming.getSource().getInstructions().size() - 1; - copy.block = incoming.getSource(); - copy.block.getInstructions().add(copy.index, copyInstruction); - } else { - final BasicBlock copyBlock = program.createBasicBlock(); - copyBlock.getInstructions().add(copyInstruction); - JumpInstruction jumpInstruction = new JumpInstruction(); - jumpInstruction.setTarget(phi.getBasicBlock()); - copyBlock.getInstructions().add(jumpInstruction); - incoming.getSource().getLastInstruction().acceptVisitor(new BasicBlockMapper() { - @Override protected BasicBlock map(BasicBlock block) { - if (block == phi.getBasicBlock()) { - return copyBlock; - } else { - return block; - } - } - }); - blockMap.put(source, copyBlock); - incoming.setSource(copyBlock); - copy.index = 0; - copy.block = incoming.getSource(); - } - incoming.setValue(copyInstruction.getReceiver()); - copies.add(copy); + insertCopy(incoming, blockMap); + } + } + for (Phi phi : program.basicBlockAt(i).getPhis()) { + for (Incoming incoming : phi.getIncomings()) { + insertCopy(incoming, blockMap); } } } - return copies; } - private void removeRedundantCopies(Program program, List copies, - List interferenceGraph, DisjointSet congruenceClasses) { - for (PhiArgumentCopy copy : copies) { - boolean interfere = false; - int varClass = congruenceClasses.find(copy.var); - int origClass = congruenceClasses.find(copy.original); - for (MutableGraphEdge edge : interferenceGraph.get(copy.original).getEdges()) { - if (edge.getFirst() == edge.getSecond()) { - continue; - } - int neighbour = congruenceClasses.find(edge.getSecond().getTag()); - if (neighbour == varClass || neighbour == origClass) { - interfere = true; - break; - } - } - if (!interfere) { - int newClass = congruenceClasses.union(varClass, origClass); - copy.block.getInstructions().set(copy.index, new EmptyInstruction()); - copy.incoming.setValue(program.variableAt(copy.original)); - for (MutableGraphEdge edge : interferenceGraph.get(varClass).getEdges() - .toArray(new MutableGraphEdge[0])) { - if (edge.getFirst() != null) { - edge.setFirst(interferenceGraph.get(newClass)); + private void insertCopy(Incoming incoming, Map blockMap) { + final Phi phi = incoming.getPhi(); + Program program = phi.getBasicBlock().getProgram(); + AssignInstruction copyInstruction = new AssignInstruction(); + Variable firstCopy = program.createVariable(); + copyInstruction.setReceiver(firstCopy); + copyInstruction.setAssignee(incoming.getValue()); + BasicBlock source = blockMap.get(incoming.getSource()); + if (source == null) { + source = incoming.getSource(); + } else { + incoming.setSource(source); + } + if (!(incoming.getSource().getLastInstruction() instanceof JumpInstruction)) { + final BasicBlock copyBlock = program.createBasicBlock(); + JumpInstruction jumpInstruction = new JumpInstruction(); + jumpInstruction.setTarget(phi.getBasicBlock()); + copyBlock.getInstructions().add(jumpInstruction); + incoming.getSource().getLastInstruction().acceptVisitor(new BasicBlockMapper() { + @Override protected BasicBlock map(BasicBlock block) { + if (block == phi.getBasicBlock()) { + return copyBlock; + } else { + return block; } } - for (MutableGraphEdge edge : interferenceGraph.get(origClass).getEdges() - .toArray(new MutableGraphEdge[0])) { - if (edge.getFirst() != null) { - edge.setFirst(interferenceGraph.get(newClass)); + }); + blockMap.put(source, copyBlock); + incoming.setSource(copyBlock); + source = copyBlock; + } + source.getInstructions().add(source.getInstructions().size() - 1, copyInstruction); + incoming.setValue(copyInstruction.getReceiver()); + } + + private void removeRedundantCopies(Program program, List interferenceGraph, + DisjointSet congruenceClasses) { + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlock block = program.basicBlockAt(i); + for (int j = 0; j < block.getInstructions().size(); ++j) { + Instruction insn = block.getInstructions().get(j); + if (!(insn instanceof AssignInstruction)) { + continue; + } + AssignInstruction assignment = (AssignInstruction)insn; + boolean interfere = false; + int copyClass = congruenceClasses.find(assignment.getReceiver().getIndex()); + int origClass = congruenceClasses.find(assignment.getAssignee().getIndex()); + for (MutableGraphEdge edge : interferenceGraph.get(origClass).getEdges()) { + if (edge.getFirst() == edge.getSecond()) { + continue; + } + int neighbour = congruenceClasses.find(edge.getSecond().getTag()); + if (neighbour == copyClass || neighbour == origClass) { + interfere = true; + break; + } + } + if (!interfere) { + int newClass = congruenceClasses.union(copyClass, origClass); + block.getInstructions().set(j, new EmptyInstruction()); + MutableGraphNode newNode = interferenceGraph.get(origClass); + if (newClass == interferenceGraph.size()) { + newNode = new MutableGraphNode(interferenceGraph.size()); + interferenceGraph.add(newNode); + } + for (MutableGraphEdge edge : interferenceGraph.get(origClass).getEdges() + .toArray(new MutableGraphEdge[0])) { + if (edge.getFirst() != null) { + edge.setFirst(interferenceGraph.get(newClass)); + } + } + for (MutableGraphEdge edge : interferenceGraph.get(copyClass).getEdges() + .toArray(new MutableGraphEdge[0])) { + if (edge.getFirst() != null) { + edge.setFirst(interferenceGraph.get(newClass)); + } } } } } } + private void renameVariables(final Program program, final int[] varMap) { + InstructionVariableMapper mapper = new InstructionVariableMapper() { + @Override protected Variable map(Variable var) { + return program.variableAt(varMap[var.getIndex()]); + } + }; + for (int i = 0; i < program.basicBlockCount(); ++i) { + BasicBlock block = program.basicBlockAt(i); + for (Instruction insn : block.getInstructions()) { + insn.acceptVisitor(mapper); + } + for (Phi phi : block.getPhis()) { + phi.setReceiver(program.variableAt(varMap[phi.getReceiver().getIndex()])); + for (Incoming incoming : phi.getIncomings()) { + incoming.setValue(program.variableAt(varMap[incoming.getValue().getIndex()])); + } + } + } + } + + private Graph renameInterferenceGraph(Graph graph, final int[] varMap) { + GraphBuilder renamedGraph = new GraphBuilder(); + for (int i = 0; i < graph.size(); ++i) { + for (int j : graph.outgoingEdges(i)) { + renamedGraph.addEdge(varMap[i], varMap[j]); + } + } + return renamedGraph.build(); + } + private DisjointSet buildPhiCongruenceClasses(Program program) { DisjointSet classes = new DisjointSet(); for (int i = 0; i < program.variableCount(); ++i) { diff --git a/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java b/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java index c926727e6..d2faf84c4 100644 --- a/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java +++ b/teavm-core/src/main/java/org/teavm/optimization/ClassSetOptimizer.java @@ -36,7 +36,8 @@ public class ClassSetOptimizer { } private List getOptimizations() { - return Arrays.asList(new UnusedVariableElimination()); + return Arrays.asList(new CommonSubexpressionElimination(), + new UnusedVariableElimination()); } public void optimizeAll(ListableClassHolderSource classSource) {