1 /*
2 * Copyright (c) 2014, 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 static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
28
29 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
30 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp;
31 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow;
32 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend;
33 import org.graalvm.compiler.core.common.type.IntegerStamp;
34 import org.graalvm.compiler.core.common.type.PrimitiveStamp;
35 import org.graalvm.compiler.graph.NodeClass;
36 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
37 import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
38 import org.graalvm.compiler.nodeinfo.NodeInfo;
39 import org.graalvm.compiler.nodes.NodeView;
40 import org.graalvm.compiler.nodes.ValueNode;
41 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
42
43 import jdk.vm.ci.code.CodeUtil;
44
45 /**
46 * The {@code NarrowNode} converts an integer to a narrower integer.
47 */
48 @NodeInfo(cycles = CYCLES_1)
49 public final class NarrowNode extends IntegerConvertNode<Narrow, SignExtend> {
50
51 public static final NodeClass<NarrowNode> TYPE = NodeClass.create(NarrowNode.class);
52
53 public NarrowNode(ValueNode input, int resultBits) {
54 this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits);
58 public NarrowNode(ValueNode input, int inputBits, int resultBits) {
59 super(TYPE, ArithmeticOpTable::getNarrow, ArithmeticOpTable::getSignExtend, inputBits, resultBits, input);
60 }
61
62 public static ValueNode create(ValueNode input, int resultBits, NodeView view) {
63 return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view);
64 }
65
66 public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view) {
67 IntegerConvertOp<Narrow> signExtend = ArithmeticOpTable.forStamp(input.stamp(view)).getNarrow();
68 ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp(view)));
69 if (synonym != null) {
70 return synonym;
71 } else {
72 return new NarrowNode(input, inputBits, resultBits);
73 }
74 }
75
76 @Override
77 public boolean isLossless() {
78 return false;
79 }
80
81 @Override
82 public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
83 NodeView view = NodeView.from(tool);
84 ValueNode ret = super.canonical(tool, forValue);
85 if (ret != this) {
86 return ret;
87 }
88
89 if (forValue instanceof NarrowNode) {
90 // zzzzzzzz yyyyxxxx -(narrow)-> yyyyxxxx -(narrow)-> xxxx
91 // ==> zzzzzzzz yyyyxxxx -(narrow)-> xxxx
92 NarrowNode other = (NarrowNode) forValue;
93 return new NarrowNode(other.getValue(), other.getInputBits(), getResultBits());
94 } else if (forValue instanceof IntegerConvertNode) {
95 // SignExtendNode or ZeroExtendNode
96 IntegerConvertNode<?, ?> other = (IntegerConvertNode<?, ?>) forValue;
97 if (other.getValue().hasExactlyOneUsage() && other.hasMoreThanOneUsage()) {
98 // Do not perform if this will introduce a new live value.
|
1 /*
2 * Copyright (c) 2014, 2019, 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 static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1;
28
29 import org.graalvm.compiler.core.common.calc.CanonicalCondition;
30 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
31 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp;
32 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow;
33 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.SignExtend;
34 import org.graalvm.compiler.core.common.type.IntegerStamp;
35 import org.graalvm.compiler.core.common.type.PrimitiveStamp;
36 import org.graalvm.compiler.core.common.type.Stamp;
37 import org.graalvm.compiler.graph.NodeClass;
38 import org.graalvm.compiler.graph.spi.CanonicalizerTool;
39 import org.graalvm.compiler.lir.gen.ArithmeticLIRGeneratorTool;
40 import org.graalvm.compiler.nodeinfo.NodeInfo;
41 import org.graalvm.compiler.nodes.NodeView;
42 import org.graalvm.compiler.nodes.ValueNode;
43 import org.graalvm.compiler.nodes.spi.NodeLIRBuilderTool;
44
45 import jdk.vm.ci.code.CodeUtil;
46
47 /**
48 * The {@code NarrowNode} converts an integer to a narrower integer.
49 */
50 @NodeInfo(cycles = CYCLES_1)
51 public final class NarrowNode extends IntegerConvertNode<Narrow, SignExtend> {
52
53 public static final NodeClass<NarrowNode> TYPE = NodeClass.create(NarrowNode.class);
54
55 public NarrowNode(ValueNode input, int resultBits) {
56 this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits);
60 public NarrowNode(ValueNode input, int inputBits, int resultBits) {
61 super(TYPE, ArithmeticOpTable::getNarrow, ArithmeticOpTable::getSignExtend, inputBits, resultBits, input);
62 }
63
64 public static ValueNode create(ValueNode input, int resultBits, NodeView view) {
65 return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view);
66 }
67
68 public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view) {
69 IntegerConvertOp<Narrow> signExtend = ArithmeticOpTable.forStamp(input.stamp(view)).getNarrow();
70 ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp(view)));
71 if (synonym != null) {
72 return synonym;
73 } else {
74 return new NarrowNode(input, inputBits, resultBits);
75 }
76 }
77
78 @Override
79 public boolean isLossless() {
80 return checkLossless(this.getResultBits());
81 }
82
83 private boolean checkLossless(int bits) {
84 Stamp valueStamp = this.getValue().stamp(NodeView.DEFAULT);
85 if (bits > 0 && valueStamp instanceof IntegerStamp) {
86 IntegerStamp integerStamp = (IntegerStamp) valueStamp;
87 long valueUpMask = integerStamp.upMask();
88 if ((valueUpMask & CodeUtil.mask(bits)) == valueUpMask) {
89 return true;
90 }
91 }
92 return false;
93 }
94
95 @Override
96 public boolean preservesOrder(CanonicalCondition cond) {
97 switch (cond) {
98 case LT:
99 // Must guarantee that also sign bit does not flip.
100 return checkLossless(this.getResultBits() - 1);
101 default:
102 return checkLossless(this.getResultBits());
103 }
104 }
105
106 @Override
107 public ValueNode canonical(CanonicalizerTool tool, ValueNode forValue) {
108 NodeView view = NodeView.from(tool);
109 ValueNode ret = super.canonical(tool, forValue);
110 if (ret != this) {
111 return ret;
112 }
113
114 if (forValue instanceof NarrowNode) {
115 // zzzzzzzz yyyyxxxx -(narrow)-> yyyyxxxx -(narrow)-> xxxx
116 // ==> zzzzzzzz yyyyxxxx -(narrow)-> xxxx
117 NarrowNode other = (NarrowNode) forValue;
118 return new NarrowNode(other.getValue(), other.getInputBits(), getResultBits());
119 } else if (forValue instanceof IntegerConvertNode) {
120 // SignExtendNode or ZeroExtendNode
121 IntegerConvertNode<?, ?> other = (IntegerConvertNode<?, ?>) forValue;
122 if (other.getValue().hasExactlyOneUsage() && other.hasMoreThanOneUsage()) {
123 // Do not perform if this will introduce a new live value.
|