# HG changeset patch # User Roland Schatz # Date 1411559197 -7200 # Node ID ec35bb4eccb8c47b5ea94a25e349f2342d8cd2b7 # Parent 189479d72dc85a92ddd85f354e2be7e286288c52 Add support for other data types to integer arithmetic nodes. diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java --- a/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.api.meta/src/com/oracle/graal/api/meta/Constant.java Wed Sep 24 13:46:37 2014 +0200 @@ -255,6 +255,12 @@ */ public static Constant forIntegerKind(Kind kind, long i) { switch (kind) { + case Byte: + return new PrimitiveConstant(kind, (byte) i); + case Short: + return new PrimitiveConstant(kind, (short) i); + case Char: + return new PrimitiveConstant(kind, (char) i); case Int: return new PrimitiveConstant(kind, (int) i); case Long: diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.compiler.amd64/src/com/oracle/graal/compiler/amd64/AMD64NodeLIRBuilder.java Wed Sep 24 13:46:37 2014 +0200 @@ -275,7 +275,7 @@ protected AMD64Arithmetic getOp(ValueNode operation, Access access) { Kind memoryKind = getMemoryKind(access); - if (operation.getNodeClass().is(IntegerAddNode.class)) { + if (operation.getNodeClass().is(AddNode.class)) { switch (memoryKind) { case Int: return IADD; @@ -310,7 +310,7 @@ case Long: return LXOR; } - } else if (operation.getNodeClass().is(IntegerSubNode.class)) { + } else if (operation.getNodeClass().is(SubNode.class)) { switch (memoryKind) { case Int: return ISUB; @@ -324,7 +324,7 @@ case Double: return DSUB; } - } else if (operation.getNodeClass().is(IntegerMulNode.class)) { + } else if (operation.getNodeClass().is(MulNode.class)) { switch (memoryKind) { case Int: return IMUL; @@ -370,7 +370,7 @@ return null; } - @MatchRule("(Or (LeftShift value (IntegerSub Constant=delta shiftAmount)) (UnsignedRightShift value shiftAmount))") + @MatchRule("(Or (LeftShift value (Sub Constant=delta shiftAmount)) (UnsignedRightShift value shiftAmount))") public ComplexMatchResult rotateRightVariable(ValueNode value, ConstantNode delta, ValueNode shiftAmount) { if (delta.asConstant().asLong() == 0 || delta.asConstant().asLong() == 32) { return builder -> getLIRGeneratorTool().emitRor(operand(value), operand(shiftAmount)); @@ -378,7 +378,7 @@ return null; } - @MatchRule("(Or (LeftShift value shiftAmount) (UnsignedRightShift value (IntegerSub Constant=delta shiftAmount)))") + @MatchRule("(Or (LeftShift value shiftAmount) (UnsignedRightShift value (Sub Constant=delta shiftAmount)))") public ComplexMatchResult rotateLeftVariable(ValueNode value, ValueNode shiftAmount, ConstantNode delta) { if (delta.asConstant().asLong() == 0 || delta.asConstant().asLong() == 32) { return builder -> getLIRGeneratorTool().emitRol(operand(value), operand(shiftAmount)); @@ -386,18 +386,18 @@ return null; } - @MatchRule("(IntegerAdd value Read=access)") - @MatchRule("(IntegerSub value Read=access)") - @MatchRule("(IntegerMul value Read=access)") + @MatchRule("(Add value Read=access)") + @MatchRule("(Sub value Read=access)") + @MatchRule("(Mul value Read=access)") @MatchRule("(FloatAdd value Read=access)") @MatchRule("(FloatSub value Read=access)") @MatchRule("(FloatMul value Read=access)") @MatchRule("(Or value Read=access)") @MatchRule("(Xor value Read=access)") @MatchRule("(And value Read=access)") - @MatchRule("(IntegerAdd value FloatingRead=access)") - @MatchRule("(IntegerSub value FloatingRead=access)") - @MatchRule("(IntegerMul value FloatingRead=access)") + @MatchRule("(Add value FloatingRead=access)") + @MatchRule("(Sub value FloatingRead=access)") + @MatchRule("(Mul value FloatingRead=access)") @MatchRule("(FloatAdd value FloatingRead=access)") @MatchRule("(FloatSub value FloatingRead=access)") @MatchRule("(FloatMul value FloatingRead=access)") diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Wed Sep 24 13:46:37 2014 +0200 @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2014, 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.compiler.common.type; + +import com.oracle.graal.api.meta.*; + +/** + * Information about arithmetic operations. + */ +public final class ArithmeticOpTable { + + protected UnaryOp neg; + protected BinaryOp add; + protected BinaryOp sub; + + protected BinaryOp mul; + protected BinaryOp div; + protected BinaryOp rem; + + public static ArithmeticOpTable forStamp(Stamp s) { + return ((ArithmeticStamp) s).getOps(); + } + + /** + * Describes the unary negation operation. + */ + public final UnaryOp getNeg() { + return neg; + } + + /** + * Describes the addition operation. + */ + public final BinaryOp getAdd() { + return add; + } + + /** + * Describes the subtraction operation. + */ + public final BinaryOp getSub() { + return sub; + } + + /** + * Describes the multiplication operation. + */ + public final BinaryOp getMul() { + return mul; + } + + /** + * Describes the division operation. + */ + public final BinaryOp getDiv() { + return div; + } + + /** + * Describes the remainder operation. + */ + public final BinaryOp getRem() { + return rem; + } + + /** + * Describes a unary arithmetic operation. + */ + public abstract static class UnaryOp { + + /** + * Apply the operation to a {@link Constant}. + */ + public abstract Constant foldConstant(Constant value); + + /** + * Apply the operation to a {@link Stamp}. + */ + public abstract Stamp foldStamp(Stamp stamp); + } + + /** + * Describes a binary arithmetic operation. + */ + public abstract static class BinaryOp { + + private final boolean associative; + private final boolean commutative; + + protected BinaryOp(boolean associative, boolean commutative) { + this.associative = associative; + this.commutative = commutative; + } + + /** + * Apply the operation to two {@linkplain Constant Constants}. + */ + public abstract Constant foldConstant(Constant a, Constant b); + + /** + * Apply the operation to two {@linkplain Stamp Stamps}. + */ + public abstract Stamp foldStamp(Stamp a, Stamp b); + + /** + * Checks whether this operation is associative. An operation is associative when + * {@code (a . b) . c == a . (b . c)} for all a, b, c. Note that you still have to be + * careful with inverses. For example the integer subtraction operation will report + * {@code true} here, since you can still reassociate as long as the correct negations are + * inserted. + */ + public final boolean isAssociative() { + return associative; + } + + /** + * Checks whether this operation is commutative. An operation is commutative when + * {@code a . b == b . a} for all a, b. + */ + public final boolean isCommutative() { + return commutative; + } + + /** + * Check whether a {@link Constant} is a neutral element for this operation. A neutral + * element is any element {@code n} where {@code a . n == a} for all a. + * + * @param n the {@link Constant} that should be tested + * @return true iff for all {@code a}: {@code a . n == a} + */ + public boolean isNeutral(Constant n) { + return false; + } + + /** + * Check whether this operation has a zero {@code z == a . a} for each a. Examples of + * operations having such an element are subtraction and exclusive-or. Note that this may be + * different from the numbers tested by {@link #isNeutral}. + * + * @param stamp a {@link Stamp} + * @return a unique {@code z} such that {@code z == a . a} for each {@code a} in + * {@code stamp} if it exists, otherwise {@code null} + */ + public Constant getZero(Stamp stamp) { + return null; + } + } +} \ No newline at end of file diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticStamp.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticStamp.java Wed Sep 24 13:46:37 2014 +0200 @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, 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.compiler.common.type; + +/** + * Type describing values that support arithmetic operations. + */ +public abstract class ArithmeticStamp extends Stamp { + + private final ArithmeticOpTable ops; + + protected ArithmeticStamp(ArithmeticOpTable ops) { + this.ops = ops; + } + + public ArithmeticOpTable getOps() { + return ops; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + ops.hashCode(); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (!(obj instanceof ArithmeticStamp)) { + return false; + } + ArithmeticStamp other = (ArithmeticStamp) obj; + return this.ops == other.ops; + } +} diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Wed Sep 24 13:46:37 2014 +0200 @@ -27,6 +27,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.spi.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp; public class FloatStamp extends PrimitiveStamp { @@ -39,7 +41,7 @@ } public FloatStamp(int bits, double lowerBound, double upperBound, boolean nonNaN) { - super(bits); + super(bits, OPS); this.lowerBound = lowerBound; this.upperBound = upperBound; this.nonNaN = nonNaN; @@ -234,7 +236,7 @@ if (nonNaN != other.nonNaN) { return false; } - return true; + return super.equals(other); } @Override @@ -249,4 +251,189 @@ } return null; } + + private static final ArithmeticOpTable OPS = new ArithmeticOpTable(); + + static { + OPS.neg = new UnaryOp() { + + @Override + public Constant foldConstant(Constant value) { + switch (value.getKind()) { + case Float: + return Constant.forFloat(-value.asFloat()); + case Double: + return Constant.forDouble(-value.asDouble()); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp s) { + FloatStamp stamp = (FloatStamp) s; + return new FloatStamp(stamp.getBits(), -stamp.upperBound(), -stamp.lowerBound(), stamp.isNonNaN()); + } + }; + + OPS.add = new BinaryOp(false, true) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + switch (a.getKind()) { + case Float: + return Constant.forFloat(a.asFloat() + b.asFloat()); + case Double: + return Constant.forDouble(a.asDouble() + b.asDouble()); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + // TODO + return stamp1.unrestricted(); + } + + @Override + public boolean isNeutral(Constant n) { + switch (n.getKind()) { + case Float: + return Float.compare(n.asFloat(), -0.0f) == 0; + case Double: + return Double.compare(n.asDouble(), -0.0) == 0; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + }; + + OPS.sub = new BinaryOp(false, false) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + switch (a.getKind()) { + case Float: + return Constant.forFloat(a.asFloat() - b.asFloat()); + case Double: + return Constant.forDouble(a.asDouble() - b.asDouble()); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + // TODO + return stamp1.unrestricted(); + } + + @Override + public boolean isNeutral(Constant n) { + switch (n.getKind()) { + case Float: + return Float.compare(n.asFloat(), 0.0f) == 0; + case Double: + return Double.compare(n.asDouble(), 0.0) == 0; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + }; + + OPS.mul = new BinaryOp(false, true) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + switch (a.getKind()) { + case Float: + return Constant.forFloat(a.asFloat() * b.asFloat()); + case Double: + return Constant.forDouble(a.asDouble() * b.asDouble()); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp a, Stamp b) { + // TODO + return a.unrestricted(); + } + + @Override + public boolean isNeutral(Constant n) { + switch (n.getKind()) { + case Float: + return Float.compare(n.asFloat(), 1.0f) == 0; + case Double: + return Double.compare(n.asDouble(), 1.0) == 0; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + // there is no multiplicative zero, since both 0.0 and -0.0 can flip sign + }; + + OPS.div = new BinaryOp(false, false) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + switch (a.getKind()) { + case Float: + return Constant.forFloat(a.asFloat() / b.asFloat()); + case Double: + return Constant.forDouble(a.asDouble() / b.asDouble()); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + // TODO + return stamp1.unrestricted(); + } + + @Override + public boolean isNeutral(Constant n) { + switch (n.getKind()) { + case Float: + return Float.compare(n.asFloat(), 1.0f) == 0; + case Double: + return Double.compare(n.asDouble(), 1.0) == 0; + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + }; + + OPS.rem = new BinaryOp(false, false) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + switch (a.getKind()) { + case Float: + return Constant.forFloat(a.asFloat() % b.asFloat()); + case Double: + return Constant.forDouble(a.asDouble() % b.asDouble()); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + // TODO + return stamp1.unrestricted(); + } + }; + } } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Wed Sep 24 13:46:37 2014 +0200 @@ -28,6 +28,8 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.spi.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp; /** * Describes the possible values of a node that produces an int or long result. @@ -43,7 +45,7 @@ private final long upMask; public IntegerStamp(int bits, long lowerBound, long upperBound, long downMask, long upMask) { - super(bits); + super(bits, OPS); this.lowerBound = lowerBound; this.upperBound = upperBound; this.downMask = downMask; @@ -55,7 +57,7 @@ } @Override - public Stamp unrestricted() { + public IntegerStamp unrestricted() { return new IntegerStamp(getBits(), CodeUtil.minValue(getBits()), CodeUtil.maxValue(getBits()), 0, CodeUtil.mask(getBits())); } @@ -266,7 +268,7 @@ if (lowerBound != other.lowerBound || upperBound != other.upperBound || downMask != other.downMask || upMask != other.upMask) { return false; } - return true; + return super.equals(other); } public static long upMaskFor(int bits, long lowerBound, long upperBound) { @@ -307,4 +309,219 @@ } return null; } + + private static boolean addOverflowsPositively(long x, long y, int bits) { + long result = x + y; + if (bits == 64) { + return (~x & ~y & result) < 0; + } else { + return result > CodeUtil.maxValue(bits); + } + } + + private static boolean addOverflowsNegatively(long x, long y, int bits) { + long result = x + y; + if (bits == 64) { + return (x & y & ~result) < 0; + } else { + return result < CodeUtil.minValue(bits); + } + } + + private static long carryBits(long x, long y) { + return (x + y) ^ x ^ y; + } + + public static final ArithmeticOpTable OPS = new ArithmeticOpTable(); + + static { + OPS.neg = new UnaryOp() { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forIntegerKind(value.getKind(), -value.asLong()); + } + + @Override + public Stamp foldStamp(Stamp s) { + IntegerStamp stamp = (IntegerStamp) s; + int bits = stamp.getBits(); + if (stamp.lowerBound() != CodeUtil.minValue(bits)) { + // TODO(ls) check if the mask calculation is correct... + return StampFactory.forInteger(bits, -stamp.upperBound(), -stamp.lowerBound()); + } else { + return stamp.unrestricted(); + } + } + }; + + OPS.add = new BinaryOp(true, true) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + return Constant.forIntegerKind(a.getKind(), a.asLong() + b.asLong()); + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + IntegerStamp a = (IntegerStamp) stamp1; + IntegerStamp b = (IntegerStamp) stamp2; + + int bits = a.getBits(); + assert bits == b.getBits(); + + if (a.isUnrestricted()) { + return a; + } else if (b.isUnrestricted()) { + return b; + } + long defaultMask = CodeUtil.mask(bits); + long variableBits = (a.downMask() ^ a.upMask()) | (b.downMask() ^ b.upMask()); + long variableBitsWithCarry = variableBits | (carryBits(a.downMask(), b.downMask()) ^ carryBits(a.upMask(), b.upMask())); + long newDownMask = (a.downMask() + b.downMask()) & ~variableBitsWithCarry; + long newUpMask = (a.downMask() + b.downMask()) | variableBitsWithCarry; + + newDownMask &= defaultMask; + newUpMask &= defaultMask; + + long newLowerBound; + long newUpperBound; + boolean lowerOverflowsPositively = addOverflowsPositively(a.lowerBound(), b.lowerBound(), bits); + boolean upperOverflowsPositively = addOverflowsPositively(a.upperBound(), b.upperBound(), bits); + boolean lowerOverflowsNegatively = addOverflowsNegatively(a.lowerBound(), b.lowerBound(), bits); + boolean upperOverflowsNegatively = addOverflowsNegatively(a.upperBound(), b.upperBound(), bits); + if ((lowerOverflowsNegatively && !upperOverflowsNegatively) || (!lowerOverflowsPositively && upperOverflowsPositively)) { + newLowerBound = CodeUtil.minValue(bits); + newUpperBound = CodeUtil.maxValue(bits); + } else { + newLowerBound = CodeUtil.signExtend((a.lowerBound() + b.lowerBound()) & defaultMask, bits); + newUpperBound = CodeUtil.signExtend((a.upperBound() + b.upperBound()) & defaultMask, bits); + } + IntegerStamp limit = StampFactory.forInteger(bits, newLowerBound, newUpperBound); + newUpMask &= limit.upMask(); + newUpperBound = CodeUtil.signExtend(newUpperBound & newUpMask, bits); + newDownMask |= limit.downMask(); + newLowerBound |= newDownMask; + return new IntegerStamp(bits, newLowerBound, newUpperBound, newDownMask, newUpMask); + } + + @Override + public boolean isNeutral(Constant n) { + return n.asLong() == 0; + } + }; + + OPS.sub = new BinaryOp(true, false) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + return Constant.forIntegerKind(a.getKind(), a.asLong() - b.asLong()); + } + + @Override + public Stamp foldStamp(Stamp a, Stamp b) { + return OPS.add.foldStamp(a, OPS.neg.foldStamp(b)); + } + + @Override + public boolean isNeutral(Constant n) { + return n.asLong() == 0; + } + + @Override + public Constant getZero(Stamp s) { + IntegerStamp stamp = (IntegerStamp) s; + return Constant.forPrimitiveInt(stamp.getBits(), 0); + } + }; + + OPS.mul = new BinaryOp(true, true) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + return Constant.forIntegerKind(a.getKind(), a.asLong() * b.asLong()); + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + IntegerStamp a = (IntegerStamp) stamp1; + IntegerStamp b = (IntegerStamp) stamp2; + if (a.upMask() == 0) { + return a; + } else if (b.upMask() == 0) { + return b; + } else { + // TODO + return a.unrestricted(); + } + } + + @Override + public boolean isNeutral(Constant n) { + return n.asLong() == 1; + } + }; + + OPS.div = new BinaryOp(true, false) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + return Constant.forIntegerKind(a.getKind(), a.asLong() / b.asLong()); + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + IntegerStamp a = (IntegerStamp) stamp1; + IntegerStamp b = (IntegerStamp) stamp2; + assert a.getBits() == b.getBits(); + if (b.isStrictlyPositive()) { + long newLowerBound = a.lowerBound() / b.lowerBound(); + long newUpperBound = a.upperBound() / b.lowerBound(); + return StampFactory.forInteger(a.getBits(), newLowerBound, newUpperBound); + } else { + return a.unrestricted(); + } + } + + @Override + public boolean isNeutral(Constant n) { + return n.asLong() == 1; + } + }; + + OPS.rem = new BinaryOp(false, false) { + + @Override + public Constant foldConstant(Constant a, Constant b) { + assert a.getKind() == b.getKind(); + return Constant.forIntegerKind(a.getKind(), a.asLong() % b.asLong()); + } + + @Override + public Stamp foldStamp(Stamp stamp1, Stamp stamp2) { + IntegerStamp a = (IntegerStamp) stamp1; + IntegerStamp b = (IntegerStamp) stamp2; + assert a.getBits() == b.getBits(); + // zero is always possible + long newLowerBound = Math.min(a.lowerBound(), 0); + long newUpperBound = Math.max(a.upperBound(), 0); + + long magnitude; // the maximum absolute value of the result, derived from b + if (b.lowerBound() == CodeUtil.minValue(b.getBits())) { + // Math.abs(...) - 1 does not work in a case + magnitude = CodeUtil.maxValue(b.getBits()); + } else { + magnitude = Math.max(Math.abs(b.lowerBound()), Math.abs(b.upperBound())) - 1; + } + newLowerBound = Math.max(newLowerBound, -magnitude); + newUpperBound = Math.min(newUpperBound, magnitude); + + return StampFactory.forInteger(a.getBits(), newLowerBound, newUpperBound); + } + }; + } } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/PrimitiveStamp.java Wed Sep 24 13:46:37 2014 +0200 @@ -25,11 +25,12 @@ /** * Type describing primitive values. */ -public abstract class PrimitiveStamp extends Stamp { +public abstract class PrimitiveStamp extends ArithmeticStamp { private final int bits; - protected PrimitiveStamp(int bits) { + protected PrimitiveStamp(int bits, ArithmeticOpTable ops) { + super(ops); this.bits = bits; } @@ -51,7 +52,7 @@ @Override public int hashCode() { final int prime = 31; - int result = 1; + int result = super.hashCode(); result = prime * result + bits; return result; } @@ -61,10 +62,13 @@ if (this == obj) { return true; } - if (obj instanceof PrimitiveStamp) { - PrimitiveStamp other = (PrimitiveStamp) obj; - return bits == other.bits; + if (!(obj instanceof PrimitiveStamp)) { + return false; } - return false; + PrimitiveStamp other = (PrimitiveStamp) obj; + if (bits != other.bits) { + return false; + } + return super.equals(obj); } } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/Stamp.java Wed Sep 24 13:46:37 2014 +0200 @@ -115,4 +115,8 @@ public Constant asConstant() { return null; } + + public final Stamp asStamp() { + return this; + } } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java --- a/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.compiler/src/com/oracle/graal/compiler/gen/NodeLIRBuilder.java Wed Sep 24 13:46:37 2014 +0200 @@ -59,7 +59,7 @@ @MatchableNode(nodeClass = FloatSubNode.class, inputs = {"x", "y"}) @MatchableNode(nodeClass = FloatingReadNode.class, inputs = {"object", "location"}) @MatchableNode(nodeClass = IfNode.class, inputs = {"condition"}) -@MatchableNode(nodeClass = IntegerSubNode.class, inputs = {"x", "y"}) +@MatchableNode(nodeClass = SubNode.class, inputs = {"x", "y"}) @MatchableNode(nodeClass = LeftShiftNode.class, inputs = {"x", "y"}) @MatchableNode(nodeClass = NarrowNode.class, inputs = {"value"}) @MatchableNode(nodeClass = ReadNode.class, inputs = {"object", "location"}) @@ -73,11 +73,11 @@ @MatchableNode(nodeClass = FloatEqualsNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = FloatLessThanNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = FloatMulNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = IntegerAddNode.class, inputs = {"x", "y"}, commutative = true) +@MatchableNode(nodeClass = AddNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = IntegerBelowNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = IntegerEqualsNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = IntegerLessThanNode.class, inputs = {"x", "y"}, commutative = true) -@MatchableNode(nodeClass = IntegerMulNode.class, inputs = {"x", "y"}, commutative = true) +@MatchableNode(nodeClass = MulNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = IntegerTestNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = ObjectEqualsNode.class, inputs = {"x", "y"}, commutative = true) @MatchableNode(nodeClass = OrNode.class, inputs = {"x", "y"}, commutative = true) diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java --- a/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.hotspot.amd64/src/com/oracle/graal/hotspot/amd64/AMD64HotSpotNodeLIRBuilder.java Wed Sep 24 13:46:37 2014 +0200 @@ -265,18 +265,18 @@ return null; } - @MatchRule("(IntegerAdd value (Read=access (Compression=compress object) ConstantLocation=location))") - @MatchRule("(IntegerSub value (Read=access (Compression=compress object) ConstantLocation=location))") - @MatchRule("(IntegerMul value (Read=access (Compression=compress object) ConstantLocation=location))") + @MatchRule("(Add value (Read=access (Compression=compress object) ConstantLocation=location))") + @MatchRule("(Sub value (Read=access (Compression=compress object) ConstantLocation=location))") + @MatchRule("(Mul value (Read=access (Compression=compress object) ConstantLocation=location))") @MatchRule("(FloatAdd value (Read=access (Compression=compress object) ConstantLocation=location))") @MatchRule("(FloatSub value (Read=access (Compression=compress object) ConstantLocation=location))") @MatchRule("(FloatMul value (Read=access (Compression=compress object) ConstantLocation=location))") @MatchRule("(Or value (Read=access (Compression=compress object) ConstantLocation=location))") @MatchRule("(Xor value (Read=access (Compression=compress object) ConstantLocation=location))") @MatchRule("(And value (Read=access (Compression=compress object) ConstantLocation=location))") - @MatchRule("(IntegerAdd value (FloatingRead=access (Compression=compress object) ConstantLocation=location))") - @MatchRule("(IntegerSub value (FloatingRead=access (Compression=compress object) ConstantLocation=location))") - @MatchRule("(IntegerMul value (FloatingRead=access (Compression=compress object) ConstantLocation=location))") + @MatchRule("(Add value (FloatingRead=access (Compression=compress object) ConstantLocation=location))") + @MatchRule("(Sub value (FloatingRead=access (Compression=compress object) ConstantLocation=location))") + @MatchRule("(Mul value (FloatingRead=access (Compression=compress object) ConstantLocation=location))") @MatchRule("(FloatAdd value (FloatingRead=access (Compression=compress object) ConstantLocation=location))") @MatchRule("(FloatSub value (FloatingRead=access (Compression=compress object) ConstantLocation=location))") @MatchRule("(FloatMul value (FloatingRead=access (Compression=compress object) ConstantLocation=location))") diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java --- a/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.hotspot/src/com/oracle/graal/hotspot/debug/BenchmarkCounters.java Wed Sep 24 13:46:37 2014 +0200 @@ -387,7 +387,7 @@ ReadNode readArray = graph.add(ReadNode.create(thread, arrayLocation, StampFactory.forKind(wordKind), BarrierType.NONE)); ConstantLocationNode location = ConstantLocationNode.create(LocationIdentity.ANY_LOCATION, Kind.Long, Unsafe.ARRAY_LONG_INDEX_SCALE * index, graph); ReadNode read = graph.add(ReadNode.create(readArray, location, StampFactory.forKind(Kind.Long), BarrierType.NONE)); - IntegerAddNode add = graph.unique(IntegerAddNode.create(read, counter.getIncrement())); + AddNode add = graph.unique(AddNode.create(read, counter.getIncrement())); WriteNode write = graph.add(WriteNode.create(readArray, add, location, BarrierType.NONE)); graph.addBeforeFixed(counter, thread); diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java --- a/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.java/src/com/oracle/graal/java/GraphBuilderPhase.java Wed Sep 24 13:46:37 2014 +0200 @@ -472,17 +472,17 @@ @Override protected ValueNode genIntegerAdd(Kind kind, ValueNode x, ValueNode y) { - return IntegerAddNode.create(x, y); + return AddNode.create(x, y); } @Override protected ValueNode genIntegerSub(Kind kind, ValueNode x, ValueNode y) { - return IntegerSubNode.create(x, y); + return SubNode.create(x, y); } @Override protected ValueNode genIntegerMul(Kind kind, ValueNode x, ValueNode y) { - return IntegerMulNode.create(x, y); + return MulNode.create(x, y); } @Override diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/BasicInductionVariable.java Wed Sep 24 13:46:37 2014 +0200 @@ -32,9 +32,9 @@ private ValuePhiNode phi; private ValueNode init; private ValueNode rawStride; - private IntegerArithmeticNode op; + private BinaryArithmeticNode op; - public BasicInductionVariable(LoopEx loop, ValuePhiNode phi, ValueNode init, ValueNode rawStride, IntegerArithmeticNode op) { + public BasicInductionVariable(LoopEx loop, ValuePhiNode phi, ValueNode init, ValueNode rawStride, BinaryArithmeticNode op) { super(loop); this.phi = phi; this.init = init; @@ -59,10 +59,10 @@ dir = Direction.Down; } if (dir != null) { - if (op instanceof IntegerAddNode) { + if (op instanceof AddNode) { return dir; } else { - assert op instanceof IntegerSubNode; + assert op instanceof SubNode; return dir.opposite(); } } @@ -82,10 +82,10 @@ @Override public ValueNode strideNode() { - if (op instanceof IntegerAddNode) { + if (op instanceof AddNode) { return rawStride; } - if (op instanceof IntegerSubNode) { + if (op instanceof SubNode) { return graph().unique(NegateNode.create(rawStride)); } throw GraalInternalError.shouldNotReachHere(); @@ -108,10 +108,10 @@ @Override public long constantStride() { - if (op instanceof IntegerAddNode) { + if (op instanceof AddNode) { return rawStride.asConstant().asLong(); } - if (op instanceof IntegerSubNode) { + if (op instanceof SubNode) { return -rawStride.asConstant().asLong(); } throw GraalInternalError.shouldNotReachHere(); @@ -131,7 +131,7 @@ if (!maxTripCount.stamp().isCompatible(stamp)) { maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph()); } - return IntegerArithmeticNode.add(graph, IntegerArithmeticNode.mul(graph, stride, IntegerArithmeticNode.sub(graph, maxTripCount, ConstantNode.forIntegerStamp(stamp, 1, graph))), initNode); + return BinaryArithmeticNode.add(graph, BinaryArithmeticNode.mul(graph, stride, BinaryArithmeticNode.sub(graph, maxTripCount, ConstantNode.forIntegerStamp(stamp, 1, graph))), initNode); } @Override @@ -141,7 +141,7 @@ if (!maxTripCount.stamp().isCompatible(stamp)) { maxTripCount = IntegerConvertNode.convert(maxTripCount, stamp, graph()); } - return IntegerArithmeticNode.add(graph(), IntegerArithmeticNode.mul(graph(), strideNode(), maxTripCount), initNode()); + return BinaryArithmeticNode.add(graph(), BinaryArithmeticNode.mul(graph(), strideNode(), maxTripCount), initNode()); } @Override diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/CountedLoopInfo.java Wed Sep 24 13:46:37 2014 +0200 @@ -22,7 +22,7 @@ */ package com.oracle.graal.loop; -import static com.oracle.graal.nodes.calc.IntegerArithmeticNode.*; +import static com.oracle.graal.nodes.calc.BinaryArithmeticNode.*; import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; @@ -55,12 +55,12 @@ public ValueNode maxTripCountNode(boolean assumePositive) { StructuredGraph graph = iv.valueNode().graph(); Stamp stamp = iv.valueNode().stamp(); - IntegerArithmeticNode range = IntegerArithmeticNode.sub(graph, end, iv.initNode()); + BinaryArithmeticNode range = BinaryArithmeticNode.sub(graph, end, iv.initNode()); if (oneOff) { if (iv.direction() == Direction.Up) { - range = IntegerArithmeticNode.add(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); + range = BinaryArithmeticNode.add(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); } else { - range = IntegerArithmeticNode.sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); + range = BinaryArithmeticNode.sub(graph, range, ConstantNode.forIntegerStamp(stamp, 1, graph)); } } IntegerDivNode div = graph.add(IntegerDivNode.create(range, iv.strideNode())); @@ -144,14 +144,14 @@ CompareNode cond; // we use a negated guard with a < condition to achieve a >= ConstantNode one = ConstantNode.forIntegerStamp(stamp, 1, graph); if (iv.direction() == Direction.Up) { - IntegerArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one)); + BinaryArithmeticNode v1 = sub(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.maxValue(stamp.getBits()), graph), sub(graph, iv.strideNode(), one)); if (oneOff) { v1 = sub(graph, v1, one); } cond = graph.unique(IntegerLessThanNode.create(v1, end)); } else { assert iv.direction() == Direction.Down; - IntegerArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode())); + BinaryArithmeticNode v1 = add(graph, ConstantNode.forIntegerStamp(stamp, CodeUtil.minValue(stamp.getBits()), graph), sub(graph, one, iv.strideNode())); if (oneOff) { v1 = add(graph, v1, one); } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedOffsetInductionVariable.java Wed Sep 24 13:46:37 2014 +0200 @@ -31,9 +31,9 @@ private InductionVariable base; private ValueNode offset; - private IntegerArithmeticNode value; + private BinaryArithmeticNode value; - public DerivedOffsetInductionVariable(LoopEx loop, InductionVariable base, ValueNode offset, IntegerArithmeticNode value) { + public DerivedOffsetInductionVariable(LoopEx loop, InductionVariable base, ValueNode offset, BinaryArithmeticNode value) { super(loop); this.base = base; this.offset = offset; @@ -72,7 +72,7 @@ @Override public long constantStride() { - if (value instanceof IntegerSubNode && base.valueNode() == value.getY()) { + if (value instanceof SubNode && base.valueNode() == value.getY()) { return -base.constantStride(); } return base.constantStride(); @@ -85,7 +85,7 @@ @Override public ValueNode strideNode() { - if (value instanceof IntegerSubNode && base.valueNode() == value.getY()) { + if (value instanceof SubNode && base.valueNode() == value.getY()) { return graph().unique(NegateNode.create(base.strideNode())); } return base.strideNode(); @@ -112,10 +112,10 @@ } private long op(long b, long o) { - if (value instanceof IntegerAddNode) { + if (value instanceof AddNode) { return b + o; } - if (value instanceof IntegerSubNode) { + if (value instanceof SubNode) { if (base.valueNode() == value.getX()) { return b - o; } else { @@ -127,15 +127,15 @@ } private ValueNode op(ValueNode b, ValueNode o) { - if (value instanceof IntegerAddNode) { - return IntegerArithmeticNode.add(graph(), b, o); + if (value instanceof AddNode) { + return BinaryArithmeticNode.add(graph(), b, o); } - if (value instanceof IntegerSubNode) { + if (value instanceof SubNode) { if (base.valueNode() == value.getX()) { - return IntegerArithmeticNode.sub(graph(), b, o); + return BinaryArithmeticNode.sub(graph(), b, o); } else { assert base.valueNode() == value.getY(); - return IntegerArithmeticNode.sub(graph(), o, b); + return BinaryArithmeticNode.sub(graph(), o, b); } } throw GraalInternalError.shouldNotReachHere(); diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/DerivedScaledInductionVariable.java Wed Sep 24 13:46:37 2014 +0200 @@ -73,12 +73,12 @@ @Override public ValueNode initNode() { - return IntegerArithmeticNode.mul(graph(), base.initNode(), scale); + return BinaryArithmeticNode.mul(graph(), base.initNode(), scale); } @Override public ValueNode strideNode() { - return IntegerArithmeticNode.mul(graph(), base.strideNode(), scale); + return BinaryArithmeticNode.mul(graph(), base.strideNode(), scale); } @Override @@ -103,12 +103,12 @@ @Override public ValueNode extremumNode(boolean assumePositiveTripCount, Stamp stamp) { - return IntegerArithmeticNode.mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp, graph())); + return BinaryArithmeticNode.mul(graph(), base.extremumNode(assumePositiveTripCount, stamp), IntegerConvertNode.convert(scale, stamp, graph())); } @Override public ValueNode exitValueNode() { - return IntegerArithmeticNode.mul(graph(), base.exitValueNode(), scale); + return BinaryArithmeticNode.mul(graph(), base.exitValueNode(), scale); } @Override diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/InductionVariables.java Wed Sep 24 13:46:37 2014 +0200 @@ -56,7 +56,7 @@ } ValueNode stride = addSub(backValue, phi); if (stride != null) { - BasicInductionVariable biv = new BasicInductionVariable(loop, (ValuePhiNode) phi, phi.valueAt(forwardEnd), stride, (IntegerArithmeticNode) backValue); + BasicInductionVariable biv = new BasicInductionVariable(loop, (ValuePhiNode) phi, phi.valueAt(forwardEnd), stride, (BinaryArithmeticNode) backValue); ivs.put(phi, biv); bivs.add(biv); } @@ -77,7 +77,7 @@ ValueNode offset = addSub(op, baseIvNode); ValueNode scale; if (offset != null) { - iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (IntegerArithmeticNode) op); + iv = new DerivedOffsetInductionVariable(loop, baseIv, offset, (BinaryArithmeticNode) op); } else if (op instanceof NegateNode) { iv = new DerivedScaledInductionVariable(loop, baseIv, (NegateNode) op); } else if ((scale = mul(op, baseIvNode)) != null) { @@ -93,8 +93,8 @@ } private ValueNode addSub(ValueNode op, ValueNode base) { - if (op instanceof IntegerAddNode || op instanceof IntegerSubNode) { - IntegerArithmeticNode aritOp = (IntegerArithmeticNode) op; + if (op instanceof AddNode || op instanceof SubNode) { + BinaryArithmeticNode aritOp = (BinaryArithmeticNode) op; if (aritOp.getX() == base && loop.isOutsideLoop(aritOp.getY())) { return aritOp.getY(); } else if (aritOp.getY() == base && loop.isOutsideLoop(aritOp.getX())) { @@ -105,8 +105,8 @@ } private ValueNode mul(ValueNode op, ValueNode base) { - if (op instanceof IntegerMulNode) { - IntegerMulNode mul = (IntegerMulNode) op; + if (op instanceof MulNode) { + MulNode mul = (MulNode) op; if (mul.getX() == base && loop.isOutsideLoop(mul.getY())) { return mul.getY(); } else if (mul.getY() == base && loop.isOutsideLoop(mul.getX())) { diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java --- a/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Wed Sep 24 13:46:37 2014 +0200 @@ -138,10 +138,10 @@ InvariantPredicate invariant = new InvariantPredicate(); StructuredGraph graph = loopBegin().graph(); for (BinaryNode binary : whole().nodes().filter(BinaryNode.class)) { - if (!BinaryNode.canTryReassociate(binary)) { + if (!BinaryArithmeticNode.canTryReassociate(binary)) { continue; } - BinaryNode result = BinaryNode.reassociate(binary, invariant, binary.getX(), binary.getY()); + BinaryNode result = BinaryArithmeticNode.reassociate(binary, invariant, binary.getX(), binary.getY()); if (result != binary) { if (Debug.isLogEnabled()) { Debug.log("%s : Reassociated %s into %s", graph.method().format("%H::%n"), binary, result); diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/LoopBeginNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -247,8 +247,8 @@ for (int i = 0; i < phi.valueCount(); i++) { ValueNode input = phi.valueAt(i); long increment = NO_INCREMENT; - if (input != null && input instanceof IntegerAddNode) { - IntegerAddNode add = (IntegerAddNode) input; + if (input != null && input instanceof AddNode) { + AddNode add = (AddNode) input; if (add.getX() == phi && add.getY().isConstant()) { increment = add.getY().asConstant().asLong(); } else if (add.getY() == phi && add.getX().isConstant()) { diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AddNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011, 2014, 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.calc; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo(shortName = "+") +public class AddNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { + + public static AddNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new AddNodeGen(x, y) : new AddNode(x, y); + } + + protected AddNode(ValueNode x, ValueNode y) { + super(ArithmeticOpTable.forStamp(x.stamp()).getAdd(), x, y); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode ret = super.canonical(tool, forX, forY); + if (ret != this) { + return ret; + } + + if (forX.isConstant() && !forY.isConstant()) { + return AddNode.create(forY, forX); + } + boolean associative = getOp().isAssociative(); + if (associative) { + if (forX instanceof SubNode) { + SubNode sub = (SubNode) forX; + if (sub.getY() == forY) { + // (a - b) + b + return sub.getX(); + } + } + if (forY instanceof SubNode) { + SubNode sub = (SubNode) forY; + if (sub.getY() == forX) { + // b + (a - b) + return sub.getX(); + } + } + } + if (forY.isConstant()) { + Constant c = forY.asConstant(); + if (getOp().isNeutral(c)) { + return forX; + } + if (associative) { + // canonicalize expressions like "(a + 1) + 2" + BinaryNode reassociated = reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + if (reassociated != this) { + return reassociated; + } + } + } + if (forX instanceof NegateNode) { + return BinaryArithmeticNode.sub(forY, ((NegateNode) forX).getValue()); + } else if (forY instanceof NegateNode) { + return BinaryArithmeticNode.sub(forX, ((NegateNode) forY).getValue()); + } + return this; + } + + @Override + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { + Value op1 = builder.operand(getX()); + assert op1 != null : getX() + ", this=" + this; + Value op2 = builder.operand(getY()); + if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) { + Value op = op1; + op1 = op2; + op2 = op; + } + builder.setResult(this, gen.emitAdd(op1, op2)); + } +} diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -89,7 +89,7 @@ } } - return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + return BinaryArithmeticNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } return this; } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2009, 2014, 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.calc; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; +import com.oracle.graal.graph.iterators.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo +public abstract class BinaryArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable { + + private final BinaryOp op; + + public BinaryArithmeticNode(BinaryOp op, ValueNode x, ValueNode y) { + super(op.foldStamp(x.stamp(), y.stamp()), x, y); + this.op = op; + } + + public BinaryOp getOp() { + return op; + } + + @Override + public Constant evalConst(Constant... inputs) { + assert inputs.length == 2; + return op.foldConstant(inputs[0], inputs[1]); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + Constant ret = op.foldConstant(forX.asConstant(), forY.asConstant()); + return ConstantNode.forPrimitive(stamp(), ret); + } + return this; + } + + @Override + public boolean inferStamp() { + return updateStamp(op.foldStamp(getX().stamp(), getY().stamp())); + } + + public static AddNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) { + return graph.unique(AddNode.create(v1, v2)); + } + + public static AddNode add(ValueNode v1, ValueNode v2) { + return AddNode.create(v1, v2); + } + + public static MulNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) { + return graph.unique(MulNode.create(v1, v2)); + } + + public static MulNode mul(ValueNode v1, ValueNode v2) { + return MulNode.create(v1, v2); + } + + public static SubNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) { + return graph.unique(SubNode.create(v1, v2)); + } + + public static SubNode sub(ValueNode v1, ValueNode v2) { + return SubNode.create(v1, v2); + } + + private enum ReassociateMatch { + x, + y; + + public ValueNode getValue(BinaryNode binary) { + switch (this) { + case x: + return binary.getX(); + case y: + return binary.getY(); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + public ValueNode getOtherValue(BinaryNode binary) { + switch (this) { + case x: + return binary.getY(); + case y: + return binary.getX(); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + } + + public static boolean canTryReassociate(BinaryNode node) { + return (node instanceof BinaryArithmeticNode && ((BinaryArithmeticNode) node).getOp().isAssociative()) || node instanceof AndNode || node instanceof OrNode || node instanceof XorNode; + } + + public static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) { + boolean resultX = criterion.apply(binary.getX()); + boolean resultY = criterion.apply(binary.getY()); + if (resultX && !resultY) { + return ReassociateMatch.x; + } + if (!resultX && resultY) { + return ReassociateMatch.y; + } + return null; + } + + //@formatter:off + /* + * In reassociate, complexity comes from the handling of IntegerSub (non commutative) which can + * be mixed with IntegerAdd. It first tries to find m1, m2 which match the criterion : + * (a o m2) o m1 + * (m2 o a) o m1 + * m1 o (a o m2) + * m1 o (m2 o a) + * It then produces 4 boolean for the -/+ cases: + * invertA : should the final expression be like *-a (rather than a+*) + * aSub : should the final expression be like a-* (rather than a+*) + * invertM1 : should the final expression contain -m1 + * invertM2 : should the final expression contain -m2 + * + */ + //@formatter:on + /** + * Tries to re-associate values which satisfy the criterion. For example with a constantness + * criterion: {@code (a + 2) + 1 => a + (1 + 2)} + *

+ * This method accepts only {@linkplain #canTryReassociate(BinaryNode) reassociable} operations + * such as +, -, *, &, | and ^ + * + * @param forY + * @param forX + */ + public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) { + assert canTryReassociate(node); + ReassociateMatch match1 = findReassociate(node, criterion); + if (match1 == null) { + return node; + } + ValueNode otherValue = match1.getOtherValue(node); + boolean addSub = false; + boolean subAdd = false; + if (otherValue.getClass() != node.getClass()) { + if (node instanceof AddNode && otherValue instanceof SubNode) { + addSub = true; + } else if (node instanceof SubNode && otherValue instanceof AddNode) { + subAdd = true; + } else { + return node; + } + } + BinaryNode other = (BinaryNode) otherValue; + ReassociateMatch match2 = findReassociate(other, criterion); + if (match2 == null) { + return node; + } + boolean invertA = false; + boolean aSub = false; + boolean invertM1 = false; + boolean invertM2 = false; + if (addSub) { + invertM2 = match2 == ReassociateMatch.y; + invertA = !invertM2; + } else if (subAdd) { + invertA = invertM2 = match1 == ReassociateMatch.x; + invertM1 = !invertM2; + } else if (node instanceof SubNode && other instanceof SubNode) { + invertA = match1 == ReassociateMatch.x ^ match2 == ReassociateMatch.x; + aSub = match1 == ReassociateMatch.y && match2 == ReassociateMatch.y; + invertM1 = match1 == ReassociateMatch.y && match2 == ReassociateMatch.x; + invertM2 = match1 == ReassociateMatch.x && match2 == ReassociateMatch.x; + } + assert !(invertM1 && invertM2) && !(invertA && aSub); + ValueNode m1 = match1.getValue(node); + ValueNode m2 = match2.getValue(other); + ValueNode a = match2.getOtherValue(other); + if (node instanceof AddNode || node instanceof SubNode) { + BinaryNode associated; + if (invertM1) { + associated = BinaryArithmeticNode.sub(m2, m1); + } else if (invertM2) { + associated = BinaryArithmeticNode.sub(m1, m2); + } else { + associated = BinaryArithmeticNode.add(m1, m2); + } + if (invertA) { + return BinaryArithmeticNode.sub(associated, a); + } + if (aSub) { + return BinaryArithmeticNode.sub(a, associated); + } + return BinaryArithmeticNode.add(a, associated); + } else if (node instanceof MulNode) { + return BinaryArithmeticNode.mul(a, AddNode.mul(m1, m2)); + } else if (node instanceof AndNode) { + return BitLogicNode.and(a, BitLogicNode.and(m1, m2)); + } else if (node instanceof OrNode) { + return BitLogicNode.or(a, BitLogicNode.or(m1, m2)); + } else if (node instanceof XorNode) { + return BitLogicNode.xor(a, BitLogicNode.xor(m1, m2)); + } else { + throw GraalInternalError.shouldNotReachHere(); + } + } +} diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -24,7 +24,6 @@ import com.oracle.graal.compiler.common.*; import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.iterators.*; import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; @@ -59,38 +58,11 @@ this.y = y; } - public enum ReassociateMatch { - x, - y; - - public ValueNode getValue(BinaryNode binary) { - switch (this) { - case x: - return binary.getX(); - case y: - return binary.getY(); - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - - public ValueNode getOtherValue(BinaryNode binary) { - switch (this) { - case x: - return binary.getY(); - case y: - return binary.getX(); - default: - throw GraalInternalError.shouldNotReachHere(); - } - } - } - public static BinaryNode add(StructuredGraph graph, ValueNode x, ValueNode y) { assert x.stamp().isCompatible(y.stamp()); Stamp stamp = x.stamp(); if (stamp instanceof IntegerStamp) { - return IntegerArithmeticNode.add(graph, x, y); + return BinaryArithmeticNode.add(graph, x, y); } else if (stamp instanceof FloatStamp) { return graph.unique(FloatAddNode.create(x, y, false)); } else { @@ -102,7 +74,7 @@ assert x.stamp().isCompatible(y.stamp()); Stamp stamp = x.stamp(); if (stamp instanceof IntegerStamp) { - return IntegerArithmeticNode.sub(graph, x, y); + return BinaryArithmeticNode.sub(graph, x, y); } else if (stamp instanceof FloatStamp) { return graph.unique(FloatSubNode.create(x, y, false)); } else { @@ -114,125 +86,11 @@ assert x.stamp().isCompatible(y.stamp()); Stamp stamp = x.stamp(); if (stamp instanceof IntegerStamp) { - return IntegerArithmeticNode.mul(graph, x, y); + return BinaryArithmeticNode.mul(graph, x, y); } else if (stamp instanceof FloatStamp) { return graph.unique(FloatMulNode.create(x, y, false)); } else { throw GraalInternalError.shouldNotReachHere(); } } - - public static boolean canTryReassociate(BinaryNode node) { - return node instanceof IntegerAddNode || node instanceof IntegerSubNode || node instanceof IntegerMulNode || node instanceof AndNode || node instanceof OrNode || node instanceof XorNode; - } - - public static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) { - boolean resultX = criterion.apply(binary.getX()); - boolean resultY = criterion.apply(binary.getY()); - if (resultX && !resultY) { - return ReassociateMatch.x; - } - if (!resultX && resultY) { - return ReassociateMatch.y; - } - return null; - } - - //@formatter:off - /* - * In reassociate, complexity comes from the handling of IntegerSub (non commutative) which can - * be mixed with IntegerAdd. It first tries to find m1, m2 which match the criterion : - * (a o m2) o m1 - * (m2 o a) o m1 - * m1 o (a o m2) - * m1 o (m2 o a) - * It then produces 4 boolean for the -/+ cases: - * invertA : should the final expression be like *-a (rather than a+*) - * aSub : should the final expression be like a-* (rather than a+*) - * invertM1 : should the final expression contain -m1 - * invertM2 : should the final expression contain -m2 - * - */ - //@formatter:on - /** - * Tries to re-associate values which satisfy the criterion. For example with a constantness - * criterion: {@code (a + 2) + 1 => a + (1 + 2)} - *

- * This method accepts only {@linkplain #canTryReassociate(BinaryNode) reassociable} operations - * such as +, -, *, &, | and ^ - * - * @param forY - * @param forX - */ - public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) { - assert canTryReassociate(node); - ReassociateMatch match1 = findReassociate(node, criterion); - if (match1 == null) { - return node; - } - ValueNode otherValue = match1.getOtherValue(node); - boolean addSub = false; - boolean subAdd = false; - if (otherValue.getClass() != node.getClass()) { - if (node instanceof IntegerAddNode && otherValue instanceof IntegerSubNode) { - addSub = true; - } else if (node instanceof IntegerSubNode && otherValue instanceof IntegerAddNode) { - subAdd = true; - } else { - return node; - } - } - BinaryNode other = (BinaryNode) otherValue; - ReassociateMatch match2 = findReassociate(other, criterion); - if (match2 == null) { - return node; - } - boolean invertA = false; - boolean aSub = false; - boolean invertM1 = false; - boolean invertM2 = false; - if (addSub) { - invertM2 = match2 == ReassociateMatch.y; - invertA = !invertM2; - } else if (subAdd) { - invertA = invertM2 = match1 == ReassociateMatch.x; - invertM1 = !invertM2; - } else if (node instanceof IntegerSubNode && other instanceof IntegerSubNode) { - invertA = match1 == ReassociateMatch.x ^ match2 == ReassociateMatch.x; - aSub = match1 == ReassociateMatch.y && match2 == ReassociateMatch.y; - invertM1 = match1 == ReassociateMatch.y && match2 == ReassociateMatch.x; - invertM2 = match1 == ReassociateMatch.x && match2 == ReassociateMatch.x; - } - assert !(invertM1 && invertM2) && !(invertA && aSub); - ValueNode m1 = match1.getValue(node); - ValueNode m2 = match2.getValue(other); - ValueNode a = match2.getOtherValue(other); - if (node instanceof IntegerAddNode || node instanceof IntegerSubNode) { - BinaryNode associated; - if (invertM1) { - associated = IntegerArithmeticNode.sub(m2, m1); - } else if (invertM2) { - associated = IntegerArithmeticNode.sub(m1, m2); - } else { - associated = IntegerArithmeticNode.add(m1, m2); - } - if (invertA) { - return IntegerArithmeticNode.sub(associated, a); - } - if (aSub) { - return IntegerArithmeticNode.sub(a, associated); - } - return IntegerArithmeticNode.add(a, associated); - } else if (node instanceof IntegerMulNode) { - return IntegerArithmeticNode.mul(a, IntegerAddNode.mul(m1, m2)); - } else if (node instanceof AndNode) { - return BitLogicNode.and(a, BitLogicNode.and(m1, m2)); - } else if (node instanceof OrNode) { - return BitLogicNode.or(a, BitLogicNode.or(m1, m2)); - } else if (node instanceof XorNode) { - return BitLogicNode.xor(a, BitLogicNode.xor(m1, m2)); - } else { - throw GraalInternalError.shouldNotReachHere(); - } - } } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerAddNode.java Fri Sep 19 11:00:46 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,108 +0,0 @@ -/* - * Copyright (c) 2011, 2014, 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.calc; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.lir.gen.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; - -@NodeInfo(shortName = "+") -public class IntegerAddNode extends IntegerArithmeticNode implements NarrowableArithmeticNode { - - public static IntegerAddNode create(ValueNode x, ValueNode y) { - return USE_GENERATED_NODES ? new IntegerAddNodeGen(x, y) : new IntegerAddNode(x, y); - } - - protected IntegerAddNode(ValueNode x, ValueNode y) { - super(StampTool.add(x.stamp(), y.stamp()), x, y); - } - - @Override - public boolean inferStamp() { - return updateStamp(StampTool.add(getX().stamp(), getY().stamp())); - } - - @Override - public Constant evalConst(Constant... inputs) { - assert inputs.length == 2; - return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() + inputs[1].asLong()); - } - - @Override - public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - if (forX.isConstant() && !forY.isConstant()) { - return IntegerAddNode.create(forY, forX); - } - if (forX instanceof IntegerSubNode) { - IntegerSubNode sub = (IntegerSubNode) forX; - if (sub.getY() == forY) { - // (a - b) + b - return sub.getX(); - } - } - if (forY instanceof IntegerSubNode) { - IntegerSubNode sub = (IntegerSubNode) forY; - if (sub.getY() == forX) { - // b + (a - b) - return sub.getX(); - } - } - if (forX.isConstant()) { - return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); - } else if (forY.isConstant()) { - long c = forY.asConstant().asLong(); - if (c == 0) { - return forX; - } - // canonicalize expressions like "(a + 1) + 2" - BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); - if (reassociated != this) { - return reassociated; - } - } - if (forX instanceof NegateNode) { - return IntegerArithmeticNode.sub(forY, ((NegateNode) forX).getValue()); - } else if (forY instanceof NegateNode) { - return IntegerArithmeticNode.sub(forX, ((NegateNode) forY).getValue()); - } - return this; - } - - @Override - public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value op1 = builder.operand(getX()); - assert op1 != null : getX() + ", this=" + this; - Value op2 = builder.operand(getY()); - if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) { - Value op = op1; - op1 = op2; - op2 = op; - } - builder.setResult(this, gen.emitAdd(op1, op2)); - } -} diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerArithmeticNode.java Fri Sep 19 11:00:46 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2011, 2014, 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.calc; - -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -@NodeInfo -public abstract class IntegerArithmeticNode extends BinaryNode implements ArithmeticLIRLowerable { - - public IntegerArithmeticNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); - assert stamp instanceof IntegerStamp; - } - - public static IntegerAddNode add(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(IntegerAddNode.create(v1, v2)); - } - - public static IntegerAddNode add(ValueNode v1, ValueNode v2) { - return IntegerAddNode.create(v1, v2); - } - - public static IntegerMulNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(IntegerMulNode.create(v1, v2)); - } - - public static IntegerMulNode mul(ValueNode v1, ValueNode v2) { - return IntegerMulNode.create(v1, v2); - } - - public static IntegerSubNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(IntegerSubNode.create(v1, v2)); - } - - public static IntegerSubNode sub(ValueNode v1, ValueNode v2) { - return IntegerSubNode.create(v1, v2); - } -} diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerDivNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -74,7 +74,7 @@ int bits = PrimitiveStamp.getBits(stamp()); RightShiftNode sign = RightShiftNode.create(forX, ConstantNode.forInt(bits - 1)); UnsignedRightShiftNode round = UnsignedRightShiftNode.create(sign, ConstantNode.forInt(bits - log2)); - dividend = IntegerArithmeticNode.add(dividend, round); + dividend = BinaryArithmeticNode.add(dividend, round); } RightShiftNode shift = RightShiftNode.create(dividend, ConstantNode.forInt(log2)); if (c < 0) { @@ -85,8 +85,8 @@ } // Convert the expression ((a - a % b) / b) into (a / b). - if (forX instanceof IntegerSubNode) { - IntegerSubNode integerSubNode = (IntegerSubNode) forX; + if (forX instanceof SubNode) { + SubNode integerSubNode = (SubNode) forX; if (integerSubNode.getY() instanceof IntegerRemNode) { IntegerRemNode integerRemNode = (IntegerRemNode) integerSubNode.getY(); if (integerSubNode.stamp().isCompatible(this.stamp()) && integerRemNode.stamp().isCompatible(this.stamp()) && integerSubNode.getX() == integerRemNode.getX() && diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerMulNode.java Fri Sep 19 11:00:46 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2011, 2014, 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.calc; - -import com.oracle.graal.api.code.*; -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.lir.gen.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -@NodeInfo(shortName = "*") -public class IntegerMulNode extends IntegerArithmeticNode implements NarrowableArithmeticNode { - - public static IntegerMulNode create(ValueNode x, ValueNode y) { - return USE_GENERATED_NODES ? new IntegerMulNodeGen(x, y) : new IntegerMulNode(x, y); - } - - protected IntegerMulNode(ValueNode x, ValueNode y) { - super(x.stamp().unrestricted(), x, y); - assert x.stamp().isCompatible(y.stamp()); - } - - @Override - public Constant evalConst(Constant... inputs) { - assert inputs.length == 2; - return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() * inputs[1].asLong()); - } - - @Override - public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - if (forX.isConstant() && !forY.isConstant()) { - return IntegerMulNode.create(forY, forX); - } - if (forX.isConstant()) { - return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); - } else if (forY.isConstant()) { - long c = forY.asConstant().asLong(); - if (c == 1) { - return forX; - } - if (c == 0) { - return ConstantNode.forIntegerStamp(stamp(), 0); - } - long abs = Math.abs(c); - if (abs > 0 && CodeUtil.isPowerOf2(abs)) { - LeftShiftNode shift = LeftShiftNode.create(forX, ConstantNode.forInt(CodeUtil.log2(abs))); - if (c < 0) { - return NegateNode.create(shift); - } else { - return shift; - } - } - // canonicalize expressions like "(a * 1) * 2" - return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); - } - return this; - } - - @Override - public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - Value op1 = builder.operand(getX()); - Value op2 = builder.operand(getY()); - if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) { - Value op = op1; - op1 = op2; - op2 = op; - } - builder.setResult(this, gen.emitMul(op1, op2)); - } -} diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerSubNode.java Fri Sep 19 11:00:46 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,130 +0,0 @@ -/* - * Copyright (c) 2011, 2014, 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.calc; - -import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.type.*; -import com.oracle.graal.graph.spi.*; -import com.oracle.graal.lir.gen.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; -import com.oracle.graal.nodes.util.*; - -@NodeInfo(shortName = "-") -public class IntegerSubNode extends IntegerArithmeticNode implements NarrowableArithmeticNode { - - public static IntegerSubNode create(ValueNode x, ValueNode y) { - return USE_GENERATED_NODES ? new IntegerSubNodeGen(x, y) : new IntegerSubNode(x, y); - } - - protected IntegerSubNode(ValueNode x, ValueNode y) { - super(StampTool.sub(x.stamp(), y.stamp()), x, y); - } - - @Override - public boolean inferStamp() { - return updateStamp(StampTool.sub(getX().stamp(), getY().stamp())); - } - - @Override - public Constant evalConst(Constant... inputs) { - assert inputs.length == 2; - return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), inputs[0].asLong() - inputs[1].asLong()); - } - - @SuppressWarnings("hiding") - @Override - public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - return ConstantNode.forIntegerStamp(stamp(), 0); - } - if (forX instanceof IntegerAddNode) { - IntegerAddNode x = (IntegerAddNode) forX; - if (x.getY() == forY) { - // (a + b) - b - return x.getX(); - } - if (x.getX() == forY) { - // (a + b) - a - return x.getY(); - } - } else if (forX instanceof IntegerSubNode) { - IntegerSubNode x = (IntegerSubNode) forX; - if (x.getX() == forY) { - // (a - b) - a - return NegateNode.create(x.getY()); - } - } - if (forY instanceof IntegerAddNode) { - IntegerAddNode y = (IntegerAddNode) forY; - if (y.getX() == forX) { - // a - (a + b) - return NegateNode.create(y.getY()); - } - if (y.getY() == forX) { - // b - (a + b) - return NegateNode.create(y.getX()); - } - } else if (forY instanceof IntegerSubNode) { - IntegerSubNode y = (IntegerSubNode) forY; - if (y.getX() == forX) { - // a - (a - b) - return y.getY(); - } - } - if (forX.isConstant() && forY.isConstant()) { - return ConstantNode.forPrimitive(evalConst(forX.asConstant(), forY.asConstant())); - } else if (forY.isConstant()) { - long c = forY.asConstant().asLong(); - if (c == 0) { - return forX; - } - BinaryNode reassociated = BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); - if (reassociated != this) { - return reassociated; - } - if (c < 0 || ((IntegerStamp) StampFactory.forKind(forY.getKind())).contains(-c)) { - // Adding a negative is more friendly to the backend since adds are - // commutative, so prefer add when it fits. - return IntegerArithmeticNode.add(forX, ConstantNode.forIntegerStamp(stamp(), -c)); - } - } else if (forX.isConstant()) { - long c = forX.asConstant().asLong(); - if (c == 0) { - return NegateNode.create(forY); - } - return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); - } - if (forY instanceof NegateNode) { - return IntegerArithmeticNode.add(forX, ((NegateNode) forY).getValue()); - } - return this; - } - - @Override - public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { - builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY()))); - } -} diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/MulNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2011, 2014, 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.calc; + +import com.oracle.graal.api.code.*; +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; + +@NodeInfo(shortName = "*") +public class MulNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { + + public static MulNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new MulNodeGen(x, y) : new MulNode(x, y); + } + + protected MulNode(ValueNode x, ValueNode y) { + super(ArithmeticOpTable.forStamp(x.stamp()).getMul(), x, y); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode ret = super.canonical(tool, forX, forY); + if (ret != this) { + return ret; + } + + if (forX.isConstant() && !forY.isConstant()) { + return MulNode.create(forY, forX); + } + if (forY.isConstant()) { + Constant c = forY.asConstant(); + if (getOp().isNeutral(c)) { + return forX; + } + + if (c.getKind().isNumericInteger()) { + long i = c.asLong(); + long abs = Math.abs(i); + if (abs > 0 && CodeUtil.isPowerOf2(abs)) { + LeftShiftNode shift = LeftShiftNode.create(forX, ConstantNode.forInt(CodeUtil.log2(abs))); + if (i < 0) { + return NegateNode.create(shift); + } else { + return shift; + } + } + } + + if (getOp().isAssociative()) { + // canonicalize expressions like "(a * 1) * 2" + return reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + } + } + return this; + } + + @Override + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { + Value op1 = builder.operand(getX()); + Value op2 = builder.operand(getY()); + if (!getY().isConstant() && !FloatAddNode.livesLonger(this, getY(), builder)) { + Value op = op1; + op1 = op2; + op2 = op; + } + builder.setResult(this, gen.emitMul(op1, op2)); + } +} diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -23,13 +23,13 @@ package com.oracle.graal.nodes.calc; import com.oracle.graal.api.meta.*; -import com.oracle.graal.compiler.common.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp; import com.oracle.graal.graph.spi.*; import com.oracle.graal.lir.gen.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * The {@code NegateNode} node negates its operand. @@ -37,9 +37,11 @@ @NodeInfo public class NegateNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { + private final UnaryOp op; + @Override public boolean inferStamp() { - return updateStamp(StampTool.negate(getValue().stamp())); + return updateStamp(op.foldStamp(getValue().stamp())); } /** @@ -48,41 +50,34 @@ * @param value the instruction producing the value that is input to this instruction */ public static NegateNode create(ValueNode value) { - return USE_GENERATED_NODES ? new NegateNodeGen(value) : new NegateNode(value); + return create(ArithmeticOpTable.forStamp(value.stamp()).getNeg(), value); } - protected NegateNode(ValueNode value) { - super(StampTool.negate(value.stamp()), value); + public static NegateNode create(UnaryOp op, ValueNode value) { + return USE_GENERATED_NODES ? new NegateNodeGen(op, value) : new NegateNode(op, value); + } + + protected NegateNode(UnaryOp op, ValueNode value) { + super(op.foldStamp(value.stamp()), value); + this.op = op; } public Constant evalConst(Constant... inputs) { assert inputs.length == 1; - Constant constant = inputs[0]; - switch (constant.getKind()) { - case Int: - return Constant.forInt(-(constant.asInt())); - case Long: - return Constant.forLong(-(constant.asLong())); - case Float: - return Constant.forFloat(-(constant.asFloat())); - case Double: - return Constant.forDouble(-(constant.asDouble())); - default: - throw GraalInternalError.shouldNotReachHere("unknown kind " + constant.getKind()); - } + return op.foldConstant(inputs[0]); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { if (forValue.isConstant()) { - return ConstantNode.forConstant(evalConst(forValue.asConstant()), null); + return ConstantNode.forPrimitive(stamp(), op.foldConstant(forValue.asConstant())); } if (forValue instanceof NegateNode) { return ((NegateNode) forValue).getValue(); } - if (forValue instanceof IntegerSubNode) { - IntegerSubNode sub = (IntegerSubNode) forValue; - return IntegerSubNode.create(sub.getY(), sub.getX()); + if (forValue instanceof SubNode) { + SubNode sub = (SubNode) forValue; + return SubNode.create(sub.getY(), sub.getX()); } return this; } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -75,7 +75,7 @@ if ((rawY & mask) == 0) { return forX; } - return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + return BinaryArithmeticNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } return this; } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/SubNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2011, 2014, 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.calc; + +import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.graph.spi.*; +import com.oracle.graal.lir.gen.*; +import com.oracle.graal.nodeinfo.*; +import com.oracle.graal.nodes.*; +import com.oracle.graal.nodes.spi.*; +import com.oracle.graal.nodes.util.*; + +@NodeInfo(shortName = "-") +public class SubNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { + + public static SubNode create(ValueNode x, ValueNode y) { + return USE_GENERATED_NODES ? new SubNodeGen(x, y) : new SubNode(x, y); + } + + protected SubNode(ValueNode x, ValueNode y) { + super(ArithmeticOpTable.forStamp(x.stamp()).getSub(), x, y); + } + + @SuppressWarnings("hiding") + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + ValueNode ret = super.canonical(tool, forX, forY); + if (ret != this) { + return ret; + } + + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { + Constant zero = getOp().getZero(forX.stamp()); + if (zero != null) { + return ConstantNode.forPrimitive(stamp(), zero); + } + } + boolean associative = getOp().isAssociative(); + if (associative) { + if (forX instanceof AddNode) { + AddNode x = (AddNode) forX; + if (x.getY() == forY) { + // (a + b) - b + return x.getX(); + } + if (x.getX() == forY) { + // (a + b) - a + return x.getY(); + } + } else if (forX instanceof SubNode) { + SubNode x = (SubNode) forX; + if (x.getX() == forY) { + // (a - b) - a + return NegateNode.create(x.getY()); + } + } + if (forY instanceof AddNode) { + AddNode y = (AddNode) forY; + if (y.getX() == forX) { + // a - (a + b) + return NegateNode.create(y.getY()); + } + if (y.getY() == forX) { + // b - (a + b) + return NegateNode.create(y.getX()); + } + } else if (forY instanceof SubNode) { + SubNode y = (SubNode) forY; + if (y.getX() == forX) { + // a - (a - b) + return y.getY(); + } + } + } + if (forY.isConstant()) { + Constant c = forY.asConstant(); + if (getOp().isNeutral(c)) { + return forX; + } + if (associative) { + BinaryNode reassociated = reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + if (reassociated != this) { + return reassociated; + } + } + if (c.getKind().isNumericInteger()) { + long i = c.asLong(); + if (i < 0 || ((IntegerStamp) StampFactory.forKind(forY.getKind())).contains(-i)) { + // Adding a negative is more friendly to the backend since adds are + // commutative, so prefer add when it fits. + return BinaryArithmeticNode.add(forX, ConstantNode.forIntegerStamp(stamp(), -i)); + } + } + } else if (forX.isConstant()) { + Constant c = forX.asConstant(); + if (ArithmeticOpTable.forStamp(stamp()).getAdd().isNeutral(c)) { + /* + * Note that for floating point numbers, + and - have different neutral elements. We + * have to test for the neutral element of +, because we are doing this + * transformation: 0 - x == (-x) + 0 == -x. + */ + return NegateNode.create(forY); + } + if (associative) { + return reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + } + } + if (forY instanceof NegateNode) { + return BinaryArithmeticNode.add(forX, ((NegateNode) forY).getValue()); + } + return this; + } + + @Override + public void generate(NodeMappableLIRBuilder builder, ArithmeticLIRGenerator gen) { + builder.setResult(this, gen.emitSub(builder.operand(getX()), builder.operand(getY()))); + } +} diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -74,7 +74,7 @@ } else if ((rawY & mask) == mask) { return NotNode.create(forX); } - return BinaryNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + return BinaryArithmeticNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } return this; } diff -r 189479d72dc8 -r ec35bb4eccb8 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 Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/AddLocationNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -88,7 +88,7 @@ IndexedLocationNode yIdx = (IndexedLocationNode) forY; if (xIdx.getIndexScaling() == yIdx.getIndexScaling()) { long displacement = xIdx.getDisplacement() + yIdx.getDisplacement(); - ValueNode index = IntegerArithmeticNode.add(xIdx.getIndex(), yIdx.getIndex()); + ValueNode index = BinaryArithmeticNode.add(xIdx.getIndex(), yIdx.getIndex()); return IndexedLocationNode.create(getLocationIdentity(), getValueKind(), displacement, index, xIdx.getIndexScaling()); } } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java --- a/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.phases.common/src/com/oracle/graal/phases/common/ProfileCompiledMethodsPhase.java Wed Sep 24 13:46:37 2014 +0200 @@ -138,7 +138,7 @@ return 1; } else if (node instanceof IntegerDivNode || node instanceof FloatDivNode || node instanceof IntegerRemNode || node instanceof FloatRemNode) { return 10; - } else if (node instanceof IntegerMulNode || node instanceof FloatMulNode) { + } else if (node instanceof MulNode || node instanceof FloatMulNode) { return 3; } else if (node instanceof Invoke) { return 5; diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/DefaultJavaLoweringProvider.java Wed Sep 24 13:46:37 2014 +0200 @@ -625,19 +625,19 @@ offset = extend.getValue(); } } - if (offset instanceof IntegerAddNode) { - IntegerAddNode integerAddNode = (IntegerAddNode) offset; + if (offset instanceof AddNode) { + AddNode integerAddNode = (AddNode) offset; if (integerAddNode.getY() instanceof ConstantNode) { displacement = integerAddNode.getY().asConstant().asLong(); offset = integerAddNode.getX(); } } - if (base != null && signExtend == false && offset instanceof IntegerAddNode) { + if (base != null && signExtend == false && offset instanceof AddNode) { /* * Try to decompose the operation into base plus offset so the base can go into a new * node. Prefer the unshifted side of an add as the base. */ - IntegerAddNode integerAddNode = (IntegerAddNode) offset; + AddNode integerAddNode = (AddNode) offset; if (integerAddNode.getY() instanceof LeftShiftNode) { base[0] = integerAddNode.getX(); offset = integerAddNode.getY(); @@ -645,8 +645,8 @@ base[0] = integerAddNode.getY(); offset = integerAddNode.getX(); } - if (offset instanceof IntegerAddNode) { - integerAddNode = (IntegerAddNode) offset; + if (offset instanceof AddNode) { + integerAddNode = (AddNode) offset; if (integerAddNode.getY() instanceof ConstantNode) { displacement = integerAddNode.getY().asConstant().asLong(); offset = integerAddNode.getX(); @@ -748,7 +748,7 @@ if (base == 0) { return index; } else { - return IntegerArithmeticNode.add(graph, ConstantNode.forInt((int) base, graph), index); + return BinaryArithmeticNode.add(graph, ConstantNode.forInt((int) base, graph), index); } } } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerAddExactNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -37,7 +37,7 @@ * case the addition would overflow the 32 bit range. */ @NodeInfo -public class IntegerAddExactNode extends IntegerAddNode implements IntegerExactArithmeticNode { +public class IntegerAddExactNode extends AddNode implements IntegerExactArithmeticNode { public static IntegerAddExactNode create(ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new IntegerAddExactNodeGen(x, y) : new IntegerAddExactNode(x, y); diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulExactNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -36,7 +36,7 @@ * in case the addition would overflow the 32 bit range. */ @NodeInfo -public class IntegerMulExactNode extends IntegerMulNode implements IntegerExactArithmeticNode { +public class IntegerMulExactNode extends MulNode implements IntegerExactArithmeticNode { public static IntegerMulExactNode create(ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new IntegerMulExactNodeGen(x, y) : new IntegerMulExactNode(x, y); diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerMulHighNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -36,21 +36,21 @@ import com.oracle.truffle.api.*; @NodeInfo(shortName = "*H") -public class IntegerMulHighNode extends IntegerArithmeticNode { +public class IntegerMulHighNode extends BinaryNode implements ArithmeticLIRLowerable { public static IntegerMulHighNode create(ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new IntegerMulHighNodeGen(x, y) : new IntegerMulHighNode(x, y); } protected IntegerMulHighNode(ValueNode x, ValueNode y) { - this(x.stamp().unrestricted(), x, y); + this((IntegerStamp) x.stamp().unrestricted(), x, y); } - public static IntegerMulHighNode create(Stamp stamp, ValueNode x, ValueNode y) { + public static IntegerMulHighNode create(IntegerStamp stamp, ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new IntegerMulHighNodeGen(stamp, x, y) : new IntegerMulHighNode(stamp, x, y); } - protected IntegerMulHighNode(Stamp stamp, ValueNode x, ValueNode y) { + protected IntegerMulHighNode(IntegerStamp stamp, ValueNode x, ValueNode y) { super(stamp, x, y); } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/IntegerSubExactNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -38,7 +38,7 @@ * case the addition would overflow the 32 bit range. */ @NodeInfo -public class IntegerSubExactNode extends IntegerSubNode implements IntegerExactArithmeticNode { +public class IntegerSubExactNode extends SubNode implements IntegerExactArithmeticNode { public static IntegerSubExactNode create(ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new IntegerSubExactNodeGen(x, y) : new IntegerSubExactNode(x, y); diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java --- a/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.truffle/src/com/oracle/graal/truffle/nodes/arithmetic/UnsignedMulHighNode.java Wed Sep 24 13:46:37 2014 +0200 @@ -36,21 +36,21 @@ import com.oracle.truffle.api.*; @NodeInfo(shortName = "|*H|") -public class UnsignedMulHighNode extends IntegerArithmeticNode { +public class UnsignedMulHighNode extends BinaryNode implements ArithmeticLIRLowerable { public static UnsignedMulHighNode create(ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new UnsignedMulHighNodeGen(x, y) : new UnsignedMulHighNode(x, y); } protected UnsignedMulHighNode(ValueNode x, ValueNode y) { - this(x.stamp().unrestricted(), x, y); + this((IntegerStamp) x.stamp().unrestricted(), x, y); } - public static UnsignedMulHighNode create(Stamp stamp, ValueNode x, ValueNode y) { + public static UnsignedMulHighNode create(IntegerStamp stamp, ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new UnsignedMulHighNodeGen(stamp, x, y) : new UnsignedMulHighNode(stamp, x, y); } - protected UnsignedMulHighNode(Stamp stamp, ValueNode x, ValueNode y) { + protected UnsignedMulHighNode(IntegerStamp stamp, ValueNode x, ValueNode y) { super(stamp, x, y); } diff -r 189479d72dc8 -r ec35bb4eccb8 graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java --- a/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Fri Sep 19 11:00:46 2014 +0200 +++ b/graal/com.oracle.graal.word/src/com/oracle/graal/word/Word.java Wed Sep 24 13:46:37 2014 +0200 @@ -181,70 +181,70 @@ public native Object toObject(); @Override - @Operation(node = IntegerAddNode.class) + @Operation(node = AddNode.class) public Word add(Signed val) { return add((Word) val); } @Override - @Operation(node = IntegerAddNode.class) + @Operation(node = AddNode.class) public Word add(Unsigned val) { return add((Word) val); } @Override - @Operation(node = IntegerAddNode.class) + @Operation(node = AddNode.class) public Word add(int val) { return add(intParam(val)); } - @Operation(node = IntegerAddNode.class) + @Operation(node = AddNode.class) public Word add(Word val) { return box(unbox() + val.unbox()); } @Override - @Operation(node = IntegerSubNode.class) + @Operation(node = SubNode.class) public Word subtract(Signed val) { return subtract((Word) val); } @Override - @Operation(node = IntegerSubNode.class) + @Operation(node = SubNode.class) public Word subtract(Unsigned val) { return subtract((Word) val); } @Override - @Operation(node = IntegerSubNode.class) + @Operation(node = SubNode.class) public Word subtract(int val) { return subtract(intParam(val)); } - @Operation(node = IntegerSubNode.class) + @Operation(node = SubNode.class) public Word subtract(Word val) { return box(unbox() - val.unbox()); } @Override - @Operation(node = IntegerMulNode.class) + @Operation(node = MulNode.class) public Word multiply(Signed val) { return multiply((Word) val); } @Override - @Operation(node = IntegerMulNode.class) + @Operation(node = MulNode.class) public Word multiply(Unsigned val) { return multiply((Word) val); } @Override - @Operation(node = IntegerMulNode.class) + @Operation(node = MulNode.class) public Word multiply(int val) { return multiply(intParam(val)); } - @Operation(node = IntegerMulNode.class) + @Operation(node = MulNode.class) public Word multiply(Word val) { return box(unbox() * val.unbox()); }