# HG changeset patch # User Roland Schatz # Date 1411561783 -7200 # Node ID 88012c1750a06a72983dd3e32c60f449ab1567b6 # Parent 75177b3cc5a83d5328bdd3c21490892333c47a32 Move bit logic nodes into the arithmetic node hierarchies. diff -r 75177b3cc5a8 -r 88012c1750a0 graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java --- a/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Wed Sep 24 14:29:43 2014 +0200 @@ -37,6 +37,11 @@ protected BinaryOp div; protected BinaryOp rem; + protected UnaryOp not; + protected BinaryOp and; + protected BinaryOp or; + protected BinaryOp xor; + public static ArithmeticOpTable forStamp(Stamp s) { return ((ArithmeticStamp) s).getOps(); } @@ -84,6 +89,34 @@ } /** + * Describes the bitwise not operation. + */ + public final UnaryOp getNot() { + return not; + } + + /** + * Describes the bitwise and operation. + */ + public final BinaryOp getAnd() { + return and; + } + + /** + * Describes the bitwise or operation. + */ + public final BinaryOp getOr() { + return or; + } + + /** + * Describes the bitwise xor operation. + */ + public final BinaryOp getXor() { + return xor; + } + + /** * Describes a unary arithmetic operation. */ public abstract static class UnaryOp { diff -r 75177b3cc5a8 -r 88012c1750a0 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 Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Wed Sep 24 14:29:43 2014 +0200 @@ -56,6 +56,24 @@ assert (upMask & CodeUtil.mask(bits)) == upMask : this; } + public static IntegerStamp stampForMask(int bits, long downMask, long upMask) { + long lowerBound; + long upperBound; + if (((upMask >>> (bits - 1)) & 1) == 0) { + lowerBound = downMask; + upperBound = upMask; + } else if (((downMask >>> (bits - 1)) & 1) == 1) { + lowerBound = downMask; + upperBound = upMask; + } else { + lowerBound = downMask | (-1L << (bits - 1)); + upperBound = CodeUtil.maxValue(bits) & upMask; + } + lowerBound = CodeUtil.convert(lowerBound, bits, false); + upperBound = CodeUtil.convert(upperBound, bits, false); + return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask); + } + @Override public IntegerStamp unrestricted() { return new IntegerStamp(getBits(), CodeUtil.minValue(getBits()), CodeUtil.maxValue(getBits()), 0, CodeUtil.mask(getBits())); @@ -523,5 +541,99 @@ return StampFactory.forInteger(a.getBits(), newLowerBound, newUpperBound); } }; + + OPS.not = new UnaryOp() { + + @Override + public Constant foldConstant(Constant value) { + return Constant.forIntegerKind(value.getKind(), ~value.asLong()); + } + + @Override + public Stamp foldStamp(Stamp stamp) { + IntegerStamp integerStamp = (IntegerStamp) stamp; + int bits = integerStamp.getBits(); + long defaultMask = CodeUtil.mask(bits); + return new IntegerStamp(bits, ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask); + } + }; + + OPS.and = 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; + assert a.getBits() == b.getBits(); + return stampForMask(a.getBits(), a.downMask() & b.downMask(), a.upMask() & b.upMask()); + } + + @Override + public boolean isNeutral(Constant n) { + int bits = n.getKind().getBitCount(); + long mask = CodeUtil.mask(bits); + return (n.asLong() & mask) == mask; + } + }; + + OPS.or = 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; + assert a.getBits() == b.getBits(); + return stampForMask(a.getBits(), a.downMask() | b.downMask(), a.upMask() | b.upMask()); + } + + @Override + public boolean isNeutral(Constant n) { + return n.asLong() == 0; + } + }; + + OPS.xor = 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; + assert a.getBits() == b.getBits(); + + long variableBits = (a.downMask() ^ a.upMask()) | (b.downMask() ^ b.upMask()); + long newDownMask = (a.downMask() ^ b.downMask()) & ~variableBits; + long newUpMask = (a.downMask() ^ b.downMask()) | variableBits; + return stampForMask(a.getBits(), newDownMask, newUpMask); + } + + @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); + } + }; } } diff -r 75177b3cc5a8 -r 88012c1750a0 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 Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.loop/src/com/oracle/graal/loop/LoopEx.java Wed Sep 24 14:29:43 2014 +0200 @@ -137,11 +137,11 @@ public void reassociateInvariants() { InvariantPredicate invariant = new InvariantPredicate(); StructuredGraph graph = loopBegin().graph(); - for (BinaryNode binary : whole().nodes().filter(BinaryNode.class)) { - if (!BinaryArithmeticNode.canTryReassociate(binary)) { + for (BinaryArithmeticNode binary : whole().nodes().filter(BinaryArithmeticNode.class)) { + if (!binary.getOp().isAssociative()) { continue; } - BinaryNode result = BinaryArithmeticNode.reassociate(binary, invariant, binary.getX(), binary.getY()); + BinaryArithmeticNode 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 75177b3cc5a8 -r 88012c1750a0 graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java --- a/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Wed Sep 24 14:29:43 2014 +0200 @@ -164,15 +164,15 @@ @Test public void testXor() { - assertEquals(new IntegerStamp(32, 0, 0xff, 0, 0xff), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0, 0xff, 0, 0xff))); - assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f))); - assertEquals(new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f))); - assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), StampTool.xor(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf))); + assertEquals(new IntegerStamp(32, 0, 0xff, 0, 0xff), IntegerStamp.OPS.getXor().foldStamp(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0, 0xff, 0, 0xff))); + assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), IntegerStamp.OPS.getXor().foldStamp(new IntegerStamp(32, 0, 0, 0, 0), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f))); + assertEquals(new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf), IntegerStamp.OPS.getXor().foldStamp(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f))); + assertEquals(new IntegerStamp(32, 0x10, 0x1f, 0x10, 0x1f), IntegerStamp.OPS.getXor().foldStamp(new IntegerStamp(32, 0x10, 0x10, 0x10, 0x10), new IntegerStamp(32, 0x0, 0xf, 0x0, 0xf))); } @Test public void testNot() { - assertEquals(new IntegerStamp(32, -11, -1, 0xffff_fff0L, 0xffff_ffffL), StampTool.not(new IntegerStamp(32, 0, 10, 0, 0xf))); + assertEquals(new IntegerStamp(32, -11, -1, 0xffff_fff0L, 0xffff_ffffL), IntegerStamp.OPS.getNot().foldStamp(new IntegerStamp(32, 0, 10, 0, 0xf))); } @Test @@ -263,7 +263,8 @@ @Test public void testAnd() { - assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), StampTool.and(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000)))); + assertEquals(new IntegerStamp(32, Integer.MIN_VALUE, 0x40000000L, 0, 0xc0000000L), + IntegerStamp.OPS.getAnd().foldStamp(StampFactory.forKind(Kind.Int), StampFactory.forConstant(Constant.forInt(0xc0000000)))); } private static void testSignExtendShort(long lower, long upper) { diff -r 75177b3cc5a8 -r 88012c1750a0 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 Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/AndNode.java Wed Sep 24 14:29:43 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -30,58 +30,50 @@ 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 AndNode extends BitLogicNode implements NarrowableArithmeticNode { +public class AndNode extends BinaryArithmeticNode implements NarrowableArithmeticNode { public static AndNode create(ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new AndNodeGen(x, y) : new AndNode(x, y); } AndNode(ValueNode x, ValueNode y) { - super(StampTool.and(x.stamp(), y.stamp()), x, y); - assert x.stamp().isCompatible(y.stamp()); - } - - @Override - public boolean inferStamp() { - return updateStamp(StampTool.and(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()); + super(ArithmeticOpTable.forStamp(x.stamp()).getAnd(), 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 (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return forX; } if (forX.isConstant() && !forY.isConstant()) { return AndNode.create(forY, forX); } - if (forX.isConstant()) { - return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant())); - } else if (forY.isConstant()) { - long rawY = forY.asConstant().asLong(); - long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp())); - if ((rawY & mask) == mask) { + if (forY.isConstant()) { + Constant c = forY.asConstant(); + if (getOp().isNeutral(c)) { return forX; } - if ((rawY & mask) == 0) { - return ConstantNode.forIntegerStamp(stamp(), 0); - } - if (forX instanceof SignExtendNode) { - SignExtendNode ext = (SignExtendNode) forX; - if (rawY == ((1L << ext.getInputBits()) - 1)) { - return ZeroExtendNode.create(ext.getValue(), ext.getResultBits()); + + if (c.getKind().isNumericInteger()) { + long rawY = c.asLong(); + long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp())); + if ((rawY & mask) == 0) { + return ConstantNode.forIntegerStamp(stamp(), 0); } - } - if (forX.stamp() instanceof IntegerStamp) { + if (forX instanceof SignExtendNode) { + SignExtendNode ext = (SignExtendNode) forX; + if (rawY == ((1L << ext.getInputBits()) - 1)) { + return ZeroExtendNode.create(ext.getValue(), ext.getResultBits()); + } + } IntegerStamp xStamp = (IntegerStamp) forX.stamp(); if (((xStamp.upMask() | xStamp.downMask()) & ~rawY) == 0) { // No bits are set which are outside the mask, so the mask will have no effect. @@ -89,7 +81,7 @@ } } - return BinaryArithmeticNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + return reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } return this; } diff -r 75177b3cc5a8 -r 88012c1750a0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BinaryArithmeticNode.java Wed Sep 24 14:29:43 2014 +0200 @@ -116,11 +116,7 @@ } } - 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) { + private static ReassociateMatch findReassociate(BinaryNode binary, NodePredicate criterion) { boolean resultX = criterion.apply(binary.getX()); boolean resultY = criterion.apply(binary.getY()); if (resultX && !resultY) { @@ -152,14 +148,14 @@ * 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 ^ + * This method accepts only {@linkplain BinaryOp#isAssociative() associative} operations such as + * +, -, *, &, | and ^ * * @param forY * @param forX */ - public static BinaryNode reassociate(BinaryNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) { - assert canTryReassociate(node); + public static BinaryArithmeticNode reassociate(BinaryArithmeticNode node, NodePredicate criterion, ValueNode forX, ValueNode forY) { + assert node.getOp().isAssociative(); ReassociateMatch match1 = findReassociate(node, criterion); if (match1 == null) { return node; @@ -220,11 +216,11 @@ } 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)); + return AndNode.create(a, AndNode.create(m1, m2)); } else if (node instanceof OrNode) { - return BitLogicNode.or(a, BitLogicNode.or(m1, m2)); + return OrNode.create(a, OrNode.create(m1, m2)); } else if (node instanceof XorNode) { - return BitLogicNode.xor(a, BitLogicNode.xor(m1, m2)); + return XorNode.create(a, XorNode.create(m1, m2)); } else { throw GraalInternalError.shouldNotReachHere(); } diff -r 75177b3cc5a8 -r 88012c1750a0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/BitLogicNode.java Wed Sep 24 14:22:01 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* - * 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.compiler.common.type.*; -import com.oracle.graal.nodeinfo.*; -import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.spi.*; - -/** - * The {@code LogicNode} class definition. - */ -@NodeInfo -public abstract class BitLogicNode extends BinaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { - - /** - * Constructs a new logic operation node. - * - * @param x the first input into this node - * @param y the second input into this node - */ - public BitLogicNode(Stamp stamp, ValueNode x, ValueNode y) { - super(stamp, x, y); - assert stamp instanceof IntegerStamp; - } - - public static BitLogicNode and(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(AndNode.create(v1, v2)); - } - - public static BitLogicNode and(ValueNode v1, ValueNode v2) { - return AndNode.create(v1, v2); - } - - public static BitLogicNode or(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(OrNode.create(v1, v2)); - } - - public static BitLogicNode or(ValueNode v1, ValueNode v2) { - return OrNode.create(v1, v2); - } - - public static BitLogicNode xor(StructuredGraph graph, ValueNode v1, ValueNode v2) { - return graph.unique(XorNode.create(v1, v2)); - } - - public static BitLogicNode xor(ValueNode v1, ValueNode v2) { - return XorNode.create(v1, v2); - } -} diff -r 75177b3cc5a8 -r 88012c1750a0 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 Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NegateNode.java Wed Sep 24 14:29:43 2014 +0200 @@ -22,9 +22,7 @@ */ package com.oracle.graal.nodes.calc; -import com.oracle.graal.api.meta.*; 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.*; @@ -35,14 +33,7 @@ * The {@code NegateNode} node negates its operand. */ @NodeInfo -public class NegateNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { - - private final UnaryOp op; - - @Override - public boolean inferStamp() { - return updateStamp(op.foldStamp(getValue().stamp())); - } +public class NegateNode extends UnaryArithmeticNode implements NarrowableArithmeticNode { /** * Creates new NegateNode instance. @@ -50,27 +41,18 @@ * @param value the instruction producing the value that is input to this instruction */ public static NegateNode create(ValueNode value) { - return create(ArithmeticOpTable.forStamp(value.stamp()).getNeg(), value); - } - - public static NegateNode create(UnaryOp op, ValueNode value) { - return USE_GENERATED_NODES ? new NegateNodeGen(op, value) : new NegateNode(op, value); + return USE_GENERATED_NODES ? new NegateNodeGen(value) : new NegateNode(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; - return op.foldConstant(inputs[0]); + NegateNode(ValueNode value) { + super(ArithmeticOpTable.forStamp(value.stamp()).getNeg(), value); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - if (forValue.isConstant()) { - return ConstantNode.forPrimitive(stamp(), op.foldConstant(forValue.asConstant())); + ValueNode ret = super.canonical(tool, forValue); + if (ret != this) { + return ret; } if (forValue instanceof NegateNode) { return ((NegateNode) forValue).getValue(); diff -r 75177b3cc5a8 -r 88012c1750a0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/NotNode.java Wed Sep 24 14:29:43 2014 +0200 @@ -22,34 +22,21 @@ */ 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.*; /** * Binary negation of long or integer values. */ @NodeInfo -public class NotNode extends UnaryNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { - - @Override - public boolean inferStamp() { - return updateStamp(StampTool.not(getValue().stamp())); - } - - @Override - public Constant evalConst(Constant... inputs) { - assert inputs.length == 1; - return Constant.forPrimitiveInt(PrimitiveStamp.getBits(stamp()), ~inputs[0].asLong()); - } +public class NotNode extends UnaryArithmeticNode implements ArithmeticLIRLowerable, NarrowableArithmeticNode { /** - * Creates new NegateNode instance. + * Creates new NotNode instance. * * @param x the instruction producing the value that is input to this instruction */ @@ -58,13 +45,14 @@ } protected NotNode(ValueNode x) { - super(StampTool.not(x.stamp()), x); + super(ArithmeticOpTable.forStamp(x.stamp()).getNot(), x); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { - if (forValue.isConstant()) { - return ConstantNode.forConstant(evalConst(forValue.asConstant()), null); + ValueNode ret = super.canonical(tool, forValue); + if (ret != this) { + return ret; } if (forValue instanceof NotNode) { return ((NotNode) forValue).getValue(); diff -r 75177b3cc5a8 -r 88012c1750a0 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 Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/OrNode.java Wed Sep 24 14:29:43 2014 +0200 @@ -30,52 +30,46 @@ 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 OrNode extends BitLogicNode { +public class OrNode extends BinaryArithmeticNode { public static OrNode create(ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new OrNodeGen(x, y) : new OrNode(x, y); } OrNode(ValueNode x, ValueNode y) { - super(StampTool.or(x.stamp(), y.stamp()), x, y); - assert x.stamp().isCompatible(y.stamp()); - } - - @Override - public boolean inferStamp() { - return updateStamp(StampTool.or(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()); + super(ArithmeticOpTable.forStamp(x.stamp()).getOr(), 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 (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { return forX; } if (forX.isConstant() && !forY.isConstant()) { return create(forY, forX); } - if (forX.isConstant()) { - return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant())); - } else if (forY.isConstant()) { - long rawY = forY.asConstant().asLong(); - long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp())); - if ((rawY & mask) == mask) { - return ConstantNode.forIntegerStamp(stamp(), mask); - } - if ((rawY & mask) == 0) { + if (forY.isConstant()) { + Constant c = forY.asConstant(); + if (getOp().isNeutral(c)) { return forX; } - return BinaryArithmeticNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + + if (c.getKind().isNumericInteger()) { + long rawY = c.asLong(); + long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp())); + if ((rawY & mask) == mask) { + return ConstantNode.forIntegerStamp(stamp(), mask); + } + } + return reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } return this; } diff -r 75177b3cc5a8 -r 88012c1750a0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnaryArithmeticNode.java Wed Sep 24 14:29:43 2014 +0200 @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2014, 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.ArithmeticOpTable.UnaryOp; +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 UnaryArithmeticNode extends UnaryNode implements ArithmeticLIRLowerable { + + private final UnaryOp op; + + protected UnaryArithmeticNode(UnaryOp op, ValueNode value) { + super(op.foldStamp(value.stamp()), value); + this.op = op; + } + + public UnaryOp getOp() { + return op; + } + + public Constant evalConst(Constant... inputs) { + assert inputs.length == 1; + return op.foldConstant(inputs[0]); + } + + @Override + public boolean inferStamp() { + return updateStamp(op.foldStamp(getValue().stamp())); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) { + if (forValue.isConstant()) { + return ConstantNode.forPrimitive(stamp(), op.foldConstant(forValue.asConstant())); + } + return this; + } +} diff -r 75177b3cc5a8 -r 88012c1750a0 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 Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/XorNode.java Wed Sep 24 14:29:43 2014 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -30,51 +30,47 @@ 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 XorNode extends BitLogicNode { +public class XorNode extends BinaryArithmeticNode { public static XorNode create(ValueNode x, ValueNode y) { return USE_GENERATED_NODES ? new XorNodeGen(x, y) : new XorNode(x, y); } protected XorNode(ValueNode x, ValueNode y) { - super(StampTool.xor(x.stamp(), y.stamp()), x, y); + super(ArithmeticOpTable.forStamp(x.stamp()).getXor(), x, y); assert x.stamp().isCompatible(y.stamp()); } @Override - public boolean inferStamp() { - return updateStamp(StampTool.xor(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) { + ValueNode ret = super.canonical(tool, forX, forY); + if (ret != this) { + return ret; + } + if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { - return ConstantNode.forIntegerStamp(stamp(), 0); + return ConstantNode.forPrimitive(stamp(), getOp().getZero(forX.stamp())); } if (forX.isConstant() && !forY.isConstant()) { return XorNode.create(forY, forX); } - if (forX.isConstant()) { - return ConstantNode.forPrimitive(stamp(), evalConst(forX.asConstant(), forY.asConstant())); - } else if (forY.isConstant()) { - long rawY = forY.asConstant().asLong(); - long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp())); - if ((rawY & mask) == 0) { + if (forY.isConstant()) { + Constant c = forY.asConstant(); + if (getOp().isNeutral(c)) { return forX; - } else if ((rawY & mask) == mask) { - return NotNode.create(forX); } - return BinaryArithmeticNode.reassociate(this, ValueNode.isConstantPredicate(), forX, forY); + + if (c.getKind().isNumericInteger()) { + long rawY = c.asLong(); + long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp())); + if ((rawY & mask) == mask) { + return NotNode.create(forX); + } + } + return reassociate(this, ValueNode.isConstantPredicate(), forX, forY); } return this; } diff -r 75177b3cc5a8 -r 88012c1750a0 graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Wed Sep 24 14:29:43 2014 +0200 @@ -34,16 +34,6 @@ */ public class StampTool { - public static Stamp not(Stamp stamp) { - if (stamp instanceof IntegerStamp) { - IntegerStamp integerStamp = (IntegerStamp) stamp; - int bits = integerStamp.getBits(); - long defaultMask = CodeUtil.mask(bits); - return new IntegerStamp(bits, ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask); - } - return stamp.unrestricted(); - } - public static Stamp meet(Collection values) { Iterator iterator = values.iterator(); if (iterator.hasNext()) { @@ -57,63 +47,6 @@ } } - public static Stamp stampForMask(int bits, long downMask, long upMask) { - long lowerBound; - long upperBound; - if (((upMask >>> (bits - 1)) & 1) == 0) { - lowerBound = downMask; - upperBound = upMask; - } else if (((downMask >>> (bits - 1)) & 1) == 1) { - lowerBound = downMask; - upperBound = upMask; - } else { - lowerBound = downMask | (-1L << (bits - 1)); - upperBound = CodeUtil.maxValue(bits) & upMask; - } - lowerBound = CodeUtil.convert(lowerBound, bits, false); - upperBound = CodeUtil.convert(upperBound, bits, false); - return new IntegerStamp(bits, lowerBound, upperBound, downMask, upMask); - } - - public static Stamp and(Stamp stamp1, Stamp stamp2) { - if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) { - return and((IntegerStamp) stamp1, (IntegerStamp) stamp2); - } - return StampFactory.illegal(); - } - - public static Stamp and(IntegerStamp stamp1, IntegerStamp stamp2) { - assert stamp1.getBits() == stamp2.getBits(); - return stampForMask(stamp1.getBits(), stamp1.downMask() & stamp2.downMask(), stamp1.upMask() & stamp2.upMask()); - } - - public static Stamp or(Stamp stamp1, Stamp stamp2) { - if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) { - return or((IntegerStamp) stamp1, (IntegerStamp) stamp2); - } - return StampFactory.illegal(); - } - - public static Stamp or(IntegerStamp stamp1, IntegerStamp stamp2) { - assert stamp1.getBits() == stamp2.getBits(); - return stampForMask(stamp1.getBits(), stamp1.downMask() | stamp2.downMask(), stamp1.upMask() | stamp2.upMask()); - } - - public static Stamp xor(Stamp stamp1, Stamp stamp2) { - if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) { - return xor((IntegerStamp) stamp1, (IntegerStamp) stamp2); - } - return StampFactory.illegal(); - } - - public static Stamp xor(IntegerStamp stamp1, IntegerStamp stamp2) { - assert stamp1.getBits() == stamp2.getBits(); - long variableBits = (stamp1.downMask() ^ stamp1.upMask()) | (stamp2.downMask() ^ stamp2.upMask()); - long newDownMask = (stamp1.downMask() ^ stamp2.downMask()) & ~variableBits; - long newUpMask = (stamp1.downMask() ^ stamp2.downMask()) | variableBits; - return stampForMask(stamp1.getBits(), newDownMask, newUpMask); - } - public static Stamp rightShift(Stamp value, Stamp shift) { if (value instanceof IntegerStamp && shift instanceof IntegerStamp) { return rightShift((IntegerStamp) value, (IntegerStamp) shift); @@ -134,7 +67,7 @@ return new IntegerStamp(bits, value.lowerBound() >> shiftCount, value.upperBound() >> shiftCount, downMask, upMask); } long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); - return stampForMask(bits, 0, mask); + return IntegerStamp.stampForMask(bits, 0, mask); } public static Stamp unsignedRightShift(Stamp value, Stamp shift) { @@ -158,7 +91,7 @@ } } long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); - return stampForMask(bits, 0, mask); + return IntegerStamp.stampForMask(bits, 0, mask); } public static Stamp leftShift(Stamp value, Stamp shift) { @@ -197,7 +130,7 @@ upMask |= value.upMask() << (i & shiftMask); } } - Stamp result = stampForMask(bits, downMask, upMask & defaultMask); + Stamp result = IntegerStamp.stampForMask(bits, downMask, upMask & defaultMask); return result; } return value.unrestricted(); @@ -231,7 +164,7 @@ if (inputStamp.lowerBound() < 0 && inputStamp.upperBound() >= 0) { // signed range including 0 and -1 // after sign extension, the whole range from 0 to MAX_INT is possible - return stampForMask(resultBits, downMask, upMask); + return IntegerStamp.stampForMask(resultBits, downMask, upMask); } long lowerBound = CodeUtil.zeroExtend(inputStamp.lowerBound(), inputBits); diff -r 75177b3cc5a8 -r 88012c1750a0 graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java --- a/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Wed Sep 24 14:22:01 2014 +0200 +++ b/graal/com.oracle.graal.replacements/src/com/oracle/graal/replacements/nodes/ReverseBytesNode.java Wed Sep 24 14:29:43 2014 +0200 @@ -30,7 +30,6 @@ import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.calc.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; @NodeInfo public class ReverseBytesNode extends UnaryNode implements LIRLowerable { @@ -50,9 +49,9 @@ Stamp newStamp; if (getKind() == Kind.Int) { long mask = CodeUtil.mask(Kind.Int.getBitCount()); - newStamp = StampTool.stampForMask(valueStamp.getBits(), reverse((int) valueStamp.downMask()) & mask, reverse((int) valueStamp.upMask()) & mask); + newStamp = IntegerStamp.stampForMask(valueStamp.getBits(), reverse((int) valueStamp.downMask()) & mask, reverse((int) valueStamp.upMask()) & mask); } else if (getKind() == Kind.Long) { - newStamp = StampTool.stampForMask(valueStamp.getBits(), reverse(valueStamp.downMask()), reverse(valueStamp.upMask())); + newStamp = IntegerStamp.stampForMask(valueStamp.getBits(), reverse(valueStamp.downMask()), reverse(valueStamp.upMask())); } else { return false; }