25 package org.graalvm.compiler.nodes.calc; |
25 package org.graalvm.compiler.nodes.calc; |
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.Or; |
29 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Or; |
30 import org.graalvm.compiler.core.common.type.PrimitiveStamp; |
30 import org.graalvm.compiler.core.common.type.IntegerStamp; |
31 import org.graalvm.compiler.core.common.type.Stamp; |
31 import org.graalvm.compiler.core.common.type.Stamp; |
32 import org.graalvm.compiler.graph.NodeClass; |
32 import org.graalvm.compiler.graph.NodeClass; |
33 import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative; |
33 import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative; |
34 import org.graalvm.compiler.graph.spi.CanonicalizerTool; |
34 import org.graalvm.compiler.graph.spi.CanonicalizerTool; |
35 import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; |
35 import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool; |
38 import org.graalvm.compiler.nodes.NodeView; |
38 import org.graalvm.compiler.nodes.NodeView; |
39 import org.graalvm.compiler.nodes.ValueNode; |
39 import org.graalvm.compiler.nodes.ValueNode; |
40 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; |
40 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool; |
41 import org.graalvm.compiler.nodes.util.GraphUtil; |
41 import org.graalvm.compiler.nodes.util.GraphUtil; |
42 |
42 |
43 import jdk.vm.ci.code.CodeUtil; |
|
44 import jdk.vm.ci.meta.Constant; |
43 import jdk.vm.ci.meta.Constant; |
45 import jdk.vm.ci.meta.PrimitiveConstant; |
|
46 |
44 |
47 @NodeInfo(shortName = "|") |
45 @NodeInfo(shortName = "|") |
48 public final class OrNode extends BinaryArithmeticNode<Or> implements BinaryCommutative<ValueNode>, NarrowableArithmeticNode { |
46 public final class OrNode extends BinaryArithmeticNode<Or> implements BinaryCommutative<ValueNode>, NarrowableArithmeticNode { |
49 |
47 |
50 public static final NodeClass<OrNode> TYPE = NodeClass.create(OrNode.class); |
48 public static final NodeClass<OrNode> TYPE = NodeClass.create(OrNode.class); |
51 |
49 |
52 public OrNode(ValueNode x, ValueNode y) { |
50 public OrNode(ValueNode x, ValueNode y) { |
53 super(TYPE, getArithmeticOpTable(x).getOr(), x, y); |
51 super(TYPE, getArithmeticOpTable(x).getOr(), x, y); |
54 } |
52 } |
55 |
53 |
|
54 private OrNode(ValueNode x, ValueNode y, Stamp forcedStamp) { |
|
55 super(TYPE, forcedStamp, x, y); |
|
56 } |
|
57 |
|
58 /** |
|
59 * Create a new XorNode with a forced stamp, without eager folding. This should only be used in |
|
60 * snippet code, where native-image may assign wrong stamps during graph generation. |
|
61 */ |
|
62 public static ValueNode createForSnippet(ValueNode x, ValueNode y, Stamp forcedStamp) { |
|
63 return new OrNode(x, y, forcedStamp); |
|
64 } |
|
65 |
56 public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { |
66 public static ValueNode create(ValueNode x, ValueNode y, NodeView view) { |
57 BinaryOp<Or> op = ArithmeticOpTable.forStamp(x.stamp(view)).getOr(); |
67 BinaryOp<Or> op = ArithmeticOpTable.forStamp(x.stamp(view)).getOr(); |
58 Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); |
68 Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view)); |
59 ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); |
69 ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view); |
60 if (tryConstantFold != null) { |
70 if (tryConstantFold != null) { |
61 return tryConstantFold; |
71 return tryConstantFold; |
62 } |
72 } |
63 return canonical(null, op, stamp, x, y, view); |
73 return canonical(null, op, x, y, view); |
64 } |
74 } |
65 |
75 |
66 @Override |
76 @Override |
67 protected BinaryOp<Or> getOp(ArithmeticOpTable table) { |
77 protected BinaryOp<Or> getOp(ArithmeticOpTable table) { |
68 return table.getOr(); |
78 return table.getOr(); |
74 ValueNode ret = super.canonical(tool, forX, forY); |
84 ValueNode ret = super.canonical(tool, forX, forY); |
75 if (ret != this) { |
85 if (ret != this) { |
76 return ret; |
86 return ret; |
77 } |
87 } |
78 |
88 |
79 return canonical(this, getOp(forX, forY), stamp(view), forX, forY, view); |
89 return canonical(this, getOp(forX, forY), forX, forY, view); |
80 } |
90 } |
81 |
91 |
82 private static ValueNode canonical(OrNode self, BinaryOp<Or> op, Stamp stamp, ValueNode forX, ValueNode forY, NodeView view) { |
92 private static ValueNode canonical(OrNode self, BinaryOp<Or> op, ValueNode forX, ValueNode forY, NodeView view) { |
83 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { |
93 if (GraphUtil.unproxify(forX) == GraphUtil.unproxify(forY)) { |
84 return forX; |
94 return forX; |
85 } |
95 } |
86 if (forX.isConstant() && !forY.isConstant()) { |
96 if (forX.isConstant() && !forY.isConstant()) { |
87 return new OrNode(forY, forX); |
97 return new OrNode(forY, forX); |
88 } |
98 } |
|
99 |
|
100 Stamp rawXStamp = forX.stamp(view); |
|
101 Stamp rawYStamp = forY.stamp(view); |
|
102 if (rawXStamp instanceof IntegerStamp && rawYStamp instanceof IntegerStamp) { |
|
103 IntegerStamp xStamp = (IntegerStamp) rawXStamp; |
|
104 IntegerStamp yStamp = (IntegerStamp) rawYStamp; |
|
105 if (((~xStamp.downMask()) & yStamp.upMask()) == 0) { |
|
106 return forX; |
|
107 } else if (((~yStamp.downMask()) & xStamp.upMask()) == 0) { |
|
108 return forY; |
|
109 } |
|
110 } |
|
111 |
89 if (forY.isConstant()) { |
112 if (forY.isConstant()) { |
90 Constant c = forY.asConstant(); |
113 Constant c = forY.asConstant(); |
91 if (op.isNeutral(c)) { |
114 if (op.isNeutral(c)) { |
92 return forX; |
115 return forX; |
93 } |
116 } |
94 |
117 |
95 if (c instanceof PrimitiveConstant && ((PrimitiveConstant) c).getJavaKind().isNumericInteger()) { |
|
96 long rawY = ((PrimitiveConstant) c).asLong(); |
|
97 long mask = CodeUtil.mask(PrimitiveStamp.getBits(stamp)); |
|
98 if ((rawY & mask) == mask) { |
|
99 return ConstantNode.forIntegerStamp(stamp, mask); |
|
100 } |
|
101 } |
|
102 return reassociate(self != null ? self : (OrNode) new OrNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); |
118 return reassociate(self != null ? self : (OrNode) new OrNode(forX, forY).maybeCommuteInputs(), ValueNode.isConstantPredicate(), forX, forY, view); |
103 } |
119 } |
|
120 |
104 if (forX instanceof NotNode && forY instanceof NotNode) { |
121 if (forX instanceof NotNode && forY instanceof NotNode) { |
105 return new NotNode(AndNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue(), view)); |
122 return new NotNode(AndNode.create(((NotNode) forX).getValue(), ((NotNode) forY).getValue(), view)); |
106 } |
123 } |
|
124 |
107 return self != null ? self : new OrNode(forX, forY).maybeCommuteInputs(); |
125 return self != null ? self : new OrNode(forX, forY).maybeCommuteInputs(); |
108 } |
126 } |
109 |
127 |
110 @Override |
128 @Override |
111 public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) { |
129 public void generate(NodeLIRBuilderTool nodeValueMap, ArithmeticLIRGeneratorTool gen) { |