26 |
26 |
27 import org.graalvm.compiler.core.common.type.ArithmeticOpTable; |
27 import org.graalvm.compiler.core.common.type.ArithmeticOpTable; |
28 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; |
28 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp; |
29 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And; |
29 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.And; |
30 import org.graalvm.compiler.core.common.type.IntegerStamp; |
30 import org.graalvm.compiler.core.common.type.IntegerStamp; |
31 import org.graalvm.compiler.core.common.type.PrimitiveStamp; |
|
32 import org.graalvm.compiler.core.common.type.Stamp; |
31 import org.graalvm.compiler.core.common.type.Stamp; |
33 import org.graalvm.compiler.graph.NodeClass; |
32 import org.graalvm.compiler.graph.NodeClass; |
34 import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative; |
33 import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative; |
35 import org.graalvm.compiler.graph.spi.CanonicalizerTool; |
34 import org.graalvm.compiler.graph.spi.CanonicalizerTool; |
36 import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; |
35 import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; |
39 import org.graalvm.compiler.nodes.NodeView; |
38 import org.graalvm.compiler.nodes.NodeView; |
40 import org.graalvm.compiler.nodes.ValueNode; |
39 import org.graalvm.compiler.nodes.ValueNode; |
41 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; |
40 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; |
42 import org.graalvm.compiler.nodes.util.GraphUtil; |
41 import org.graalvm.compiler.nodes.util.GraphUtil; |
43 |
42 |
44 import jdk.vm.ci.code.CodeUtil; |
|
45 import jdk.vm.ci.meta.Constant; |
43 import jdk.vm.ci.meta.Constant; |
46 import jdk.vm.ci.meta.PrimitiveConstant; |
44 import jdk.vm.ci.meta.PrimitiveConstant; |
47 |
45 |
48 @NodeInfo(shortName = "&") |
46 @NodeInfo(shortName = "&") |
49 public final class AndNode extends BinaryArithmeticNode<And> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> { |
47 public final class AndNode extends BinaryArithmeticNode<And> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> { |
59 Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); |
57 Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); |
60 ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); |
58 ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); |
61 if (tryConstantFold != null) { |
59 if (tryConstantFold != null) { |
62 return tryConstantFold; |
60 return tryConstantFold; |
63 } |
61 } |
64 return canonical(null, op, stamp, x, y, view); |
62 return canonical(null, op, x, y, view); |
65 } |
63 } |
66 |
64 |
67 @Override |
65 @Override |
68 protected BinaryOp<And> getOp(ArithmeticOpTable table) { |
66 protected BinaryOp<And> getOp(ArithmeticOpTable table) { |
69 return table.getAnd(); |
67 return table.getAnd(); |
75 if (ret != this) { |
73 if (ret != this) { |
76 return ret; |
74 return ret; |
77 } |
75 } |
78 |
76 |
79 NodeView view = NodeView.from(tool); |
77 NodeView view = NodeView.from(tool); |
80 return canonical(this, getOp(forX, forY), stamp(view), forX, forY, view); |
78 return canonical(this, getOp(forX, forY), forX, forY, view); |
81 } |
79 } |
82 |
80 |
83 private static ValueNode canonical(AndNode self, BinaryOp<And> op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { |
81 private static ValueNode canonical(AndNode self, BinaryOp<And> op, ValueNode forX, ValueNode forY, NodeView view) { |
84 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { |
82 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { |
85 return forX; |
83 return forX; |
86 } |
84 } |
87 if (forX.isConstant() && !forY.isConstant()) { |
85 if (forX.isConstant() && !forY.isConstant()) { |
88 return new AndNode(forY, forX); |
86 return new AndNode(forY, forX); |
89 } |
87 } |
|
88 |
|
89 Stamp rawXStamp = forX.stamp(view); |
|
90 Stamp rawYStamp = forY.stamp(view); |
|
91 if (rawXStamp instanceof IntegerStamp && rawYStamp instanceof IntegerStamp) { |
|
92 IntegerStamp xStamp = (IntegerStamp) rawXStamp; |
|
93 IntegerStamp yStamp = (IntegerStamp) rawYStamp; |
|
94 if (((~xStamp.downMask()) & yStamp.upMask()) == 0) { |
|
95 return forY; |
|
96 } else if (((~yStamp.downMask()) & xStamp.upMask()) == 0) { |
|
97 return forX; |
|
98 } |
|
99 } |
|
100 |
90 if (forY.isConstant()) { |
101 if (forY.isConstant()) { |
91 Constant c = forY.asConstant(); |
102 Constant c = forY.asConstant(); |
92 if (op.isNeutral(c)) { |
103 if (op.isNeutral(c)) { |
93 return forX; |
104 return forX; |
94 } |
105 } |
95 |
106 |
96 if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { |
107 if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { |
97 long rawY = ((PrimitiveConstant) c).asLong(); |
108 long rawY = ((PrimitiveConstant) c).asLong(); |
98 long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp)); |
|
99 if ((rawY & mask) == 0) { |
|
100 return ConstantNode.forIntegerStamp(stamp, 0); |
|
101 } |
|
102 if (forX instanceof SignExtendNode) { |
109 if (forX instanceof SignExtendNode) { |
103 SignExtendNode ext = (SignExtendNode) forX; |
110 SignExtendNode ext = (SignExtendNode) forX; |
104 if (rawY == ((1L << ext.getInputBits()) - 1)) { |
111 if (rawY == ((1L << ext.getInputBits()) - 1)) { |
105 return new ZeroExtendNode(ext.getValue(), ext.getResultBits()); |
112 return new ZeroExtendNode(ext.getValue(), ext.getResultBits()); |
106 } |
113 } |
107 } |
|
108 IntegerStamp xStamp = (IntegerStamp) forX.stamp(view); |
|
109 if (((xStamp.upMask() | xStamp.downMask()) & ~rawY) == 0) { |
|
110 // No bits are set which are outside the mask, so the mask will have no effect. |
|
111 return forX; |
|
112 } |
114 } |
113 } |
115 } |
114 |
116 |
115 return reassociate(self != null ? self : (AndNode) new AndNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); |
117 return reassociate(self != null ? self : (AndNode) new AndNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); |
116 } |
118 } |