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

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

Issue 11066053: Better value range propagation by supporting negating ranges. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 2 months 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);
Søren Gjesse 2012/10/08 14:00:42 Don't you want to add unary minus here as well?
ngeoffray 2012/10/08 14:16:39 Yes. Done.
15 Value operator &(Value other); 15 Value operator &(Value other);
16 16
17 Value min(Value other) { 17 Value min(Value other) {
18 if (this == other) return this; 18 if (this == other) return this;
19 if (other == const MinIntValue()) return other; 19 if (other == const MinIntValue()) return other;
20 if (other == const MaxIntValue()) return this; 20 if (other == const MaxIntValue()) return this;
21 Value value = this - other; 21 Value value = this - other;
22 if (value.isPositive()) return other; 22 if (value.isPositive()) return other;
23 if (value.isNegative()) return this; 23 if (value.isNegative()) return this;
24 return const UnknownValue(); 24 return const UnknownValue();
(...skipping 15 matching lines...) Expand all
40 } 40 }
41 41
42 /** 42 /**
43 * An [IntValue] contains a constant integer value. 43 * An [IntValue] contains a constant integer value.
44 */ 44 */
45 class IntValue extends Value { 45 class IntValue extends Value {
46 final int value; 46 final int value;
47 const IntValue(this.value); 47 const IntValue(this.value);
48 48
49 Value operator +(other) { 49 Value operator +(other) {
50 if (other.isZero()) return this;
50 if (other is !IntValue) return other + this; 51 if (other is !IntValue) return other + this;
51 return new IntValue(value + other.value); 52 return new IntValue(value + other.value);
52 } 53 }
53 54
54 Value operator -(other) { 55 Value operator -(other) {
55 if (other is !IntValue) { 56 if (other.isZero()) return this;
56 return new OperationValue(this, other, const SubtractOperation()); 57 if (other is !IntValue) return -other + this;
57 }
58 return new IntValue(value - other.value); 58 return new IntValue(value - other.value);
59 } 59 }
60 60
61 Value operator -() {
62 if (isZero()) return this;
63 return new IntValue(-value);
64 }
65
61 Value operator &(other) { 66 Value operator &(other) {
62 if (other is !IntValue) { 67 if (other is !IntValue) {
63 if (isPositive()) return this; 68 if (isPositive()) return this;
64 if (other.isPositive()) return new IntValue(-value); 69 if (other.isPositive()) return new IntValue(-value);
65 return const UnknownValue(); 70 return const UnknownValue();
66 } 71 }
67 return new IntValue(value & other.value); 72 return new IntValue(value & other.value);
68 } 73 }
69 74
70 Value min(other) { 75 Value min(other) {
(...skipping 18 matching lines...) Expand all
89 } 94 }
90 95
91 /** 96 /**
92 * The [MaxIntValue] represents the maximum value an integer can have, 97 * The [MaxIntValue] represents the maximum value an integer can have,
93 * which is currently +infinity. 98 * which is currently +infinity.
94 */ 99 */
95 class MaxIntValue extends Value { 100 class MaxIntValue extends Value {
96 const MaxIntValue(); 101 const MaxIntValue();
97 Value operator +(Value other) => this; 102 Value operator +(Value other) => this;
98 Value operator -(Value other) => this; 103 Value operator -(Value other) => this;
104 Value operator -() => const MinIntValue();
99 Value operator &(Value other) { 105 Value operator &(Value other) {
100 if (other.isPositive()) return other; 106 if (other.isPositive()) return other;
101 if (other.isNegative()) return const IntValue(0); 107 if (other.isNegative()) return const IntValue(0);
102 return this; 108 return this;
103 } 109 }
104 Value min(Value other) => other; 110 Value min(Value other) => other;
105 Value max(Value other) => this; 111 Value max(Value other) => this;
106 String toString() => 'Max'; 112 String toString() => 'Max';
107 bool isNegative() => false; 113 bool isNegative() => false;
108 bool isPositive() => true; 114 bool isPositive() => true;
109 } 115 }
110 116
111 /** 117 /**
112 * The [MinIntValue] represents the minimum value an integer can have, 118 * The [MinIntValue] represents the minimum value an integer can have,
113 * which is currently -infinity. 119 * which is currently -infinity.
114 */ 120 */
115 class MinIntValue extends Value { 121 class MinIntValue extends Value {
116 const MinIntValue(); 122 const MinIntValue();
117 Value operator +(Value other) => this; 123 Value operator +(Value other) => this;
118 Value operator -(Value other) => this; 124 Value operator -(Value other) => this;
125 Value operator -() => const MaxIntValue();
119 Value operator &(Value other) { 126 Value operator &(Value other) {
120 if (other.isPositive()) return const IntValue(0); 127 if (other.isPositive()) return const IntValue(0);
121 return this; 128 return this;
122 } 129 }
123 Value min(Value other) => this; 130 Value min(Value other) => this;
124 Value max(Value other) => other; 131 Value max(Value other) => other;
125 String toString() => 'Min'; 132 String toString() => 'Min';
126 bool isNegative() => true; 133 bool isNegative() => true;
127 bool isPositive() => false; 134 bool isPositive() => false;
128 } 135 }
129 136
130 /** 137 /**
131 * The [UnknownValue] is the sentinel in our analysis to mark an 138 * The [UnknownValue] is the sentinel in our analysis to mark an
132 * operation that could not be done because of too much complexity. 139 * operation that could not be done because of too much complexity.
133 */ 140 */
134 class UnknownValue extends Value { 141 class UnknownValue extends Value {
135 const UnknownValue(); 142 const UnknownValue();
136 Value operator +(Value other) => const UnknownValue(); 143 Value operator +(Value other) => const UnknownValue();
137 Value operator -(Value other) => const UnknownValue(); 144 Value operator -(Value other) => const UnknownValue();
145 Value operator -() => const UnknownValue();
138 Value operator &(Value other) => const UnknownValue(); 146 Value operator &(Value other) => const UnknownValue();
139 Value min(Value other) => const UnknownValue(); 147 Value min(Value other) => const UnknownValue();
140 Value max(Value other) => const UnknownValue(); 148 Value max(Value other) => const UnknownValue();
141 bool isNegative() => false; 149 bool isNegative() => false;
142 bool isPositive() => false; 150 bool isPositive() => false;
143 String toString() => 'Unknown'; 151 String toString() => 'Unknown';
144 } 152 }
145 153
146 /** 154 /**
147 * A symbolic value representing an [HInstruction]. 155 * A symbolic value representing an [HInstruction].
148 */ 156 */
149 class InstructionValue extends Value { 157 class InstructionValue extends Value {
150 final HInstruction instruction; 158 final HInstruction instruction;
151 InstructionValue(this.instruction); 159 InstructionValue(this.instruction);
152 160
153 bool operator ==(other) { 161 bool operator ==(other) {
154 if (other is !InstructionValue) return false; 162 if (other is !InstructionValue) return false;
155 return this.instruction == other.instruction; 163 return this.instruction == other.instruction;
156 } 164 }
157 165
158 Value operator +(Value other) { 166 Value operator +(Value other) {
159 if (other.isZero()) return this; 167 if (other.isZero()) return this;
160 return new OperationValue(this, other, const AddOperation()); 168 if (other is IntValue) {
169 if (other.isNegative()) {
170 return new SubtractValue(this, -other);
171 }
172 return new AddValue(this, other);
173 }
174 if (other is InstructionValue) {
175 return new AddValue(this, other);
176 }
177 return other + this;
161 } 178 }
162 179
163 Value operator -(Value other) { 180 Value operator -(Value other) {
164 if (other.isZero()) return this; 181 if (other.isZero()) return this;
165 if (this == other) return const IntValue(0); 182 if (this == other) return const IntValue(0);
166 return new OperationValue(this, other, const SubtractOperation()); 183 if (other is IntValue) {
184 if (other.isNegative()) {
185 return new AddValue(this, -other);
186 }
187 return new SubtractValue(this, other);
188 }
189 if (other is InstructionValue) {
190 return new SubtractValue(this, other);
191 }
192 return -other + this;
193 }
194
195 Value operator -() {
196 return new NegateValue(this);
167 } 197 }
168 198
169 Value operator &(Value other) { 199 Value operator &(Value other) {
170 if (other is IntValue) return other & this; 200 if (other is IntValue) return other & this;
171 return this; 201 return this;
172 } 202 }
173 203
174 bool isNegative() => false; 204 bool isNegative() => false;
175 bool isPositive() => false; 205 bool isPositive() => false;
176 206
177 String toString() => 'Instruction: $instruction'; 207 String toString() => 'Instruction: $instruction';
178 } 208 }
179 209
180 /** 210 /**
181 * Special value for instructions that represent the length of an 211 * Special value for instructions that represent the length of an
182 * array. The difference with an [InstructionValue] is that we know 212 * array. The difference with an [InstructionValue] is that we know
183 * the value is positive. 213 * the value is positive.
184 */ 214 */
185 class LengthValue extends InstructionValue { 215 class LengthValue extends InstructionValue {
186 LengthValue(HInstruction instruction) : super(instruction); 216 LengthValue(HInstruction instruction) : super(instruction);
187 bool isPositive() => true; 217 bool isPositive() => true;
188 String toString() => 'Length: $instruction'; 218 String toString() => 'Length: $instruction';
189 } 219 }
190 220
191 /** 221 /**
192 * Represents a binary operation on two [Value], where the operation 222 * Represents a binary operation on two [Value], where the operation
193 * did not yield a canonical value. 223 * did not yield a canonical value.
194 */ 224 */
195 class OperationValue extends Value { 225 class OperationValue extends Value {
226 Operation operation;
227 }
228
229 class BinaryOperationValue extends OperationValue {
196 final Value left; 230 final Value left;
197 final Value right; 231 final Value right;
198 final BinaryOperation operation; 232 BinaryOperationValue(this.left, this.right);
199 OperationValue(this.left, this.right, this.operation); 233 }
234
235 class AddValue extends BinaryOperationValue {
236 AddValue(left, right) : super(left, right);
200 237
201 bool operator ==(other) { 238 bool operator ==(other) {
202 if (other is !OperationValue) return false; 239 if (other is !AddValue) return false;
203 return left == other.left 240 return (left == other.left && right == other.right)
204 && right == other.right 241 || (left == other.right && right == other.left);
205 && operation == other.operation;
206 } 242 }
207 243
208 Value operator +(Value other) => const UnknownValue();
209 Value operator &(Value other) => const UnknownValue(); 244 Value operator &(Value other) => const UnknownValue();
245 Value operator -() => -left - right;
Søren Gjesse 2012/10/08 14:00:42 Maybe -(left + right) instead.
ngeoffray 2012/10/08 14:16:39 Calling -(left + right) will actually yield -left
210 246
211 Value operator -(Value other) { 247 Value operator +(Value other) {
212 if (operation is! SubtractOperation && operation is! AddOperation) { 248 if (other.isZero()) return this;
213 return const UnknownValue(); 249 Value value = left + other;
214 } 250 if (value != const UnknownValue() && value is! BinaryOperationValue) {
215 // We try to create a simple [Value] out of this operation. So we 251 return value + right;
216 // first try to substract [other] to [left]. If the result is simple
217 // enough (not unknown and not an operation), we return the result
218 // of doing the operation of this [OperationValue] on the previous
219 // result and [right].
220 //
221 // For example:
222 // OperationValue(LengthValue(i1), IntValue(42), '-') - LengthValue(i1)
223 //
224 // Will return IntValue(-42)
225 Value value = left - other;
226 if (value != const UnknownValue() && value is! OperationValue) {
227 return operation.apply(value, right);
228 } 252 }
229 // If the result is not simple enough, we try the same approach 253 // If the result is not simple enough, we try the same approach
230 // with [right]. 254 // with [right].
231 if (operation is SubtractOperation) { 255 value = right + other;
232 value = right + other; 256 if (value != const UnknownValue() && value is! BinaryOperationValue) {
233 } else { 257 return left + value;
234 assert(operation is AddOperation);
235 value = right - other;
236 } 258 }
237 if (value != const UnknownValue() && value is! OperationValue) { 259 return const UnknownValue();
238 return operation.apply(left, value); 260 }
261
262 Value operator -(Value other) {
263 if (other.isZero()) return this;
264 Value value = left - other;
265 if (value != const UnknownValue() && value is! BinaryOperationValue) {
266 return value + right;
267 }
268 // If the result is not simple enough, we try the same approach
269 // with [right].
270 value = right - other;
271 if (value != const UnknownValue() && value is! BinaryOperationValue) {
272 return left + value;
273 }
274 return const UnknownValue();
275 }
276
277 bool isNegative() => left.isNegative() && right.isNegative();
278 bool isPositive() => left.isPositive() && right.isPositive();
279 String toString() => '$left + $right';
280 }
281
282 class SubtractValue extends BinaryOperationValue {
283 SubtractValue(left, right) : super(left, right);
284
285 bool operator ==(other) {
286 if (other is !SubtractValue) return false;
287 return left == other.left && right == other.right;
288 }
289
290 Value operator &(Value other) => const UnknownValue();
291 Value operator -() => right - left;
292
293 Value operator +(Value other) {
294 if (other.isZero()) return this;
295 Value value = left + other;
296 if (value != const UnknownValue() && value is! BinaryOperationValue) {
297 return value - right;
298 }
299 // If the result is not simple enough, we try the same approach
300 // with [right].
301 value = other - right;
302 if (value != const UnknownValue() && value is! BinaryOperationValue) {
303 return left + value;
304 }
305 return const UnknownValue();
306 }
307
308 Value operator -(Value other) {
309 if (other.isZero()) return this;
310 Value value = left - other;
311 if (value != const UnknownValue() && value is! BinaryOperationValue) {
312 return value - right;
313 }
314 // If the result is not simple enough, we try the same approach
315 // with [right].
316 value = right + other;
317 if (value != const UnknownValue() && value is! BinaryOperationValue) {
318 return left - value;
239 } 319 }
240 return const UnknownValue(); 320 return const UnknownValue();
241 } 321 }
242 322
243 bool isNegative() => false; 323 bool isNegative() => false;
Søren Gjesse 2012/10/08 14:00:42 Isn't this negative if left is negative and right
ngeoffray 2012/10/08 14:16:39 You're right. Done.
244 bool isPositive() => false; 324 bool isPositive() => left.isPositive() && right.isNegative();
245 String toString() => '$left ${operation.name} $right'; 325 String toString() => '$left - $right';
326 }
327
328 class NegateValue extends OperationValue {
329 final Value value;
330 NegateValue(this.value);
331
332 bool operator ==(other) {
333 if (other is !NegateValue) return false;
334 return value == other.value;
335 }
336
337 Value operator +(other) {
338 if (other.isZero()) return this;
339 if (other == value) return const IntValue(0);
340 if (other is NegateValue) return this - other.value;
341 if (other is IntValue) {
342 if (other.isNegative()) {
343 return new SubtractValue(this, -other);
344 }
345 return new SubtractValue(other, value);
346 }
347 if (other is InstructionValue) {
348 return new SubtractValue(other, value);
349 }
350 return other - value;
351 }
352
353 Value operator &(Value other) => const UnknownValue();
354
355 Value operator -(other) {
356 if (other.isZero()) return this;
357 if (other is IntValue) {
358 if (other.isNegative()) {
359 return new SubtractValue(-other, value);
360 }
361 return new SubtractValue(this, other);
362 }
363 if (other is InstructionValue) {
364 return new SubtractValue(this, other);
365 }
366 if (other is NegateValue) return this + other.value;
367 return -other - value;
368 }
369
370 Value operator -() => value;
371
372 bool isNegative() => value.isPositive();
373 bool isPositive() => value.isNegative();
374 String toString() => '-$value';
246 } 375 }
247 376
248 /** 377 /**
249 * A [Range] represents the possible integer values an instruction 378 * A [Range] represents the possible integer values an instruction
250 * can have, from its [lower] bound to its [upper] bound, both 379 * can have, from its [lower] bound to its [upper] bound, both
251 * included. 380 * included.
252 */ 381 */
253 class Range { 382 class Range {
254 final Value lower; 383 final Value lower;
255 final Value upper; 384 final Value upper;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
288 } 417 }
289 418
290 Range operator +(Range other) { 419 Range operator +(Range other) {
291 return new Range.normalize(lower + other.lower, upper + other.upper); 420 return new Range.normalize(lower + other.lower, upper + other.upper);
292 } 421 }
293 422
294 Range operator -(Range other) { 423 Range operator -(Range other) {
295 return new Range.normalize(lower - other.upper, upper - other.lower); 424 return new Range.normalize(lower - other.upper, upper - other.lower);
296 } 425 }
297 426
427 Range operator -() {
428 return new Range.normalize(-upper, -lower);
429 }
430
298 Range operator &(Range other) { 431 Range operator &(Range other) {
299 if (isSingleValue() 432 if (isSingleValue()
300 && other.isSingleValue() 433 && other.isSingleValue()
301 && lower is IntValue 434 && lower is IntValue
302 && other.lower is IntValue) { 435 && other.lower is IntValue) {
303 return new Range(lower & other.lower, upper & other.upper); 436 return new Range(lower & other.lower, upper & other.upper);
304 } 437 }
305 if (isPositive() && other.isPositive()) { 438 if (isPositive() && other.isPositive()) {
306 Value up = upper.min(other.upper); 439 Value up = upper.min(other.upper);
307 if (up == const UnknownValue()) { 440 if (up == const UnknownValue()) {
(...skipping 495 matching lines...) Expand 10 before | Expand all | Expand 10 after
803 if (instruction is HPhi && !instruction.block.isLoopHeader()) { 936 if (instruction is HPhi && !instruction.block.isLoopHeader()) {
804 HInstruction result = unwrap(instruction.inputs[0]); 937 HInstruction result = unwrap(instruction.inputs[0]);
805 for (int i = 1; i < instruction.inputs.length; i++) { 938 for (int i = 1; i < instruction.inputs.length; i++) {
806 if (result != unwrap(instruction.inputs[i])) return instruction; 939 if (result != unwrap(instruction.inputs[i])) return instruction;
807 } 940 }
808 return result; 941 return result;
809 } 942 }
810 return instruction; 943 return instruction;
811 } 944 }
812 } 945 }
OLDNEW
« no previous file with comments | « no previous file | tests/compiler/dart2js/value_range2_test.dart » ('j') | tests/compiler/dart2js/value_range2_test.dart » ('J')

Powered by Google App Engine
This is Rietveld 408576698