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

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

Powered by Google App Engine
This is Rietveld 408576698