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

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();
307 319
308 String toString() => '[$lower, $upper]'; 320 String toString() => '[$lower, $upper]';
309 } 321 }
310 322
311 /** 323 /**
312 * Visits the graph in dominator order, and computes value ranges for 324 * Visits the graph in dominator order, and computes value ranges for
313 * integer instructions. While visiting the graph, this phase also 325 * integer instructions. While visiting the graph, this phase also
314 * removes unnecessary bounds checks, and comparisons that are proven 326 * removes unnecessary bounds checks, and comparisons that are proven
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
428 && indexRange.upper.min(maxIndex) == indexRange.upper; 440 && indexRange.upper.min(maxIndex) == indexRange.upper;
429 441
430 // Check if the index is strictly below the lower bound of the length 442 // Check if the index is strictly below the lower bound of the length
431 // range. 443 // range.
432 belowLength = belowLength 444 belowLength = belowLength
433 || (indexRange.upper != lengthRange.lower 445 || (indexRange.upper != lengthRange.lower
434 && indexRange.upper.min(lengthRange.lower) == indexRange.upper); 446 && indexRange.upper.min(lengthRange.lower) == indexRange.upper);
435 if (indexRange.isPositive() && belowLength) { 447 if (indexRange.isPositive() && belowLength) {
436 check.block.rewrite(check, check.index); 448 check.block.rewrite(check, check.index);
437 check.block.remove(check); 449 check.block.remove(check);
438 } else if (indexRange.isNegative() || lengthRange.isLessThan(indexRange)) { 450 } else if (indexRange.isNegative() || lengthRange < indexRange) {
439 check.staticChecks = HBoundsCheck.ALWAYS_FALSE; 451 check.staticChecks = HBoundsCheck.ALWAYS_FALSE;
440 // The check is always false, and whatever instruction it 452 // The check is always false, and whatever instruction it
441 // dominates is dead code. 453 // dominates is dead code.
442 return indexRange; 454 return indexRange;
443 } else if (indexRange.isPositive()) { 455 } else if (indexRange.isPositive()) {
444 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO; 456 check.staticChecks = HBoundsCheck.ALWAYS_ABOVE_ZERO;
445 } else if (belowLength) { 457 } else if (belowLength) {
446 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH; 458 check.staticChecks = HBoundsCheck.ALWAYS_BELOW_LENGTH;
447 } 459 }
448 460
(...skipping 15 matching lines...) Expand all
464 new Range(lengthRange.lower, maxIndex)); 476 new Range(lengthRange.lower, maxIndex));
465 if (indexRange == newIndexRange) return indexRange; 477 if (indexRange == newIndexRange) return indexRange;
466 HInstruction instruction = createRangeConversion(next, check.index); 478 HInstruction instruction = createRangeConversion(next, check.index);
467 ranges[instruction] = newIndexRange; 479 ranges[instruction] = newIndexRange;
468 return newIndexRange; 480 return newIndexRange;
469 } 481 }
470 482
471 return indexRange; 483 return indexRange;
472 } 484 }
473 485
474 Range visitLess(HLess less) { 486 Range visitRelational(HRelation relational) {
475 HInstruction right = less.right; 487 HInstruction right = relational.right;
476 HInstruction left = less.left; 488 HInstruction left = relational.left;
477 if (!left.isInteger(types)) return const Range.unbound(); 489 if (!left.isInteger(types)) return const Range.unbound();
478 if (!right.isInteger(types)) return const Range.unbound(); 490 if (!right.isInteger(types)) return const Range.unbound();
479 if (ranges[left].isLessThan(ranges[right])) { 491 Operation operation = relational.operation(constantSystem);
480 less.block.rewrite(less, graph.addConstantBool(true, constantSystem)); 492 Range rightRange = ranges[relational.right];
481 less.block.remove(less); 493 Range leftRange = ranges[relational.left];
482 return const Range.unbound(); 494
483 } 495 if (relational is HEquals || relational is HIdentity) {
484 if (ranges[right].isLessThan(ranges[left])) { 496 handleEqualityCheck(relational);
485 less.block.rewrite(less, graph.addConstantBool(false, constantSystem)); 497 } else if (operation.apply(leftRange, rightRange)) {
486 less.block.remove(less); 498 relational.block.rewrite(
487 return const Range.unbound(); 499 relational, graph.addConstantBool(true, constantSystem));
500 relational.block.remove(relational);
501 } else if (reverseOperation(operation).apply(leftRange, rightRange)) {
502 relational.block.rewrite(
503 relational, graph.addConstantBool(false, constantSystem));
504 relational.block.remove(relational);
488 } 505 }
489 return const Range.unbound(); 506 return const Range.unbound();
490 } 507 }
491 508
509 void handleEqualityCheck(HRelational node) {
510 Range right = ranges[node.right];
511 Range left = ranges[node.left];
512 if (left.lower == left.upper && left == right) {
Søren Gjesse 2012/10/02 08:07:20 Maybe have an isSingleValue on Range and express t
ngeoffray 2012/10/04 08:51:08 Done.
513 node.block.rewrite(
514 node, graph.addConstantBool(true, constantSystem));
515 node.block.remove(node);
516 }
517 }
518
492 Range handleBinaryOperation(HBinaryArithmetic instruction) { 519 Range handleBinaryOperation(HBinaryArithmetic instruction) {
493 if (!instruction.isInteger(types)) return const Range.unbound(); 520 if (!instruction.isInteger(types)) return const Range.unbound();
494 return instruction.operation(constantSystem).apply( 521 return instruction.operation(constantSystem).apply(
495 ranges[instruction.left], ranges[instruction.right]); 522 ranges[instruction.left], ranges[instruction.right]);
496 } 523 }
497 524
498 Range visitAdd(HAdd add) { 525 Range visitAdd(HAdd add) {
499 return handleBinaryOperation(add); 526 return handleBinaryOperation(add);
500 } 527 }
501 528
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 cursor.block.addBefore(cursor, newInstruction); 570 cursor.block.addBefore(cursor, newInstruction);
544 // Update the users of the instruction dominated by [cursor] to 571 // Update the users of the instruction dominated by [cursor] to
545 // use the new instruction, that has an narrower range. 572 // use the new instruction, that has an narrower range.
546 Set<HInstruction> dominatedUsers = instruction.dominatedUsers(cursor); 573 Set<HInstruction> dominatedUsers = instruction.dominatedUsers(cursor);
547 for (HInstruction user in dominatedUsers) { 574 for (HInstruction user in dominatedUsers) {
548 user.changeUse(instruction, newInstruction); 575 user.changeUse(instruction, newInstruction);
549 } 576 }
550 return newInstruction; 577 return newInstruction;
551 } 578 }
552 579
580 static Operation reverseOperation(BinaryOperation operation) {
581 if (operation == const LessOperation()) {
582 return const GreaterEqualOperation();
583 } else if (operation == const LessEqualOperation()) {
584 return const GreaterOperation();
585 } else if (operation == const GreaterOperation()) {
586 return const LessEqualOperation();
587 } else if (operation == const GreaterEqualOperation()) {
588 return const LessOperation();
589 } else {
590 return null;
591 }
592 }
593
594 static Range computeNewRange(BinaryOperation operation, Range range) {
595 if (operation == const LessOperation()) {
596 return new Range(const MinIntValue(), range.upper - const IntValue(1));
597 } else if (operation == const LessEqualOperation()) {
598 return new Range(const MinIntValue(), range.upper);
599 } else if (operation == const GreaterOperation()) {
600 return new Range(range.lower + const IntValue(1), const MaxIntValue());
601 } else if (operation == const GreaterEqualOperation()) {
602 return new Range(range.lower, const MaxIntValue());
603 } else {
604 return const Range.unbound();
605 }
606 }
607
553 Range visitConditionalBranch(HConditionalBranch branch) { 608 Range visitConditionalBranch(HConditionalBranch branch) {
554 var condition = branch.condition; 609 var condition = branch.condition;
555 // TODO(ngeoffray): Handle more condition kinds. 610 // TODO(ngeoffray): Handle complex conditions.
556 if (condition is !HLess) return const Range.unbound(); 611 if (condition is !HRelational) return const Range.unbound();
612 if (condition is HEquals) return const Range.unbound();
613 if (condition is HIdentity) return const Range.unbound();
557 HInstruction right = condition.right; 614 HInstruction right = condition.right;
558 HInstruction left = condition.left; 615 HInstruction left = condition.left;
559 if (!left.isInteger(types)) return const Range.unbound(); 616 if (!left.isInteger(types)) return const Range.unbound();
560 if (!right.isInteger(types)) return const Range.unbound(); 617 if (!right.isInteger(types)) return const Range.unbound();
561 618
562 // Update the true branch to use a narrower range for [left]. 619 Range rightRange = ranges[right];
563 // TODO(ngeoffray): Also do it for [right]. 620 Range leftRange = ranges[left];
564 HInstruction instruction = 621 Operation operation = condition.operation(constantSystem);
565 createRangeConversion(branch.trueBranch.first, left); 622 Operation reverse = reverseOperation(operation);
566 Range range = new Range( 623 // Update the true branch to use narrower ranges for [left] and
567 const MinIntValue(), ranges[right].upper - const IntValue(1)); 624 // [right].
568 range = range.intersection(ranges[left]); 625 Range range = computeNewRange(operation, rightRange);
Søren Gjesse 2012/10/02 08:07:20 Wouldn't it be better to include the intersection
ngeoffray 2012/10/02 16:03:09 Not sure I understand that comment. Could you expa
Søren Gjesse 2012/10/02 16:26:56 What I ment was to change Range range = compute
ngeoffray 2012/10/04 08:51:08 Done.
569 ranges[instruction] = range; 626 range = range.intersection(leftRange);
627 if (leftRange != range) {
628 HInstruction instruction =
629 createRangeConversion(branch.trueBranch.first, left);
630 ranges[instruction] = range;
631 }
570 632
571 // Update the false branch to use a narrower range for [left]. 633 range = computeNewRange(reverse, leftRange);
572 // TODO(ngeoffray): Also do it for [right]. 634 range = range.intersection(rightRange);
573 instruction = createRangeConversion(branch.falseBranch.first, left); 635 if (rightRange != range) {
574 range = new Range(ranges[right].lower, const MaxIntValue()); 636 HInstruction instruction =
575 range = range.intersection(ranges[left]); 637 createRangeConversion(branch.trueBranch.first, right);
576 ranges[instruction] = range; 638 ranges[instruction] = range;
639 }
640
641 // Update the false branch to use narrower ranges for [left] and
642 // [right].
643 range = computeNewRange(reverse, rightRange);
644 range = range.intersection(leftRange);
645 if (leftRange != range) {
646 HInstruction instruction =
647 createRangeConversion(branch.falseBranch.first, left);
648 ranges[instruction] = range;
649 }
650
651 range = computeNewRange(operation, leftRange);
652 range = range.intersection(rightRange);
653 if (rightRange != range) {
654 HInstruction instruction =
655 createRangeConversion(branch.falseBranch.first, right);
656 ranges[instruction] = range;
657 }
577 658
578 return const Range.unbound(); 659 return const Range.unbound();
579 } 660 }
580 661
581 Range visitRangeConversion(HRangeConversion conversion) { 662 Range visitRangeConversion(HRangeConversion conversion) {
582 return ranges[conversion]; 663 return ranges[conversion];
583 } 664 }
584 } 665 }
585 666
586 /** 667 /**
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
679 if (instruction is HPhi && !instruction.block.isLoopHeader()) { 760 if (instruction is HPhi && !instruction.block.isLoopHeader()) {
680 HInstruction result = unwrap(instruction.inputs[0]); 761 HInstruction result = unwrap(instruction.inputs[0]);
681 for (int i = 1; i < instruction.inputs.length; i++) { 762 for (int i = 1; i < instruction.inputs.length; i++) {
682 if (result != unwrap(instruction.inputs[i])) return instruction; 763 if (result != unwrap(instruction.inputs[i])) return instruction;
683 } 764 }
684 return result; 765 return result;
685 } 766 }
686 return instruction; 767 return instruction;
687 } 768 }
688 } 769 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698