# HG changeset patch # User Lukas Stadler # Date 1306511308 -7200 # Node ID e1dad0edd57a9e12733ca4881373baa0cceade35 # Parent 58e65eb6bb5d54d7a9ccec498bf8e849c8309fb7 first part of loop reworking diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java --- a/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/oracle/max/graal/schedule/Schedule.java Fri May 27 17:48:28 2011 +0200 @@ -86,6 +86,13 @@ return false; } + if (n instanceof LoopBegin) { + // a LoopBegin is always a merge + assignBlock(n); + blockBeginNodes.add(n); + return true; + } + Node singlePred = null; for (Node pred : n.predecessors()) { if (isCFG(pred)) { @@ -147,10 +154,15 @@ predBlock.addSuccessor(block); } } + if (n instanceof LoopBegin) { + LoopBegin loopBegin = (LoopBegin) n; + nodeToBlock.get(loopBegin.loopEnd()).addSuccessor(block); +// System.out.println("added LoopEnd to LoopBegin successor 2: " + loopBegin.loopEnd() + "->" + loopBegin); + } } orderBlocks(); - //print(); +// print(); } private void orderBlocks() { diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java --- a/graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/debug/GraphvizPrinterObserver.java Fri May 27 17:48:28 2011 +0200 @@ -28,6 +28,7 @@ import com.oracle.graal.graph.*; import com.oracle.graal.graph.vis.*; import com.sun.c1x.*; +import com.sun.c1x.ir.*; import com.sun.c1x.observer.*; import com.sun.c1x.value.*; @@ -70,26 +71,14 @@ try { if (pdf) { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); - GraphvizPrinter printer = new GraphvizPrinter(buffer); - if (C1XOptions.OmitDOTFrameStates) { - printer.addOmittedClass(FrameState.class); - } - printer.begin(name); - printer.print(graph, true); - printer.end(); + printGraph(graph, name, buffer); out = new FileOutputStream(filename + ".pdf"); GraphvizRunner.process(GraphvizRunner.DOT_LAYOUT, new ByteArrayInputStream(buffer.toByteArray()), out, "pdf"); } else { out = new FileOutputStream(filename + ".gv"); - GraphvizPrinter printer = new GraphvizPrinter(out); - if (C1XOptions.OmitDOTFrameStates) { - printer.addOmittedClass(FrameState.class); - } - printer.begin(name); - printer.print(graph, true); - printer.end(); + printGraph(graph, name, out); } } catch (IOException e) { e.printStackTrace(); @@ -103,4 +92,20 @@ } } } + + private static void printGraph(Graph graph, String name, OutputStream buffer) { + GraphvizPrinter printer = new GraphvizPrinter(buffer); + if (C1XOptions.OmitDOTFrameStates) { + printer.addOmittedClass(FrameState.class); + } + printer.addClassColor(StartNode.class, "snow3"); + printer.addClassColor(EndNode.class, "snow3"); + printer.addClassColor(LoopBegin.class, "skyblue"); + printer.addClassColor(LoopEnd.class, "skyblue3"); + printer.addClassColor(Unwind.class, "red"); + printer.addClassColor(Return.class, "indianred1"); + printer.begin(name); + printer.print(graph, true); + printer.end(); + } } diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java --- a/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/graph/GraphBuilder.java Fri May 27 17:48:28 2011 +0200 @@ -287,6 +287,9 @@ public void mergeOrClone(Block target, FrameStateAccess newState) { Instruction first = target.firstInstruction; + if (target.isLoopHeader && isVisited(target)) { + first = ((LoopBegin) first).loopEnd(); + } assert first instanceof StateSplit; int bci = target.startBci; @@ -294,13 +297,13 @@ FrameState existingState = ((StateSplit) first).stateBefore(); if (existingState == null) { - assert first instanceof Merge ^ !target.isLoopHeader : "isLoopHeader: " + target.isLoopHeader; +// assert first instanceof Merge ^ !target.isLoopHeader : "isLoopHeader: " + target.isLoopHeader; // copy state because it is modified FrameState duplicate = newState.duplicate(bci); // if the block is a loop header, insert all necessary phis - if (target.isLoopHeader) { + if (first instanceof LoopBegin && target.isLoopHeader) { assert first instanceof Merge; insertLoopPhis((Merge) first, duplicate); ((Merge) first).setStateBefore(duplicate); @@ -318,16 +321,18 @@ assert existingState.stackSize() == newState.stackSize(); if (first instanceof Placeholder) { - Merge merge = new Merge(existingState.bci, target.isLoopHeader, graph); + assert !target.isLoopHeader; + Merge merge = new Merge(graph); Placeholder p = (Placeholder) first; assert p.next() == null; p.replace(merge); target.firstInstruction = merge; merge.setStateBefore(existingState); + first = merge; } - existingState.merge((Merge) target.firstInstruction, newState); + existingState.merge((Merge) first, newState); } for (int j = 0; j < frameState.localsSize() + frameState.stackSize(); ++j) { @@ -1056,7 +1061,6 @@ } private Instruction createTarget(Block block, FrameStateAccess stateAfter) { - assert block != null && stateAfter != null; assert block.isLoopHeader || block.firstInstruction == null || block.firstInstruction.next() == null : "non-loop block must be iterated after all its predecessors"; @@ -1066,14 +1070,24 @@ if (block.firstInstruction == null) { if (block.isLoopHeader) { - block.firstInstruction = new Merge(block.startBci, block.isLoopHeader, graph); +// block.firstInstruction = new Merge(block.startBci, graph); + + LoopBegin loopBegin = new LoopBegin(graph); + LoopEnd loopEnd = new LoopEnd(graph); + loopEnd.setLoopBegin(loopBegin); + block.firstInstruction = loopBegin; } else { block.firstInstruction = new Placeholder(graph); } } mergeOrClone(block, stateAfter); addToWorkList(block); - return block.firstInstruction; + + if (block.firstInstruction instanceof LoopBegin && isVisited(block)) { + return ((LoopBegin) block.firstInstruction).loopEnd(); + } else { + return block.firstInstruction; + } } private Value synchronizedObject(FrameStateAccess state, RiMethod target) { @@ -1135,6 +1149,28 @@ } } } + for (Block b : blocksVisited) { + if (b.isLoopHeader) { + LoopBegin begin = (LoopBegin) b.firstInstruction; + LoopEnd end = begin.loopEnd(); + +// This can happen with degenerated loops like this one: +// for (;;) { +// try { +// break; +// } catch (UnresolvedException iioe) { +// } +// } + if (end.stateBefore() != null) { + begin.stateBefore().merge(begin, end.stateBefore()); + } else { + end.delete(); + Merge merge = new Merge(graph); + merge.successors().setAndClear(merge.nextIndex(), begin, begin.nextIndex()); + begin.replace(merge); + } + } + } } private void createExceptionDispatch(ExceptionBlock block) { diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/BlockEnd.java Fri May 27 17:48:28 2011 +0200 @@ -58,7 +58,6 @@ public Instruction setBlockSuccessor(int index, Instruction n) { assert index >= 0 && index < blockSuccessorCount; -// assert n == null || n instanceof BlockBegin : "only BlockBegins, for now... " + n.getClass(); return (Merge) successors().set(super.successorCount() + SUCCESSOR_COUNT + index, n); } diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Instruction.java Fri May 27 17:48:28 2011 +0200 @@ -46,7 +46,7 @@ private static final int INPUT_COUNT = 0; private static final int SUCCESSOR_COUNT = 1; - private static final int SUCCESSOR_NEXT = 0; + public static final int SUCCESSOR_NEXT = 0; @Override protected int inputCount() { @@ -70,6 +70,10 @@ return successors().set(super.successorCount() + SUCCESSOR_NEXT, next); } + public int nextIndex() { + return super.successorCount() + SUCCESSOR_NEXT; + } + public static final int SYNCHRONIZATION_ENTRY_BCI = -1; diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/ir/LoopBegin.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LoopBegin.java Fri May 27 17:48:28 2011 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.c1x.ir; + +import com.oracle.graal.graph.*; +import com.sun.c1x.debug.*; + +public class LoopBegin extends Merge { + + private static final int INPUT_COUNT = 0; + private static final int SUCCESSOR_COUNT = 0; + + public LoopBegin(Graph graph) { + super(INPUT_COUNT, SUCCESSOR_COUNT, graph); + } + + public LoopEnd loopEnd() { + for (Node usage : usages()) { + if (usage instanceof LoopEnd) { + LoopEnd end = (LoopEnd) usage; + if (end.loopBegin() == this) { + return end; + } + } + } + assert false : "Begin should always have a LoopEnd"; + return null; + } + + @Override + public void accept(ValueVisitor v) { + v.visitLoopBegin(this); + } + + @Override + public void print(LogStream out) { + out.print("loopBegin"); + } + +} diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/ir/LoopEnd.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/LoopEnd.java Fri May 27 17:48:28 2011 +0200 @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.c1x.ir; + +import com.oracle.graal.graph.*; +import com.sun.c1x.debug.*; + + +public class LoopEnd extends Merge { + + private static final int INPUT_COUNT = 1; + private static final int INPUT_LOOP_BEGIN = 0; + + private static final int SUCCESSOR_COUNT = 0; + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + @Override + protected int successorCount() { + return super.successorCount() + SUCCESSOR_COUNT; + } + + /** + * The instruction which produces the input value to this instruction. + */ + public LoopBegin loopBegin() { + return (LoopBegin) inputs().get(super.inputCount() + INPUT_LOOP_BEGIN); + } + + public LoopBegin setLoopBegin(LoopBegin n) { + return (LoopBegin) inputs().set(super.inputCount() + INPUT_LOOP_BEGIN, n); + } + + public LoopEnd(Graph graph) { + super(INPUT_COUNT, SUCCESSOR_COUNT, graph); + } + + @Override + public void accept(ValueVisitor v) { + v.visitLoopEnd(this); + } + + @Override + public void print(LogStream out) { + out.print("loopEnd ").print(loopBegin()); + } + + +} diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Merge.java Fri May 27 17:48:28 2011 +0200 @@ -33,7 +33,7 @@ * about the basic block, including the successor and * predecessor blocks, exception handlers, liveness information, etc. */ -public final class Merge extends StateSplit { +public class Merge extends StateSplit { private static final int INPUT_COUNT = 0; @@ -54,32 +54,18 @@ return false; } - public final boolean isLoopHeader; - - /** - * Index of bytecode that generated this node when appended in a basic block. - * Negative values indicate special cases. - */ - private int bci; - /** * Constructs a new Merge at the specified bytecode index. * @param bci the bytecode index of the start * @param blockID the ID of the block * @param graph */ - public Merge(int bci, boolean isLoopHeader, Graph graph) { + public Merge(Graph graph) { super(CiKind.Illegal, INPUT_COUNT, SUCCESSOR_COUNT, graph); - this.bci = bci; - this.isLoopHeader = isLoopHeader; } - /** - * Gets the bytecode index of this instruction. - * @return the bytecode index of this instruction - */ - public int bci() { - return bci; + protected Merge(int inputCount, int successorCount, Graph graph) { + super(CiKind.Illegal, inputCount + INPUT_COUNT, successorCount + SUCCESSOR_COUNT, graph); } @Override @@ -99,12 +85,14 @@ builder.append(" -> "); boolean hasSucc = false; for (Node s : this.successors()) { - if (hasSucc) { - builder.append(", "); + if (s != null) { + if (hasSucc) { + builder.append(", "); + } + builder.append("#"); + builder.append(s.id()); + hasSucc = true; } - builder.append("#"); - builder.append(s.id()); - hasSucc = true; } //} return builder.toString(); @@ -264,8 +252,4 @@ return sb.toString(); } - @Override - public String shortName() { - return "Merge #" + id(); - } } diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/Phi.java Fri May 27 17:48:28 2011 +0200 @@ -120,7 +120,18 @@ @Override public String shortName() { - return "Phi: (" + valueCount() + ")"; + StringBuilder str = new StringBuilder(); + for (int i = 1; i < inputs().size(); ++i) { + if (i != 1) { + str.append(' '); + } + if (inputs().get(i) != null) { + str.append(inputs().get(i).id()); + } else { + str.append("-"); + } + } + return "Phi: (" + str + ")"; } public Phi addInput(Node y) { diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java --- a/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/ir/ValueVisitor.java Fri May 27 17:48:28 2011 +0200 @@ -70,4 +70,6 @@ public abstract void visitDeoptimize(Deoptimize deoptimize); public abstract void visitExceptionDispatch(ExceptionDispatch exceptionDispatch); public abstract void visitUnwind(Unwind unwind); + public abstract void visitLoopBegin(LoopBegin loopBegin); + public abstract void visitLoopEnd(LoopEnd loopEnd); } diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java --- a/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/target/amd64/AMD64LIRGenerator.java Fri May 27 17:48:28 2011 +0200 @@ -531,4 +531,20 @@ lir.jump(getLIRBlock(x.otherSuccessor())); } + @Override + public void visitLoopBegin(LoopBegin x) { + visitMerge(x); + } + + @Override + public void visitLoopEnd(LoopEnd x) { + setNoResult(x); + + // emit phi-instruction moves after safepoint since this simplifies + // describing the state at the safepoint. + + moveToPhi(); + lir.jump(getLIRBlock(x.loopBegin())); + } + } diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java --- a/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalCompiler/src/com/sun/c1x/value/FrameState.java Fri May 27 17:48:28 2011 +0200 @@ -371,7 +371,11 @@ } } - assert phi.valueCount() == block.predecessors().size() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.predecessors().size(); + if (block instanceof LoopBegin) { +// assert phi.valueCount() == ((LoopBegin) block).loopEnd().predecessors().size() + 1 : "loop, valueCount=" + phi.valueCount() + " predSize= " + ((LoopBegin) block).loopEnd().predecessors().size(); + } else { + assert phi.valueCount() == block.predecessors().size() + 1 : "valueCount=" + phi.valueCount() + " predSize= " + block.predecessors().size(); + } } } } diff -r 58e65eb6bb5d -r e1dad0edd57a graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java --- a/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java Fri May 27 14:20:30 2011 +0200 +++ b/graal/GraalGraphviz/src/com/oracle/graal/graph/vis/GraphvizPrinter.java Fri May 27 17:48:28 2011 +0200 @@ -25,6 +25,7 @@ import java.awt.Color; import java.io.OutputStream; import java.io.PrintStream; +import java.util.HashMap; import java.util.HashSet; import com.oracle.graal.graph.Graph; @@ -46,6 +47,7 @@ private final PrintStream out; private final HashSet> omittedClasses = new HashSet>(); + private final HashMap, String> classColors = new HashMap, String>(); /** * Creates a new {@link GraphvizPrinter} that writes to the specified output stream. @@ -58,6 +60,10 @@ omittedClasses.add(clazz); } + public void addClassColor(Class clazz, String color) { + classColors.put(clazz, color); + } + /** * Opens a graph with the specified title (label). Call this before printing any nodes, but not more than once * without calling {@link #end()} first. @@ -104,10 +110,12 @@ NodeArray inputs = node.inputs(); NodeArray successors = node.successors(); + String color = classColors.get(node.getClass()); + if (shortNames) { - printNode(name, node.shortName(), inputs.size(), successors.size()); + printNode(name, node.id(), excapeLabel(node.shortName()), color, inputs.size(), successors.size()); } else { - printNode(name, node.toString(), inputs.size(), successors.size()); + printNode(name, node.id(), excapeLabel(node.toString()), color, inputs.size(), successors.size()); } for (int i = 0; i < successors.size(); ++i) { @@ -128,8 +136,8 @@ } } - private void printNode(String name, String label, int ninputs, int nsuccessors) { - int minWidth = Math.min(label.length() / 3, 10); + private void printNode(String name, Number number, String label, String color, int ninputs, int nsuccessors) { + int minWidth = Math.min(1 + label.length() / 3, 10); minWidth = Math.max(minWidth, Math.max(ninputs + 1, nsuccessors + 1)); out.println(name + " [shape=plaintext,"); out.println(" label=< "); @@ -144,11 +152,11 @@ printPort("in" + i, "lightgrey"); } - label = label.replace("&", "&"); - label = label.replace("<", "<"); - label = label.replace(">", ">"); - label = label.replace("\"", """); - out.println(" "); + if (number != null) { + label = "" + number + " " + label; + } + + out.println(" "); for (int i = 0; i < nsuccessors; i++) { printPort("succ" + i, "rosybrown1"); @@ -163,6 +171,14 @@ out.println("
" + label + "
" + label + "
>]; "); } + private static String excapeLabel(String label) { + label = label.replace("&", "&"); + label = label.replace("<", "<"); + label = label.replace(">", ">"); + label = label.replace("\"", """); + return label; + } + private void printPort(String name, String color) { out.print("
n" + to + ":predecessors:n [color=red, weight=2];"); + out.println("n" + from + ":succ" + fromPort + ":s -> n" + to + ":predecessors:n [color=red, weight=2];"); } private void printDataEdge(int from, int fromPort, int to) { diff -r 58e65eb6bb5d -r e1dad0edd57a src/share/vm/compiler/compilerOracle.cpp --- a/src/share/vm/compiler/compilerOracle.cpp Fri May 27 14:20:30 2011 +0200 +++ b/src/share/vm/compiler/compilerOracle.cpp Fri May 27 17:48:28 2011 +0200 @@ -471,7 +471,7 @@ line += bytes_read; if (command == UnknownCommand) { - tty->print_cr("CompilerOracle: unrecognized line"); + tty->print_cr("CompilerOracle: UnknownCommand"); tty->print_cr(" \"%s\"", original_line); return; }