Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(724)

Side by Side Diff: lib/compiler/implementation/ssa/value_range_analyzer.dart

Issue 11227042: isEven, isOdd, isNegative, isMaxValue, isMinValue, isInfinite, isPositive, isSingleValue. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase. Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /** 5 /**
6 * A [Value] represents both symbolic values like the value of a 6 * A [Value] represents both symbolic values like the value of a
7 * parameter, or the length of an array, and concrete values, like 7 * parameter, or the length of an array, and concrete values, like
8 * constants. 8 * constants.
9 */ 9 */
10 abstract class Value { 10 abstract class Value {
11 const Value(); 11 const Value();
12 12
13 Value operator +(Value other); 13 Value operator +(Value other);
14 Value operator -(Value other); 14 Value operator -(Value other);
15 Value operator -(); 15 Value operator -();
16 Value operator &(Value other); 16 Value operator &(Value other);
17 17
18 Value min(Value other) { 18 Value min(Value other) {
19 if (this == other) return this; 19 if (this == other) return this;
20 if (other == const MinIntValue()) return other; 20 if (other == const MinIntValue()) return other;
21 if (other == const MaxIntValue()) return this; 21 if (other == const MaxIntValue()) return this;
22 Value value = this - other; 22 Value value = this - other;
23 if (value.isPositive()) return other; 23 if (value.isPositive) return other;
24 if (value.isNegative()) return this; 24 if (value.isNegative) return this;
25 return const UnknownValue(); 25 return const UnknownValue();
26 } 26 }
27 27
28 Value max(Value other) { 28 Value max(Value other) {
29 if (this == other) return this; 29 if (this == other) return this;
30 if (other == const MinIntValue()) return this; 30 if (other == const MinIntValue()) return this;
31 if (other == const MaxIntValue()) return other; 31 if (other == const MaxIntValue()) return other;
32 Value value = this - other; 32 Value value = this - other;
33 if (value.isPositive()) return this; 33 if (value.isPositive) return this;
34 if (value.isNegative()) return other; 34 if (value.isNegative) return other;
35 return const UnknownValue(); 35 return const UnknownValue();
36 } 36 }
37 37
38 bool isNegative() => false; 38 bool get isNegative => false;
39 bool isPositive() => false; 39 bool get isPositive => false;
40 bool isZero() => false; 40 bool get isZero => false;
41 } 41 }
42 42
43 /** 43 /**
44 * An [IntValue] contains a constant integer value. 44 * An [IntValue] contains a constant integer value.
45 */ 45 */
46 class IntValue extends Value { 46 class IntValue extends Value {
47 final int value; 47 final int value;
48 const IntValue(this.value); 48 const IntValue(this.value);
49 49
50 Value operator +(other) { 50 Value operator +(other) {
51 if (other.isZero()) return this; 51 if (other.isZero) return this;
52 if (other is !IntValue) return other + this; 52 if (other is !IntValue) return other + this;
53 return new IntValue(value + other.value); 53 return new IntValue(value + other.value);
54 } 54 }
55 55
56 Value operator -(other) { 56 Value operator -(other) {
57 if (other.isZero()) return this; 57 if (other.isZero) return this;
58 if (other is !IntValue) return -other + this; 58 if (other is !IntValue) return -other + this;
59 return new IntValue(value - other.value); 59 return new IntValue(value - other.value);
60 } 60 }
61 61
62 Value operator -() { 62 Value operator -() {
63 if (isZero()) return this; 63 if (isZero) return this;
64 return new IntValue(-value); 64 return new IntValue(-value);
65 } 65 }
66 66
67 Value operator &(other) { 67 Value operator &(other) {
68 if (other is !IntValue) { 68 if (other is !IntValue) {
69 if (isPositive()) return this; 69 if (isPositive) return this;
70 if (other.isPositive()) return new IntValue(-value); 70 if (other.isPositive) return new IntValue(-value);
71 return const UnknownValue(); 71 return const UnknownValue();
72 } 72 }
73 return new IntValue(value & other.value); 73 return new IntValue(value & other.value);
74 } 74 }
75 75
76 Value min(other) { 76 Value min(other) {
77 if (other is !IntValue) return other.min(this); 77 if (other is !IntValue) return other.min(this);
78 return this.value < other.value ? this : other; 78 return this.value < other.value ? this : other;
79 } 79 }
80 80
81 Value max(other) { 81 Value max(other) {
82 if (other is !IntValue) return other.max(this); 82 if (other is !IntValue) return other.max(this);
83 return this.value < other.value ? other : this; 83 return this.value < other.value ? other : this;
84 } 84 }
85 85
86 bool operator ==(other) { 86 bool operator ==(other) {
87 if (other is !IntValue) return false; 87 if (other is !IntValue) return false;
88 return this.value == other.value; 88 return this.value == other.value;
89 } 89 }
90 90
91 String toString() => 'IntValue $value'; 91 String toString() => 'IntValue $value';
92 bool isNegative() => value < 0; 92 bool get isNegative => value < 0;
93 bool isPositive() => value >= 0; 93 bool get isPositive => value >= 0;
94 bool isZero() => value == 0; 94 bool get isZero => value == 0;
95 } 95 }
96 96
97 /** 97 /**
98 * The [MaxIntValue] represents the maximum value an integer can have, 98 * The [MaxIntValue] represents the maximum value an integer can have,
99 * which is currently +infinity. 99 * which is currently +infinity.
100 */ 100 */
101 class MaxIntValue extends Value { 101 class MaxIntValue extends Value {
102 const MaxIntValue(); 102 const MaxIntValue();
103 Value operator +(Value other) => this; 103 Value operator +(Value other) => this;
104 Value operator -(Value other) => this; 104 Value operator -(Value other) => this;
105 Value operator -() => const MinIntValue(); 105 Value operator -() => const MinIntValue();
106 Value operator &(Value other) { 106 Value operator &(Value other) {
107 if (other.isPositive()) return other; 107 if (other.isPositive) return other;
108 if (other.isNegative()) return const IntValue(0); 108 if (other.isNegative) return const IntValue(0);
109 return this; 109 return this;
110 } 110 }
111 Value min(Value other) => other; 111 Value min(Value other) => other;
112 Value max(Value other) => this; 112 Value max(Value other) => this;
113 String toString() => 'Max'; 113 String toString() => 'Max';
114 bool isNegative() => false; 114 bool get isNegative => false;
115 bool isPositive() => true; 115 bool get isPositive => true;
116 } 116 }
117 117
118 /** 118 /**
119 * The [MinIntValue] represents the minimum value an integer can have, 119 * The [MinIntValue] represents the minimum value an integer can have,
120 * which is currently -infinity. 120 * which is currently -infinity.
121 */ 121 */
122 class MinIntValue extends Value { 122 class MinIntValue extends Value {
123 const MinIntValue(); 123 const MinIntValue();
124 Value operator +(Value other) => this; 124 Value operator +(Value other) => this;
125 Value operator -(Value other) => this; 125 Value operator -(Value other) => this;
126 Value operator -() => const MaxIntValue(); 126 Value operator -() => const MaxIntValue();
127 Value operator &(Value other) { 127 Value operator &(Value other) {
128 if (other.isPositive()) return const IntValue(0); 128 if (other.isPositive) return const IntValue(0);
129 return this; 129 return this;
130 } 130 }
131 Value min(Value other) => this; 131 Value min(Value other) => this;
132 Value max(Value other) => other; 132 Value max(Value other) => other;
133 String toString() => 'Min'; 133 String toString() => 'Min';
134 bool isNegative() => true; 134 bool get isNegative => true;
135 bool isPositive() => false; 135 bool get isPositive => false;
136 } 136 }
137 137
138 /** 138 /**
139 * The [UnknownValue] is the sentinel in our analysis to mark an 139 * The [UnknownValue] is the sentinel in our analysis to mark an
140 * operation that could not be done because of too much complexity. 140 * operation that could not be done because of too much complexity.
141 */ 141 */
142 class UnknownValue extends Value { 142 class UnknownValue extends Value {
143 const UnknownValue(); 143 const UnknownValue();
144 Value operator +(Value other) => const UnknownValue(); 144 Value operator +(Value other) => const UnknownValue();
145 Value operator -(Value other) => const UnknownValue(); 145 Value operator -(Value other) => const UnknownValue();
146 Value operator -() => const UnknownValue(); 146 Value operator -() => const UnknownValue();
147 Value operator &(Value other) => const UnknownValue(); 147 Value operator &(Value other) => const UnknownValue();
148 Value min(Value other) => const UnknownValue(); 148 Value min(Value other) => const UnknownValue();
149 Value max(Value other) => const UnknownValue(); 149 Value max(Value other) => const UnknownValue();
150 bool isNegative() => false; 150 bool get isNegative => false;
151 bool isPositive() => false; 151 bool get isPositive => false;
152 String toString() => 'Unknown'; 152 String toString() => 'Unknown';
153 } 153 }
154 154
155 /** 155 /**
156 * A symbolic value representing an [HInstruction]. 156 * A symbolic value representing an [HInstruction].
157 */ 157 */
158 class InstructionValue extends Value { 158 class InstructionValue extends Value {
159 final HInstruction instruction; 159 final HInstruction instruction;
160 InstructionValue(this.instruction); 160 InstructionValue(this.instruction);
161 161
162 bool operator ==(other) { 162 bool operator ==(other) {
163 if (other is !InstructionValue) return false; 163 if (other is !InstructionValue) return false;
164 return this.instruction == other.instruction; 164 return this.instruction == other.instruction;
165 } 165 }
166 166
167 Value operator +(Value other) { 167 Value operator +(Value other) {
168 if (other.isZero()) return this; 168 if (other.isZero) return this;
169 if (other is IntValue) { 169 if (other is IntValue) {
170 if (other.isNegative()) { 170 if (other.isNegative) {
171 return new SubtractValue(this, -other); 171 return new SubtractValue(this, -other);
172 } 172 }
173 return new AddValue(this, other); 173 return new AddValue(this, other);
174 } 174 }
175 if (other is InstructionValue) { 175 if (other is InstructionValue) {
176 return new AddValue(this, other); 176 return new AddValue(this, other);
177 } 177 }
178 return other + this; 178 return other + this;
179 } 179 }
180 180
181 Value operator -(Value other) { 181 Value operator -(Value other) {
182 if (other.isZero()) return this; 182 if (other.isZero) return this;
183 if (this == other) return const IntValue(0); 183 if (this == other) return const IntValue(0);
184 if (other is IntValue) { 184 if (other is IntValue) {
185 if (other.isNegative()) { 185 if (other.isNegative) {
186 return new AddValue(this, -other); 186 return new AddValue(this, -other);
187 } 187 }
188 return new SubtractValue(this, other); 188 return new SubtractValue(this, other);
189 } 189 }
190 if (other is InstructionValue) { 190 if (other is InstructionValue) {
191 return new SubtractValue(this, other); 191 return new SubtractValue(this, other);
192 } 192 }
193 return -other + this; 193 return -other + this;
194 } 194 }
195 195
196 Value operator -() { 196 Value operator -() {
197 return new NegateValue(this); 197 return new NegateValue(this);
198 } 198 }
199 199
200 Value operator &(Value other) { 200 Value operator &(Value other) {
201 if (other is IntValue) return other & this; 201 if (other is IntValue) return other & this;
202 return this; 202 return this;
203 } 203 }
204 204
205 bool isNegative() => false; 205 bool get isNegative => false;
206 bool isPositive() => false; 206 bool get isPositive => false;
207 207
208 String toString() => 'Instruction: $instruction'; 208 String toString() => 'Instruction: $instruction';
209 } 209 }
210 210
211 /** 211 /**
212 * Special value for instructions that represent the length of an 212 * Special value for instructions that represent the length of an
213 * array. The difference with an [InstructionValue] is that we know 213 * array. The difference with an [InstructionValue] is that we know
214 * the value is positive. 214 * the value is positive.
215 */ 215 */
216 class LengthValue extends InstructionValue { 216 class LengthValue extends InstructionValue {
217 LengthValue(HInstruction instruction) : super(instruction); 217 LengthValue(HInstruction instruction) : super(instruction);
218 bool isPositive() => true; 218 bool get isPositive => true;
219 String toString() => 'Length: $instruction'; 219 String toString() => 'Length: $instruction';
220 } 220 }
221 221
222 /** 222 /**
223 * Represents a binary operation on two [Value], where the operation 223 * Represents a binary operation on two [Value], where the operation
224 * did not yield a canonical value. 224 * did not yield a canonical value.
225 */ 225 */
226 class OperationValue extends Value { 226 class OperationValue extends Value {
227 Operation operation; 227 Operation operation;
228 } 228 }
(...skipping 10 matching lines...) Expand all
239 bool operator ==(other) { 239 bool operator ==(other) {
240 if (other is !AddValue) return false; 240 if (other is !AddValue) return false;
241 return (left == other.left && right == other.right) 241 return (left == other.left && right == other.right)
242 || (left == other.right && right == other.left); 242 || (left == other.right && right == other.left);
243 } 243 }
244 244
245 Value operator &(Value other) => const UnknownValue(); 245 Value operator &(Value other) => const UnknownValue();
246 Value operator -() => -left - right; 246 Value operator -() => -left - right;
247 247
248 Value operator +(Value other) { 248 Value operator +(Value other) {
249 if (other.isZero()) return this; 249 if (other.isZero) return this;
250 Value value = left + other; 250 Value value = left + other;
251 if (value != const UnknownValue() && value is! BinaryOperationValue) { 251 if (value != const UnknownValue() && value is! BinaryOperationValue) {
252 return value + right; 252 return value + right;
253 } 253 }
254 // If the result is not simple enough, we try the same approach 254 // If the result is not simple enough, we try the same approach
255 // with [right]. 255 // with [right].
256 value = right + other; 256 value = right + other;
257 if (value != const UnknownValue() && value is! BinaryOperationValue) { 257 if (value != const UnknownValue() && value is! BinaryOperationValue) {
258 return left + value; 258 return left + value;
259 } 259 }
260 return const UnknownValue(); 260 return const UnknownValue();
261 } 261 }
262 262
263 Value operator -(Value other) { 263 Value operator -(Value other) {
264 if (other.isZero()) return this; 264 if (other.isZero) return this;
265 Value value = left - other; 265 Value value = left - other;
266 if (value != const UnknownValue() && value is! BinaryOperationValue) { 266 if (value != const UnknownValue() && value is! BinaryOperationValue) {
267 return value + right; 267 return value + right;
268 } 268 }
269 // If the result is not simple enough, we try the same approach 269 // If the result is not simple enough, we try the same approach
270 // with [right]. 270 // with [right].
271 value = right - other; 271 value = right - other;
272 if (value != const UnknownValue() && value is! BinaryOperationValue) { 272 if (value != const UnknownValue() && value is! BinaryOperationValue) {
273 return left + value; 273 return left + value;
274 } 274 }
275 return const UnknownValue(); 275 return const UnknownValue();
276 } 276 }
277 277
278 bool isNegative() => left.isNegative() && right.isNegative(); 278 bool get isNegative => left.isNegative && right.isNegative;
279 bool isPositive() => left.isPositive() && right.isPositive(); 279 bool get isPositive => left.isPositive && right.isPositive;
280 String toString() => '$left + $right'; 280 String toString() => '$left + $right';
281 } 281 }
282 282
283 class SubtractValue extends BinaryOperationValue { 283 class SubtractValue extends BinaryOperationValue {
284 SubtractValue(left, right) : super(left, right); 284 SubtractValue(left, right) : super(left, right);
285 285
286 bool operator ==(other) { 286 bool operator ==(other) {
287 if (other is !SubtractValue) return false; 287 if (other is !SubtractValue) return false;
288 return left == other.left && right == other.right; 288 return left == other.left && right == other.right;
289 } 289 }
290 290
291 Value operator &(Value other) => const UnknownValue(); 291 Value operator &(Value other) => const UnknownValue();
292 Value operator -() => right - left; 292 Value operator -() => right - left;
293 293
294 Value operator +(Value other) { 294 Value operator +(Value other) {
295 if (other.isZero()) return this; 295 if (other.isZero) return this;
296 Value value = left + other; 296 Value value = left + other;
297 if (value != const UnknownValue() && value is! BinaryOperationValue) { 297 if (value != const UnknownValue() && value is! BinaryOperationValue) {
298 return value - right; 298 return value - right;
299 } 299 }
300 // If the result is not simple enough, we try the same approach 300 // If the result is not simple enough, we try the same approach
301 // with [right]. 301 // with [right].
302 value = other - right; 302 value = other - right;
303 if (value != const UnknownValue() && value is! BinaryOperationValue) { 303 if (value != const UnknownValue() && value is! BinaryOperationValue) {
304 return left + value; 304 return left + value;
305 } 305 }
306 return const UnknownValue(); 306 return const UnknownValue();
307 } 307 }
308 308
309 Value operator -(Value other) { 309 Value operator -(Value other) {
310 if (other.isZero()) return this; 310 if (other.isZero) return this;
311 Value value = left - other; 311 Value value = left - other;
312 if (value != const UnknownValue() && value is! BinaryOperationValue) { 312 if (value != const UnknownValue() && value is! BinaryOperationValue) {
313 return value - right; 313 return value - right;
314 } 314 }
315 // If the result is not simple enough, we try the same approach 315 // If the result is not simple enough, we try the same approach
316 // with [right]. 316 // with [right].
317 value = right + other; 317 value = right + other;
318 if (value != const UnknownValue() && value is! BinaryOperationValue) { 318 if (value != const UnknownValue() && value is! BinaryOperationValue) {
319 return left - value; 319 return left - value;
320 } 320 }
321 return const UnknownValue(); 321 return const UnknownValue();
322 } 322 }
323 323
324 bool isNegative() => left.isNegative() && right.isPositive(); 324 bool get isNegative => left.isNegative && right.isPositive;
325 bool isPositive() => left.isPositive() && right.isNegative(); 325 bool get isPositive => left.isPositive && right.isNegative;
326 String toString() => '$left - $right'; 326 String toString() => '$left - $right';
327 } 327 }
328 328
329 class NegateValue extends OperationValue { 329 class NegateValue extends OperationValue {
330 final Value value; 330 final Value value;
331 NegateValue(this.value); 331 NegateValue(this.value);
332 332
333 bool operator ==(other) { 333 bool operator ==(other) {
334 if (other is !NegateValue) return false; 334 if (other is !NegateValue) return false;
335 return value == other.value; 335 return value == other.value;
336 } 336 }
337 337
338 Value operator +(other) { 338 Value operator +(other) {
339 if (other.isZero()) return this; 339 if (other.isZero) return this;
340 if (other == value) return const IntValue(0); 340 if (other == value) return const IntValue(0);
341 if (other is NegateValue) return this - other.value; 341 if (other is NegateValue) return this - other.value;
342 if (other is IntValue) { 342 if (other is IntValue) {
343 if (other.isNegative()) { 343 if (other.isNegative) {
344 return new SubtractValue(this, -other); 344 return new SubtractValue(this, -other);
345 } 345 }
346 return new SubtractValue(other, value); 346 return new SubtractValue(other, value);
347 } 347 }
348 if (other is InstructionValue) { 348 if (other is InstructionValue) {
349 return new SubtractValue(other, value); 349 return new SubtractValue(other, value);
350 } 350 }
351 return other - value; 351 return other - value;
352 } 352 }
353 353
354 Value operator &(Value other) => const UnknownValue(); 354 Value operator &(Value other) => const UnknownValue();
355 355
356 Value operator -(other) { 356 Value operator -(other) {
357 if (other.isZero()) return this; 357 if (other.isZero) return this;
358 if (other is IntValue) { 358 if (other is IntValue) {
359 if (other.isNegative()) { 359 if (other.isNegative) {
360 return new SubtractValue(-other, value); 360 return new SubtractValue(-other, value);
361 } 361 }
362 return new SubtractValue(this, other); 362 return new SubtractValue(this, other);
363 } 363 }
364 if (other is InstructionValue) { 364 if (other is InstructionValue) {
365 return new SubtractValue(this, other); 365 return new SubtractValue(this, other);
366 } 366 }
367 if (other is NegateValue) return this + other.value; 367 if (other is NegateValue) return this + other.value;
368 return -other - value; 368 return -other - value;
369 } 369 }
370 370
371 Value operator -() => value; 371 Value operator -() => value;
372 372
373 bool isNegative() => value.isPositive(); 373 bool get isNegative => value.isPositive;
374 bool isPositive() => value.isNegative(); 374 bool get isPositive => value.isNegative;
375 String toString() => '-$value'; 375 String toString() => '-$value';
376 } 376 }
377 377
378 /** 378 /**
379 * A [Range] represents the possible integer values an instruction 379 * A [Range] represents the possible integer values an instruction
380 * can have, from its [lower] bound to its [upper] bound, both 380 * can have, from its [lower] bound to its [upper] bound, both
381 * included. 381 * included.
382 */ 382 */
383 class Range { 383 class Range {
384 final Value lower; 384 final Value lower;
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
423 423
424 Range operator -(Range other) { 424 Range operator -(Range other) {
425 return new Range.normalize(lower - other.upper, upper - other.lower); 425 return new Range.normalize(lower - other.upper, upper - other.lower);
426 } 426 }
427 427
428 Range operator -() { 428 Range operator -() {
429 return new Range.normalize(-upper, -lower); 429 return new Range.normalize(-upper, -lower);
430 } 430 }
431 431
432 Range operator &(Range other) { 432 Range operator &(Range other) {
433 if (isSingleValue() 433 if (isSingleValue
434 && other.isSingleValue() 434 && other.isSingleValue
435 && lower is IntValue 435 && lower is IntValue
436 && other.lower is IntValue) { 436 && other.lower is IntValue) {
437 return new Range(lower & other.lower, upper & other.upper); 437 return new Range(lower & other.lower, upper & other.upper);
438 } 438 }
439 if (isPositive() && other.isPositive()) { 439 if (isPositive && other.isPositive) {
440 Value up = upper.min(other.upper); 440 Value up = upper.min(other.upper);
441 if (up == const UnknownValue()) { 441 if (up == const UnknownValue()) {
442 // If we could not find a trivial bound, just try to use the 442 // If we could not find a trivial bound, just try to use the
443 // one that is an int. 443 // one that is an int.
444 up = upper is IntValue ? upper : other.upper; 444 up = upper is IntValue ? upper : other.upper;
445 // Make sure we get the same upper bound, whether it's a & b 445 // Make sure we get the same upper bound, whether it's a & b
446 // or b & a. 446 // or b & a.
447 if (up is! IntValue && upper != other.upper) up = const MaxIntValue(); 447 if (up is! IntValue && upper != other.upper) up = const MaxIntValue();
448 } 448 }
449 return new Range(const IntValue(0), up); 449 return new Range(const IntValue(0), up);
450 } else if (isPositive()) { 450 } else if (isPositive) {
451 return new Range(const IntValue(0), upper); 451 return new Range(const IntValue(0), upper);
452 } else if (other.isPositive()) { 452 } else if (other.isPositive) {
453 return new Range(const IntValue(0), other.upper); 453 return new Range(const IntValue(0), other.upper);
454 } else { 454 } else {
455 return const Range.unbound(); 455 return const Range.unbound();
456 } 456 }
457 } 457 }
458 458
459 bool operator ==(other) { 459 bool operator ==(other) {
460 if (other is! Range) return false; 460 if (other is! Range) return false;
461 return other.lower == lower && other.upper == upper; 461 return other.lower == lower && other.upper == upper;
462 } 462 }
463 463
464 bool operator <(Range other) { 464 bool operator <(Range other) {
465 return upper != other.lower && upper.min(other.lower) == upper; 465 return upper != other.lower && upper.min(other.lower) == upper;
466 } 466 }
467 467
468 bool operator >(Range other) { 468 bool operator >(Range other) {
469 return lower != other.upper && lower.max(other.upper) == lower; 469 return lower != other.upper && lower.max(other.upper) == lower;
470 } 470 }
471 471
472 bool operator <=(Range other) { 472 bool operator <=(Range other) {
473 return upper.min(other.lower) == upper; 473 return upper.min(other.lower) == upper;
474 } 474 }
475 475
476 bool operator >=(Range other) { 476 bool operator >=(Range other) {
477 return lower.max(other.upper) == lower; 477 return lower.max(other.upper) == lower;
478 } 478 }
479 479
480 bool isNegative() => upper.isNegative(); 480 bool get isNegative => upper.isNegative;
481 bool isPositive() => lower.isPositive(); 481 bool get isPositive => lower.isPositive;
482 bool isSingleValue() => lower == upper; 482 bool get isSingleValue => lower == upper;
483 483
484 String toString() => '[$lower, $upper]'; 484 String toString() => '[$lower, $upper]';
485 } 485 }
486 486
487 /** 487 /**
488 * Visits the graph in dominator order, and computes value ranges for 488 * Visits the graph in dominator order, and computes value ranges for
489 * integer instructions. While visiting the graph, this phase also 489 * integer instructions. While visiting the graph, this phase also
490 * removes unnecessary bounds checks, and comparisons that are proven 490 * removes unnecessary bounds checks, and comparisons that are proven
491 * to be true or false. 491 * to be true or false.
492 */ 492 */
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 // range. 602 // range.
603 Value maxIndex = lengthRange.upper - const IntValue(1); 603 Value maxIndex = lengthRange.upper - const IntValue(1);
604 bool belowLength = maxIndex != const MaxIntValue() 604 bool belowLength = maxIndex != const MaxIntValue()
605 && indexRange.upper.min(maxIndex) == indexRange.upper; 605 && indexRange.upper.min(maxIndex) == indexRange.upper;
606 606
607 // Check if the index is strictly below the lower bound of the length 607 // Check if the index is strictly below the lower bound of the length
608 // range. 608 // range.
609 belowLength = belowLength 609 belowLength = belowLength
610 || (indexRange.upper != lengthRange.lower 610 || (indexRange.upper != lengthRange.lower
611 && indexRange.upper.min(lengthRange.lower) == indexRange.upper); 611 && indexRange.upper.min(lengthRange.lower) == indexRange.upper);
612 if (indexRange.isPositive() && belowLength) { 612 if (indexRange.isPositive && belowLength) {
613 check.block.rewrite(check, check.index); 613 check.block.rewrite(check, check.index);
614 check.block.remove(check); 614 check.block.remove(check);
615 } else if (indexRange.isNegative() || lengthRange < indexRange) { 615 } else if (indexRange.isNegative || lengthRange < indexRange) {
616 check.staticChecks = HBoundsCheck.ALWAYS_FALSE; 616 check.staticChecks = HBoundsCheck.ALWAYS_FALSE;
617 // The check is always false, and whatever instruction it 617 // The check is always false, and whatever instruction it
618 // dominates is dead code. 618 // dominates is dead code.
619 return indexRange; 619 return indexRange;
620 } else if (indexRange.isPositive()) { 620 } else if (indexRange.isPositive) {
621 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO; 621 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO;
622 } else if (belowLength) { 622 } else if (belowLength) {
623 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH; 623 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH;
624 } 624 }
625 625
626 if (indexRange.isPositive()) { 626 if (indexRange.isPositive) {
627 // If the test passes, we know the lower bound of the length is 627 // If the test passes, we know the lower bound of the length is
628 // greater or equal than the lower bound of the index. 628 // greater or equal than the lower bound of the index.
629 Value low = lengthRange.lower.max(indexRange.lower); 629 Value low = lengthRange.lower.max(indexRange.lower);
630 if (low != const UnknownValue()) { 630 if (low != const UnknownValue()) {
631 HInstruction instruction = 631 HInstruction instruction =
632 createRangeConversion(next, check.length); 632 createRangeConversion(next, check.length);
633 ranges[instruction] = new Range(low, lengthRange.upper); 633 ranges[instruction] = new Range(low, lengthRange.upper);
634 } 634 }
635 } 635 }
636 636
(...skipping 30 matching lines...) Expand all
667 relational.block.rewrite( 667 relational.block.rewrite(
668 relational, graph.addConstantBool(false, constantSystem)); 668 relational, graph.addConstantBool(false, constantSystem));
669 relational.block.remove(relational); 669 relational.block.remove(relational);
670 } 670 }
671 return const Range.unbound(); 671 return const Range.unbound();
672 } 672 }
673 673
674 void handleEqualityCheck(HRelational node) { 674 void handleEqualityCheck(HRelational node) {
675 Range right = ranges[node.right]; 675 Range right = ranges[node.right];
676 Range left = ranges[node.left]; 676 Range left = ranges[node.left];
677 if (left.isSingleValue() && right.isSingleValue() && left == right) { 677 if (left.isSingleValue && right.isSingleValue && left == right) {
678 node.block.rewrite( 678 node.block.rewrite(
679 node, graph.addConstantBool(true, constantSystem)); 679 node, graph.addConstantBool(true, constantSystem));
680 node.block.remove(node); 680 node.block.remove(node);
681 } 681 }
682 } 682 }
683 683
684 Range handleBinaryOperation(HBinaryArithmetic instruction) { 684 Range handleBinaryOperation(HBinaryArithmetic instruction) {
685 if (!instruction.isInteger(types)) return const Range.unbound(); 685 if (!instruction.isInteger(types)) return const Range.unbound();
686 return instruction.operation(constantSystem).apply( 686 return instruction.operation(constantSystem).apply(
687 ranges[instruction.left], ranges[instruction.right]); 687 ranges[instruction.left], ranges[instruction.right]);
(...skipping 10 matching lines...) Expand all
698 Range visitBitAnd(HBitAnd node) { 698 Range visitBitAnd(HBitAnd node) {
699 if (!node.isInteger(types)) return const Range.unbound(); 699 if (!node.isInteger(types)) return const Range.unbound();
700 HInstruction right = node.right; 700 HInstruction right = node.right;
701 HInstruction left = node.left; 701 HInstruction left = node.left;
702 if (left.isInteger(types) && right.isInteger(types)) { 702 if (left.isInteger(types) && right.isInteger(types)) {
703 return ranges[left] & ranges[right]; 703 return ranges[left] & ranges[right];
704 } 704 }
705 705
706 Range tryComputeRange(HInstruction instruction) { 706 Range tryComputeRange(HInstruction instruction) {
707 Range range = ranges[instruction]; 707 Range range = ranges[instruction];
708 if (range.isPositive()) { 708 if (range.isPositive) {
709 return new Range(const IntValue(0), range.upper); 709 return new Range(const IntValue(0), range.upper);
710 } else if (range.isNegative()) { 710 } else if (range.isNegative) {
711 return new Range(range.lower, const IntValue(0)); 711 return new Range(range.lower, const IntValue(0));
712 } 712 }
713 return const Range.unbound(); 713 return const Range.unbound();
714 } 714 }
715 715
716 if (left.isInteger(types)) { 716 if (left.isInteger(types)) {
717 return tryComputeRange(left); 717 return tryComputeRange(left);
718 } else if (right.isInteger(types)) { 718 } else if (right.isInteger(types)) {
719 return tryComputeRange(right); 719 return tryComputeRange(right);
720 } 720 }
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
848 class LoopUpdateRecognizer extends HBaseVisitor { 848 class LoopUpdateRecognizer extends HBaseVisitor {
849 final HPhi loopPhi; 849 final HPhi loopPhi;
850 final Map<HInstruction, Range> ranges; 850 final Map<HInstruction, Range> ranges;
851 final HTypeMap types; 851 final HTypeMap types;
852 LoopUpdateRecognizer(this.loopPhi, this.ranges, this.types); 852 LoopUpdateRecognizer(this.loopPhi, this.ranges, this.types);
853 853
854 Range visitAdd(HAdd operation) { 854 Range visitAdd(HAdd operation) {
855 Range range = getRangeForRecognizableOperation(operation); 855 Range range = getRangeForRecognizableOperation(operation);
856 if (range == null) return const Range.unbound(); 856 if (range == null) return const Range.unbound();
857 Range initial = ranges[loopPhi.inputs[0]]; 857 Range initial = ranges[loopPhi.inputs[0]];
858 if (range.isPositive()) { 858 if (range.isPositive) {
859 return new Range(initial.lower, const MaxIntValue()); 859 return new Range(initial.lower, const MaxIntValue());
860 } else if (range.isNegative()) { 860 } else if (range.isNegative) {
861 return new Range(const MinIntValue(), initial.upper); 861 return new Range(const MinIntValue(), initial.upper);
862 } 862 }
863 return const Range.unbound(); 863 return const Range.unbound();
864 } 864 }
865 865
866 Range visitSubtract(HSubtract operation) { 866 Range visitSubtract(HSubtract operation) {
867 Range range = getRangeForRecognizableOperation(operation); 867 Range range = getRangeForRecognizableOperation(operation);
868 if (range == null) return const Range.unbound(); 868 if (range == null) return const Range.unbound();
869 Range initial = ranges[loopPhi.inputs[0]]; 869 Range initial = ranges[loopPhi.inputs[0]];
870 if (range.isPositive()) { 870 if (range.isPositive) {
871 return new Range(const MinIntValue(), initial.upper); 871 return new Range(const MinIntValue(), initial.upper);
872 } else if (range.isNegative()) { 872 } else if (range.isNegative) {
873 return new Range(initial.lower, const MaxIntValue()); 873 return new Range(initial.lower, const MaxIntValue());
874 } 874 }
875 return const Range.unbound(); 875 return const Range.unbound();
876 } 876 }
877 877
878 Range visitPhi(HPhi phi) { 878 Range visitPhi(HPhi phi) {
879 Range phiRange; 879 Range phiRange;
880 for (HInstruction input in phi.inputs) { 880 for (HInstruction input in phi.inputs) {
881 HInstruction instruction = unwrap(input); 881 HInstruction instruction = unwrap(input);
882 // If one of the inputs is the loop phi, then we're only 882 // If one of the inputs is the loop phi, then we're only
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
937 if (instruction is HPhi && !instruction.block.isLoopHeader()) { 937 if (instruction is HPhi && !instruction.block.isLoopHeader()) {
938 HInstruction result = unwrap(instruction.inputs[0]); 938 HInstruction result = unwrap(instruction.inputs[0]);
939 for (int i = 1; i < instruction.inputs.length; i++) { 939 for (int i = 1; i < instruction.inputs.length; i++) {
940 if (result != unwrap(instruction.inputs[i])) return instruction; 940 if (result != unwrap(instruction.inputs[i])) return instruction;
941 } 941 }
942 return result; 942 return result;
943 } 943 }
944 return instruction; 944 return instruction;
945 } 945 }
946 } 946 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698