# HG changeset patch # User Roland Schatz # Date 1421065963 -3600 # Node ID 1b7dbb81df4f2bc593d8c0bcb6cc41578432f59a # Parent ae827362559dee1c8bff2c76a37388c629f1e522 Use ArithmeticOpTable for shift operations. diff -r ae827362559d -r 1b7dbb81df4f 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 Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/ArithmeticOpTable.java Mon Jan 12 13:32:43 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -41,6 +41,9 @@ import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp.ZeroExtend; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.Shl; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.Shr; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp.UShr; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Abs; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Neg; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp.Not; @@ -64,6 +67,10 @@ private final BinaryOp or; private final BinaryOp xor; + private final ShiftOp shl; + private final ShiftOp shr; + private final ShiftOp ushr; + private final UnaryOp abs; private final UnaryOp sqrt; @@ -81,12 +88,12 @@ } } - public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); + public static final ArithmeticOpTable EMPTY = new ArithmeticOpTable(null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null, null); public ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, - BinaryOp xor, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, IntegerConvertOp signExtend, IntegerConvertOp narrow, - FloatConvertOp... floatConvert) { - this(neg, add, sub, mul, div, rem, not, and, or, xor, abs, sqrt, zeroExtend, signExtend, narrow, Stream.of(floatConvert)); + BinaryOp xor, ShiftOp shl, ShiftOp shr, ShiftOp ushr, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, + IntegerConvertOp signExtend, IntegerConvertOp narrow, FloatConvertOp... floatConvert) { + this(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow, Stream.of(floatConvert)); } public interface ArithmeticOpWrapper { @@ -95,6 +102,8 @@ BinaryOp wrapBinaryOp(BinaryOp op); + ShiftOp wrapShiftOp(ShiftOp op); + IntegerConvertOp wrapIntegerConvertOp(IntegerConvertOp op); FloatConvertOp wrapFloatConvertOp(FloatConvertOp op); @@ -122,6 +131,10 @@ BinaryOp or = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getOr()); BinaryOp xor = wrapIfNonNull(wrapper::wrapBinaryOp, inner.getXor()); + ShiftOp shl = wrapIfNonNull(wrapper::wrapShiftOp, inner.getShl()); + ShiftOp shr = wrapIfNonNull(wrapper::wrapShiftOp, inner.getShr()); + ShiftOp ushr = wrapIfNonNull(wrapper::wrapShiftOp, inner.getUShr()); + UnaryOp abs = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getAbs()); UnaryOp sqrt = wrapIfNonNull(wrapper::wrapUnaryOp, inner.getSqrt()); @@ -131,12 +144,12 @@ Stream floatConvert = Stream.of(inner.floatConvert).filter(Objects::nonNull).map(wrapper::wrapFloatConvertOp); - return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor, abs, sqrt, zeroExtend, signExtend, narrow, floatConvert); + return new ArithmeticOpTable(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow, floatConvert); } private ArithmeticOpTable(UnaryOp neg, BinaryOp add, BinaryOp sub, BinaryOp mul, BinaryOp
div, BinaryOp rem, UnaryOp not, BinaryOp and, BinaryOp or, - BinaryOp xor, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, IntegerConvertOp signExtend, IntegerConvertOp narrow, - Stream floatConvert) { + BinaryOp xor, ShiftOp shl, ShiftOp shr, ShiftOp ushr, UnaryOp abs, UnaryOp sqrt, IntegerConvertOp zeroExtend, + IntegerConvertOp signExtend, IntegerConvertOp narrow, Stream floatConvert) { this.neg = neg; this.add = add; this.sub = sub; @@ -147,6 +160,9 @@ this.and = and; this.or = or; this.xor = xor; + this.shl = shl; + this.shr = shr; + this.ushr = ushr; this.abs = abs; this.sqrt = sqrt; this.zeroExtend = zeroExtend; @@ -227,6 +243,27 @@ } /** + * Describes the shift left operation. + */ + public ShiftOp getShl() { + return shl; + } + + /** + * Describes the signed shift right operation. + */ + public ShiftOp getShr() { + return shr; + } + + /** + * Describes the unsigned shift right operation. + */ + public ShiftOp getUShr() { + return ushr; + } + + /** * Describes the absolute value operation. */ public UnaryOp getAbs() { @@ -274,8 +311,8 @@ @Override public String toString() { - return getClass().getSimpleName() + "[" + toString(neg, add, sub, mul, div, rem, not, and, or, xor, abs, sqrt, zeroExtend, signExtend, narrow) + ",floatConvert[" + toString(floatConvert) + - "]]"; + return getClass().getSimpleName() + "[" + toString(neg, add, sub, mul, div, rem, not, and, or, xor, shl, shr, ushr, abs, sqrt, zeroExtend, signExtend, narrow) + ",floatConvert[" + + toString(floatConvert) + "]]"; } public abstract static class Op { @@ -502,6 +539,53 @@ } } + /** + * Describes a shift operation. The right argument of a shift operation always has kind + * {@link Kind#Int}. + */ + public abstract static class ShiftOp extends Op { + + public abstract static class Shl extends ShiftOp { + + public Shl() { + super("<<"); + } + } + + public abstract static class Shr extends ShiftOp { + + public Shr() { + super(">>"); + } + } + + public abstract static class UShr extends ShiftOp { + + public UShr() { + super(">>>"); + } + } + + protected ShiftOp(String operation) { + super(operation); + } + + /** + * Apply the shift to a constant. + */ + public abstract Constant foldConstant(Constant c, int amount); + + /** + * Apply the shift to a stamp. + */ + public abstract Stamp foldStamp(Stamp s, IntegerStamp amount); + + /** + * Get the shift amount mask for a given result stamp. + */ + public abstract int getShiftAmountMask(Stamp s); + } + public abstract static class FloatConvertOp extends UnaryOp { private final FloatConvert op; diff -r ae827362559d -r 1b7dbb81df4f 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 Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/FloatStamp.java Mon Jan 12 13:32:43 2015 +0100 @@ -609,6 +609,8 @@ } }, + null, null, null, + new UnaryOp.Abs() { @Override diff -r ae827362559d -r 1b7dbb81df4f 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 Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.compiler.common/src/com/oracle/graal/compiler/common/type/IntegerStamp.java Mon Jan 12 13:32:43 2015 +0100 @@ -34,6 +34,7 @@ import com.oracle.graal.compiler.common.type.ArithmeticOpTable.BinaryOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.FloatConvertOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.UnaryOp; /** @@ -700,6 +701,155 @@ } }, + new ShiftOp.Shl() { + + @Override + public Constant foldConstant(Constant value, int amount) { + PrimitiveConstant c = (PrimitiveConstant) value; + switch (c.getKind()) { + case Int: + return JavaConstant.forInt(c.asInt() << amount); + case Long: + return JavaConstant.forLong(c.asLong() << amount); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { + IntegerStamp value = (IntegerStamp) stamp; + int bits = value.getBits(); + long defaultMask = CodeUtil.mask(bits); + if (value.upMask() == 0) { + return value; + } + int shiftMask = getShiftAmountMask(stamp); + int shiftBits = Integer.bitCount(shiftMask); + if (shift.lowerBound() == shift.upperBound()) { + int shiftAmount = (int) (shift.lowerBound() & shiftMask); + if (shiftAmount == 0) { + return value; + } + // the mask of bits that will be lost or shifted into the sign bit + long removedBits = -1L << (bits - shiftAmount - 1); + if ((value.lowerBound() & removedBits) == 0 && (value.upperBound() & removedBits) == 0) { + // use a better stamp if neither lower nor upper bound can lose bits + return new IntegerStamp(bits, value.lowerBound() << shiftAmount, value.upperBound() << shiftAmount, value.downMask() << shiftAmount, value.upMask() << shiftAmount); + } + } + if ((shift.lowerBound() >>> shiftBits) == (shift.upperBound() >>> shiftBits)) { + long downMask = defaultMask; + long upMask = 0; + for (long i = shift.lowerBound(); i <= shift.upperBound(); i++) { + if (shift.contains(i)) { + downMask &= value.downMask() << (i & shiftMask); + upMask |= value.upMask() << (i & shiftMask); + } + } + Stamp result = IntegerStamp.stampForMask(bits, downMask, upMask & defaultMask); + return result; + } + return value.unrestricted(); + } + + @Override + public int getShiftAmountMask(Stamp s) { + IntegerStamp stamp = (IntegerStamp) s; + assert CodeUtil.isPowerOf2(stamp.getBits()); + return stamp.getBits() - 1; + } + }, + + new ShiftOp.Shr() { + + @Override + public Constant foldConstant(Constant value, int amount) { + PrimitiveConstant c = (PrimitiveConstant) value; + switch (c.getKind()) { + case Int: + return JavaConstant.forInt(c.asInt() >> amount); + case Long: + return JavaConstant.forLong(c.asLong() >> amount); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { + IntegerStamp value = (IntegerStamp) stamp; + int bits = value.getBits(); + if (shift.lowerBound() == shift.upperBound()) { + long shiftCount = shift.lowerBound() & getShiftAmountMask(stamp); + if (shiftCount == 0) { + return stamp; + } + + int extraBits = 64 - bits; + long defaultMask = CodeUtil.mask(bits); + // shifting back and forth performs sign extension + long downMask = (value.downMask() << extraBits) >> (shiftCount + extraBits) & defaultMask; + long upMask = (value.upMask() << extraBits) >> (shiftCount + extraBits) & defaultMask; + return new IntegerStamp(bits, value.lowerBound() >> shiftCount, value.upperBound() >> shiftCount, downMask, upMask); + } + long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); + return IntegerStamp.stampForMask(bits, 0, mask); + } + + @Override + public int getShiftAmountMask(Stamp s) { + IntegerStamp stamp = (IntegerStamp) s; + assert CodeUtil.isPowerOf2(stamp.getBits()); + return stamp.getBits() - 1; + } + }, + + new ShiftOp.UShr() { + + @Override + public Constant foldConstant(Constant value, int amount) { + PrimitiveConstant c = (PrimitiveConstant) value; + switch (c.getKind()) { + case Int: + return JavaConstant.forInt(c.asInt() >>> amount); + case Long: + return JavaConstant.forLong(c.asLong() >>> amount); + default: + throw GraalInternalError.shouldNotReachHere(); + } + } + + @Override + public Stamp foldStamp(Stamp stamp, IntegerStamp shift) { + IntegerStamp value = (IntegerStamp) stamp; + int bits = value.getBits(); + if (shift.lowerBound() == shift.upperBound()) { + long shiftCount = shift.lowerBound() & getShiftAmountMask(stamp); + if (shiftCount == 0) { + return stamp; + } + + long downMask = value.downMask() >>> shiftCount; + long upMask = value.upMask() >>> shiftCount; + if (value.lowerBound() < 0) { + return new IntegerStamp(bits, downMask, upMask, downMask, upMask); + } else { + return new IntegerStamp(bits, value.lowerBound() >>> shiftCount, value.upperBound() >>> shiftCount, downMask, upMask); + } + } + long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); + return IntegerStamp.stampForMask(bits, 0, mask); + } + + @Override + public int getShiftAmountMask(Stamp s) { + IntegerStamp stamp = (IntegerStamp) s; + assert CodeUtil.isPowerOf2(stamp.getBits()); + return stamp.getBits() - 1; + } + }, + new UnaryOp.Abs() { @Override diff -r ae827362559d -r 1b7dbb81df4f 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 Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.nodes.test/src/com/oracle/graal/nodes/test/IntegerStampTest.java Mon Jan 12 13:32:43 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 @@ -28,9 +28,9 @@ import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.ArithmeticOpTable.IntegerConvertOp; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; -import com.oracle.graal.nodes.type.*; /** * This class tests that integer stamps are created correctly for constants. @@ -311,13 +311,14 @@ @Test public void testShiftLeft() { - assertEquals(new IntegerStamp(32, 0, 0x1ff, 0, 0x1ff), StampTool.leftShift(new IntegerStamp(32, 0, 0xff, 0, 0xff), new IntegerStamp(32, 0, 1, 0, 1))); - assertEquals(new IntegerStamp(32, 0, 0x1fe0, 0, 0x1fe0), StampTool.leftShift(new IntegerStamp(32, 0, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5))); - assertEquals(new IntegerStamp(32, 0x1e0, 0x1fe0, 0, 0x1fe0), StampTool.leftShift(new IntegerStamp(32, 0xf, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5))); + ShiftOp shl = IntegerStamp.OPS.getShl(); + assertEquals(new IntegerStamp(32, 0, 0x1ff, 0, 0x1ff), shl.foldStamp(new IntegerStamp(32, 0, 0xff, 0, 0xff), new IntegerStamp(32, 0, 1, 0, 1))); + assertEquals(new IntegerStamp(32, 0, 0x1fe0, 0, 0x1fe0), shl.foldStamp(new IntegerStamp(32, 0, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5))); + assertEquals(new IntegerStamp(32, 0x1e0, 0x1fe0, 0, 0x1fe0), shl.foldStamp(new IntegerStamp(32, 0xf, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5))); - assertEquals(new IntegerStamp(64, 0, 0x1ff, 0, 0x1ff), StampTool.leftShift(new IntegerStamp(64, 0, 0xff, 0, 0xff), new IntegerStamp(32, 0, 1, 0, 1))); - assertEquals(new IntegerStamp(64, 0, 0x1fe0, 0, 0x1fe0), StampTool.leftShift(new IntegerStamp(64, 0, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5))); - assertEquals(new IntegerStamp(64, 0x1e0, 0x1fe0, 0, 0x1fe0), StampTool.leftShift(new IntegerStamp(64, 0xf, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5))); + assertEquals(new IntegerStamp(64, 0, 0x1ff, 0, 0x1ff), shl.foldStamp(new IntegerStamp(64, 0, 0xff, 0, 0xff), new IntegerStamp(32, 0, 1, 0, 1))); + assertEquals(new IntegerStamp(64, 0, 0x1fe0, 0, 0x1fe0), shl.foldStamp(new IntegerStamp(64, 0, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5))); + assertEquals(new IntegerStamp(64, 0x1e0, 0x1fe0, 0, 0x1fe0), shl.foldStamp(new IntegerStamp(64, 0xf, 0xff, 0, 0xff), new IntegerStamp(32, 5, 5, 5, 5))); } } diff -r ae827362559d -r 1b7dbb81df4f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/IntegerEqualsNode.java Mon Jan 12 13:32:43 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -102,7 +102,7 @@ if (nonConstant instanceof AndNode) { AndNode andNode = (AndNode) nonConstant; return IntegerTestNode.create(andNode.getX(), andNode.getY()); - } else if (nonConstant instanceof ShiftNode) { + } else if (nonConstant instanceof ShiftNode && nonConstant.stamp() instanceof IntegerStamp) { if (nonConstant instanceof LeftShiftNode) { LeftShiftNode shift = (LeftShiftNode) nonConstant; if (shift.getY().isConstant()) { diff -r ae827362559d -r 1b7dbb81df4f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/LeftShiftNode.java Mon Jan 12 13:32:43 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -23,43 +23,33 @@ 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.ShiftOp.Shl; 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 LeftShiftNode extends ShiftNode { +public class LeftShiftNode extends ShiftNode { public static LeftShiftNode create(ValueNode x, ValueNode y) { return new LeftShiftNode(x, y); } protected LeftShiftNode(ValueNode x, ValueNode y) { - super(x, y); - } - - @Override - public boolean inferStamp() { - return updateStamp(StampTool.leftShift(getX().stamp(), getY().stamp())); - } - - private static JavaConstant evalConst(JavaConstant a, JavaConstant b) { - if (a.getKind() == Kind.Int) { - return JavaConstant.forInt(a.asInt() << b.asInt()); - } else { - assert a.getKind() == Kind.Long; - return JavaConstant.forLong(a.asLong() << b.asLong()); - } + super(ArithmeticOpTable::getShl, x, y); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - if (forX.isConstant() && forY.isConstant()) { - return ConstantNode.forPrimitive(evalConst(forX.asJavaConstant(), forY.asJavaConstant())); - } else if (forY.isConstant()) { + ValueNode ret = super.canonical(tool, forX, forY); + if (ret != this) { + return ret; + } + + if (forY.isConstant()) { int amount = forY.asJavaConstant().asInt(); int originalAmout = amount; int mask = getShiftAmountMask(); @@ -68,7 +58,7 @@ return forX; } if (forX instanceof ShiftNode) { - ShiftNode other = (ShiftNode) forX; + ShiftNode other = (ShiftNode) forX; if (other.getY().isConstant()) { int otherAmount = other.getY().asJavaConstant().asInt() & mask; if (other instanceof LeftShiftNode) { diff -r ae827362559d -r 1b7dbb81df4f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/RightShiftNode.java Mon Jan 12 13:32:43 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -22,48 +22,37 @@ */ 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.ShiftOp.Shr; 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 RightShiftNode extends ShiftNode { +public class RightShiftNode extends ShiftNode { public static RightShiftNode create(ValueNode x, ValueNode y) { return new RightShiftNode(x, y); } protected RightShiftNode(ValueNode x, ValueNode y) { - super(x, y); - } - - @Override - public boolean inferStamp() { - return updateStamp(StampTool.rightShift(getX().stamp(), getY().stamp())); - } - - private static JavaConstant evalConst(JavaConstant a, JavaConstant b) { - if (a.getKind() == Kind.Int) { - return JavaConstant.forInt(a.asInt() >> b.asInt()); - } else { - assert a.getKind() == Kind.Long; - return JavaConstant.forLong(a.asLong() >> b.asLong()); - } + super(ArithmeticOpTable::getShr, 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.stamp() instanceof IntegerStamp && ((IntegerStamp) forX.stamp()).isPositive()) { return UnsignedRightShiftNode.create(forX, forY); } - if (forX.isConstant() && forY.isConstant()) { - return ConstantNode.forPrimitive(evalConst(forX.asJavaConstant(), forY.asJavaConstant())); - } else if (forY.isConstant()) { + + if (forY.isConstant()) { int amount = forY.asJavaConstant().asInt(); int originalAmout = amount; int mask = getShiftAmountMask(); @@ -72,7 +61,7 @@ return forX; } if (forX instanceof ShiftNode) { - ShiftNode other = (ShiftNode) forX; + ShiftNode other = (ShiftNode) forX; if (other.getY().isConstant()) { int otherAmount = other.getY().asJavaConstant().asInt() & mask; if (other instanceof RightShiftNode) { diff -r ae827362559d -r 1b7dbb81df4f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/ShiftNode.java Mon Jan 12 13:32:43 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2015, 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 @@ -22,7 +22,13 @@ */ package com.oracle.graal.nodes.calc; +import java.io.*; +import java.util.function.*; + import com.oracle.graal.api.meta.*; +import com.oracle.graal.compiler.common.type.*; +import com.oracle.graal.compiler.common.type.ArithmeticOpTable.ShiftOp; +import com.oracle.graal.graph.spi.*; import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; @@ -31,7 +37,12 @@ * The {@code ShiftOp} class represents shift operations. */ @NodeInfo -public abstract class ShiftNode extends BinaryNode implements ArithmeticLIRLowerable { +public abstract class ShiftNode extends BinaryNode implements ArithmeticLIRLowerable { + + protected interface SerializableShiftFunction extends Function>, Serializable { + } + + protected final SerializableShiftFunction getOp; /** * Creates a new shift operation. @@ -39,19 +50,33 @@ * @param x the first input value * @param s the second input value */ - public ShiftNode(ValueNode x, ValueNode s) { - super(x.stamp().unrestricted(), x, s); - assert s.getKind() == Kind.Int; + public ShiftNode(SerializableShiftFunction getOp, ValueNode x, ValueNode s) { + super(getOp.apply(ArithmeticOpTable.forStamp(x.stamp())).foldStamp(x.stamp(), (IntegerStamp) s.stamp()), x, s); + assert ((IntegerStamp) s.stamp()).getBits() == 32; + this.getOp = getOp; + } + + protected final ShiftOp getOp(ValueNode forValue) { + return getOp.apply(ArithmeticOpTable.forStamp(forValue.stamp())); + } + + @Override + public boolean inferStamp() { + return updateStamp(getOp(getX()).foldStamp(getX().stamp(), (IntegerStamp) getY().stamp())); + } + + @Override + public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { + if (forX.isConstant() && forY.isConstant()) { + JavaConstant amount = forY.asJavaConstant(); + assert amount.getKind() == Kind.Int; + return ConstantNode.forPrimitive(stamp(), getOp(forX).foldConstant(forX.asConstant(), amount.asInt())); + } + return this; } public int getShiftAmountMask() { - int mask; - if (getKind() == Kind.Int) { - mask = 0x1f; - } else { - assert getKind() == Kind.Long; - mask = 0x3f; - } - return mask; + return getOp(getX()).getShiftAmountMask(stamp()); } + } diff -r ae827362559d -r 1b7dbb81df4f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/calc/UnsignedRightShiftNode.java Mon Jan 12 13:32:43 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -23,43 +23,33 @@ 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.ShiftOp.UShr; 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 UnsignedRightShiftNode extends ShiftNode { +public class UnsignedRightShiftNode extends ShiftNode { public static UnsignedRightShiftNode create(ValueNode x, ValueNode y) { return new UnsignedRightShiftNode(x, y); } protected UnsignedRightShiftNode(ValueNode x, ValueNode y) { - super(x, y); - } - - @Override - public boolean inferStamp() { - return updateStamp(StampTool.unsignedRightShift(getX().stamp(), getY().stamp())); - } - - private static JavaConstant evalConst(JavaConstant a, JavaConstant b) { - if (a.getKind() == Kind.Int) { - return JavaConstant.forInt(a.asInt() >>> b.asInt()); - } else { - assert a.getKind() == Kind.Long; - return JavaConstant.forLong(a.asLong() >>> b.asLong()); - } + super(ArithmeticOpTable::getUShr, x, y); } @Override public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { - if (forX.isConstant() && forY.isConstant()) { - return ConstantNode.forPrimitive(evalConst(forX.asJavaConstant(), forY.asJavaConstant())); - } else if (forY.isConstant()) { + ValueNode ret = super.canonical(tool, forX, forY); + if (ret != this) { + return ret; + } + + if (forY.isConstant()) { int amount = forY.asJavaConstant().asInt(); int originalAmout = amount; int mask = getShiftAmountMask(); @@ -68,7 +58,7 @@ return forX; } if (forX instanceof ShiftNode) { - ShiftNode other = (ShiftNode) forX; + ShiftNode other = (ShiftNode) forX; if (other.getY().isConstant()) { int otherAmount = other.getY().asJavaConstant().asInt() & mask; if (other instanceof UnsignedRightShiftNode) { diff -r ae827362559d -r 1b7dbb81df4f graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java --- a/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/extended/IndexedLocationNode.java Mon Jan 12 13:32:43 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -31,7 +31,6 @@ import com.oracle.graal.nodeinfo.*; import com.oracle.graal.nodes.*; import com.oracle.graal.nodes.spi.*; -import com.oracle.graal.nodes.type.*; /** * Location node that has a displacement and a scaled index. Can represent locations in the form of @@ -100,7 +99,7 @@ assert indexScaling > 0 && CodeUtil.isPowerOf2(indexScaling); int scale = CodeUtil.log2(indexScaling); return (IntegerStamp) IntegerStamp.OPS.getAdd().foldStamp(StampFactory.forInteger(64, displacement, displacement), - IntegerStamp.OPS.getSignExtend().foldStamp(32, 64, StampTool.leftShift(index.stamp(), StampFactory.forInteger(64, scale, scale)))); + IntegerStamp.OPS.getSignExtend().foldStamp(32, 64, IntegerStamp.OPS.getShl().foldStamp(index.stamp(), StampFactory.forInteger(64, scale, scale)))); } @Override diff -r ae827362559d -r 1b7dbb81df4f 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 Mon Jan 12 12:04:22 2015 +0100 +++ b/graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java Mon Jan 12 13:32:43 2015 +0100 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 @@ -24,7 +24,6 @@ import java.util.*; -import com.oracle.graal.api.code.*; import com.oracle.graal.api.meta.*; import com.oracle.graal.compiler.common.type.*; import com.oracle.graal.nodes.*; @@ -47,95 +46,6 @@ } } - public static Stamp rightShift(Stamp value, Stamp shift) { - if (value instanceof IntegerStamp && shift instanceof IntegerStamp) { - return rightShift((IntegerStamp) value, (IntegerStamp) shift); - } - return value.illegal(); - } - - public static Stamp rightShift(IntegerStamp value, IntegerStamp shift) { - int bits = value.getBits(); - if (shift.lowerBound() == shift.upperBound()) { - int extraBits = 64 - bits; - long shiftMask = bits > 32 ? 0x3FL : 0x1FL; - long shiftCount = shift.lowerBound() & shiftMask; - long defaultMask = CodeUtil.mask(bits); - // shifting back and forth performs sign extension - long downMask = (value.downMask() << extraBits) >> (shiftCount + extraBits) & defaultMask; - long upMask = (value.upMask() << extraBits) >> (shiftCount + extraBits) & defaultMask; - return new IntegerStamp(bits, value.lowerBound() >> shiftCount, value.upperBound() >> shiftCount, downMask, upMask); - } - long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); - return IntegerStamp.stampForMask(bits, 0, mask); - } - - public static Stamp unsignedRightShift(Stamp value, Stamp shift) { - if (value instanceof IntegerStamp && shift instanceof IntegerStamp) { - return unsignedRightShift((IntegerStamp) value, (IntegerStamp) shift); - } - return value.illegal(); - } - - public static Stamp unsignedRightShift(IntegerStamp value, IntegerStamp shift) { - int bits = value.getBits(); - if (shift.lowerBound() == shift.upperBound()) { - long shiftMask = bits > 32 ? 0x3FL : 0x1FL; - long shiftCount = shift.lowerBound() & shiftMask; - long downMask = value.downMask() >>> shiftCount; - long upMask = value.upMask() >>> shiftCount; - if (value.lowerBound() < 0) { - return new IntegerStamp(bits, downMask, upMask, downMask, upMask); - } else { - return new IntegerStamp(bits, value.lowerBound() >>> shiftCount, value.upperBound() >>> shiftCount, downMask, upMask); - } - } - long mask = IntegerStamp.upMaskFor(bits, value.lowerBound(), value.upperBound()); - return IntegerStamp.stampForMask(bits, 0, mask); - } - - public static Stamp leftShift(Stamp value, Stamp shift) { - if (value instanceof IntegerStamp && shift instanceof IntegerStamp) { - return leftShift((IntegerStamp) value, (IntegerStamp) shift); - } - return value.illegal(); - } - - public static Stamp leftShift(IntegerStamp value, IntegerStamp shift) { - int bits = value.getBits(); - long defaultMask = CodeUtil.mask(bits); - if (value.upMask() == 0) { - return value; - } - int shiftBits = bits > 32 ? 6 : 5; - long shiftMask = bits > 32 ? 0x3FL : 0x1FL; - if (shift.lowerBound() == shift.upperBound()) { - int shiftAmount = (int) (shift.lowerBound() & shiftMask); - if (shiftAmount == 0) { - return value; - } - // the mask of bits that will be lost or shifted into the sign bit - long removedBits = -1L << (bits - shiftAmount - 1); - if ((value.lowerBound() & removedBits) == 0 && (value.upperBound() & removedBits) == 0) { - // use a better stamp if neither lower nor upper bound can lose bits - return new IntegerStamp(bits, value.lowerBound() << shiftAmount, value.upperBound() << shiftAmount, value.downMask() << shiftAmount, value.upMask() << shiftAmount); - } - } - if ((shift.lowerBound() >>> shiftBits) == (shift.upperBound() >>> shiftBits)) { - long downMask = defaultMask; - long upMask = 0; - for (long i = shift.lowerBound(); i <= shift.upperBound(); i++) { - if (shift.contains(i)) { - downMask &= value.downMask() << (i & shiftMask); - upMask |= value.upMask() << (i & shiftMask); - } - } - Stamp result = IntegerStamp.stampForMask(bits, downMask, upMask & defaultMask); - return result; - } - return value.unrestricted(); - } - /** * Compute the stamp resulting from the unsigned comparison being true. *