# HG changeset patch # User Thomas Wuerthinger # Date 1308165644 -7200 # Node ID a8e8035916a3b8ed0c781dbe1b3a39a48d931c53 # Parent 2bf5ac3f6fc3334324a27e9b0a17387ad9755a32# Parent ed63c8695fad3ff981075f01d9ec7da9e1096373 Merge. diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Wed Jun 15 21:20:20 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java Wed Jun 15 21:20:44 2011 +0200 @@ -240,7 +240,7 @@ nodes.add(merge.stateBefore()); } for (Node usage : merge.usages()) { - if (usage instanceof Phi) { + if (usage instanceof Phi || usage instanceof LoopCounter) { nodes.add(usage); } } diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Wed Jun 15 21:20:20 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java Wed Jun 15 21:20:44 2011 +0200 @@ -225,10 +225,16 @@ } if (block.blockPredecessors().size() > 1) { + if (GraalOptions.TraceLIRGeneratorLevel >= 2) { + TTY.println("STATE RESET"); + } lastState = null; } for (Node instr : block.getInstructions()) { + if (GraalOptions.TraceLIRGeneratorLevel >= 3) { + TTY.println("LIRGen for " + instr); + } FrameState stateAfter = null; if (instr instanceof Instruction) { stateAfter = ((Instruction) instr).stateAfter(); @@ -1011,10 +1017,22 @@ emitXir(prologue, null, null, null, false); } FrameState fs = setOperandsForLocals(); + if (GraalOptions.TraceLIRGeneratorLevel >= 2) { + TTY.println("STATE CHANGE (setOperandsForLocals)"); + if (GraalOptions.TraceLIRGeneratorLevel >= 3) { + TTY.println(fs.toString()); + } + } lastState = fs; } else if (block.blockPredecessors().size() == 1) { FrameState fs = block.blockPredecessors().get(0).lastState(); assert fs != null; + if (GraalOptions.TraceLIRGeneratorLevel >= 2) { + TTY.println("STATE CHANGE (singlePred)"); + if (GraalOptions.TraceLIRGeneratorLevel >= 3) { + TTY.println(fs.toString()); + } + } lastState = fs; } } @@ -1183,7 +1201,7 @@ } } - protected void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right, LIRDebugInfo info) { + protected void arithmeticOpLong(int code, CiValue result, CiValue left, CiValue right) { CiValue leftOp = left; if (isTwoOperand && leftOp != result) { @@ -1441,6 +1459,27 @@ } } resolver.dispose(); + //TODO (gd) remove that later + if (merge instanceof LoopBegin) { + for (Node usage : merge.usages()) { + if (usage instanceof LoopCounter) { + LoopCounter counter = (LoopCounter) usage; + if (counter.operand().isIllegal()) { + createResultVariable(counter); + } + if (nextSuccIndex == 0) { // (gd) nasty + lir.move(operandForInstruction(counter.init()), counter.operand()); + } else { + if (counter.kind == CiKind.Int) { + this.arithmeticOpInt(IADD, counter.operand(), counter.operand(), operandForInstruction(counter.stride()), CiValue.IllegalValue); + } else { + assert counter.kind == CiKind.Long; + this.arithmeticOpLong(LADD, counter.operand(), counter.operand(), operandForInstruction(counter.stride())); + } + } + } + } + } } /** @@ -1459,7 +1498,7 @@ if (x instanceof Constant) { x.setOperand(x.asConstant()); } else { - assert x instanceof Phi || x instanceof Local : "only for Phi and Local"; + assert x instanceof Phi || x instanceof Local : "only for Phi and Local : " + x; // allocate a variable for this local or phi createResultVariable(x); } @@ -1471,8 +1510,7 @@ assert !phi.isDead() : "dead phi: " + phi.id(); if (phi.operand().isIllegal()) { // allocate a variable for this phi - CiVariable operand = newVariable(phi.kind); - setResult(phi, operand); + createResultVariable(phi); } return phi.operand(); } diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Wed Jun 15 21:20:20 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java Wed Jun 15 21:20:44 2011 +0200 @@ -70,20 +70,19 @@ public void build() { new GraphBuilderPhase(compilation, compilation.method, false, false).apply(compilation.graph); - - printGraph("After GraphBuilding", compilation.graph); + //printGraph("After GraphBuilding", compilation.graph); if (GraalOptions.TestGraphDuplication) { new DuplicationPhase().apply(compilation.graph); - printGraph("After Duplication", compilation.graph); + //printGraph("After Duplication", compilation.graph); } new DeadCodeEliminationPhase().apply(compilation.graph); - printGraph("After DeadCodeElimination", compilation.graph); + //printGraph("After DeadCodeElimination", compilation.graph); if (GraalOptions.Inline) { new InliningPhase(compilation, this, GraalOptions.TraceInlining).apply(compilation.graph); - printGraph("After Ininling", compilation.graph); + //printGraph("After Ininling", compilation.graph); } if (GraalOptions.Time) { @@ -98,6 +97,8 @@ printGraph("After Canonicalization", graph); } + new LoopPhase().apply(graph); + new LoweringPhase().apply(graph); IdentifyBlocksPhase schedule = new IdentifyBlocksPhase(true); diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java Wed Jun 15 21:20:20 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/FloatSub.java Wed Jun 15 21:20:44 2011 +0200 @@ -83,12 +83,14 @@ if (c == 0.0f) { return x; } + return new FloatAdd(kind, x, Constant.forFloat(-c, graph), sub.isStrictFP(), graph); } else { assert kind == CiKind.Double; double c = y.asConstant().asDouble(); if (c == 0.0) { return x; } + return new FloatAdd(kind, x, Constant.forDouble(-c, graph), sub.isStrictFP(), graph); } } else if (x.isConstant()) { // TODO (gd) check that Negate impl for floating point is really faster/better than 0.0 - x diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java Wed Jun 15 21:20:20 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java Wed Jun 15 21:20:44 2011 +0200 @@ -109,7 +109,7 @@ @Override public String shortName() { - return "If " + (compare() == null ? "?" : compare().condition.operator); + return "If"; } @Override diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java Wed Jun 15 21:20:20 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/IntegerSub.java Wed Jun 15 21:20:44 2011 +0200 @@ -82,6 +82,12 @@ if (c == 0) { return x; } + if (kind == CiKind.Int) { + return new IntegerAdd(kind, x, Constant.forInt((int) -c, graph), graph); + } else { + assert kind == CiKind.Long; + return new IntegerAdd(kind, x, Constant.forLong(-c, graph), graph); + } } else if (x.isConstant()) { long c = x.asConstant().asLong(); if (c == 0) { diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopCounter.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopCounter.java Wed Jun 15 21:20:44 2011 +0200 @@ -0,0 +1,97 @@ +/* + * 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.oracle.max.graal.compiler.ir; + +import com.oracle.max.graal.compiler.debug.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public final class LoopCounter extends FloatingNode { + + private static final int INPUT_COUNT = 3; + private static final int INPUT_MERGE = 0; + private static final int INPUT_INIT = 1; + private static final int INPUT_STRIDE = 2; + + private static final int SUCCESSOR_COUNT = 0; + + public LoopCounter(CiKind kind, Value init, Value stride, LoopBegin loop, Graph graph) { + super(kind, INPUT_COUNT, SUCCESSOR_COUNT, graph); + setInit(init); + setStride(stride); + setLoopBegin(loop); + } + + @Override + protected int inputCount() { + return super.inputCount() + INPUT_COUNT; + } + + @Override + protected int successorCount() { + return super.successorCount() + SUCCESSOR_COUNT; + } + + public Value init() { + return (Value) inputs().get(super.inputCount() + INPUT_INIT); + } + + public Value setInit(Value n) { + return (Value) inputs().set(super.inputCount() + INPUT_INIT, n); + } + + public Value stride() { + return (Value) inputs().get(super.inputCount() + INPUT_STRIDE); + } + + public Value setStride(Value n) { + return (Value) inputs().set(super.inputCount() + INPUT_STRIDE, n); + } + + public LoopBegin loopBegin() { + return (LoopBegin) inputs().get(super.inputCount() + INPUT_MERGE); + } + + public Value setLoopBegin(LoopBegin n) { + return (Value) inputs().set(super.inputCount() + INPUT_MERGE, n); + } + + @Override + public void accept(ValueVisitor v) { + // TODO Auto-generated method stub + + } + + @Override + public void print(LogStream out) { + out.print("loopcounter [").print(init()).print(",+").print(stride()).print("]"); + + } + + @Override + public Node copy(Graph into) { + return new LoopCounter(kind, null, null, null, into); + } + +} diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java Wed Jun 15 21:20:20 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopEnd.java Wed Jun 15 21:20:44 2011 +0200 @@ -78,4 +78,9 @@ LoopEnd x = new LoopEnd(into); return x; } + + @Override + public String toString() { + return "LoopEnd:" + super.toString(); + } } diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java Wed Jun 15 21:20:44 2011 +0200 @@ -0,0 +1,165 @@ +/* + * 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.oracle.max.graal.compiler.phases; + +import java.util.*; + +import com.oracle.max.graal.compiler.ir.*; +import com.oracle.max.graal.compiler.value.*; +import com.oracle.max.graal.graph.*; +import com.sun.cri.ci.*; + + +public class LoopPhase extends Phase { + + @Override + protected void run(Graph graph) { + List nodes = new ArrayList(graph.getNodes()); + for (Node n : nodes) { + if (n instanceof LoopBegin) { + doLoop((LoopBegin) n); + } + } + } + + private void doLoop(LoopBegin loopBegin) { + NodeBitMap loopNodes = computeLoopNodes(loopBegin); + List counters = findLoopCounters(loopBegin, loopNodes); + mergeLoopCounters(counters, loopBegin); + } + + private void mergeLoopCounters(List counters, LoopBegin loopBegin) { + Graph graph = loopBegin.graph(); + LoopCounter[] acounters = counters.toArray(new LoopCounter[counters.size()]); + for (int i = 0; i < acounters.length; i++) { + LoopCounter c1 = acounters[i]; + if (c1 == null) { + continue; + } + for (int j = i + 1; j < acounters.length; j++) { + LoopCounter c2 = acounters[j]; + if (c2 != null && c1.stride().valueEqual(c2.stride())) { + acounters[j] = null; + CiKind kind = c1.kind; + IntegerSub sub = new IntegerSub(kind, c2.init(), c1.init(), graph); + IntegerAdd addStride = new IntegerAdd(kind, sub, c1.stride(), graph); + IntegerAdd add = new IntegerAdd(kind, c1, addStride, graph); + Phi phi = new Phi(kind, loopBegin, graph); // TODO (gd) assumes order on loopBegin preds + phi.addInput(c2.init()); + phi.addInput(add); + c2.replace(phi); + //System.out.println("--> merged Loop Counters"); + } + } + } + } + + private List findLoopCounters(LoopBegin loopBegin, NodeBitMap loopNodes) { + LoopEnd loopEnd = loopBegin.loopEnd(); + List usages = new ArrayList(loopBegin.usages()); + List counters = new LinkedList(); + for (Node usage : usages) { + if (usage instanceof Phi) { + Phi phi = (Phi) usage; + if (phi.valueCount() == 2) { + Value backEdge = phi.valueAt(1); + Value init = phi.valueAt(0); + if (loopNodes.isMarked(init)) { + // try to reverse init/backEdge order + Value tmp = backEdge; + backEdge = init; + init = tmp; + } + Value stride = null; + boolean useCounterAfterAdd = false; + if (!loopNodes.isMarked(init) && backEdge instanceof IntegerAdd && loopNodes.isMarked(backEdge)) { + IntegerAdd add = (IntegerAdd) backEdge; + int addUsageCount = 0; + for (Node u : add.usages()) { + if (u != loopEnd.stateBefore() && u != phi) { + addUsageCount++; + } + } + if (add.x() == phi) { + stride = add.y(); + } else if (add.y() == phi) { + stride = add.x(); + } + if (addUsageCount > 0) { + useCounterAfterAdd = true; + } + } + if (stride != null && !loopNodes.isMarked(stride)) { + Graph graph = loopBegin.graph(); + LoopCounter counter = new LoopCounter(init.kind, init, stride, loopBegin, graph); + counters.add(counter); + phi.replace(counter); + loopEnd.stateBefore().inputs().replace(backEdge, counter); + if (useCounterAfterAdd) { + /*IntegerAdd otherInit = new IntegerAdd(init.kind, init, stride, graph); // would be nice to canonicalize + LoopCounter otherCounter = new LoopCounter(init.kind, otherInit, stride, loopBegin, graph); + backEdge.replace(otherCounter);*/ + } else { + backEdge.delete(); + } + } + } + } + } + return counters; + } + + private NodeBitMap computeLoopNodes(LoopBegin loopBegin) { + LoopEnd loopEnd = loopBegin.loopEnd(); + NodeBitMap loopNodes = loopBegin.graph().createNodeBitMap(); + NodeFlood workCFG = loopBegin.graph().createNodeFlood(); + NodeFlood workData = loopBegin.graph().createNodeFlood(); + workCFG.add(loopEnd); + for (Node n : workCFG) { + workData.add(n); + loopNodes.mark(n); + if (n == loopBegin) { + continue; + } + for (Node pred : n.predecessors()) { + workCFG.add(pred); + } + if (n instanceof Merge) { + Merge merge = (Merge) n; + for (int i = 0; i < merge.endCount(); i++) { + workCFG.add(merge.endAt(i)); + } + } + } + for (Node n : workData) { + loopNodes.mark(n); + for (Node usage : n.usages()) { + if (usage instanceof FrameState) { + continue; + } + workData.add(usage); + } + } + return loopNodes; + } +} diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java Wed Jun 15 21:20:20 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java Wed Jun 15 21:20:44 2011 +0200 @@ -23,6 +23,8 @@ package com.oracle.max.graal.compiler.phases; import com.oracle.max.graal.compiler.*; +import com.oracle.max.graal.compiler.observer.*; +import com.oracle.max.graal.compiler.schedule.*; import com.oracle.max.graal.graph.Graph; public abstract class Phase { @@ -67,6 +69,10 @@ GraalMetrics.get(getName().concat(".deletedNodes")).increment(deletedNodeCount); GraalMetrics.get(getName().concat(".createdNodes")).increment(createdNodeCount); } + GraalCompilation compilation = GraalCompilation.compilation(); + if (compilation.compiler.isObserved() && this.getClass() != IdentifyBlocksPhase.class) { + compilation.compiler.fireCompilationEvent(new CompilationEvent(compilation, "After " + getName(), graph, true, false)); + } // (Item|Graph|Phase|Value) } diff -r 2bf5ac3f6fc3 -r a8e8035916a3 graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java --- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Wed Jun 15 21:20:20 2011 +0200 +++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java Wed Jun 15 21:20:44 2011 +0200 @@ -155,12 +155,12 @@ Node n = block.firstNode(); if (n instanceof Merge) { for (Node usage : n.usages()) { - if (usage instanceof Phi) { + if (usage instanceof Phi || usage instanceof LoopCounter) { nodeToBlock.set(usage, block); } } Merge m = (Merge) n; - for (int i=0; i - + diff -r 2bf5ac3f6fc3 -r a8e8035916a3 src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java --- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java Wed Jun 15 21:20:20 2011 +0200 +++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java Wed Jun 15 21:20:44 2011 +0200 @@ -71,4 +71,10 @@ public int compareTo(Cluster o) { return toString().compareTo(o.toString()); } + + @Override + public String toString() { + return inputBlock.getName(); + } } +