|
55 | 55 | import jdk.graal.compiler.nodes.util.IntegerHelper;
|
56 | 56 | import jdk.graal.compiler.nodes.util.SignedIntegerHelper;
|
57 | 57 | import jdk.graal.compiler.nodes.util.UnsignedIntegerHelper;
|
| 58 | +import jdk.graal.compiler.phases.common.util.LoopUtility; |
58 | 59 | import jdk.vm.ci.meta.DeoptimizationAction;
|
59 | 60 | import jdk.vm.ci.meta.DeoptimizationReason;
|
60 | 61 | import jdk.vm.ci.meta.JavaKind;
|
@@ -619,70 +620,92 @@ public boolean counterNeverOverflows() {
|
619 | 620 | }
|
620 | 621 |
|
621 | 622 | public boolean ivCanNeverOverflow(InductionVariable iv) {
|
622 |
| - if (!isLimitIncluded && iv.isConstantStride() && Loop.absStrideIsOne(iv)) { |
623 |
| - return true; |
624 |
| - } |
625 |
| - if (loop.loopBegin().isProtectedNonOverflowingUnsigned()) { |
626 |
| - return true; |
627 |
| - } |
628 |
| - // @formatter:off |
629 |
| - /* |
630 |
| - * Following comment reasons about the simplest possible loop form: |
631 |
| - * |
632 |
| - * for(i = 0;i < end;i += stride) |
633 |
| - * |
634 |
| - * The problem is we want to create an overflow guard for the loop that can be hoisted |
635 |
| - * before the loop, i.e., the overflow guard must not have loop variant inputs else it must |
636 |
| - * be scheduled inside the loop. This means we cannot refer explicitly to the induction |
637 |
| - * variable's phi but must establish a relation between end, stride and max (max integer |
638 |
| - * range for a given loop) that is sufficient for most cases. |
639 |
| - * |
640 |
| - * We know that a head counted loop with a stride > 1 may overflow if the stride is big |
641 |
| - * enough that end + stride will be > MAX, i.e. it overflows into negative value range. |
642 |
| - * |
643 |
| - * It is important that "end" in this context is the checked value of the loop condition: |
644 |
| - * i.e., an arbitrary value. There is no relation between end and MAX established except |
645 |
| - * that based on the integer representation we know that end <= MAX. |
646 |
| - * |
647 |
| - * A loop can overflow if the last checked value of the iv allows an overflow in the next |
648 |
| - * iteration: the value range for which an overflow can happen is [MAX-(stride-1),MAX] e.g. |
649 |
| - * |
650 |
| - * MAX=10, stride = 3, overflow if number > 10 |
651 |
| - * end = MAX -> 10 -> 10 + 3 = 13 -> overflow |
652 |
| - * end = MAX-1 -> 9 -> 9 + 3 = 12 -> overflow |
653 |
| - * end = MAX-2 -> 8 -> 8 + 3 = 11 -> overflow |
654 |
| - * end = MAX-3 -> 7 -> 7 + 3 = 10 -> No overflow at MAX - stride |
655 |
| - * |
656 |
| - * Note that this guard is pessimistic, i.e., it marks loops as potentially overflowing that |
657 |
| - * are actually not overflowing. Consider the following loop: |
658 |
| - * |
659 |
| - * <pre> |
660 |
| - * for(i = MAX-56; i < MAX, i += 8) |
661 |
| - * </pre> |
662 |
| - * |
663 |
| - * where i in last loop body visit = MAX - 8, i after = MAX, no overflow |
664 |
| - * |
665 |
| - * which is wrongly detected as overflowing since "end" is element of [MAX-(stride-1),MAX] |
666 |
| - * which is [MAX-7,MAX] and end is MAX. We handle such cases with a speculation and disable |
667 |
| - * counted loop detection on subsequent compilations. We can only avoid such false positive |
668 |
| - * detections by actually computing the number of iterations with a division, however we try |
669 |
| - * to avoid that since that may be part of the fast path. |
670 |
| - * |
671 |
| - * And additional backup strategy could be to actually emit the precise guard inside the |
672 |
| - * loop if the deopt already failed, but we refrain from this for now for simplicity |
673 |
| - * reasons. |
674 |
| - */ |
675 |
| - // @formatter:on |
676 |
| - IntegerStamp endStamp = (IntegerStamp) getTripCountLimit().stamp(NodeView.DEFAULT); |
677 |
| - ValueNode strideNode = iv.strideNode(); |
678 |
| - IntegerStamp strideStamp = (IntegerStamp) strideNode.stamp(NodeView.DEFAULT); |
679 |
| - IntegerHelper integerHelper = getCounterIntegerHelper(); |
680 |
| - if (getDirection() == InductionVariable.Direction.Up) { |
681 |
| - long max = integerHelper.maxValue(); |
682 |
| - return integerHelper.compare(endStamp.upperBound(), max - (strideStamp.upperBound() - 1) - (isLimitIncluded ? 1 : 0)) <= 0; |
683 |
| - } else if (getDirection() == InductionVariable.Direction.Down) { |
684 |
| - long min = integerHelper.minValue(); |
685 |
| - return integerHelper.compare(min + (1 - strideStamp.lowerBound()) + (isLimitIncluded ? 1 : 0), endStamp.lowerBound()) <= 0; |
| 623 | + if (iv == getLimitCheckedIV()) { |
| 624 | + if (!isLimitIncluded && iv.isConstantStride() && Loop.absStrideIsOne(iv)) { |
| 625 | + return true; |
| 626 | + } |
| 627 | + if (loop.loopBegin().isProtectedNonOverflowingUnsigned()) { |
| 628 | + return true; |
| 629 | + } |
| 630 | + // @formatter:off |
| 631 | + /* |
| 632 | + * Following comment reasons about the simplest possible loop form: |
| 633 | + * |
| 634 | + * for(i = 0;i < end;i += stride) |
| 635 | + * |
| 636 | + * The problem is we want to create an overflow guard for the loop that can be hoisted |
| 637 | + * before the loop, i.e., the overflow guard must not have loop variant inputs else it must |
| 638 | + * be scheduled inside the loop. This means we cannot refer explicitly to the induction |
| 639 | + * variable's phi but must establish a relation between end, stride and max (max integer |
| 640 | + * range for a given loop) that is sufficient for most cases. |
| 641 | + * |
| 642 | + * We know that a head counted loop with a stride > 1 may overflow if the stride is big |
| 643 | + * enough that end + stride will be > MAX, i.e. it overflows into negative value range. |
| 644 | + * |
| 645 | + * It is important that "end" in this context is the checked value of the loop condition: |
| 646 | + * i.e., an arbitrary value. There is no relation between end and MAX established except |
| 647 | + * that based on the integer representation we know that end <= MAX. |
| 648 | + * |
| 649 | + * A loop can overflow if the last checked value of the iv allows an overflow in the next |
| 650 | + * iteration: the value range for which an overflow can happen is [MAX-(stride-1),MAX] e.g. |
| 651 | + * |
| 652 | + * MAX=10, stride = 3, overflow if number > 10 |
| 653 | + * end = MAX -> 10 -> 10 + 3 = 13 -> overflow |
| 654 | + * end = MAX-1 -> 9 -> 9 + 3 = 12 -> overflow |
| 655 | + * end = MAX-2 -> 8 -> 8 + 3 = 11 -> overflow |
| 656 | + * end = MAX-3 -> 7 -> 7 + 3 = 10 -> No overflow at MAX - stride |
| 657 | + * |
| 658 | + * Note that this guard is pessimistic, i.e., it marks loops as potentially overflowing that |
| 659 | + * are actually not overflowing. Consider the following loop: |
| 660 | + * |
| 661 | + * <pre> |
| 662 | + * for(i = MAX-56; i < MAX, i += 8) |
| 663 | + * </pre> |
| 664 | + * |
| 665 | + * where i in last loop body visit = MAX - 8, i after = MAX, no overflow |
| 666 | + * |
| 667 | + * which is wrongly detected as overflowing since "end" is element of [MAX-(stride-1),MAX] |
| 668 | + * which is [MAX-7,MAX] and end is MAX. We handle such cases with a speculation and disable |
| 669 | + * counted loop detection on subsequent compilations. We can only avoid such false positive |
| 670 | + * detections by actually computing the number of iterations with a division, however we try |
| 671 | + * to avoid that since that may be part of the fast path. |
| 672 | + * |
| 673 | + * And additional backup strategy could be to actually emit the precise guard inside the |
| 674 | + * loop if the deopt already failed, but we refrain from this for now for simplicity |
| 675 | + * reasons. |
| 676 | + */ |
| 677 | + // @formatter:on |
| 678 | + IntegerStamp endStamp = (IntegerStamp) getTripCountLimit().stamp(NodeView.DEFAULT); |
| 679 | + ValueNode strideNode = getLimitCheckedIV().strideNode(); |
| 680 | + IntegerStamp strideStamp = (IntegerStamp) strideNode.stamp(NodeView.DEFAULT); |
| 681 | + IntegerHelper integerHelper = getCounterIntegerHelper(); |
| 682 | + if (getDirection() == InductionVariable.Direction.Up) { |
| 683 | + long max = integerHelper.maxValue(); |
| 684 | + return integerHelper.compare(endStamp.upperBound(), max - (strideStamp.upperBound() - 1) - (isLimitIncluded ? 1 : 0)) <= 0; |
| 685 | + } else if (getDirection() == InductionVariable.Direction.Down) { |
| 686 | + long min = integerHelper.minValue(); |
| 687 | + return integerHelper.compare(min + (1 - strideStamp.lowerBound()) + (isLimitIncluded ? 1 : 0), endStamp.lowerBound()) <= 0; |
| 688 | + } |
| 689 | + return false; |
| 690 | + } else { |
| 691 | + /* |
| 692 | + * All over IVs: This IV is not compared against limit and thus we cannot play the trick |
| 693 | + * comparing against the end stamp. We have to compute (if possible) the extremum value |
| 694 | + * and use that. |
| 695 | + */ |
| 696 | + if (iv.isConstantInit() && isConstantMaxTripCount() && iv.isConstantStride()) { |
| 697 | + try { |
| 698 | + final int bits = IntegerStamp.getBits(iv.valueNode().stamp(NodeView.DEFAULT)); |
| 699 | + long tripCountMinus1 = LoopUtility.subtractExact(bits, maxTripCountNode().asJavaConstant().asLong(), 1); |
| 700 | + long stripTimesTripCount = LoopUtility.multiplyExact(bits, iv.constantStride(), tripCountMinus1); |
| 701 | + @SuppressWarnings("unused") |
| 702 | + long extremum = LoopUtility.addExact(bits, stripTimesTripCount, iv.initNode().asJavaConstant().asLong()); |
| 703 | + return true; |
| 704 | + } catch (ArithmeticException e) { |
| 705 | + // overflow |
| 706 | + return false; |
| 707 | + } |
| 708 | + } |
686 | 709 | }
|
687 | 710 | return false;
|
688 | 711 | }
|
|
0 commit comments