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

Side by Side Diff: pkg/compiler/lib/src/ssa/value_range_analyzer.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
« no previous file with comments | « pkg/compiler/lib/src/ssa/validate.dart ('k') | pkg/compiler/lib/src/ssa/value_set.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 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 5 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
6 import '../compiler.dart' show Compiler; 6 import '../compiler.dart' show Compiler;
7 import '../constant_system_dart.dart'; 7 import '../constant_system_dart.dart';
8 import '../constants/constant_system.dart'; 8 import '../constants/constant_system.dart';
9 import '../constants/values.dart'; 9 import '../constants/values.dart';
10 import '../js_backend/js_backend.dart'; 10 import '../js_backend/js_backend.dart';
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
49 49
50 Range newUnboundRange() { 50 Range newUnboundRange() {
51 return new Range.unbound(this); 51 return new Range.unbound(this);
52 } 52 }
53 53
54 Range newNormalizedRange(Value low, Value up) { 54 Range newNormalizedRange(Value low, Value up) {
55 return new Range.normalize(low, up, this); 55 return new Range.normalize(low, up, this);
56 } 56 }
57 57
58 Range newMarkerRange() { 58 Range newMarkerRange() {
59 return new Range(new MarkerValue(false, this), 59 return new Range(
60 new MarkerValue(true, this), 60 new MarkerValue(false, this), new MarkerValue(true, this), this);
61 this);
62 } 61 }
63 } 62 }
64 63
65 /** 64 /**
66 * A [Value] represents both symbolic values like the value of a 65 * A [Value] represents both symbolic values like the value of a
67 * parameter, or the length of an array, and concrete values, like 66 * parameter, or the length of an array, and concrete values, like
68 * constants. 67 * constants.
69 */ 68 */
70 abstract class Value { 69 abstract class Value {
71 final ValueRangeInfo info; 70 final ValueRangeInfo info;
72 const Value(this.info); 71 const Value(this.info);
73 72
74 Value operator +(Value other) => const UnknownValue(); 73 Value operator +(Value other) => const UnknownValue();
75 Value operator -(Value other) => const UnknownValue(); 74 Value operator -(Value other) => const UnknownValue();
76 Value operator -() => const UnknownValue(); 75 Value operator -() => const UnknownValue();
77 Value operator &(Value other) => const UnknownValue(); 76 Value operator &(Value other) => const UnknownValue();
78 77
79 Value min(Value other) { 78 Value min(Value other) {
80 if (this == other) return this; 79 if (this == other) return this;
81 if (other == const MinIntValue()) return other; 80 if (other == const MinIntValue()) return other;
82 if (other == const MaxIntValue()) return this; 81 if (other == const MaxIntValue()) return this;
83 Value value = this - other; 82 Value value = this - other;
84 if (value.isPositive) return other; 83 if (value.isPositive) return other;
85 if (value.isNegative) return this; 84 if (value.isNegative) return this;
86 return const UnknownValue(); 85 return const UnknownValue();
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
131 /** 130 /**
132 * An [IntValue] contains a constant integer value. 131 * An [IntValue] contains a constant integer value.
133 */ 132 */
134 class IntValue extends Value { 133 class IntValue extends Value {
135 final int value; 134 final int value;
136 135
137 const IntValue(this.value, info) : super(info); 136 const IntValue(this.value, info) : super(info);
138 137
139 Value operator +(other) { 138 Value operator +(other) {
140 if (other.isZero) return this; 139 if (other.isZero) return this;
141 if (other is !IntValue) return other + this; 140 if (other is! IntValue) return other + this;
142 ConstantSystem constantSystem = info.constantSystem; 141 ConstantSystem constantSystem = info.constantSystem;
143 var constant = constantSystem.add.fold( 142 var constant = constantSystem.add.fold(
144 constantSystem.createInt(value), constantSystem.createInt(other.value)); 143 constantSystem.createInt(value), constantSystem.createInt(other.value));
145 if (!constant.isInt) return const UnknownValue(); 144 if (!constant.isInt) return const UnknownValue();
146 return info.newIntValue(constant.primitiveValue); 145 return info.newIntValue(constant.primitiveValue);
147 } 146 }
148 147
149 Value operator -(other) { 148 Value operator -(other) {
150 if (other.isZero) return this; 149 if (other.isZero) return this;
151 if (other is !IntValue) return -other + this; 150 if (other is! IntValue) return -other + this;
152 ConstantSystem constantSystem = info.constantSystem; 151 ConstantSystem constantSystem = info.constantSystem;
153 var constant = constantSystem.subtract.fold( 152 var constant = constantSystem.subtract.fold(
154 constantSystem.createInt(value), constantSystem.createInt(other.value)); 153 constantSystem.createInt(value), constantSystem.createInt(other.value));
155 if (!constant.isInt) return const UnknownValue(); 154 if (!constant.isInt) return const UnknownValue();
156 return info.newIntValue(constant.primitiveValue); 155 return info.newIntValue(constant.primitiveValue);
157 } 156 }
158 157
159 Value operator -() { 158 Value operator -() {
160 if (isZero) return this; 159 if (isZero) return this;
161 ConstantSystem constantSystem = info.constantSystem; 160 ConstantSystem constantSystem = info.constantSystem;
162 var constant = constantSystem.negate.fold( 161 var constant = constantSystem.negate.fold(constantSystem.createInt(value));
163 constantSystem.createInt(value));
164 if (!constant.isInt) return const UnknownValue(); 162 if (!constant.isInt) return const UnknownValue();
165 return info.newIntValue(constant.primitiveValue); 163 return info.newIntValue(constant.primitiveValue);
166 } 164 }
167 165
168 Value operator &(other) { 166 Value operator &(other) {
169 if (other is !IntValue) return const UnknownValue(); 167 if (other is! IntValue) return const UnknownValue();
170 ConstantSystem constantSystem = info.constantSystem; 168 ConstantSystem constantSystem = info.constantSystem;
171 var constant = constantSystem.bitAnd.fold( 169 var constant = constantSystem.bitAnd.fold(
172 constantSystem.createInt(value), constantSystem.createInt(other.value)); 170 constantSystem.createInt(value), constantSystem.createInt(other.value));
173 return info.newIntValue(constant.primitiveValue); 171 return info.newIntValue(constant.primitiveValue);
174 } 172 }
175 173
176 Value min(other) { 174 Value min(other) {
177 if (other is !IntValue) return other.min(this); 175 if (other is! IntValue) return other.min(this);
178 return this.value < other.value ? this : other; 176 return this.value < other.value ? this : other;
179 } 177 }
180 178
181 Value max(other) { 179 Value max(other) {
182 if (other is !IntValue) return other.max(this); 180 if (other is! IntValue) return other.max(this);
183 return this.value < other.value ? other : this; 181 return this.value < other.value ? other : this;
184 } 182 }
185 183
186 bool operator ==(other) { 184 bool operator ==(other) {
187 if (other is !IntValue) return false; 185 if (other is! IntValue) return false;
188 return this.value == other.value; 186 return this.value == other.value;
189 } 187 }
190 188
191 int get hashCode => throw new UnsupportedError('IntValue.hashCode'); 189 int get hashCode => throw new UnsupportedError('IntValue.hashCode');
192 190
193 String toString() => 'IntValue $value'; 191 String toString() => 'IntValue $value';
194 bool get isNegative => value < 0; 192 bool get isNegative => value < 0;
195 bool get isPositive => value >= 0; 193 bool get isPositive => value >= 0;
196 bool get isZero => value == 0; 194 bool get isZero => value == 0;
197 } 195 }
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
245 } 243 }
246 244
247 /** 245 /**
248 * A symbolic value representing an [HInstruction]. 246 * A symbolic value representing an [HInstruction].
249 */ 247 */
250 class InstructionValue extends Value { 248 class InstructionValue extends Value {
251 final HInstruction instruction; 249 final HInstruction instruction;
252 InstructionValue(this.instruction, info) : super(info); 250 InstructionValue(this.instruction, info) : super(info);
253 251
254 bool operator ==(other) { 252 bool operator ==(other) {
255 if (other is !InstructionValue) return false; 253 if (other is! InstructionValue) return false;
256 return this.instruction == other.instruction; 254 return this.instruction == other.instruction;
257 } 255 }
258 256
259 int get hashCode => throw new UnsupportedError('InstructionValue.hashCode'); 257 int get hashCode => throw new UnsupportedError('InstructionValue.hashCode');
260 258
261 Value operator +(Value other) { 259 Value operator +(Value other) {
262 if (other.isZero) return this; 260 if (other.isZero) return this;
263 if (other is IntValue) { 261 if (other is IntValue) {
264 if (other.isNegative) { 262 if (other.isNegative) {
265 return info.newSubtractValue(this, -other); 263 return info.newSubtractValue(this, -other);
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 class BinaryOperationValue extends Value { 310 class BinaryOperationValue extends Value {
313 final Value left; 311 final Value left;
314 final Value right; 312 final Value right;
315 BinaryOperationValue(this.left, this.right, info) : super(info); 313 BinaryOperationValue(this.left, this.right, info) : super(info);
316 } 314 }
317 315
318 class AddValue extends BinaryOperationValue { 316 class AddValue extends BinaryOperationValue {
319 AddValue(left, right, info) : super(left, right, info); 317 AddValue(left, right, info) : super(left, right, info);
320 318
321 bool operator ==(other) { 319 bool operator ==(other) {
322 if (other is !AddValue) return false; 320 if (other is! AddValue) return false;
323 return (left == other.left && right == other.right) 321 return (left == other.left && right == other.right) ||
324 || (left == other.right && right == other.left); 322 (left == other.right && right == other.left);
325 } 323 }
326 324
327 int get hashCode => throw new UnsupportedError('AddValue.hashCode'); 325 int get hashCode => throw new UnsupportedError('AddValue.hashCode');
328 326
329 Value operator -() => -left - right; 327 Value operator -() => -left - right;
330 328
331 Value operator +(Value other) { 329 Value operator +(Value other) {
332 if (other.isZero) return this; 330 if (other.isZero) return this;
333 Value value = left + other; 331 Value value = left + other;
334 if (value != const UnknownValue() && value is! BinaryOperationValue) { 332 if (value != const UnknownValue() && value is! BinaryOperationValue) {
(...skipping 25 matching lines...) Expand all
360 358
361 bool get isNegative => left.isNegative && right.isNegative; 359 bool get isNegative => left.isNegative && right.isNegative;
362 bool get isPositive => left.isPositive && right.isPositive; 360 bool get isPositive => left.isPositive && right.isPositive;
363 String toString() => '$left + $right'; 361 String toString() => '$left + $right';
364 } 362 }
365 363
366 class SubtractValue extends BinaryOperationValue { 364 class SubtractValue extends BinaryOperationValue {
367 SubtractValue(left, right, info) : super(left, right, info); 365 SubtractValue(left, right, info) : super(left, right, info);
368 366
369 bool operator ==(other) { 367 bool operator ==(other) {
370 if (other is !SubtractValue) return false; 368 if (other is! SubtractValue) return false;
371 return left == other.left && right == other.right; 369 return left == other.left && right == other.right;
372 } 370 }
373 371
374 int get hashCode => throw new UnsupportedError('SubtractValue.hashCode'); 372 int get hashCode => throw new UnsupportedError('SubtractValue.hashCode');
375 373
376 Value operator -() => right - left; 374 Value operator -() => right - left;
377 375
378 Value operator +(Value other) { 376 Value operator +(Value other) {
379 if (other.isZero) return this; 377 if (other.isZero) return this;
380 Value value = left + other; 378 Value value = left + other;
(...skipping 27 matching lines...) Expand all
408 bool get isNegative => left.isNegative && right.isPositive; 406 bool get isNegative => left.isNegative && right.isPositive;
409 bool get isPositive => left.isPositive && right.isNegative; 407 bool get isPositive => left.isPositive && right.isNegative;
410 String toString() => '$left - $right'; 408 String toString() => '$left - $right';
411 } 409 }
412 410
413 class NegateValue extends Value { 411 class NegateValue extends Value {
414 final Value value; 412 final Value value;
415 NegateValue(this.value, info) : super(info); 413 NegateValue(this.value, info) : super(info);
416 414
417 bool operator ==(other) { 415 bool operator ==(other) {
418 if (other is !NegateValue) return false; 416 if (other is! NegateValue) return false;
419 return value == other.value; 417 return value == other.value;
420 } 418 }
421 419
422 int get hashCode => throw new UnsupportedError('Negate.hashCode'); 420 int get hashCode => throw new UnsupportedError('Negate.hashCode');
423 421
424 Value operator +(other) { 422 Value operator +(other) {
425 if (other.isZero) return this; 423 if (other.isZero) return this;
426 if (other == value) return info.intZero; 424 if (other == value) return info.intZero;
427 if (other is NegateValue) return this - other.value; 425 if (other is NegateValue) return this - other.value;
428 if (other is IntValue) { 426 if (other is IntValue) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
474 assert(lower != const UnknownValue()); 472 assert(lower != const UnknownValue());
475 assert(upper != const UnknownValue()); 473 assert(upper != const UnknownValue());
476 } 474 }
477 475
478 Range.unbound(info) : this(const MinIntValue(), const MaxIntValue(), info); 476 Range.unbound(info) : this(const MinIntValue(), const MaxIntValue(), info);
479 477
480 /** 478 /**
481 * Checks if the given values are unknown, and creates a 479 * Checks if the given values are unknown, and creates a
482 * range that does not have any unknown values. 480 * range that does not have any unknown values.
483 */ 481 */
484 Range.normalize(Value low, Value up, info) : this( 482 Range.normalize(Value low, Value up, info)
485 low == const UnknownValue() ? const MinIntValue() : low, 483 : this(low == const UnknownValue() ? const MinIntValue() : low,
486 up == const UnknownValue() ? const MaxIntValue() : up, 484 up == const UnknownValue() ? const MaxIntValue() : up, info);
487 info);
488 485
489 Range union(Range other) { 486 Range union(Range other) {
490 return info.newNormalizedRange( 487 return info.newNormalizedRange(
491 lower.min(other.lower), upper.max(other.upper)); 488 lower.min(other.lower), upper.max(other.upper));
492 } 489 }
493 490
494 Range intersection(Range other) { 491 Range intersection(Range other) {
495 Value low = lower.max(other.lower); 492 Value low = lower.max(other.lower);
496 Value up = upper.min(other.upper); 493 Value up = upper.min(other.upper);
497 // If we could not compute max or min, pick a value in the two 494 // If we could not compute max or min, pick a value in the two
498 // ranges, with priority to [IntValue]s because they are simpler. 495 // ranges, with priority to [IntValue]s because they are simpler.
499 if (low == const UnknownValue()) { 496 if (low == const UnknownValue()) {
500 if (lower is IntValue) low = lower; 497 if (lower is IntValue)
501 else if (other.lower is IntValue) low = other.lower; 498 low = lower;
502 else low = lower; 499 else if (other.lower is IntValue)
500 low = other.lower;
501 else
502 low = lower;
503 } 503 }
504 if (up == const UnknownValue()) { 504 if (up == const UnknownValue()) {
505 if (upper is IntValue) up = upper; 505 if (upper is IntValue)
506 else if (other.upper is IntValue) up = other.upper; 506 up = upper;
507 else up = upper; 507 else if (other.upper is IntValue)
508 up = other.upper;
509 else
510 up = upper;
508 } 511 }
509 return info.newNormalizedRange(low, up); 512 return info.newNormalizedRange(low, up);
510 } 513 }
511 514
512 Range operator +(Range other) { 515 Range operator +(Range other) {
513 return info.newNormalizedRange(lower + other.lower, upper + other.upper); 516 return info.newNormalizedRange(lower + other.lower, upper + other.upper);
514 } 517 }
515 518
516 Range operator -(Range other) { 519 Range operator -(Range other) {
517 return info.newNormalizedRange(lower - other.upper, upper - other.lower); 520 return info.newNormalizedRange(lower - other.upper, upper - other.lower);
518 } 521 }
519 522
520 Range operator -() { 523 Range operator -() {
521 return info.newNormalizedRange(-upper, -lower); 524 return info.newNormalizedRange(-upper, -lower);
522 } 525 }
523 526
524 Range operator &(Range other) { 527 Range operator &(Range other) {
525 if (isSingleValue 528 if (isSingleValue &&
526 && other.isSingleValue 529 other.isSingleValue &&
527 && lower is IntValue 530 lower is IntValue &&
528 && other.lower is IntValue) { 531 other.lower is IntValue) {
529 return info.newNormalizedRange(lower & other.lower, upper & other.upper); 532 return info.newNormalizedRange(lower & other.lower, upper & other.upper);
530 } 533 }
531 if (isPositive && other.isPositive) { 534 if (isPositive && other.isPositive) {
532 Value up = upper.min(other.upper); 535 Value up = upper.min(other.upper);
533 if (up == const UnknownValue()) { 536 if (up == const UnknownValue()) {
534 // If we could not find a trivial bound, just try to use the 537 // If we could not find a trivial bound, just try to use the
535 // one that is an int. 538 // one that is an int.
536 up = upper is IntValue ? upper : other.upper; 539 up = upper is IntValue ? upper : other.upper;
537 // Make sure we get the same upper bound, whether it's a & b 540 // Make sure we get the same upper bound, whether it's a & b
538 // or b & a. 541 // or b & a.
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
600 final Map<HInstruction, Range> ranges = new Map<HInstruction, Range>(); 603 final Map<HInstruction, Range> ranges = new Map<HInstruction, Range>();
601 604
602 final Compiler compiler; 605 final Compiler compiler;
603 final ConstantSystem constantSystem; 606 final ConstantSystem constantSystem;
604 final ValueRangeInfo info; 607 final ValueRangeInfo info;
605 final SsaOptimizerTask optimizer; 608 final SsaOptimizerTask optimizer;
606 609
607 CodegenWorkItem work; 610 CodegenWorkItem work;
608 HGraph graph; 611 HGraph graph;
609 612
610 SsaValueRangeAnalyzer(this.compiler, 613 SsaValueRangeAnalyzer(
611 constantSystem, 614 this.compiler, constantSystem, this.optimizer, this.work)
612 this.optimizer,
613 this.work)
614 : info = new ValueRangeInfo(constantSystem), 615 : info = new ValueRangeInfo(constantSystem),
615 this.constantSystem = constantSystem; 616 this.constantSystem = constantSystem;
616 617
617 void visitGraph(HGraph graph) { 618 void visitGraph(HGraph graph) {
618 this.graph = graph; 619 this.graph = graph;
619 visitDominatorTree(graph); 620 visitDominatorTree(graph);
620 // We remove the range conversions after visiting the graph so 621 // We remove the range conversions after visiting the graph so
621 // that the graph does not get polluted with these instructions 622 // that the graph does not get polluted with these instructions
622 // only necessary for this phase. 623 // only necessary for this phase.
623 removeRangeConversion(); 624 removeRangeConversion();
624 // TODO(herhut): Find a cleaner way to pass around ranges. 625 // TODO(herhut): Find a cleaner way to pass around ranges.
625 optimizer.ranges = ranges; 626 optimizer.ranges = ranges;
626 } 627 }
627 628
628 void removeRangeConversion() { 629 void removeRangeConversion() {
629 conversions.forEach((HRangeConversion instruction) { 630 conversions.forEach((HRangeConversion instruction) {
630 instruction.block.rewrite(instruction, instruction.inputs[0]); 631 instruction.block.rewrite(instruction, instruction.inputs[0]);
631 instruction.block.remove(instruction); 632 instruction.block.remove(instruction);
632 }); 633 });
633 } 634 }
634 635
635 void visitBasicBlock(HBasicBlock block) { 636 void visitBasicBlock(HBasicBlock block) {
636
637 void visit(HInstruction instruction) { 637 void visit(HInstruction instruction) {
638 Range range = instruction.accept(this); 638 Range range = instruction.accept(this);
639 if (instruction.isInteger(compiler)) { 639 if (instruction.isInteger(compiler)) {
640 assert(range != null); 640 assert(range != null);
641 ranges[instruction] = range; 641 ranges[instruction] = range;
642 } 642 }
643 } 643 }
644 644
645 block.forEachPhi(visit); 645 block.forEachPhi(visit);
646 block.forEachInstruction(visit); 646 block.forEachInstruction(visit);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
725 // We might have lost the length range due to a type conversion that 725 // We might have lost the length range due to a type conversion that
726 // asserts a non-integer type. In such a case, the program will never 726 // asserts a non-integer type. In such a case, the program will never
727 // get to this point anyway, so no need to try and refine ranges. 727 // get to this point anyway, so no need to try and refine ranges.
728 return indexRange; 728 return indexRange;
729 } 729 }
730 assert(check.length.isInteger(compiler)); 730 assert(check.length.isInteger(compiler));
731 731
732 // Check if the index is strictly below the upper bound of the length 732 // Check if the index is strictly below the upper bound of the length
733 // range. 733 // range.
734 Value maxIndex = lengthRange.upper - info.intOne; 734 Value maxIndex = lengthRange.upper - info.intOne;
735 bool belowLength = maxIndex != const MaxIntValue() 735 bool belowLength = maxIndex != const MaxIntValue() &&
736 && indexRange.upper.min(maxIndex) == indexRange.upper; 736 indexRange.upper.min(maxIndex) == indexRange.upper;
737 737
738 // Check if the index is strictly below the lower bound of the length 738 // Check if the index is strictly below the lower bound of the length
739 // range. 739 // range.
740 belowLength = belowLength 740 belowLength = belowLength ||
741 || (indexRange.upper != lengthRange.lower 741 (indexRange.upper != lengthRange.lower &&
742 && indexRange.upper.min(lengthRange.lower) == indexRange.upper); 742 indexRange.upper.min(lengthRange.lower) == indexRange.upper);
743 if (indexRange.isPositive && belowLength) { 743 if (indexRange.isPositive && belowLength) {
744 check.block.rewrite(check, check.index); 744 check.block.rewrite(check, check.index);
745 check.block.remove(check); 745 check.block.remove(check);
746 } else if (indexRange.isNegative || lengthRange < indexRange) { 746 } else if (indexRange.isNegative || lengthRange < indexRange) {
747 check.staticChecks = HBoundsCheck.ALWAYS_FALSE; 747 check.staticChecks = HBoundsCheck.ALWAYS_FALSE;
748 // The check is always false, and whatever instruction it 748 // The check is always false, and whatever instruction it
749 // dominates is dead code. 749 // dominates is dead code.
750 return indexRange; 750 return indexRange;
751 } else if (indexRange.isPositive) { 751 } else if (indexRange.isPositive) {
752 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO; 752 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO;
753 } else if (belowLength) { 753 } else if (belowLength) {
754 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH; 754 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH;
755 } 755 }
756 756
757 if (indexRange.isPositive) { 757 if (indexRange.isPositive) {
758 // If the test passes, we know the lower bound of the length is 758 // If the test passes, we know the lower bound of the length is
759 // greater or equal than the lower bound of the index. 759 // greater or equal than the lower bound of the index.
760 Value low = lengthRange.lower.max(indexRange.lower); 760 Value low = lengthRange.lower.max(indexRange.lower);
761 if (low != const UnknownValue()) { 761 if (low != const UnknownValue()) {
762 HInstruction instruction = 762 HInstruction instruction = createRangeConversion(next, check.length);
763 createRangeConversion(next, check.length);
764 ranges[instruction] = info.newNormalizedRange(low, lengthRange.upper); 763 ranges[instruction] = info.newNormalizedRange(low, lengthRange.upper);
765 } 764 }
766 } 765 }
767 766
768 // Update the range of the index if using the maximum index 767 // Update the range of the index if using the maximum index
769 // narrows it. Use that new range for this instruction as well. 768 // narrows it. Use that new range for this instruction as well.
770 Range newIndexRange = indexRange.intersection( 769 Range newIndexRange = indexRange
771 info.newNormalizedRange(info.intZero, maxIndex)); 770 .intersection(info.newNormalizedRange(info.intZero, maxIndex));
772 if (indexRange == newIndexRange) return indexRange; 771 if (indexRange == newIndexRange) return indexRange;
773 // Explicitly attach the range information to the index instruction, 772 // Explicitly attach the range information to the index instruction,
774 // which may be used by other instructions. Returning the new range will 773 // which may be used by other instructions. Returning the new range will
775 // attach it to this instruction. 774 // attach it to this instruction.
776 HInstruction instruction = createRangeConversion(next, check.index); 775 HInstruction instruction = createRangeConversion(next, check.index);
777 ranges[instruction] = newIndexRange; 776 ranges[instruction] = newIndexRange;
778 return newIndexRange; 777 return newIndexRange;
779 } 778 }
780 779
781 Range visitRelational(HRelational relational) { 780 Range visitRelational(HRelational relational) {
782 HInstruction right = relational.right; 781 HInstruction right = relational.right;
783 HInstruction left = relational.left; 782 HInstruction left = relational.left;
784 if (!left.isInteger(compiler)) return info.newUnboundRange(); 783 if (!left.isInteger(compiler)) return info.newUnboundRange();
785 if (!right.isInteger(compiler)) return info.newUnboundRange(); 784 if (!right.isInteger(compiler)) return info.newUnboundRange();
786 BinaryOperation operation = relational.operation(constantSystem); 785 BinaryOperation operation = relational.operation(constantSystem);
787 Range rightRange = ranges[relational.right]; 786 Range rightRange = ranges[relational.right];
788 Range leftRange = ranges[relational.left]; 787 Range leftRange = ranges[relational.left];
789 788
790 if (relational is HIdentity) { 789 if (relational is HIdentity) {
791 handleEqualityCheck(relational); 790 handleEqualityCheck(relational);
792 } else if (operation.apply(leftRange, rightRange)) { 791 } else if (operation.apply(leftRange, rightRange)) {
793 relational.block.rewrite( 792 relational.block
794 relational, graph.addConstantBool(true, compiler)); 793 .rewrite(relational, graph.addConstantBool(true, compiler));
795 relational.block.remove(relational); 794 relational.block.remove(relational);
796 } else if (negateOperation(operation).apply(leftRange, rightRange)) { 795 } else if (negateOperation(operation).apply(leftRange, rightRange)) {
797 relational.block.rewrite( 796 relational.block
798 relational, graph.addConstantBool(false, compiler)); 797 .rewrite(relational, graph.addConstantBool(false, compiler));
799 relational.block.remove(relational); 798 relational.block.remove(relational);
800 } 799 }
801 return info.newUnboundRange(); 800 return info.newUnboundRange();
802 } 801 }
803 802
804 void handleEqualityCheck(HRelational node) { 803 void handleEqualityCheck(HRelational node) {
805 Range right = ranges[node.right]; 804 Range right = ranges[node.right];
806 Range left = ranges[node.left]; 805 Range left = ranges[node.left];
807 if (left.isSingleValue && right.isSingleValue && left == right) { 806 if (left.isSingleValue && right.isSingleValue && left == right) {
808 node.block.rewrite( 807 node.block.rewrite(node, graph.addConstantBool(true, compiler));
809 node, graph.addConstantBool(true, compiler));
810 node.block.remove(node); 808 node.block.remove(node);
811 } 809 }
812 } 810 }
813 811
814 Range handleInvokeModulo(HInvokeDynamicMethod invoke) { 812 Range handleInvokeModulo(HInvokeDynamicMethod invoke) {
815 HInstruction left = invoke.inputs[1]; 813 HInstruction left = invoke.inputs[1];
816 HInstruction right = invoke.inputs[2]; 814 HInstruction right = invoke.inputs[2];
817 Range divisor = ranges[right]; 815 Range divisor = ranges[right];
818 if (divisor != null) { 816 if (divisor != null) {
819 // For Integer values we can be precise in the upper bound, 817 // For Integer values we can be precise in the upper bound,
820 // so special case those. 818 // so special case those.
821 if (left.isInteger(compiler) && right.isInteger(compiler)) { 819 if (left.isInteger(compiler) && right.isInteger(compiler)) {
822 if (divisor.isPositive) { 820 if (divisor.isPositive) {
823 return info.newNormalizedRange(info.intZero, divisor.upper - 821 return info.newNormalizedRange(
824 info.intOne); 822 info.intZero, divisor.upper - info.intOne);
825 } else if (divisor.isNegative) { 823 } else if (divisor.isNegative) {
826 return info.newNormalizedRange(info.intZero, info.newNegateValue( 824 return info.newNormalizedRange(
827 divisor.lower) - info.intOne); 825 info.intZero, info.newNegateValue(divisor.lower) - info.intOne);
828 } 826 }
829 } else if (left.isNumber(compiler) && right.isNumber(compiler)) { 827 } else if (left.isNumber(compiler) && right.isNumber(compiler)) {
830 if (divisor.isPositive) { 828 if (divisor.isPositive) {
831 return info.newNormalizedRange(info.intZero, divisor.upper); 829 return info.newNormalizedRange(info.intZero, divisor.upper);
832 } else if (divisor.isNegative) { 830 } else if (divisor.isNegative) {
833 return info.newNormalizedRange(info.intZero, info.newNegateValue( 831 return info.newNormalizedRange(
834 divisor.lower)); 832 info.intZero, info.newNegateValue(divisor.lower));
835 } 833 }
836 } 834 }
837 } 835 }
838 return info.newUnboundRange(); 836 return info.newUnboundRange();
839 } 837 }
840 838
841 Range visitInvokeDynamicMethod(HInvokeDynamicMethod invoke) { 839 Range visitInvokeDynamicMethod(HInvokeDynamicMethod invoke) {
842 if ((invoke.inputs.length == 3) && (invoke.selector.name == "%")) 840 if ((invoke.inputs.length == 3) && (invoke.selector.name == "%"))
843 return handleInvokeModulo(invoke); 841 return handleInvokeModulo(invoke);
844 return super.visitInvokeDynamicMethod(invoke); 842 return super.visitInvokeDynamicMethod(invoke);
845 } 843 }
846 844
847 Range handleBinaryOperation(HBinaryArithmetic instruction) { 845 Range handleBinaryOperation(HBinaryArithmetic instruction) {
848 if (!instruction.isInteger(compiler)) return info.newUnboundRange(); 846 if (!instruction.isInteger(compiler)) return info.newUnboundRange();
849 return instruction.operation(constantSystem).apply( 847 return instruction
850 ranges[instruction.left], ranges[instruction.right]); 848 .operation(constantSystem)
849 .apply(ranges[instruction.left], ranges[instruction.right]);
851 } 850 }
852 851
853 Range visitAdd(HAdd add) { 852 Range visitAdd(HAdd add) {
854 return handleBinaryOperation(add); 853 return handleBinaryOperation(add);
855 } 854 }
856 855
857 Range visitSubtract(HSubtract sub) { 856 Range visitSubtract(HSubtract sub) {
858 return handleBinaryOperation(sub); 857 return handleBinaryOperation(sub);
859 } 858 }
860 859
(...skipping 23 matching lines...) Expand all
884 return info.newUnboundRange(); 883 return info.newUnboundRange();
885 } 884 }
886 885
887 Range visitCheck(HCheck instruction) { 886 Range visitCheck(HCheck instruction) {
888 if (ranges[instruction.checkedInput] == null) { 887 if (ranges[instruction.checkedInput] == null) {
889 return visitInstruction(instruction); 888 return visitInstruction(instruction);
890 } 889 }
891 return ranges[instruction.checkedInput]; 890 return ranges[instruction.checkedInput];
892 } 891 }
893 892
894 HInstruction createRangeConversion(HInstruction cursor, 893 HInstruction createRangeConversion(
895 HInstruction instruction) { 894 HInstruction cursor, HInstruction instruction) {
896 JavaScriptBackend backend = compiler.backend; 895 JavaScriptBackend backend = compiler.backend;
897 HRangeConversion newInstruction = 896 HRangeConversion newInstruction =
898 new HRangeConversion(instruction, backend.intType); 897 new HRangeConversion(instruction, backend.intType);
899 conversions.add(newInstruction); 898 conversions.add(newInstruction);
900 cursor.block.addBefore(cursor, newInstruction); 899 cursor.block.addBefore(cursor, newInstruction);
901 // Update the users of the instruction dominated by [cursor] to 900 // Update the users of the instruction dominated by [cursor] to
902 // use the new instruction, that has an narrower range. 901 // use the new instruction, that has an narrower range.
903 instruction.replaceAllUsersDominatedBy(cursor, newInstruction); 902 instruction.replaceAllUsersDominatedBy(cursor, newInstruction);
904 return newInstruction; 903 return newInstruction;
905 } 904 }
(...skipping 19 matching lines...) Expand all
925 return const GreaterEqualOperation(); 924 return const GreaterEqualOperation();
926 } else if (operation == const GreaterOperation()) { 925 } else if (operation == const GreaterOperation()) {
927 return const LessOperation(); 926 return const LessOperation();
928 } else if (operation == const GreaterEqualOperation()) { 927 } else if (operation == const GreaterEqualOperation()) {
929 return const LessEqualOperation(); 928 return const LessEqualOperation();
930 } else { 929 } else {
931 return null; 930 return null;
932 } 931 }
933 } 932 }
934 933
935 Range computeConstrainedRange(BinaryOperation operation, 934 Range computeConstrainedRange(
936 Range leftRange, 935 BinaryOperation operation, Range leftRange, Range rightRange) {
937 Range rightRange) {
938 Range range; 936 Range range;
939 if (operation == const LessOperation()) { 937 if (operation == const LessOperation()) {
940 range = info.newNormalizedRange( 938 range = info.newNormalizedRange(
941 const MinIntValue(), rightRange.upper - info.intOne); 939 const MinIntValue(), rightRange.upper - info.intOne);
942 } else if (operation == const LessEqualOperation()) { 940 } else if (operation == const LessEqualOperation()) {
943 range = info.newNormalizedRange(const MinIntValue(), rightRange.upper); 941 range = info.newNormalizedRange(const MinIntValue(), rightRange.upper);
944 } else if (operation == const GreaterOperation()) { 942 } else if (operation == const GreaterOperation()) {
945 range = info.newNormalizedRange( 943 range = info.newNormalizedRange(
946 rightRange.lower + info.intOne, const MaxIntValue()); 944 rightRange.lower + info.intOne, const MaxIntValue());
947 } else if (operation == const GreaterEqualOperation()) { 945 } else if (operation == const GreaterEqualOperation()) {
948 range = info.newNormalizedRange(rightRange.lower, const MaxIntValue()); 946 range = info.newNormalizedRange(rightRange.lower, const MaxIntValue());
949 } else { 947 } else {
950 range = info.newUnboundRange(); 948 range = info.newUnboundRange();
951 } 949 }
952 return range.intersection(leftRange); 950 return range.intersection(leftRange);
953 } 951 }
954 952
955 Range visitConditionalBranch(HConditionalBranch branch) { 953 Range visitConditionalBranch(HConditionalBranch branch) {
956 var condition = branch.condition; 954 var condition = branch.condition;
957 // TODO(ngeoffray): Handle complex conditions. 955 // TODO(ngeoffray): Handle complex conditions.
958 if (condition is !HRelational) return info.newUnboundRange(); 956 if (condition is! HRelational) return info.newUnboundRange();
959 if (condition is HIdentity) return info.newUnboundRange(); 957 if (condition is HIdentity) return info.newUnboundRange();
960 HInstruction right = condition.right; 958 HInstruction right = condition.right;
961 HInstruction left = condition.left; 959 HInstruction left = condition.left;
962 if (!left.isInteger(compiler)) return info.newUnboundRange(); 960 if (!left.isInteger(compiler)) return info.newUnboundRange();
963 if (!right.isInteger(compiler)) return info.newUnboundRange(); 961 if (!right.isInteger(compiler)) return info.newUnboundRange();
964 962
965 Range rightRange = ranges[right]; 963 Range rightRange = ranges[right];
966 Range leftRange = ranges[left]; 964 Range leftRange = ranges[left];
967 Operation operation = condition.operation(constantSystem); 965 Operation operation = condition.operation(constantSystem);
968 Operation mirrorOp = flipOperation(operation); 966 Operation mirrorOp = flipOperation(operation);
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1085 } 1083 }
1086 1084
1087 Range handleBinaryOperation(HBinaryArithmetic instruction) { 1085 Range handleBinaryOperation(HBinaryArithmetic instruction) {
1088 Range leftRange = visit(instruction.left); 1086 Range leftRange = visit(instruction.left);
1089 Range rightRange = visit(instruction.right); 1087 Range rightRange = visit(instruction.right);
1090 if (leftRange == null || rightRange == null) return null; 1088 if (leftRange == null || rightRange == null) return null;
1091 BinaryOperation operation = instruction.operation(info.constantSystem); 1089 BinaryOperation operation = instruction.operation(info.constantSystem);
1092 return operation.apply(leftRange, rightRange); 1090 return operation.apply(leftRange, rightRange);
1093 } 1091 }
1094 } 1092 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/ssa/validate.dart ('k') | pkg/compiler/lib/src/ssa/value_set.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698