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

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

Issue 10986085: Deal with more conditional expressions in the value range analyzer. (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 {
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
291 291
292 Range operator &(Range other) { 292 Range operator &(Range other) {
293 return new Range.normalize(lower & other.lower, upper & other.upper); 293 return new Range.normalize(lower & other.lower, upper & other.upper);
294 } 294 }
295 295
296 bool operator ==(other) { 296 bool operator ==(other) {
297 if (other is! Range) return false; 297 if (other is! Range) return false;
298 return other.lower == lower && other.upper == upper; 298 return other.lower == lower && other.upper == upper;
299 } 299 }
300 300
301 bool isLessThan(Range other) { 301 bool operator <(Range other) {
302 return upper != other.lower && upper.min(other.lower) == upper; 302 return upper != other.lower && upper.min(other.lower) == upper;
303 } 303 }
304 304
305 bool operator >(Range other) {
306 return lower != other.upper && lower.max(other.upper) == lower;
307 }
308
309 bool operator <=(Range other) {
310 return upper.min(other.lower) == upper;
311 }
312
313 bool operator >=(Range other) {
314 return lower.max(other.upper) == lower;
315 }
316
305 bool isNegative() => upper.isNegative(); 317 bool isNegative() => upper.isNegative();
306 bool isPositive() => lower.isPositive(); 318 bool isPositive() => lower.isPositive();
319 bool isSingleValue() => lower == upper;
307 320
308 String toString() => '[$lower, $upper]'; 321 String toString() => '[$lower, $upper]';
309 } 322 }
310 323
311 /** 324 /**
312 * Visits the graph in dominator order, and computes value ranges for 325 * Visits the graph in dominator order, and computes value ranges for
313 * integer instructions. While visiting the graph, this phase also 326 * integer instructions. While visiting the graph, this phase also
314 * removes unnecessary bounds checks, and comparisons that are proven 327 * removes unnecessary bounds checks, and comparisons that are proven
315 * to be true or false. 328 * to be true or false.
316 */ 329 */
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 && indexRange.upper.min(maxIndex) == indexRange.upper; 441 && indexRange.upper.min(maxIndex) == indexRange.upper;
429 442
430 // Check if the index is strictly below the lower bound of the length 443 // Check if the index is strictly below the lower bound of the length
431 // range. 444 // range.
432 belowLength = belowLength 445 belowLength = belowLength
433 || (indexRange.upper != lengthRange.lower 446 || (indexRange.upper != lengthRange.lower
434 && indexRange.upper.min(lengthRange.lower) == indexRange.upper); 447 && indexRange.upper.min(lengthRange.lower) == indexRange.upper);
435 if (indexRange.isPositive() && belowLength) { 448 if (indexRange.isPositive() && belowLength) {
436 check.block.rewrite(check, check.index); 449 check.block.rewrite(check, check.index);
437 check.block.remove(check); 450 check.block.remove(check);
438 } else if (indexRange.isNegative() || lengthRange.isLessThan(indexRange)) { 451 } else if (indexRange.isNegative() || lengthRange < indexRange) {
439 check.staticChecks = HBoundsCheck.ALWAYS_FALSE; 452 check.staticChecks = HBoundsCheck.ALWAYS_FALSE;
440 // The check is always false, and whatever instruction it 453 // The check is always false, and whatever instruction it
441 // dominates is dead code. 454 // dominates is dead code.
442 return indexRange; 455 return indexRange;
443 } else if (indexRange.isPositive()) { 456 } else if (indexRange.isPositive()) {
444 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO; 457 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO;
445 } else if (belowLength) { 458 } else if (belowLength) {
446 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH; 459 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH;
447 } 460 }
448 461
(...skipping 15 matching lines...) Expand all
464 new Range(lengthRange.lower, maxIndex)); 477 new Range(lengthRange.lower, maxIndex));
465 if (indexRange == newIndexRange) return indexRange; 478 if (indexRange == newIndexRange) return indexRange;
466 HInstruction instruction = createRangeConversion(next, check.index); 479 HInstruction instruction = createRangeConversion(next, check.index);
467 ranges[instruction] = newIndexRange; 480 ranges[instruction] = newIndexRange;
468 return newIndexRange; 481 return newIndexRange;
469 } 482 }
470 483
471 return indexRange; 484 return indexRange;
472 } 485 }
473 486
474 Range visitLess(HLess less) { 487 Range visitRelational(HRelational relational) {
475 HInstruction right = less.right; 488 HInstruction right = relational.right;
476 HInstruction left = less.left; 489 HInstruction left = relational.left;
477 if (!left.isInteger(types)) return const Range.unbound(); 490 if (!left.isInteger(types)) return const Range.unbound();
478 if (!right.isInteger(types)) return const Range.unbound(); 491 if (!right.isInteger(types)) return const Range.unbound();
479 if (ranges[left].isLessThan(ranges[right])) { 492 Operation operation = relational.operation(constantSystem);
480 less.block.rewrite(less, graph.addConstantBool(true, constantSystem)); 493 Range rightRange = ranges[relational.right];
481 less.block.remove(less); 494 Range leftRange = ranges[relational.left];
482 return const Range.unbound(); 495
483 } 496 if (relational is HEquals || relational is HIdentity) {
484 if (ranges[right].isLessThan(ranges[left])) { 497 handleEqualityCheck(relational);
485 less.block.rewrite(less, graph.addConstantBool(false, constantSystem)); 498 } else if (operation.apply(leftRange, rightRange)) {
486 less.block.remove(less); 499 relational.block.rewrite(
487 return const Range.unbound(); 500 relational, graph.addConstantBool(true, constantSystem));
501 relational.block.remove(relational);
502 } else if (reverseOperation(operation).apply(leftRange, rightRange)) {
503 relational.block.rewrite(
504 relational, graph.addConstantBool(false, constantSystem));
505 relational.block.remove(relational);
488 } 506 }
489 return const Range.unbound(); 507 return const Range.unbound();
490 } 508 }
491 509
510 void handleEqualityCheck(HRelational node) {
511 Range right = ranges[node.right];
512 Range left = ranges[node.left];
513 if (left.isSingleValue() && right.isSingleValue() && left == right) {
514 node.block.rewrite(
515 node, graph.addConstantBool(true, constantSystem));
516 node.block.remove(node);
517 }
518 }
519
492 Range handleBinaryOperation(HBinaryArithmetic instruction) { 520 Range handleBinaryOperation(HBinaryArithmetic instruction) {
493 if (!instruction.isInteger(types)) return const Range.unbound(); 521 if (!instruction.isInteger(types)) return const Range.unbound();
494 return instruction.operation(constantSystem).apply( 522 return instruction.operation(constantSystem).apply(
495 ranges[instruction.left], ranges[instruction.right]); 523 ranges[instruction.left], ranges[instruction.right]);
496 } 524 }
497 525
498 Range visitAdd(HAdd add) { 526 Range visitAdd(HAdd add) {
499 return handleBinaryOperation(add); 527 return handleBinaryOperation(add);
500 } 528 }
501 529
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 cursor.block.addBefore(cursor, newInstruction); 571 cursor.block.addBefore(cursor, newInstruction);
544 // Update the users of the instruction dominated by [cursor] to 572 // Update the users of the instruction dominated by [cursor] to
545 // use the new instruction, that has an narrower range. 573 // use the new instruction, that has an narrower range.
546 Set<HInstruction> dominatedUsers = instruction.dominatedUsers(cursor); 574 Set<HInstruction> dominatedUsers = instruction.dominatedUsers(cursor);
547 for (HInstruction user in dominatedUsers) { 575 for (HInstruction user in dominatedUsers) {
548 user.changeUse(instruction, newInstruction); 576 user.changeUse(instruction, newInstruction);
549 } 577 }
550 return newInstruction; 578 return newInstruction;
551 } 579 }
552 580
581 static Operation reverseOperation(BinaryOperation operation) {
582 if (operation == const LessOperation()) {
583 return const GreaterEqualOperation();
584 } else if (operation == const LessEqualOperation()) {
585 return const GreaterOperation();
586 } else if (operation == const GreaterOperation()) {
587 return const LessEqualOperation();
588 } else if (operation == const GreaterEqualOperation()) {
589 return const LessOperation();
590 } else {
591 return null;
592 }
593 }
594
595 static Range computeConstrainedRange(BinaryOperation operation,
596 Range leftRange,
597 Range rightRange) {
598 Range range;
599 if (operation == const LessOperation()) {
600 range = new Range(
601 const MinIntValue(), rightRange.upper - const IntValue(1));
602 } else if (operation == const LessEqualOperation()) {
603 range = new Range(const MinIntValue(), rightRange.upper);
604 } else if (operation == const GreaterOperation()) {
605 range = new Range(
606 rightRange.lower + const IntValue(1), const MaxIntValue());
607 } else if (operation == const GreaterEqualOperation()) {
608 range = new Range(rightRange.lower, const MaxIntValue());
609 } else {
610 range = const Range.unbound();
611 }
612 return range.intersection(leftRange);
613 }
614
553 Range visitConditionalBranch(HConditionalBranch branch) { 615 Range visitConditionalBranch(HConditionalBranch branch) {
554 var condition = branch.condition; 616 var condition = branch.condition;
555 // TODO(ngeoffray): Handle more condition kinds. 617 // TODO(ngeoffray): Handle complex conditions.
556 if (condition is !HLess) return const Range.unbound(); 618 if (condition is !HRelational) return const Range.unbound();
619 if (condition is HEquals) return const Range.unbound();
620 if (condition is HIdentity) return const Range.unbound();
557 HInstruction right = condition.right; 621 HInstruction right = condition.right;
558 HInstruction left = condition.left; 622 HInstruction left = condition.left;
559 if (!left.isInteger(types)) return const Range.unbound(); 623 if (!left.isInteger(types)) return const Range.unbound();
560 if (!right.isInteger(types)) return const Range.unbound(); 624 if (!right.isInteger(types)) return const Range.unbound();
561 625
562 // Update the true branch to use a narrower range for [left]. 626 Range rightRange = ranges[right];
563 // TODO(ngeoffray): Also do it for [right]. 627 Range leftRange = ranges[left];
564 HInstruction instruction = 628 Operation operation = condition.operation(constantSystem);
565 createRangeConversion(branch.trueBranch.first, left); 629 Operation reverse = reverseOperation(operation);
566 Range range = new Range( 630 // Only update the true branch if this block is the only
567 const MinIntValue(), ranges[right].upper - const IntValue(1)); 631 // predecessor.
568 range = range.intersection(ranges[left]); 632 if (branch.trueBranch.predecessors.length == 1) {
569 ranges[instruction] = range; 633 assert(branch.trueBranch.predecessors[0] == branch.block);
634 // Update the true branch to use narrower ranges for [left] and
635 // [right].
636 Range range = computeConstrainedRange(operation, leftRange, rightRange);
637 if (leftRange != range) {
638 HInstruction instruction =
639 createRangeConversion(branch.trueBranch.first, left);
640 ranges[instruction] = range;
641 }
570 642
571 // Update the false branch to use a narrower range for [left]. 643 range = computeConstrainedRange(reverse, rightRange, leftRange);
572 // TODO(ngeoffray): Also do it for [right]. 644 if (rightRange != range) {
573 instruction = createRangeConversion(branch.falseBranch.first, left); 645 HInstruction instruction =
574 range = new Range(ranges[right].lower, const MaxIntValue()); 646 createRangeConversion(branch.trueBranch.first, right);
575 range = range.intersection(ranges[left]); 647 ranges[instruction] = range;
576 ranges[instruction] = range; 648 }
649 }
650
651 // Only update the false branch if this block is the only
652 // predecessor.
653 if (branch.falseBranch.predecessors.length == 1) {
654 assert(branch.falseBranch.predecessors[0] == branch.block);
655 // Update the false branch to use narrower ranges for [left] and
656 // [right].
657 Range range = computeConstrainedRange(reverse, leftRange, rightRange);
658 if (leftRange != range) {
659 HInstruction instruction =
660 createRangeConversion(branch.falseBranch.first, left);
661 ranges[instruction] = range;
662 }
663
664 range = computeConstrainedRange(operation, rightRange, leftRange);
665 if (rightRange != range) {
666 HInstruction instruction =
667 createRangeConversion(branch.falseBranch.first, right);
668 ranges[instruction] = range;
669 }
670 }
577 671
578 return const Range.unbound(); 672 return const Range.unbound();
579 } 673 }
580 674
581 Range visitRangeConversion(HRangeConversion conversion) { 675 Range visitRangeConversion(HRangeConversion conversion) {
582 return ranges[conversion]; 676 return ranges[conversion];
583 } 677 }
584 } 678 }
585 679
586 /** 680 /**
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 if (instruction is HPhi && !instruction.block.isLoopHeader()) { 773 if (instruction is HPhi && !instruction.block.isLoopHeader()) {
680 HInstruction result = unwrap(instruction.inputs[0]); 774 HInstruction result = unwrap(instruction.inputs[0]);
681 for (int i = 1; i < instruction.inputs.length; i++) { 775 for (int i = 1; i < instruction.inputs.length; i++) {
682 if (result != unwrap(instruction.inputs[i])) return instruction; 776 if (result != unwrap(instruction.inputs[i])) return instruction;
683 } 777 }
684 return result; 778 return result;
685 } 779 }
686 return instruction; 780 return instruction;
687 } 781 }
688 } 782 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/constant_system_dart.dart ('k') | tests/compiler/dart2js/value_range_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698