comparison graal/com.oracle.graal.nodes/src/com/oracle/graal/nodes/type/StampTool.java @ 11352:8185c119d731

"always set" bit mask on IntegerStamps
author Lukas Stadler <lukas.stadler@jku.at>
date Fri, 16 Aug 2013 13:15:42 +0200
parents ef6915cf1e59
children 90201030d3cf
comparison
equal deleted inserted replaced
11314:dc14bcf752ea 11352:8185c119d731
27 import com.oracle.graal.api.meta.*; 27 import com.oracle.graal.api.meta.*;
28 28
29 /** 29 /**
30 * Helper class that is used to keep all stamp-related operations in one place. 30 * Helper class that is used to keep all stamp-related operations in one place.
31 */ 31 */
32 // TODO(ls) maybe move the contents into IntegerStamp
33 public class StampTool { 32 public class StampTool {
34 33
35 public static Stamp negate(Stamp stamp) { 34 public static Stamp negate(Stamp stamp) {
35 if (true) {
36 return StampFactory.forKind(stamp.kind());
37 }
36 Kind kind = stamp.kind(); 38 Kind kind = stamp.kind();
37 if (stamp instanceof IntegerStamp) { 39 if (stamp instanceof IntegerStamp) {
38 IntegerStamp integerStamp = (IntegerStamp) stamp; 40 IntegerStamp integerStamp = (IntegerStamp) stamp;
39 if (integerStamp.lowerBound() != kind.getMinValue()) { 41 if (integerStamp.lowerBound() != kind.getMinValue()) {
40 // TODO(ls) check if the mask calculation is correct... 42 // TODO(ls) check if the mask calculation is correct...
41 return new IntegerStamp(kind, -integerStamp.upperBound(), -integerStamp.lowerBound(), IntegerStamp.defaultMask(kind) & (integerStamp.mask() | -integerStamp.mask())); 43 return StampFactory.forInteger(kind, -integerStamp.upperBound(), -integerStamp.lowerBound());
42 } 44 }
43 } 45 } else if (stamp instanceof FloatStamp) {
46 FloatStamp floatStamp = (FloatStamp) stamp;
47 return new FloatStamp(kind, -floatStamp.upperBound(), -floatStamp.lowerBound(), floatStamp.isNonNaN());
48 }
49
44 return StampFactory.forKind(kind); 50 return StampFactory.forKind(kind);
51 }
52
53 public static Stamp not(Stamp stamp) {
54 if (stamp instanceof IntegerStamp) {
55 IntegerStamp integerStamp = (IntegerStamp) stamp;
56 assert stamp.kind() == Kind.Int || stamp.kind() == Kind.Long;
57 long defaultMask = IntegerStamp.defaultMask(stamp.kind());
58 return new IntegerStamp(stamp.kind(), ~integerStamp.upperBound(), ~integerStamp.lowerBound(), (~integerStamp.upMask()) & defaultMask, (~integerStamp.downMask()) & defaultMask);
59 }
60 return StampFactory.forKind(stamp.kind());
45 } 61 }
46 62
47 public static Stamp meet(Collection<? extends StampProvider> values) { 63 public static Stamp meet(Collection<? extends StampProvider> values) {
48 Iterator<? extends StampProvider> iterator = values.iterator(); 64 Iterator<? extends StampProvider> iterator = values.iterator();
49 if (iterator.hasNext()) { 65 if (iterator.hasNext()) {
62 return add((IntegerStamp) stamp1, (IntegerStamp) stamp2); 78 return add((IntegerStamp) stamp1, (IntegerStamp) stamp2);
63 } 79 }
64 return StampFactory.illegal(); 80 return StampFactory.illegal();
65 } 81 }
66 82
67 public static Stamp add(IntegerStamp stamp1, IntegerStamp stamp2) { 83 private static long carryBits(long x, long y) {
68 Kind kind = stamp1.kind(); 84 return (x + y) ^ x ^ y;
69 assert kind == stamp2.kind();
70 if (addOverflow(stamp1.lowerBound(), stamp2.lowerBound(), kind)) {
71 return StampFactory.forKind(kind);
72 }
73 if (addOverflow(stamp1.upperBound(), stamp2.upperBound(), kind)) {
74 return StampFactory.forKind(kind);
75 }
76 long lowerBound = stamp1.lowerBound() + stamp2.lowerBound();
77 long upperBound = stamp1.upperBound() + stamp2.upperBound();
78 long mask = IntegerStamp.maskFor(kind, lowerBound, upperBound);
79
80 return StampFactory.forInteger(kind, lowerBound, upperBound, mask);
81 } 85 }
82 86
83 public static Stamp sub(Stamp stamp1, Stamp stamp2) { 87 public static Stamp sub(Stamp stamp1, Stamp stamp2) {
84 return add(stamp1, StampTool.negate(stamp2)); 88 return add(stamp1, StampTool.negate(stamp2));
85 } 89 }
90 } 94 }
91 return StampFactory.illegal(); 95 return StampFactory.illegal();
92 } 96 }
93 97
94 public static Stamp div(IntegerStamp stamp1, IntegerStamp stamp2) { 98 public static Stamp div(IntegerStamp stamp1, IntegerStamp stamp2) {
99 assert stamp1.kind() == stamp2.kind();
95 Kind kind = stamp1.kind(); 100 Kind kind = stamp1.kind();
96 if (stamp2.isStrictlyPositive()) { 101 if (stamp2.isStrictlyPositive()) {
97 long lowerBound = stamp1.lowerBound() / stamp2.lowerBound(); 102 long lowerBound = stamp1.lowerBound() / stamp2.lowerBound();
98 long upperBound = stamp1.upperBound() / stamp2.lowerBound(); 103 long upperBound = stamp1.upperBound() / stamp2.lowerBound();
99 return StampFactory.forInteger(kind, lowerBound, upperBound, IntegerStamp.maskFor(kind, lowerBound, upperBound)); 104 return StampFactory.forInteger(kind, lowerBound, upperBound);
100 } 105 }
101 return StampFactory.forKind(kind); 106 return StampFactory.forKind(kind);
102 } 107 }
103 108
104 private static boolean addOverflow(long x, long y, Kind kind) { 109 private static boolean addOverflows(long x, long y, Kind kind) {
105 long result = x + y; 110 long result = x + y;
106 if (kind == Kind.Long) { 111 if (kind == Kind.Long) {
107 return ((x ^ result) & (y ^ result)) < 0; 112 return ((x ^ result) & (y ^ result)) < 0;
108 } else { 113 } else {
109 assert kind == Kind.Int; 114 assert kind == Kind.Int;
110 return result > Integer.MAX_VALUE || result < Integer.MIN_VALUE; 115 return result > Integer.MAX_VALUE || result < Integer.MIN_VALUE;
111 } 116 }
112 } 117 }
113 118
114 private static final long INTEGER_SIGN_BIT = 0x80000000L; 119 public static IntegerStamp add(IntegerStamp stamp1, IntegerStamp stamp2) {
115 private static final long LONG_SIGN_BIT = 0x8000000000000000L; 120 try {
116 121 if (stamp1.isUnrestricted() || stamp2.isUnrestricted()) {
117 private static Stamp stampForMask(Kind kind, long mask) { 122 return (IntegerStamp) StampFactory.forKind(stamp1.kind());
118 return stampForMask(kind, mask, 0); 123 }
119 } 124 Kind kind = stamp1.kind();
120 125 assert stamp1.kind() == stamp2.kind();
121 private static Stamp stampForMask(Kind kind, long mask, long alwaysSetBits) { 126 long defaultMask = IntegerStamp.defaultMask(kind);
127 long variableBits = (stamp1.downMask() ^ stamp1.upMask()) | (stamp2.downMask() ^ stamp2.upMask());
128 long variableBitsWithCarry = variableBits | (carryBits(stamp1.downMask(), stamp2.downMask()) ^ carryBits(stamp1.upMask(), stamp2.upMask()));
129 long newDownMask = (stamp1.downMask() + stamp2.downMask()) & ~variableBitsWithCarry;
130 long newUpMask = (stamp1.downMask() + stamp2.downMask()) | variableBitsWithCarry;
131
132 newDownMask &= defaultMask;
133 newUpMask &= defaultMask;
134
135 long lowerBound;
136 long upperBound;
137 if (addOverflows(stamp1.lowerBound(), stamp2.lowerBound(), kind) || addOverflows(stamp1.upperBound(), stamp2.upperBound(), kind)) {
138 lowerBound = kind.getMinValue();
139 upperBound = kind.getMaxValue();
140 } else {
141 lowerBound = stamp1.lowerBound() + stamp2.lowerBound();
142 upperBound = stamp1.upperBound() + stamp2.upperBound();
143 }
144 IntegerStamp limit = StampFactory.forInteger(kind, lowerBound, upperBound);
145 newUpMask &= limit.upMask();
146 return new IntegerStamp(kind, lowerBound | newDownMask, signExtend(upperBound & newUpMask, kind), newDownMask, newUpMask);
147 } catch (Throwable e) {
148 throw new RuntimeException(stamp1 + " + " + stamp2, e);
149 }
150 }
151
152 public static Stamp sub(IntegerStamp stamp1, IntegerStamp stamp2) {
153 if (stamp1.isUnrestricted() || stamp2.isUnrestricted()) {
154 return StampFactory.forKind(stamp1.kind());
155 }
156 return add(stamp1, (IntegerStamp) StampTool.negate(stamp2));
157 }
158
159 private static Stamp stampForMask(Kind kind, long downMask, long upMask) {
122 long lowerBound; 160 long lowerBound;
123 long upperBound; 161 long upperBound;
124 if (kind == Kind.Int && (mask & INTEGER_SIGN_BIT) != 0) { 162 if (((upMask >>> (kind.getBitCount() - 1)) & 1) == 0) {
125 // the mask is negative 163 lowerBound = downMask;
126 lowerBound = Integer.MIN_VALUE; 164 upperBound = upMask;
127 upperBound = mask ^ INTEGER_SIGN_BIT; 165 } else if (((downMask >>> (kind.getBitCount() - 1)) & 1) == 1) {
128 } else if (kind == Kind.Long && (mask & LONG_SIGN_BIT) != 0) { 166 lowerBound = downMask;
129 // the mask is negative 167 upperBound = upMask;
130 lowerBound = Long.MIN_VALUE; 168 } else {
131 upperBound = mask ^ LONG_SIGN_BIT; 169 lowerBound = upMask;
132 } else { 170 upperBound = kind.getMaxValue() & upMask;
133 lowerBound = alwaysSetBits; 171 }
134 upperBound = mask; 172 if (kind == Kind.Int) {
135 } 173 return StampFactory.forInteger(kind, (int) lowerBound, (int) upperBound, downMask, upMask);
136 return StampFactory.forInteger(kind, lowerBound, upperBound, mask); 174 } else {
175 return StampFactory.forInteger(kind, lowerBound, upperBound, downMask, upMask);
176 }
137 } 177 }
138 178
139 public static Stamp and(Stamp stamp1, Stamp stamp2) { 179 public static Stamp and(Stamp stamp1, Stamp stamp2) {
140 if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) { 180 if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
141 return and((IntegerStamp) stamp1, (IntegerStamp) stamp2); 181 return and((IntegerStamp) stamp1, (IntegerStamp) stamp2);
142 } 182 }
143 return StampFactory.illegal(); 183 return StampFactory.illegal();
144 } 184 }
145 185
146 public static Stamp and(IntegerStamp stamp1, IntegerStamp stamp2) { 186 public static Stamp and(IntegerStamp stamp1, IntegerStamp stamp2) {
147 Kind kind = stamp1.kind(); 187 assert stamp1.kind() == stamp2.kind();
148 long mask = stamp1.mask() & stamp2.mask(); 188 return stampForMask(stamp1.kind(), stamp1.downMask() & stamp2.downMask(), stamp1.upMask() & stamp2.upMask());
149 return stampForMask(kind, mask);
150 } 189 }
151 190
152 public static Stamp or(Stamp stamp1, Stamp stamp2) { 191 public static Stamp or(Stamp stamp1, Stamp stamp2) {
153 if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) { 192 if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
154 return or((IntegerStamp) stamp1, (IntegerStamp) stamp2); 193 return or((IntegerStamp) stamp1, (IntegerStamp) stamp2);
155 } 194 }
156 return StampFactory.illegal(); 195 return StampFactory.illegal();
157 } 196 }
158 197
159 public static Stamp or(IntegerStamp stamp1, IntegerStamp stamp2) { 198 public static Stamp or(IntegerStamp stamp1, IntegerStamp stamp2) {
160 Kind kind = stamp1.kind(); 199 assert stamp1.kind() == stamp2.kind();
161 long mask = stamp1.mask() | stamp2.mask(); 200 return stampForMask(stamp1.kind(), stamp1.downMask() | stamp2.downMask(), stamp1.upMask() | stamp2.upMask());
162 if (stamp1.lowerBound() >= 0 && stamp2.lowerBound() >= 0) {
163 return stampForMask(kind, mask, stamp1.lowerBound() | stamp2.lowerBound());
164 } else {
165 return stampForMask(kind, mask);
166 }
167 } 201 }
168 202
169 public static Stamp xor(Stamp stamp1, Stamp stamp2) { 203 public static Stamp xor(Stamp stamp1, Stamp stamp2) {
170 if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) { 204 if (stamp1 instanceof IntegerStamp && stamp2 instanceof IntegerStamp) {
171 return xor((IntegerStamp) stamp1, (IntegerStamp) stamp2); 205 return xor((IntegerStamp) stamp1, (IntegerStamp) stamp2);
172 } 206 }
173 return StampFactory.illegal(); 207 return StampFactory.illegal();
174 } 208 }
175 209
176 public static Stamp xor(IntegerStamp stamp1, IntegerStamp stamp2) { 210 public static Stamp xor(IntegerStamp stamp1, IntegerStamp stamp2) {
177 Kind kind = stamp1.kind(); 211 assert stamp1.kind() == stamp2.kind();
178 long mask = stamp1.mask() | stamp2.mask(); 212 long variableBits = (stamp1.downMask() ^ stamp1.upMask()) | (stamp2.downMask() ^ stamp2.upMask());
179 return stampForMask(kind, mask); 213 long newDownMask = (stamp1.downMask() ^ stamp2.downMask()) & ~variableBits;
214 long newUpMask = (stamp1.downMask() ^ stamp2.downMask()) | variableBits;
215 return stampForMask(stamp1.kind(), newDownMask, newUpMask);
180 } 216 }
181 217
182 public static Stamp unsignedRightShift(Stamp value, Stamp shift) { 218 public static Stamp unsignedRightShift(Stamp value, Stamp shift) {
183 if (value instanceof IntegerStamp && shift instanceof IntegerStamp) { 219 if (value instanceof IntegerStamp && shift instanceof IntegerStamp) {
184 return unsignedRightShift((IntegerStamp) value, (IntegerStamp) shift); 220 return unsignedRightShift((IntegerStamp) value, (IntegerStamp) shift);
199 upperBound = IntegerStamp.defaultMask(kind) >>> shiftCount; 235 upperBound = IntegerStamp.defaultMask(kind) >>> shiftCount;
200 } else { 236 } else {
201 lowerBound = value.lowerBound() >>> shiftCount; 237 lowerBound = value.lowerBound() >>> shiftCount;
202 upperBound = value.upperBound() >>> shiftCount; 238 upperBound = value.upperBound() >>> shiftCount;
203 } 239 }
204 long mask = value.mask() >>> shiftCount; 240 return new IntegerStamp(kind, lowerBound, upperBound, value.downMask() >>> shiftCount, value.upMask() >>> shiftCount);
205 return StampFactory.forInteger(kind, lowerBound, upperBound, mask); 241 }
206 } 242 }
207 } 243 long mask = IntegerStamp.upMaskFor(kind, value.lowerBound(), value.upperBound());
208 long mask = IntegerStamp.maskFor(kind, value.lowerBound(), value.upperBound()); 244 return stampForMask(kind, 0, mask);
209 return stampForMask(kind, mask);
210 } 245 }
211 246
212 public static Stamp leftShift(Stamp value, Stamp shift) { 247 public static Stamp leftShift(Stamp value, Stamp shift) {
213 if (value instanceof IntegerStamp && shift instanceof IntegerStamp) { 248 if (value instanceof IntegerStamp && shift instanceof IntegerStamp) {
214 return leftShift((IntegerStamp) value, (IntegerStamp) shift); 249 return leftShift((IntegerStamp) value, (IntegerStamp) shift);
216 return StampFactory.illegal(); 251 return StampFactory.illegal();
217 } 252 }
218 253
219 public static Stamp leftShift(IntegerStamp value, IntegerStamp shift) { 254 public static Stamp leftShift(IntegerStamp value, IntegerStamp shift) {
220 Kind kind = value.kind(); 255 Kind kind = value.kind();
256 long defaultMask = IntegerStamp.defaultMask(kind);
257 if (value.upMask() == 0) {
258 return value;
259 }
221 int shiftBits = kind == Kind.Int ? 5 : 6; 260 int shiftBits = kind == Kind.Int ? 5 : 6;
222 long shiftMask = kind == Kind.Int ? 0x1FL : 0x3FL; 261 long shiftMask = kind == Kind.Int ? 0x1FL : 0x3FL;
223 if ((shift.lowerBound() >>> shiftBits) == (shift.upperBound() >>> shiftBits)) { 262 if ((shift.lowerBound() >>> shiftBits) == (shift.upperBound() >>> shiftBits)) {
224 long mask = 0; 263 long downMask = defaultMask;
225 for (long i = shift.lowerBound() & shiftMask; i <= (shift.upperBound() & shiftMask); i++) { 264 long upMask = 0;
226 mask |= value.mask() << i; 265 for (long i = shift.lowerBound(); i <= shift.upperBound(); i++) {
227 } 266 if (shift.contains(i)) {
228 mask &= IntegerStamp.defaultMask(kind); 267 downMask &= value.downMask() << (i & shiftMask);
229 return stampForMask(kind, mask); 268 upMask |= value.upMask() << (i & shiftMask);
269 }
270 }
271 Stamp result = stampForMask(kind, downMask, upMask & IntegerStamp.defaultMask(kind));
272 return result;
230 } 273 }
231 return StampFactory.forKind(kind); 274 return StampFactory.forKind(kind);
232 } 275 }
233 276
234 public static Stamp intToLong(IntegerStamp intStamp) { 277 public static Stamp intToLong(IntegerStamp intStamp) {
235 long mask; 278 return StampFactory.forInteger(Kind.Long, intStamp.lowerBound(), intStamp.upperBound(), signExtend(intStamp.downMask(), Kind.Int), signExtend(intStamp.upMask(), Kind.Int));
236 if (intStamp.isPositive()) { 279 }
237 mask = intStamp.mask(); 280
238 } else { 281 private static IntegerStamp narrowingKindConvertion(IntegerStamp fromStamp, Kind toKind) {
239 mask = 0xffffffff00000000L | intStamp.mask(); 282 assert toKind == Kind.Byte || toKind == Kind.Char || toKind == Kind.Short || toKind == Kind.Int;
240 } 283 final long upperBound;
241 return StampFactory.forInteger(Kind.Long, intStamp.lowerBound(), intStamp.upperBound(), mask);
242 }
243
244 private static Stamp narrowingKindConvertion(IntegerStamp fromStamp, Kind toKind) {
245 long mask = fromStamp.mask() & IntegerStamp.defaultMask(toKind);
246 long lowerBound = saturate(fromStamp.lowerBound(), toKind);
247 long upperBound = saturate(fromStamp.upperBound(), toKind);
248 if (fromStamp.lowerBound() < toKind.getMinValue()) { 284 if (fromStamp.lowerBound() < toKind.getMinValue()) {
249 upperBound = toKind.getMaxValue(); 285 upperBound = toKind.getMaxValue();
250 } 286 } else {
287 upperBound = saturate(fromStamp.upperBound(), toKind);
288 }
289 final long lowerBound;
251 if (fromStamp.upperBound() > toKind.getMaxValue()) { 290 if (fromStamp.upperBound() > toKind.getMaxValue()) {
252 lowerBound = toKind.getMinValue(); 291 lowerBound = toKind.getMinValue();
253 } 292 } else {
254 return StampFactory.forInteger(toKind.getStackKind(), lowerBound, upperBound, mask); 293 lowerBound = saturate(fromStamp.lowerBound(), toKind);
255 } 294 }
256 295
257 public static Stamp intToByte(IntegerStamp intStamp) { 296 long defaultMask = IntegerStamp.defaultMask(toKind);
297 long intMask = IntegerStamp.defaultMask(Kind.Int);
298 long newUpMask = signExtend(fromStamp.upMask() & defaultMask, toKind) & intMask;
299 long newDownMask = signExtend(fromStamp.downMask() & defaultMask, toKind) & intMask;
300 return new IntegerStamp(toKind.getStackKind(), (int) ((lowerBound | newDownMask) & newUpMask), (int) ((upperBound | newDownMask) & newUpMask), newDownMask, newUpMask);
301 }
302
303 private static long signExtend(long value, Kind valueKind) {
304 if (valueKind != Kind.Char && (value >>> (valueKind.getBitCount() - 1) & 1) == 1) {
305 return value | (-1L << valueKind.getBitCount());
306 } else {
307 return value;
308 }
309 }
310
311 public static IntegerStamp intToByte(IntegerStamp intStamp) {
312 assert intStamp.kind() == Kind.Int;
258 return narrowingKindConvertion(intStamp, Kind.Byte); 313 return narrowingKindConvertion(intStamp, Kind.Byte);
259 } 314 }
260 315
261 public static Stamp intToShort(IntegerStamp intStamp) { 316 public static IntegerStamp intToShort(IntegerStamp intStamp) {
317 assert intStamp.kind() == Kind.Int;
262 return narrowingKindConvertion(intStamp, Kind.Short); 318 return narrowingKindConvertion(intStamp, Kind.Short);
263 } 319 }
264 320
265 public static Stamp intToChar(IntegerStamp intStamp) { 321 public static IntegerStamp intToChar(IntegerStamp intStamp) {
322 assert intStamp.kind() == Kind.Int;
266 return narrowingKindConvertion(intStamp, Kind.Char); 323 return narrowingKindConvertion(intStamp, Kind.Char);
267 } 324 }
268 325
269 public static Stamp longToInt(IntegerStamp longStamp) { 326 public static IntegerStamp longToInt(IntegerStamp longStamp) {
327 assert longStamp.kind() == Kind.Long;
270 return narrowingKindConvertion(longStamp, Kind.Int); 328 return narrowingKindConvertion(longStamp, Kind.Int);
271 } 329 }
272 330
273 public static long saturate(long v, Kind kind) { 331 public static long saturate(long v, Kind kind) {
274 long max = kind.getMaxValue(); 332 long max = kind.getMaxValue();