1 /*
2 * Copyright (c) 2011, 2015, 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 */
23
24
25 package org.graalvm.compiler.nodes.calc;
26
27 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
28 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
29 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add;
30 import org.graalvm.compiler.core.common.type.Stamp;
31 import org.graalvm.compiler.graph.NodeClass;
32 import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative;
33 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
34 import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
35 import org.graalvm.compiler.nodeinfo.NodeInfo;
36 import org.graalvm.compiler.nodes.ConstantNode;
37 import org.graalvm.compiler.nodes.NodeView;
38 import org.graalvm.compiler.nodes.ValueNode;
39 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
40
41 import jdk.vm.ci.meta.Constant;
42 import jdk.vm.ci.meta.Value;
43
44 @NodeInfo(shortName = "+")
45 public class AddNode extends BinaryArithmeticNode<Add> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> {
46
47 public static final NodeClass<AddNode> TYPE = NodeClass.create(AddNode.class);
48
49 public AddNode(ValueNode x, ValueNode y) {
50 this(TYPE, x, y);
51 }
52
53 protected AddNode(NodeClass<? extends AddNode> c, ValueNode x, ValueNode y) {
54 super(c, ArithmeticOpTable::getAdd, x, y);
55 }
56
57 public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {
58 BinaryOp<Add> op = ArithmeticOpTable.forStamp(x.stamp(view)).getAdd();
59 Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view));
60 ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view);
61 if (tryConstantFold != null) {
80 }
81 }
82 if (forY instanceof SubNode) {
83 SubNode sub = (SubNode) forY;
84 if (sub.getY() == forX) {
85 // b + (a - b)
86 return sub.getX();
87 }
88 }
89 }
90 if (forY.isConstant()) {
91 Constant c = forY.asConstant();
92 if (op.isNeutral(c)) {
93 return forX;
94 }
95 if (associative && self != null) {
96 // canonicalize expressions like "(a + 1) + 2"
97 ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY, view);
98 if (reassociated != self) {
99 return reassociated;
100 }
101 }
102 }
103 if (forX instanceof NegateNode) {
104 return BinaryArithmeticNode.sub(forY, ((NegateNode) forX).getValue(), view);
105 } else if (forY instanceof NegateNode) {
106 return BinaryArithmeticNode.sub(forX, ((NegateNode) forY).getValue(), view);
107 }
108 if (self == null) {
109 self = (AddNode) new AddNode(forX, forY).maybeCommuteInputs();
110 }
111 return self;
112 }
113
114 @Override
115 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
116 ValueNode ret = super.canonical(tool, forX, forY);
117 if (ret != this) {
118 return ret;
119 }
|
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 */
23
24
25 package org.graalvm.compiler.nodes.calc;
26
27 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
28 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp;
29 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.BinaryOp.Add;
30 import org.graalvm.compiler.core.common.type.IntegerStamp;
31 import org.graalvm.compiler.core.common.type.Stamp;
32 import org.graalvm.compiler.graph.NodeClass;
33 import org.graalvm.compiler.graph.spi.Canonicalizable.BinaryCommutative;
34 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
35 import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
36 import org.graalvm.compiler.nodeinfo.NodeInfo;
37 import org.graalvm.compiler.nodes.ConstantNode;
38 import org.graalvm.compiler.nodes.NodeView;
39 import org.graalvm.compiler.nodes.ValueNode;
40 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
41
42 import jdk.vm.ci.code.CodeUtil;
43 import jdk.vm.ci.meta.Constant;
44 import jdk.vm.ci.meta.JavaConstant;
45 import jdk.vm.ci.meta.Value;
46
47 @NodeInfo(shortName = "+")
48 public class AddNode extends BinaryArithmeticNode<Add> implements NarrowableArithmeticNode, BinaryCommutative<ValueNode> {
49
50 public static final NodeClass<AddNode> TYPE = NodeClass.create(AddNode.class);
51
52 public AddNode(ValueNode x, ValueNode y) {
53 this(TYPE, x, y);
54 }
55
56 protected AddNode(NodeClass<? extends AddNode> c, ValueNode x, ValueNode y) {
57 super(c, ArithmeticOpTable::getAdd, x, y);
58 }
59
60 public static ValueNode create(ValueNode x, ValueNode y, NodeView view) {
61 BinaryOp<Add> op = ArithmeticOpTable.forStamp(x.stamp(view)).getAdd();
62 Stamp stamp = op.foldStamp(x.stamp(view), y.stamp(view));
63 ConstantNode tryConstantFold = tryConstantFold(op, x, y, stamp, view);
64 if (tryConstantFold != null) {
83 }
84 }
85 if (forY instanceof SubNode) {
86 SubNode sub = (SubNode) forY;
87 if (sub.getY() == forX) {
88 // b + (a - b)
89 return sub.getX();
90 }
91 }
92 }
93 if (forY.isConstant()) {
94 Constant c = forY.asConstant();
95 if (op.isNeutral(c)) {
96 return forX;
97 }
98 if (associative && self != null) {
99 // canonicalize expressions like "(a + 1) + 2"
100 ValueNode reassociated = reassociate(self, ValueNode.isConstantPredicate(), forX, forY, view);
101 if (reassociated != self) {
102 return reassociated;
103 }
104 }
105
106 // Attempt to optimize the pattern of an extend node between two add nodes.
107 if (c instanceof JavaConstant && (forX instanceof SignExtendNode || forX instanceof ZeroExtendNode)) {
108 IntegerConvertNode<?, ?> integerConvertNode = (IntegerConvertNode<?, ?>) forX;
109 ValueNode valueNode = integerConvertNode.getValue();
110 long constant = ((JavaConstant) c).asLong();
111 if (valueNode instanceof AddNode) {
112 AddNode addBeforeExtend = (AddNode) valueNode;
113 if (addBeforeExtend.getY().isConstant()) {
114 // There is a second add before the extend node that also has a constant as
115 // second operand. Therefore there will be canonicalizations triggered if we
116 // can move the add above the extension. For this we need to check whether
117 // the result of the addition is the same before the extension (which can be
118 // either zero extend or sign extend).
119 IntegerStamp beforeExtendStamp = (IntegerStamp) addBeforeExtend.stamp(view);
120 int bits = beforeExtendStamp.getBits();
121 if (constant >= CodeUtil.minValue(bits) && constant <= CodeUtil.maxValue(bits)) {
122 IntegerStamp narrowConstantStamp = IntegerStamp.create(bits, constant, constant);
123
124 if (!IntegerStamp.addCanOverflow(narrowConstantStamp, beforeExtendStamp)) {
125 ConstantNode constantNode = ConstantNode.forIntegerStamp(narrowConstantStamp, constant);
126 if (forX instanceof SignExtendNode) {
127 return SignExtendNode.create(AddNode.create(addBeforeExtend, constantNode, view), integerConvertNode.getResultBits(), view);
128 } else {
129 assert forX instanceof ZeroExtendNode;
130
131 // Must check to not cross zero with the new add.
132 boolean crossesZeroPoint = true;
133 if (constant > 0) {
134 if (beforeExtendStamp.lowerBound() >= 0 || beforeExtendStamp.upperBound() < -constant) {
135 // We are good here.
136 crossesZeroPoint = false;
137 }
138 } else {
139 if (beforeExtendStamp.lowerBound() >= -constant || beforeExtendStamp.upperBound() < 0) {
140 // We are good here as well.
141 crossesZeroPoint = false;
142 }
143 }
144 if (!crossesZeroPoint) {
145 return ZeroExtendNode.create(AddNode.create(addBeforeExtend, constantNode, view), integerConvertNode.getResultBits(), view);
146 }
147 }
148 }
149 }
150 }
151 }
152 }
153 }
154 if (forX instanceof NegateNode) {
155 return BinaryArithmeticNode.sub(forY, ((NegateNode) forX).getValue(), view);
156 } else if (forY instanceof NegateNode) {
157 return BinaryArithmeticNode.sub(forX, ((NegateNode) forY).getValue(), view);
158 }
159 if (self == null) {
160 self = (AddNode) new AddNode(forX, forY).maybeCommuteInputs();
161 }
162 return self;
163 }
164
165 @Override
166 public ValueNode canonical(CanonicalizerTool tool, ValueNode forX, ValueNode forY) {
167 ValueNode ret = super.canonical(tool, forX, forY);
168 if (ret != this) {
169 return ret;
170 }
|