73 assert table.equals(ArithmeticOpTable.forStamp(forY.stamp(NodeView.DEFAULT))); 74 return getOp.apply(table); 75 } 76 77 @Override 78 public final BinaryOp<OP> getArithmeticOp() { 79 return getOp(getX(), getY()); 80 } 81 82 public boolean isAssociative() { 83 return getArithmeticOp().isAssociative(); 84 } 85 86 @Override 87 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { 88 NodeView view = NodeView.from(tool); 89 ValueNode result = tryConstantFold(getOp(forX, forY), forX, forY, stamp(view), view); 90 if (result != null) { 91 return result; 92 } 93 return this; 94 } 95 96 @SuppressWarnings("unused") 97 public static <OP> ConstantNode tryConstantFold(BinaryOp<OP> op, ValueNode forX, ValueNode forY, Stamp stamp, NodeView view) { 98 if (forX.isConstant() && forY.isConstant()) { 99 Constant ret = op.foldConstant(forX.asConstant(), forY.asConstant()); 100 if (ret != null) { 101 return ConstantNode.forPrimitive(stamp, ret); 102 } 103 } 104 return null; 105 } 106 107 @Override 108 public Stamp foldStamp(Stamp stampX, Stamp stampY) { 109 assert stampX.isCompatible(x.stamp(NodeView.DEFAULT)) && stampY.isCompatible(y.stamp(NodeView.DEFAULT)); 110 return getArithmeticOp().foldStamp(stampX, stampY); 111 } 112 113 public static ValueNode add(StructuredGraph graph, ValueNode v1, ValueNode v2, NodeView view) { 114 return graph.addOrUniqueWithInputs(AddNode.create(v1, v2, view)); 115 } 116 117 public static ValueNode add(ValueNode v1, ValueNode v2, NodeView view) { 118 return AddNode.create(v1, v2, view); 119 } 120 121 public static ValueNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2, NodeView view) { 122 return graph.addOrUniqueWithInputs(MulNode.create(v1, v2, view)); 123 } 124 125 public static ValueNode mul(ValueNode v1, ValueNode v2, NodeView view) { 126 return MulNode.create(v1, v2, view); 127 } 128 129 public static ValueNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2, NodeView view) { 130 return graph.addOrUniqueWithInputs(SubNode.create(v1, v2, view)); 131 } 132 133 public static ValueNode sub(ValueNode v1, ValueNode v2, NodeView view) { 134 return SubNode.create(v1, v2, view); 135 } 136 137 public static ValueNode branchlessMin(ValueNode v1, ValueNode v2, NodeView view) { 138 if (v1.isDefaultConstant() && !v2.isDefaultConstant()) { 139 return branchlessMin(v2, v1, view); 140 } 141 int bits = ((IntegerStamp) v1.stamp(view)).getBits(); 142 assert ((IntegerStamp) v2.stamp(view)).getBits() == bits; 143 ValueNode t1 = sub(v1, v2, view); 144 ValueNode t2 = RightShiftNode.create(t1, bits - 1, view); 145 ValueNode t3 = AndNode.create(t1, t2, view); 146 return add(v2, t3, view); 147 } 148 149 public static ValueNode branchlessMax(ValueNode v1, ValueNode v2, NodeView view) { 150 if (v1.isDefaultConstant() && !v2.isDefaultConstant()) { 151 return branchlessMax(v2, v1, view); 152 } 153 int bits = ((IntegerStamp) v1.stamp(view)).getBits(); 154 assert ((IntegerStamp) v2.stamp(view)).getBits() == bits; | 73 assert table.equals(ArithmeticOpTable.forStamp(forY.stamp(NodeView.DEFAULT))); 74 return getOp.apply(table); 75 } 76 77 @Override 78 public final BinaryOp<OP> getArithmeticOp() { 79 return getOp(getX(), getY()); 80 } 81 82 public boolean isAssociative() { 83 return getArithmeticOp().isAssociative(); 84 } 85 86 @Override 87 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) { 88 NodeView view = NodeView.from(tool); 89 ValueNode result = tryConstantFold(getOp(forX, forY), forX, forY, stamp(view), view); 90 if (result != null) { 91 return result; 92 } 93 if (forX instanceof ConditionalNode && forY.isConstant() && forX.hasExactlyOneUsage()) { 94 ConditionalNode conditionalNode = (ConditionalNode) forX; 95 BinaryOp<OP> arithmeticOp = getArithmeticOp(); 96 ConstantNode trueConstant = tryConstantFold(arithmeticOp, conditionalNode.trueValue(), forY, this.stamp(view), view); 97 if (trueConstant != null) { 98 ConstantNode falseConstant = tryConstantFold(arithmeticOp, conditionalNode.falseValue(), forY, this.stamp(view), view); 99 if (falseConstant != null) { 100 // @formatter:off 101 /* The arithmetic is folded into a constant on both sides of the conditional. 102 * Example: 103 * (cond ? -5 : 5) + 100 104 * canonicalizes to: 105 * (cond ? 95 : 105) 106 */ 107 // @formatter:on 108 return ConditionalNode.create(conditionalNode.condition, trueConstant, 109 falseConstant, view); 110 } 111 } 112 } 113 return this; 114 } 115 116 @SuppressWarnings("unused") 117 public static <OP> ConstantNode tryConstantFold(BinaryOp<OP> op, ValueNode forX, ValueNode forY, Stamp stamp, NodeView view) { 118 if (forX.isConstant() && forY.isConstant()) { 119 Constant ret = op.foldConstant(forX.asConstant(), forY.asConstant()); 120 if (ret != null) { 121 return ConstantNode.forPrimitive(stamp, ret); 122 } 123 } 124 return null; 125 } 126 127 @Override 128 public Stamp foldStamp(Stamp stampX, Stamp stampY) { 129 assert stampX.isCompatible(x.stamp(NodeView.DEFAULT)) && stampY.isCompatible(y.stamp(NodeView.DEFAULT)); 130 return getArithmeticOp().foldStamp(stampX, stampY); 131 } 132 133 public static ValueNode add(StructuredGraph graph, ValueNode v1, ValueNode v2, NodeView view) { 134 return graph.addOrUniqueWithInputs(AddNode.create(v1, v2, view)); 135 } 136 137 public static ValueNode add(ValueNode v1, ValueNode v2, NodeView view) { 138 return AddNode.create(v1, v2, view); 139 } 140 141 public static ValueNode add(ValueNode v1, ValueNode v2) { 142 return add(v1, v2, NodeView.DEFAULT); 143 } 144 145 public static ValueNode mul(StructuredGraph graph, ValueNode v1, ValueNode v2, NodeView view) { 146 return graph.addOrUniqueWithInputs(MulNode.create(v1, v2, view)); 147 } 148 149 public static ValueNode mul(ValueNode v1, ValueNode v2, NodeView view) { 150 return MulNode.create(v1, v2, view); 151 } 152 153 public static ValueNode mul(ValueNode v1, ValueNode v2) { 154 return mul(v1, v2, NodeView.DEFAULT); 155 } 156 157 public static ValueNode sub(StructuredGraph graph, ValueNode v1, ValueNode v2, NodeView view) { 158 return graph.addOrUniqueWithInputs(SubNode.create(v1, v2, view)); 159 } 160 161 public static ValueNode sub(ValueNode v1, ValueNode v2, NodeView view) { 162 return SubNode.create(v1, v2, view); 163 } 164 165 public static ValueNode sub(ValueNode v1, ValueNode v2) { 166 return sub(v1, v2, NodeView.DEFAULT); 167 } 168 169 public static ValueNode branchlessMin(ValueNode v1, ValueNode v2, NodeView view) { 170 if (v1.isDefaultConstant() && !v2.isDefaultConstant()) { 171 return branchlessMin(v2, v1, view); 172 } 173 int bits = ((IntegerStamp) v1.stamp(view)).getBits(); 174 assert ((IntegerStamp) v2.stamp(view)).getBits() == bits; 175 ValueNode t1 = sub(v1, v2, view); 176 ValueNode t2 = RightShiftNode.create(t1, bits - 1, view); 177 ValueNode t3 = AndNode.create(t1, t2, view); 178 return add(v2, t3, view); 179 } 180 181 public static ValueNode branchlessMax(ValueNode v1, ValueNode v2, NodeView view) { 182 if (v1.isDefaultConstant() && !v2.isDefaultConstant()) { 183 return branchlessMax(v2, v1, view); 184 } 185 int bits = ((IntegerStamp) v1.stamp(view)).getBits(); 186 assert ((IntegerStamp) v2.stamp(view)).getBits() == bits; |