changeset 9524:ff8d87eabda8

Refactor the LocationNode class hierarchy to allow a SnippetLocationNode, i.e., a LocationNode that can be used in snippets without requiring the individual components to be constants at the time the snippet is prepared
author Christian Wimmer <christian.wimmer@oracle.com>
date Thu, 02 May 2013 10:36:09 -0700
parents bd8cb5779a4e
children 038fa65cbd8d
files graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java
diffstat 5 files changed, 190 insertions(+), 56 deletions(-) [+]
line wrap: on
line diff
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Thu May 02 10:26:30 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java	Thu May 02 10:36:09 2013 -0700
@@ -27,6 +27,7 @@
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.calc.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that is the sum of two other location nodes. Can represent locations in the form of
@@ -38,40 +39,43 @@
     @Input private ValueNode x;
     @Input private ValueNode y;
 
-    public LocationNode getX() {
+    protected LocationNode getX() {
         return (LocationNode) x;
     }
 
-    public LocationNode getY() {
+    protected LocationNode getY() {
         return (LocationNode) y;
     }
 
     public static AddLocationNode create(LocationNode x, LocationNode y, Graph graph) {
         assert x.getValueKind().equals(y.getValueKind()) && x.locationIdentity() == y.locationIdentity();
-        return graph.unique(new AddLocationNode(x.locationIdentity(), x.getValueKind(), x, y));
+        return graph.unique(new AddLocationNode(x, y));
     }
 
-    private AddLocationNode(Object identity, Kind kind, ValueNode x, ValueNode y) {
-        super(identity, kind);
+    private AddLocationNode(ValueNode x, ValueNode y) {
+        super(StampFactory.extension());
         this.x = x;
         this.y = y;
     }
 
     @Override
-    protected LocationNode addDisplacement(long displacement) {
-        LocationNode added = getX().addDisplacement(displacement);
-        return graph().unique(new AddLocationNode(locationIdentity(), getValueKind(), added, getY()));
+    public Kind getValueKind() {
+        return getX().getValueKind();
+    }
+
+    @Override
+    public Object locationIdentity() {
+        return getX().locationIdentity();
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
         if (x instanceof ConstantLocationNode) {
-            return getY().addDisplacement(((ConstantLocationNode) x).displacement());
+            return canonical((ConstantLocationNode) x, getY());
         }
         if (y instanceof ConstantLocationNode) {
-            return getX().addDisplacement(((ConstantLocationNode) y).displacement());
+            return canonical((ConstantLocationNode) y, getX());
         }
-
         if (x instanceof IndexedLocationNode && y instanceof IndexedLocationNode) {
             IndexedLocationNode xIdx = (IndexedLocationNode) x;
             IndexedLocationNode yIdx = (IndexedLocationNode) y;
@@ -81,7 +85,23 @@
                 return IndexedLocationNode.create(locationIdentity(), getValueKind(), displacement, index, graph(), xIdx.indexScaling());
             }
         }
+        return this;
+    }
 
+    private LocationNode canonical(ConstantLocationNode constant, LocationNode other) {
+        if (other instanceof ConstantLocationNode) {
+            ConstantLocationNode otherConst = (ConstantLocationNode) other;
+            return ConstantLocationNode.create(locationIdentity(), getValueKind(), otherConst.displacement() + constant.displacement(), graph());
+        } else if (other instanceof IndexedLocationNode) {
+            IndexedLocationNode otherIdx = (IndexedLocationNode) other;
+            return IndexedLocationNode.create(locationIdentity(), getValueKind(), otherIdx.displacement() + constant.displacement(), otherIdx.index(), graph(), otherIdx.indexScaling());
+        } else if (other instanceof AddLocationNode) {
+            AddLocationNode otherAdd = (AddLocationNode) other;
+            LocationNode newInner = otherAdd.canonical(constant, otherAdd.getX());
+            if (newInner != otherAdd) {
+                return AddLocationNode.create(newInner, otherAdd.getY(), graph());
+            }
+        }
         return this;
     }
 
@@ -92,5 +112,5 @@
     }
 
     @NodeIntrinsic
-    public static native Location addLocation(@ConstantNodeParameter Object identity, @ConstantNodeParameter Kind kind, Location x, Location y);
+    public static native Location addLocation(Location x, Location y);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Thu May 02 10:26:30 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java	Thu May 02 10:36:09 2013 -0700
@@ -25,32 +25,43 @@
 import com.oracle.graal.api.meta.*;
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that has a constant displacement. Can represent addresses of the form [base + disp]
  * where base is a node and disp is a constant.
  */
 @NodeInfo(nameTemplate = "Loc {p#locationIdentity/s}")
-public class ConstantLocationNode extends LocationNode {
-
-    private final long displacement;
+public final class ConstantLocationNode extends LocationNode {
 
-    public long displacement() {
-        return displacement;
-    }
+    private final Kind valueKind;
+    private final Object locationIdentity;
+    private final long displacement;
 
     public static ConstantLocationNode create(Object identity, Kind kind, long displacement, Graph graph) {
         return graph.unique(new ConstantLocationNode(identity, kind, displacement));
     }
 
-    protected ConstantLocationNode(Object identity, Kind kind, long displacement) {
-        super(identity, kind);
+    private ConstantLocationNode(Object identity, Kind kind, long displacement) {
+        super(StampFactory.extension());
+        assert kind != Kind.Illegal && kind != Kind.Void;
+        this.valueKind = kind;
+        this.locationIdentity = identity;
         this.displacement = displacement;
     }
 
     @Override
-    protected ConstantLocationNode addDisplacement(long x) {
-        return create(locationIdentity(), getValueKind(), displacement + x, graph());
+    public Kind getValueKind() {
+        return valueKind;
+    }
+
+    @Override
+    public Object locationIdentity() {
+        return locationIdentity;
+    }
+
+    public long displacement() {
+        return displacement;
     }
 
     @Override
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Thu May 02 10:26:30 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java	Thu May 02 10:36:09 2013 -0700
@@ -26,6 +26,7 @@
 import com.oracle.graal.graph.*;
 import com.oracle.graal.nodes.*;
 import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
 
 /**
  * Location node that has a displacement and a scaled index. Can represent locations in the form of
@@ -35,8 +36,10 @@
 @NodeInfo(nameTemplate = "IdxLoc {p#locationIdentity/s}")
 public final class IndexedLocationNode extends LocationNode implements Canonicalizable {
 
+    private final Kind valueKind;
+    private final Object locationIdentity;
+    private final long displacement;
     @Input private ValueNode index;
-    private final long displacement;
     private final int indexScaling;
 
     /**
@@ -61,30 +64,32 @@
         return graph.unique(new IndexedLocationNode(identity, kind, displacement, index, indexScaling));
     }
 
-    private IndexedLocationNode(Object identity, Kind kind, ValueNode index, int indexScaling) {
-        this(identity, kind, 0, index, indexScaling);
-    }
-
     private IndexedLocationNode(Object identity, Kind kind, long displacement, ValueNode index, int indexScaling) {
-        super(identity, kind);
+        super(StampFactory.extension());
+        assert kind != Kind.Illegal && kind != Kind.Void;
+        this.valueKind = kind;
+        this.locationIdentity = identity;
         this.index = index;
         this.displacement = displacement;
         this.indexScaling = indexScaling;
     }
 
     @Override
-    protected LocationNode addDisplacement(long x) {
-        return create(locationIdentity(), getValueKind(), displacement + x, index, graph(), indexScaling);
+    public Kind getValueKind() {
+        return valueKind;
+    }
+
+    @Override
+    public Object locationIdentity() {
+        return locationIdentity;
     }
 
     @Override
     public ValueNode canonical(CanonicalizerTool tool) {
-        Constant constantIndex = index.asConstant();
-        if (constantIndex != null) {
-            long constantIndexLong = constantIndex.asLong();
-            constantIndexLong *= indexScaling;
-            constantIndexLong += displacement;
-            return ConstantLocationNode.create(locationIdentity(), getValueKind(), constantIndexLong, graph());
+        if (index == null || indexScaling == 0) {
+            return ConstantLocationNode.create(locationIdentity(), getValueKind(), displacement, graph());
+        } else if (index.isConstant()) {
+            return ConstantLocationNode.create(locationIdentity(), getValueKind(), index.asConstant().asLong() * indexScaling + displacement, graph());
         }
         return this;
     }
@@ -93,7 +98,4 @@
     public Value generateAddress(LIRGeneratorTool gen, Value base) {
         return gen.emitAddress(base, displacement, gen.operand(index()), indexScaling());
     }
-
-    @NodeIntrinsic
-    public static native Location indexedLocation(@ConstantNodeParameter Object identity, @ConstantNodeParameter Kind kind, int index, @ConstantNodeParameter int indexScaling);
 }
--- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu May 02 10:26:30 2013 -0700
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java	Thu May 02 10:36:09 2013 -0700
@@ -35,9 +35,6 @@
  */
 public abstract class LocationNode extends FloatingNode implements LIRLowerable, ValueNumberable {
 
-    private Kind valueKind;
-    private Object locationIdentity;
-
     /**
      * Creates a new unique location identity for read and write operations.
      * 
@@ -76,25 +73,24 @@
         return elementKind;
     }
 
-    protected LocationNode(Object identity, Kind kind) {
-        super(StampFactory.extension());
-        assert kind != Kind.Illegal && kind != Kind.Void;
-        this.valueKind = kind;
-        this.locationIdentity = identity;
+    protected LocationNode(Stamp stamp) {
+        super(stamp);
     }
 
-    public Kind getValueKind() {
-        return valueKind;
-    }
+    /**
+     * Returns the kind of the accessed memory value.
+     */
+    public abstract Kind getValueKind();
 
-    public Object locationIdentity() {
-        return locationIdentity;
-    }
-
-    protected abstract LocationNode addDisplacement(long displacement);
+    /**
+     * Returns the identity of the accessed memory location. Apart from the special values
+     * {@link #ANY_LOCATION} and {@link #FINAL_LOCATION}, a different location identity of two
+     * memory accesses guarantees that the two accesses do not interfere.
+     */
+    public abstract Object locationIdentity();
 
     @Override
-    public void generate(LIRGeneratorTool generator) {
+    public final void generate(LIRGeneratorTool generator) {
         // nothing to do...
     }
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java	Thu May 02 10:36:09 2013 -0700
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2013, 2013, 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.graal.nodes.extended;
+
+import com.oracle.graal.api.meta.*;
+import com.oracle.graal.graph.*;
+import com.oracle.graal.nodes.*;
+import com.oracle.graal.nodes.spi.*;
+import com.oracle.graal.nodes.type.*;
+
+/**
+ * Location node that can be used inside a snippet without having the elements (including the
+ * location identity and kind) as a snippet constant. Can represent locations in the form of [base +
+ * index * scale + disp]. When the location is created, all elements (base, index, scale, disp) are
+ * nodes. Both scale and disp must eventually canonicalize to {@link ConstantNode constants} so that
+ * this node can be canonicalized to a {@link IndexedLocationNode} or {@link ConstantLocationNode}.
+ */
+public final class SnippetLocationNode extends LocationNode implements Canonicalizable {
+
+    @Input private ValueNode valueKind;
+    @Input private ValueNode locationIdentity;
+    @Input private ValueNode displacement;
+    @Input private ValueNode index;
+    @Input private ValueNode indexScaling;
+
+    private SnippetLocationNode(ValueNode locationIdentity, ValueNode kind, ValueNode displacement) {
+        this(locationIdentity, kind, displacement, null, null);
+    }
+
+    private SnippetLocationNode(ValueNode locationIdentity, ValueNode kind, ValueNode displacement, ValueNode index, ValueNode indexScaling) {
+        super(StampFactory.object());
+        this.valueKind = kind;
+        this.locationIdentity = locationIdentity;
+        this.displacement = displacement;
+        this.index = index;
+        this.indexScaling = indexScaling;
+    }
+
+    @Override
+    public Kind getValueKind() {
+        if (valueKind.isConstant()) {
+            return (Kind) valueKind.asConstant().asObject();
+        }
+        throw new GraalInternalError("Cannot access kind yet because it is not constant: " + valueKind);
+    }
+
+    @Override
+    public Object locationIdentity() {
+        if (locationIdentity.isConstant()) {
+            return locationIdentity.asConstant().asObject();
+        }
+        // We do not know our actual location identity yet, so be conservative.
+        return LocationNode.ANY_LOCATION;
+    }
+
+    @Override
+    public ValueNode canonical(CanonicalizerTool tool) {
+        if (valueKind.isConstant() && locationIdentity.isConstant() && displacement.isConstant() && (indexScaling == null || indexScaling.isConstant())) {
+            Kind constKind = (Kind) valueKind.asConstant().asObject();
+            Object constLocation = locationIdentity.asConstant().asObject();
+            long constDisplacement = displacement.asConstant().asLong();
+            int constIndexScaling = indexScaling == null ? 0 : indexScaling.asConstant().asInt();
+
+            if (index == null || constIndexScaling == 0) {
+                return ConstantLocationNode.create(constLocation, constKind, constDisplacement, graph());
+            } else if (index.isConstant()) {
+                return ConstantLocationNode.create(constLocation, constKind, index.asConstant().asLong() * constIndexScaling + constDisplacement, graph());
+            } else {
+                return IndexedLocationNode.create(constLocation, constKind, constDisplacement, index, graph(), constIndexScaling);
+            }
+        }
+        return this;
+    }
+
+    @Override
+    public Value generateAddress(LIRGeneratorTool gen, Value base) {
+        throw new GraalInternalError("locationIdentity must be a constant so that this node can be canonicalized: " + locationIdentity);
+    }
+
+    @NodeIntrinsic
+    public static native Location constantLocation(Object identity, Kind kind, long displacement);
+
+    @NodeIntrinsic
+    public static native Location indexedLocation(Object identity, Kind kind, long displacement, int index, int indexScaling);
+}