changeset 2981:42681ed31c4d

Some LoopCounter work
author Gilles Duboscq <gilles.duboscq@oracle.com>
date Wed, 15 Jun 2011 11:20:26 +0200
parents a0b1b22e58cd
children 228276b7813b
files graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/LoopCounter.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/LoopPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java
diffstat 11 files changed, 286 insertions(+), 28 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Tue Jun 14 10:32:29 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/debug/IdealGraphPrinter.java	Wed Jun 15 11:20:26 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);
                         }
                     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Tue Jun 14 10:32:29 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/gen/LIRGenerator.java	Wed Jun 15 11:20:26 2011 +0200
@@ -248,6 +248,8 @@
             }
             if (!(instr instanceof Merge) && instr != instr.graph().start()) {
                 walkState(instr, stateAfter);
+            }
+            if (instr instanceof Value) {
                 doRoot((Value) instr);
             }
             if (stateAfter != null) {
@@ -275,7 +277,7 @@
     }
 
     private static boolean jumpsToNextBlock(Node node) {
-        return node instanceof BlockEnd || node instanceof Anchor;
+        return node instanceof BlockEnd || node instanceof Anchor || node instanceof LoopEnd;
     }
 
     @Override
@@ -1183,7 +1185,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) {
@@ -1444,6 +1446,29 @@
                         }
                     }
                     resolver.dispose();
+
+                    //TODO (gd) remove that later
+                    Node suxFirstInstr = sux.firstInstruction();
+                    if (suxFirstInstr instanceof LoopBegin) {
+                        for (Node n : suxFirstInstr.usages()) {
+                            if (n instanceof LoopCounter) {
+                                LoopCounter counter = (LoopCounter) n;
+                                if (counter.operand().isIllegal()) {
+                                    createResultVariable(counter);
+                                }
+                                if (predIndex == 0) {
+                                    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()));
+                                    }
+                                }
+                            }
+                        }
+                    }
                 }
             }
         }
@@ -1465,7 +1490,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);
             }
@@ -1477,8 +1502,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();
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Tue Jun 14 10:32:29 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/graph/IR.java	Wed Jun 15 11:20:26 2011 +0200
@@ -69,14 +69,14 @@
      */
     public void build() {
         new GraphBuilderPhase(compilation, compilation.method, false, false).apply(compilation.graph);
-        printGraph("After GraphBuilding", compilation.graph);
+        //printGraph("After GraphBuilding", compilation.graph);
         //new DuplicationPhase().apply(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) {
@@ -88,9 +88,11 @@
         if (GraalOptions.OptCanonicalizer) {
             new CanonicalizerPhase().apply(graph);
             new DeadCodeEliminationPhase().apply(compilation.graph);
-            printGraph("After Canonicalization", graph);
+            //printGraph("After Canonicalization", graph);
         }
 
+        new LoopPhase().apply(graph);
+
         new LoweringPhase().apply(graph);
 
         new SplitCriticalEdgesPhase().apply(graph);
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Tue Jun 14 10:32:29 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/If.java	Wed Jun 15 11:20:26 2011 +0200
@@ -109,7 +109,7 @@
 
     @Override
     public String shortName() {
-        return "If " + compare().condition.operator;
+        return "If";
     }
 
     @Override
--- /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 11:20:26 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);
+    }
+
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Tue Jun 14 10:32:29 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/ir/Phi.java	Wed Jun 15 11:20:26 2011 +0200
@@ -30,7 +30,7 @@
  * The {@code Phi} instruction represents the merging of dataflow
  * in the instruction graph. It refers to a join block and a variable.
  */
-public final class Phi extends FloatingNode {
+public class Phi extends FloatingNode {
 
     private static final int DEFAULT_MAX_VALUES = 2;
 
@@ -92,8 +92,8 @@
         return (Value) inputs().get(INPUT_COUNT + i);
     }
 
-    public Node setValueAt(int i, Node x) {
-        return inputs().set(INPUT_COUNT + i, x);
+    public Value setValueAt(int i, Value x) {
+        return (Value) inputs().set(INPUT_COUNT + i, x);
     }
 
     /**
@@ -144,7 +144,7 @@
         return "Phi: (" + str + ")";
     }
 
-    public Phi addInput(Node y) {
+    public Phi addInput(Value y) {
         assert !this.isDeleted() && !y.isDeleted();
         Phi phi = this;
         if (usedInputCount == maxValues) {
@@ -162,11 +162,11 @@
 
     public void removeInput(int index) {
         assert index < valueCount() : "index: " + index + ", valueCount: " + valueCount() + "@phi " + id();
-        setValueAt(index, Node.Null);
+        setValueAt(index, null);
         for (int i = index + 1; i < valueCount(); ++i) {
             setValueAt(i - 1, valueAt(i));
         }
-        setValueAt(valueCount() - 1, Node.Null);
+        setValueAt(valueCount() - 1, null);
         usedInputCount--;
     }
 
--- /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 11:20:26 2011 +0200
@@ -0,0 +1,120 @@
+/*
+ * 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.*;
+
+
+public class LoopPhase extends Phase {
+
+    @Override
+    protected void run(Graph graph) {
+        List<Node> nodes = new ArrayList<Node>(graph.getNodes());
+        for (Node n : nodes) {
+            if (n instanceof LoopBegin) {
+                doLoop((LoopBegin) n);
+            }
+        }
+    }
+
+    private void doLoop(LoopBegin loopBegin) {
+        LoopEnd loopEnd = loopBegin.loopEnd();
+        NodeBitMap loopNodes = computeLoopNodes(loopBegin);
+        List<Node> usages = new ArrayList<Node>(loopBegin.usages());
+        for (Node usage : usages) {
+            if (usage instanceof Phi) {
+                Phi phi = (Phi) usage;
+                if (phi.valueCount() == 2) { // TODO (gd) remove predecessor order assumptions
+                    Value backEdge = phi.valueAt(1); //assumes backEdge with pred index 1
+                    Value init = phi.valueAt(0);
+                    Value stride = null;
+                    boolean createAfterAddCounter = false;
+                    if (!loopNodes.isMarked(init) && backEdge instanceof IntegerAdd && loopNodes.isMarked(backEdge)) {
+                        IntegerAdd add = (IntegerAdd) backEdge;
+                        int addUsageCount = 0;
+                        System.out.println("BackEdge usages :");
+                        for (Node u : add.usages()) {
+                            if (u != loopEnd.stateBefore()) {
+                                System.out.println(" - " + u);
+                                addUsageCount++;
+                            }
+                        }
+                        if (add.x() == phi) {
+                            stride = add.y();
+                        } else if (add.y() == phi) {
+                            stride = add.x();
+                        }
+                        if (addUsageCount > 1) {
+                            createAfterAddCounter = true;
+                        }
+                    }
+                    if (stride != null && !loopNodes.isMarked(stride)) {
+                        Graph graph = loopBegin.graph();
+                        LoopCounter counter = new LoopCounter(init.kind, init, stride, loopBegin, graph);
+                        phi.replace(counter);
+                        loopEnd.stateBefore().inputs().replace(backEdge, counter);
+                        if (createAfterAddCounter) {
+                            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();
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    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);
+            }
+        }
+        for (Node n : workData) {
+            loopNodes.mark(n);
+            for (Node usage : n.usages()) {
+                if (usage instanceof FrameState) {
+                    continue;
+                }
+                workData.add(usage);
+            }
+        }
+        return loopNodes;
+    }
+}
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Tue Jun 14 10:32:29 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/phases/Phase.java	Wed Jun 15 11:20:26 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)
     }
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Tue Jun 14 10:32:29 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/schedule/IdentifyBlocksPhase.java	Wed Jun 15 11:20:26 2011 +0200
@@ -159,7 +159,7 @@
 
             if (n instanceof Merge) {
                 for (Node usage : n.usages()) {
-                    if (usage instanceof Phi) {
+                    if (usage instanceof Phi || usage instanceof LoopCounter) {
                         nodeToBlock.set(usage, block);
                     }
                 }
@@ -221,7 +221,7 @@
                 }
             } else {
                 Block dominatorBlock = b.getPredecessors().get(0);
-                for (int i=1; i<b.getPredecessors().size(); ++i) {
+                for (int i = 1; i < b.getPredecessors().size(); ++i) {
                     dominatorBlock = getCommonDominator(dominatorBlock, b.getPredecessors().get(i));
                 }
                 CiBitMap blockMap = new CiBitMap(blocks.size());
@@ -300,6 +300,13 @@
                         block = getCommonDominator(block, nodeToBlock.get(pred));
                     }
                 }
+            } else if (usage instanceof LoopCounter) {
+                LoopCounter counter = (LoopCounter) usage;
+                if (n == counter.init()) {
+                    LoopBegin loopBegin = counter.loopBegin();
+                    Block mergeBlock = nodeToBlock.get(loopBegin);
+                    block = getCommonDominator(block, mergeBlock.getPredecessors().get(0)); // TODO (gd) nasty 0 constant
+                }
             } else {
                 block = getCommonDominator(block, assignLatestPossibleBlockToNode(usage));
             }
@@ -353,7 +360,7 @@
     }
 
     private void addToSorting(Block b, Node i, List<Node> sortedInstructions, NodeBitMap map) {
-        if (i == null || map.isMarked(i) || nodeToBlock.get(i) != b || i instanceof Phi || i instanceof Local) {
+        if (i == null || map.isMarked(i) || nodeToBlock.get(i) != b || i instanceof Phi || i instanceof Local || i instanceof LoopCounter) {
             return;
         }
 
--- a/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Tue Jun 14 10:32:29 2011 +0200
+++ b/graal/com.oracle.max.graal.compiler/src/com/oracle/max/graal/compiler/target/amd64/AMD64LIRGenerator.java	Wed Jun 15 11:20:26 2011 +0200
@@ -214,7 +214,7 @@
             CiValue left = load(x.x());
             right.loadItem();
 
-            arithmeticOpLong(opcode, LMUL_OUT, left, right.result(), null);
+            arithmeticOpLong(opcode, LMUL_OUT, left, right.result());
             CiValue result = createResultVariable(x);
             lir.move(LMUL_OUT, result);
         } else {
@@ -224,7 +224,7 @@
             // don't load constants to save register
             right.loadNonconstant();
             createResultVariable(x);
-            arithmeticOpLong(opcode, x.operand(), left, right.result(), null);
+            arithmeticOpLong(opcode, x.operand(), left, right.result());
         }
     }
 
@@ -344,7 +344,7 @@
             right.loadItem();
 
             CiValue reg = LMUL_OUT;
-            arithmeticOpLong(opcode, reg, left, right.result(), null);
+            arithmeticOpLong(opcode, reg, left, right.result());
             CiValue result = createResultVariable(x);
             lir.move(reg, result);
         } else {
@@ -354,7 +354,7 @@
             // don't load constants to save register
             right.loadNonconstant();
             createResultVariable(x);
-            arithmeticOpLong(opcode, x.operand(), left, right.result(), null);
+            arithmeticOpLong(opcode, x.operand(), left, right.result());
         }
     }
 
@@ -496,10 +496,6 @@
     @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()));
     }
--- a/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java	Tue Jun 14 10:32:29 2011 +0200
+++ b/src/share/tools/IdealGraphVisualizer/Graph/src/com/sun/hotspot/igv/graph/Block.java	Wed Jun 15 11:20:26 2011 +0200
@@ -71,4 +71,10 @@
     public int compareTo(Cluster o) {
         return toString().compareTo(o.toString());
     }
+
+    @Override
+    public String toString() {
+        return inputBlock.getName();
+    }
 }
+