# HG changeset patch # User Christian Wimmer # Date 1367516169 25200 # Node ID ff8d87eabda842c8c8310ca40163b59af030ba34 # Parent bd8cb5779a4e5f31b5d0492fc418e782b14b012f 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 diff -r bd8cb5779a4e -r ff8d87eabda8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java --- 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); } diff -r bd8cb5779a4e -r ff8d87eabda8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/ConstantLocationNode.java --- 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 diff -r bd8cb5779a4e -r ff8d87eabda8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java --- 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); } diff -r bd8cb5779a4e -r ff8d87eabda8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/LocationNode.java --- 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... } diff -r bd8cb5779a4e -r ff8d87eabda8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/SnippetLocationNode.java --- /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); +}