1 /*
2 * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
30 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
31 import org.graalvm.compiler.core.common.type.FloatStamp;
32 import org.graalvm.compiler.core.common.type.IntegerStamp;
33 import org.graalvm.compiler.core.common.type.StampFactory;
34 import org.graalvm.compiler.debug.GraalError;
35 import org.graalvm.compiler.graph.Node;
36 import org.graalvm.compiler.graph.NodeClass;
37 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
38 import org.graalvm.compiler.nodeinfo.NodeInfo;
39 import org.graalvm.compiler.nodes.ConstantNode;
40 import org.graalvm.compiler.nodes.LogicConstantNode;
41 import org.graalvm.compiler.nodes.LogicNegationNode;
42 import org.graalvm.compiler.nodes.LogicNode;
43 import org.graalvm.compiler.nodes.NodeView;
44 import org.graalvm.compiler.nodes.ValueNode;
45 import org.graalvm.compiler.options.OptionValues;
46
47 import jdk.vm.ci.code.CodeUtil;
48 import jdk.vm.ci.meta.Constant;
49 import jdk.vm.ci.meta.ConstantReflectionProvider;
50 import jdk.vm.ci.meta.JavaConstant;
51 import jdk.vm.ci.meta.JavaKind;
52 import jdk.vm.ci.meta.MetaAccessProvider;
53 import jdk.vm.ci.meta.PrimitiveConstant;
54
55 @NodeInfo(shortName = "<")
56 public final class IntegerLessThanNode extends IntegerLowerThanNode {
57 public static final NodeClass<IntegerLessThanNode> TYPE = NodeClass.create(IntegerLessThanNode.class);
58 private static final LessThanOp OP = new LessThanOp();
59
60 public IntegerLessThanNode(ValueNode x, ValueNode y) {
61 super(TYPE, x, y, OP);
62 assert !x.getStackKind().isNumericFloat() && x.getStackKind() != JavaKind.Object;
63 assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object;
64 }
65
66 public static LogicNode create(ValueNode x, ValueNode y, NodeView view) {
67 return OP.create(x, y, view);
68 }
69
70 public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
158 return LogicNegationNode.create(compare);
159 } else if (cst <= -1) {
160 return LogicConstantNode.contradiction();
161 } else {
162 assert cst >= 2;
163 return LogicConstantNode.tautology();
164 }
165 }
166
167 @Override
168 protected LogicNode findSynonym(ValueNode forX, ValueNode forY, NodeView view) {
169 LogicNode result = super.findSynonym(forX, forY, view);
170 if (result != null) {
171 return result;
172 }
173 if (forX.stamp(view) instanceof IntegerStamp && forY.stamp(view) instanceof IntegerStamp) {
174 if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(view), (IntegerStamp) forY.stamp(view))) {
175 return new IntegerBelowNode(forX, forY);
176 }
177 }
178 if (forY.isConstant() && forX instanceof SubNode) {
179 SubNode sub = (SubNode) forX;
180 ValueNode xx = null;
181 ValueNode yy = null;
182 boolean negate = false;
183 if (forY.asConstant().isDefaultForKind()) {
184 // (x - y) < 0 when x - y is known not to underflow <=> x < y
185 xx = sub.getX();
186 yy = sub.getY();
187 } else if (forY.isJavaConstant() && forY.asJavaConstant().asLong() == 1) {
188 // (x - y) < 1 when x - y is known not to underflow <=> !(y < x)
189 xx = sub.getY();
190 yy = sub.getX();
191 negate = true;
192 }
193 if (xx != null) {
194 assert yy != null;
195 IntegerStamp xStamp = (IntegerStamp) sub.getX().stamp(view);
196 IntegerStamp yStamp = (IntegerStamp) sub.getY().stamp(view);
197 long minValue = CodeUtil.minValue(xStamp.getBits());
198 long maxValue = CodeUtil.maxValue(xStamp.getBits());
199
200 if (!subtractMayUnderflow(xStamp.lowerBound(), yStamp.upperBound(), minValue) && !subtractMayOverflow(xStamp.upperBound(), yStamp.lowerBound(), maxValue)) {
201 LogicNode logic = new IntegerLessThanNode(xx, yy);
202 if (negate) {
203 logic = LogicNegationNode.create(logic);
204 }
205 return logic;
206 }
207 }
208 }
209
210 if (forX.stamp(view) instanceof IntegerStamp) {
211 assert forY.stamp(view) instanceof IntegerStamp;
212 int bits = ((IntegerStamp) forX.stamp(view)).getBits();
213 assert ((IntegerStamp) forY.stamp(view)).getBits() == bits;
214 long min = OP.minValue(bits);
215 long xResidue = 0;
216 ValueNode left = null;
217 JavaConstant leftCst = null;
218 if (forX instanceof AddNode) {
219 AddNode xAdd = (AddNode) forX;
220 if (xAdd.getY().isJavaConstant()) {
221 long xCst = xAdd.getY().asJavaConstant().asLong();
222 xResidue = xCst - min;
223 left = xAdd.getX();
224 }
225 } else if (forX.isJavaConstant()) {
226 leftCst = forX.asJavaConstant();
227 }
228 if (left != null || leftCst != null) {
229 long yResidue = 0;
230 ValueNode right = null;
231 JavaConstant rightCst = null;
232 if (forY instanceof AddNode) {
233 AddNode yAdd = (AddNode) forY;
234 if (yAdd.getY().isJavaConstant()) {
235 long yCst = yAdd.getY().asJavaConstant().asLong();
236 yResidue = yCst - min;
237 right = yAdd.getX();
238 }
239 } else if (forY.isJavaConstant()) {
240 rightCst = forY.asJavaConstant();
241 }
242 if (right != null || rightCst != null) {
243 if ((xResidue == 0 && left != null) || (yResidue == 0 && right != null)) {
244 if (left == null) {
245 left = ConstantNode.forIntegerBits(bits, leftCst.asLong() - min);
246 } else if (xResidue != 0) {
247 left = AddNode.create(left, ConstantNode.forIntegerBits(bits, xResidue), view);
248 }
249 if (right == null) {
250 right = ConstantNode.forIntegerBits(bits, rightCst.asLong() - min);
251 } else if (yResidue != 0) {
252 right = AddNode.create(right, ConstantNode.forIntegerBits(bits, yResidue), view);
253 }
254 return new IntegerBelowNode(left, right);
255 }
256 }
257 }
258 }
259 return null;
260 }
261
262 @Override
263 protected CanonicalCondition getCondition() {
264 return LT;
265 }
266
267 @Override
268 protected IntegerLowerThanNode createNode(ValueNode x, ValueNode y) {
269 return new IntegerLessThanNode(x, y);
270 }
271
272 @Override
273 protected long upperBound(IntegerStamp stamp) {
274 return stamp.upperBound();
275 }
276
|
1 /*
2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
30 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
31 import org.graalvm.compiler.core.common.type.FloatStamp;
32 import org.graalvm.compiler.core.common.type.IntegerStamp;
33 import org.graalvm.compiler.core.common.type.StampFactory;
34 import org.graalvm.compiler.debug.GraalError;
35 import org.graalvm.compiler.graph.Node;
36 import org.graalvm.compiler.graph.NodeClass;
37 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
38 import org.graalvm.compiler.nodeinfo.NodeInfo;
39 import org.graalvm.compiler.nodes.ConstantNode;
40 import org.graalvm.compiler.nodes.LogicConstantNode;
41 import org.graalvm.compiler.nodes.LogicNegationNode;
42 import org.graalvm.compiler.nodes.LogicNode;
43 import org.graalvm.compiler.nodes.NodeView;
44 import org.graalvm.compiler.nodes.ValueNode;
45 import org.graalvm.compiler.options.OptionValues;
46
47 import jdk.vm.ci.code.CodeUtil;
48 import jdk.vm.ci.meta.Constant;
49 import jdk.vm.ci.meta.ConstantReflectionProvider;
50 import jdk.vm.ci.meta.JavaKind;
51 import jdk.vm.ci.meta.MetaAccessProvider;
52 import jdk.vm.ci.meta.PrimitiveConstant;
53
54 @NodeInfo(shortName = "<")
55 public final class IntegerLessThanNode extends IntegerLowerThanNode {
56 public static final NodeClass<IntegerLessThanNode> TYPE = NodeClass.create(IntegerLessThanNode.class);
57 private static final LessThanOp OP = new LessThanOp();
58
59 public IntegerLessThanNode(ValueNode x, ValueNode y) {
60 super(TYPE, x, y, OP);
61 assert !x.getStackKind().isNumericFloat() && x.getStackKind() != JavaKind.Object;
62 assert !y.getStackKind().isNumericFloat() && y.getStackKind() != JavaKind.Object;
63 }
64
65 public static LogicNode create(ValueNode x, ValueNode y, NodeView view) {
66 return OP.create(x, y, view);
67 }
68
69 public static LogicNode create(ConstantReflectionProvider constantReflection, MetaAccessProvider metaAccess, OptionValues options, Integer smallestCompareWidth,
157 return LogicNegationNode.create(compare);
158 } else if (cst <= -1) {
159 return LogicConstantNode.contradiction();
160 } else {
161 assert cst >= 2;
162 return LogicConstantNode.tautology();
163 }
164 }
165
166 @Override
167 protected LogicNode findSynonym(ValueNode forX, ValueNode forY, NodeView view) {
168 LogicNode result = super.findSynonym(forX, forY, view);
169 if (result != null) {
170 return result;
171 }
172 if (forX.stamp(view) instanceof IntegerStamp && forY.stamp(view) instanceof IntegerStamp) {
173 if (IntegerStamp.sameSign((IntegerStamp) forX.stamp(view), (IntegerStamp) forY.stamp(view))) {
174 return new IntegerBelowNode(forX, forY);
175 }
176 }
177
178 // Attempt to optimize the case where we can fold a constant from the left side (either
179 // from an add or sub) into the constant on the right side.
180 if (forY.isConstant()) {
181 if (forX instanceof SubNode) {
182 SubNode sub = (SubNode) forX;
183 ValueNode xx = null;
184 ValueNode yy = null;
185 boolean negate = false;
186 if (forY.asConstant().isDefaultForKind()) {
187 // (x - y) < 0 when x - y is known not to underflow <=> x < y
188 xx = sub.getX();
189 yy = sub.getY();
190 } else if (forY.isJavaConstant() && forY.asJavaConstant().asLong() == 1) {
191 // (x - y) < 1 when x - y is known not to underflow <=> !(y < x)
192 xx = sub.getY();
193 yy = sub.getX();
194 negate = true;
195 }
196 if (xx != null) {
197 assert yy != null;
198 IntegerStamp xStamp = (IntegerStamp) sub.getX().stamp(view);
199 IntegerStamp yStamp = (IntegerStamp) sub.getY().stamp(view);
200 long minValue = CodeUtil.minValue(xStamp.getBits());
201 long maxValue = CodeUtil.maxValue(xStamp.getBits());
202
203 if (!subtractMayUnderflow(xStamp.lowerBound(), yStamp.upperBound(), minValue) && !subtractMayOverflow(xStamp.upperBound(), yStamp.lowerBound(), maxValue)) {
204 LogicNode logic = new IntegerLessThanNode(xx, yy);
205 if (negate) {
206 logic = LogicNegationNode.create(logic);
207 }
208 return logic;
209 }
210 }
211 } else if (forX instanceof AddNode) {
212
213 // (x + xConstant) < forY => x < (forY - xConstant)
214 AddNode addNode = (AddNode) forX;
215 if (addNode.getY().isJavaConstant()) {
216 IntegerStamp xStamp = (IntegerStamp) addNode.getX().stamp(view);
217 if (!IntegerStamp.addCanOverflow(xStamp, (IntegerStamp) addNode.getY().stamp(view))) {
218 long minValue = CodeUtil.minValue(xStamp.getBits());
219 long maxValue = CodeUtil.maxValue(xStamp.getBits());
220 long yConstant = forY.asJavaConstant().asLong();
221 long xConstant = addNode.getY().asJavaConstant().asLong();
222 if (!subtractMayUnderflow(yConstant, xConstant, minValue) && !subtractMayOverflow(yConstant, xConstant, maxValue)) {
223 long newConstant = yConstant - xConstant;
224 return IntegerLessThanNode.create(addNode.getX(), ConstantNode.forIntegerStamp(xStamp, newConstant), view);
225 }
226 }
227 }
228
229 }
230 }
231
232 if (forX.stamp(view) instanceof IntegerStamp) {
233 assert forY.stamp(view) instanceof IntegerStamp;
234 int bits = ((IntegerStamp) forX.stamp(view)).getBits();
235 assert ((IntegerStamp) forY.stamp(view)).getBits() == bits;
236 LogicNode logic = canonicalizeRangeFlip(forX, forY, bits, true, view);
237 if (logic != null) {
238 return logic;
239 }
240 }
241 return null;
242 }
243
244 @Override
245 protected CanonicalCondition getCondition() {
246 return LT;
247 }
248
249 @Override
250 protected IntegerLowerThanNode createNode(ValueNode x, ValueNode y) {
251 return new IntegerLessThanNode(x, y);
252 }
253
254 @Override
255 protected long upperBound(IntegerStamp stamp) {
256 return stamp.upperBound();
257 }
258
|