22 */ |
22 */ |
23 package org.graalvm.compiler.nodes.calc; |
23 package org.graalvm.compiler.nodes.calc; |
24 |
24 |
25 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; |
25 import static org.graalvm.compiler.nodeinfo.NodeCycles.CYCLES_1; |
26 |
26 |
27 import org.graalvm.compiler.core.common.calc.Condition; |
27 import org.graalvm.compiler.core.common.calc.CanonicalCondition; |
28 import org.graalvm.compiler.core.common.type.ArithmeticOpTable; |
28 import org.graalvm.compiler.core.common.type.ArithmeticOpTable; |
29 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp; |
29 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp; |
30 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow; |
30 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.Narrow; |
31 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.ZeroExtend; |
31 import org.graalvm.compiler.core.common.type.ArithmeticOpTable.IntegerConvertOp.ZeroExtend; |
32 import org.graalvm.compiler.core.common.type.IntegerStamp; |
32 import org.graalvm.compiler.core.common.type.IntegerStamp; |
48 @NodeInfo(cycles = CYCLES_1) |
48 @NodeInfo(cycles = CYCLES_1) |
49 public final class ZeroExtendNode extends IntegerConvertNode<ZeroExtend, Narrow> { |
49 public final class ZeroExtendNode extends IntegerConvertNode<ZeroExtend, Narrow> { |
50 |
50 |
51 public static final NodeClass<ZeroExtendNode> TYPE = NodeClass.create(ZeroExtendNode.class); |
51 public static final NodeClass<ZeroExtendNode> TYPE = NodeClass.create(ZeroExtendNode.class); |
52 |
52 |
|
53 private final boolean inputAlwaysPositive; |
|
54 |
53 public ZeroExtendNode(ValueNode input, int resultBits) { |
55 public ZeroExtendNode(ValueNode input, int resultBits) { |
54 this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits); |
56 this(input, PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)), resultBits, false); |
55 assert 0 < PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) && PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) <= resultBits; |
57 assert 0 < PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) && PrimitiveStamp.getBits(input.stamp(NodeView.DEFAULT)) <= resultBits; |
56 } |
58 } |
57 |
59 |
58 public ZeroExtendNode(ValueNode input, int inputBits, int resultBits) { |
60 public ZeroExtendNode(ValueNode input, int inputBits, int resultBits, boolean inputAlwaysPositive) { |
59 super(TYPE, ArithmeticOpTable::getZeroExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input); |
61 super(TYPE, ArithmeticOpTable::getZeroExtend, ArithmeticOpTable::getNarrow, inputBits, resultBits, input); |
|
62 this.inputAlwaysPositive = inputAlwaysPositive; |
60 } |
63 } |
61 |
64 |
62 public static ValueNode create(ValueNode input, int resultBits, NodeView view) { |
65 public static ValueNode create(ValueNode input, int resultBits, NodeView view) { |
63 return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view); |
66 return create(input, PrimitiveStamp.getBits(input.stamp(view)), resultBits, view, false); |
64 } |
67 } |
65 |
68 |
66 public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view) { |
69 public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view) { |
|
70 return create(input, inputBits, resultBits, view, false); |
|
71 } |
|
72 |
|
73 public static ValueNode create(ValueNode input, int inputBits, int resultBits, NodeView view, boolean alwaysPositive) { |
67 IntegerConvertOp<ZeroExtend> signExtend = ArithmeticOpTable.forStamp(input.stamp(view)).getZeroExtend(); |
74 IntegerConvertOp<ZeroExtend> signExtend = ArithmeticOpTable.forStamp(input.stamp(view)).getZeroExtend(); |
68 ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp(view))); |
75 ValueNode synonym = findSynonym(signExtend, input, inputBits, resultBits, signExtend.foldStamp(inputBits, resultBits, input.stamp(view))); |
69 if (synonym != null) { |
76 if (synonym != null) { |
70 return synonym; |
77 return synonym; |
71 } |
78 } |
72 return canonical(null, input, inputBits, resultBits, view); |
79 return canonical(null, input, inputBits, resultBits, view, alwaysPositive); |
73 } |
80 } |
74 |
81 |
75 @Override |
82 @Override |
76 public boolean isLossless() { |
83 public boolean isLossless() { |
77 return true; |
84 return true; |
78 } |
85 } |
79 |
86 |
|
87 public boolean isInputAlwaysPositive() { |
|
88 return inputAlwaysPositive; |
|
89 } |
|
90 |
80 @Override |
91 @Override |
81 public boolean preservesOrder(Condition cond) { |
92 public boolean preservesOrder(CanonicalCondition cond) { |
82 switch (cond) { |
93 switch (cond) { |
83 case GE: |
|
84 case GT: |
|
85 case LE: |
|
86 case LT: |
94 case LT: |
87 return false; |
95 return false; |
88 default: |
96 default: |
89 return true; |
97 return true; |
90 } |
98 } |
96 ValueNode ret = super.canonical(tool, forValue); |
104 ValueNode ret = super.canonical(tool, forValue); |
97 if (ret != this) { |
105 if (ret != this) { |
98 return ret; |
106 return ret; |
99 } |
107 } |
100 |
108 |
101 return canonical(this, forValue, getInputBits(), getResultBits(), view); |
109 return canonical(this, forValue, getInputBits(), getResultBits(), view, inputAlwaysPositive); |
102 } |
110 } |
103 |
111 |
104 private static ValueNode canonical(ZeroExtendNode zeroExtendNode, ValueNode forValue, int inputBits, int resultBits, NodeView view) { |
112 private static ValueNode canonical(ZeroExtendNode zeroExtendNode, ValueNode forValue, int inputBits, int resultBits, NodeView view, boolean alwaysPositive) { |
105 ZeroExtendNode self = zeroExtendNode; |
113 ZeroExtendNode self = zeroExtendNode; |
106 if (forValue instanceof ZeroExtendNode) { |
114 if (forValue instanceof ZeroExtendNode) { |
107 // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx |
115 // xxxx -(zero-extend)-> 0000 xxxx -(zero-extend)-> 00000000 0000xxxx |
108 // ==> xxxx -(zero-extend)-> 00000000 0000xxxx |
116 // ==> xxxx -(zero-extend)-> 00000000 0000xxxx |
109 ZeroExtendNode other = (ZeroExtendNode) forValue; |
117 ZeroExtendNode other = (ZeroExtendNode) forValue; |
110 return new ZeroExtendNode(other.getValue(), other.getInputBits(), resultBits); |
118 return new ZeroExtendNode(other.getValue(), other.getInputBits(), resultBits, other.isInputAlwaysPositive()); |
111 } |
119 } |
112 if (forValue instanceof NarrowNode) { |
120 if (forValue instanceof NarrowNode) { |
113 NarrowNode narrow = (NarrowNode) forValue; |
121 NarrowNode narrow = (NarrowNode) forValue; |
114 Stamp inputStamp = narrow.getValue().stamp(view); |
122 Stamp inputStamp = narrow.getValue().stamp(view); |
115 if (inputStamp instanceof IntegerStamp) { |
123 if (inputStamp instanceof IntegerStamp) { |