Skip to content

Commit 90ae538

Browse files
committed
[SCEV] Prove implication of predicates to their sign-flipped counterparts
This patch teaches SCEV two implication rules: x <u y && y >=s 0 --> x <s y, x <s y && y <s 0 --> x <u y. And all equivalents with signs/parts swapped. Differential Revision: https://reviews.llvm.org/D110517 Reviewed By: nikic
1 parent 9e9b0f4 commit 90ae538

File tree

2 files changed

+45
-30
lines changed

2 files changed

+45
-30
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10770,18 +10770,49 @@ bool ScalarEvolution::isImpliedCondBalancedTypes(
1077010770
return false;
1077110771
}
1077210772

10773-
// Unsigned comparison is the same as signed comparison when both the operands
10774-
// are non-negative or negative.
1077510773
auto IsSignFlippedPredicate = [](CmpInst::Predicate P1,
1077610774
CmpInst::Predicate P2) {
1077710775
assert(P1 != P2 && "Handled earlier!");
1077810776
return CmpInst::isRelational(P2) &&
1077910777
P1 == CmpInst::getFlippedSignednessPredicate(P2);
1078010778
};
10781-
if (IsSignFlippedPredicate(Pred, FoundPred) &&
10782-
((isKnownNonNegative(FoundLHS) && isKnownNonNegative(FoundRHS)) ||
10783-
(isKnownNegative(FoundLHS) && isKnownNegative(FoundRHS))))
10784-
return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, CtxI);
10779+
if (IsSignFlippedPredicate(Pred, FoundPred)) {
10780+
// Unsigned comparison is the same as signed comparison when both the
10781+
// operands are non-negative or negative.
10782+
if ((isKnownNonNegative(FoundLHS) && isKnownNonNegative(FoundRHS)) ||
10783+
(isKnownNegative(FoundLHS) && isKnownNegative(FoundRHS)))
10784+
return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, CtxI);
10785+
// Create local copies that we can freely swap and canonicalize our
10786+
// conditions to "le/lt".
10787+
ICmpInst::Predicate CanonicalPred = Pred, CanonicalFoundPred = FoundPred;
10788+
const SCEV *CanonicalLHS = LHS, *CanonicalRHS = RHS,
10789+
*CanonicalFoundLHS = FoundLHS, *CanonicalFoundRHS = FoundRHS;
10790+
if (ICmpInst::isGT(CanonicalPred) || ICmpInst::isGE(CanonicalPred)) {
10791+
CanonicalPred = ICmpInst::getSwappedPredicate(CanonicalPred);
10792+
CanonicalFoundPred = ICmpInst::getSwappedPredicate(CanonicalFoundPred);
10793+
std::swap(CanonicalLHS, CanonicalRHS);
10794+
std::swap(CanonicalFoundLHS, CanonicalFoundRHS);
10795+
}
10796+
assert((ICmpInst::isLT(CanonicalPred) || ICmpInst::isLE(CanonicalPred)) &&
10797+
"Must be!");
10798+
assert((ICmpInst::isLT(CanonicalFoundPred) ||
10799+
ICmpInst::isLE(CanonicalFoundPred)) &&
10800+
"Must be!");
10801+
if (ICmpInst::isSigned(CanonicalPred) && isKnownNonNegative(CanonicalRHS))
10802+
// Use implication:
10803+
// x <u y && y >=s 0 --> x <s y.
10804+
// If we can prove the left part, the right part is also proven.
10805+
return isImpliedCondOperands(CanonicalFoundPred, CanonicalLHS,
10806+
CanonicalRHS, CanonicalFoundLHS,
10807+
CanonicalFoundRHS);
10808+
if (ICmpInst::isUnsigned(CanonicalPred) && isKnownNegative(CanonicalRHS))
10809+
// Use implication:
10810+
// x <s y && y <s 0 --> x <u y.
10811+
// If we can prove the left part, the right part is also proven.
10812+
return isImpliedCondOperands(CanonicalFoundPred, CanonicalLHS,
10813+
CanonicalRHS, CanonicalFoundLHS,
10814+
CanonicalFoundRHS);
10815+
}
1078510816

1078610817
// Check if we can make progress by sharpening ranges.
1078710818
if (FoundPred == ICmpInst::ICMP_NE &&

llvm/test/Transforms/IndVarSimplify/outer_phi.ll

Lines changed: 8 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,6 @@ exit:
463463

464464

465465
; Same as test_01a, but non-negativity of %b is known without context.
466-
; FIXME: We can remove 2nd check in loop.
467466
define i32 @test_05a(i32 %a, i32* %bp) {
468467
; CHECK-LABEL: @test_05a(
469468
; CHECK-NEXT: entry:
@@ -477,8 +476,7 @@ define i32 @test_05a(i32 %a, i32* %bp) {
477476
; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
478477
; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
479478
; CHECK: inner.1:
480-
; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
481-
; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
479+
; CHECK-NEXT: br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
482480
; CHECK: inner.backedge:
483481
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
484482
; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond()
@@ -527,7 +525,6 @@ exit:
527525
}
528526

529527
; Similar to test_05a, but inverted 2nd condition.
530-
; FIXME: We can remove 2nd check in loop.
531528
define i32 @test_05b(i32 %a, i32* %bp) {
532529
; CHECK-LABEL: @test_05b(
533530
; CHECK-NEXT: entry:
@@ -541,8 +538,7 @@ define i32 @test_05b(i32 %a, i32* %bp) {
541538
; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
542539
; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
543540
; CHECK: inner.1:
544-
; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]]
545-
; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
541+
; CHECK-NEXT: br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
546542
; CHECK: inner.backedge:
547543
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
548544
; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond()
@@ -591,7 +587,6 @@ exit:
591587
}
592588

593589
; We should prove implication: iv <s b, b <s 0 => iv <u b.
594-
; FIXME: Can remove 2nd check
595590
define i32 @test_05c(i32 %a, i32* %bp) {
596591
; CHECK-LABEL: @test_05c(
597592
; CHECK-NEXT: entry:
@@ -605,8 +600,7 @@ define i32 @test_05c(i32 %a, i32* %bp) {
605600
; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
606601
; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
607602
; CHECK: inner.1:
608-
; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
609-
; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
603+
; CHECK-NEXT: br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
610604
; CHECK: inner.backedge:
611605
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
612606
; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond()
@@ -655,7 +649,6 @@ exit:
655649
}
656650

657651
; Same as test_05c, but 2nd condition reversed.
658-
; FIXME: Can remove 2nd check
659652
define i32 @test_05d(i32 %a, i32* %bp) {
660653
; CHECK-LABEL: @test_05d(
661654
; CHECK-NEXT: entry:
@@ -669,8 +662,7 @@ define i32 @test_05d(i32 %a, i32* %bp) {
669662
; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
670663
; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
671664
; CHECK: inner.1:
672-
; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]]
673-
; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
665+
; CHECK-NEXT: br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
674666
; CHECK: inner.backedge:
675667
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
676668
; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond()
@@ -720,7 +712,6 @@ exit:
720712

721713

722714
; Same as test_05a, but 1st condition inverted.
723-
; FIXME: We can remove 2nd check in loop.
724715
define i32 @test_05e(i32 %a, i32* %bp) {
725716
; CHECK-LABEL: @test_05e(
726717
; CHECK-NEXT: entry:
@@ -734,8 +725,7 @@ define i32 @test_05e(i32 %a, i32* %bp) {
734725
; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]]
735726
; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
736727
; CHECK: inner.1:
737-
; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp slt i32 [[IV]], [[B]]
738-
; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
728+
; CHECK-NEXT: br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
739729
; CHECK: inner.backedge:
740730
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
741731
; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond()
@@ -784,7 +774,6 @@ exit:
784774
}
785775

786776
; Same as test_05b, but 1st condition inverted.
787-
; FIXME: We can remove 2nd check in loop.
788777
define i32 @test_05f(i32 %a, i32* %bp) {
789778
; CHECK-LABEL: @test_05f(
790779
; CHECK-NEXT: entry:
@@ -798,8 +787,7 @@ define i32 @test_05f(i32 %a, i32* %bp) {
798787
; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]]
799788
; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
800789
; CHECK: inner.1:
801-
; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]]
802-
; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
790+
; CHECK-NEXT: br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
803791
; CHECK: inner.backedge:
804792
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
805793
; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond()
@@ -848,7 +836,6 @@ exit:
848836
}
849837

850838
; Same as test_05c, but 1st condition inverted.
851-
; FIXME: We can remove 2nd check in loop.
852839
define i32 @test_05g(i32 %a, i32* %bp) {
853840
; CHECK-LABEL: @test_05g(
854841
; CHECK-NEXT: entry:
@@ -862,8 +849,7 @@ define i32 @test_05g(i32 %a, i32* %bp) {
862849
; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]]
863850
; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
864851
; CHECK: inner.1:
865-
; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ult i32 [[IV]], [[B]]
866-
; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
852+
; CHECK-NEXT: br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
867853
; CHECK: inner.backedge:
868854
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
869855
; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond()
@@ -912,7 +898,6 @@ exit:
912898
}
913899

914900
; Same as test_05d, but 1st condition inverted.
915-
; FIXME: We can remove 2nd check in loop.
916901
define i32 @test_05h(i32 %a, i32* %bp) {
917902
; CHECK-LABEL: @test_05h(
918903
; CHECK-NEXT: entry:
@@ -926,8 +911,7 @@ define i32 @test_05h(i32 %a, i32* %bp) {
926911
; CHECK-NEXT: [[SIGNED_COND:%.*]] = icmp sgt i32 [[B]], [[IV]]
927912
; CHECK-NEXT: br i1 [[SIGNED_COND]], label [[INNER_1:%.*]], label [[SIDE_EXIT:%.*]]
928913
; CHECK: inner.1:
929-
; CHECK-NEXT: [[UNSIGNED_COND:%.*]] = icmp ugt i32 [[B]], [[IV]]
930-
; CHECK-NEXT: br i1 [[UNSIGNED_COND]], label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
914+
; CHECK-NEXT: br i1 true, label [[INNER_BACKEDGE]], label [[SIDE_EXIT]]
931915
; CHECK: inner.backedge:
932916
; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1
933917
; CHECK-NEXT: [[INNER_LOOP_COND:%.*]] = call i1 @cond()

0 commit comments

Comments
 (0)