llvm.org GIT mirror llvm / 8229f1d
[ScalarEvolution] Re-enable Predicate implication from operations The patch rL298481 was reverted due to crash on clang-with-lto-ubuntu build. The reason of the crash was type mismatch between either a or b and RHS in the following situation: LHS = sext(a +nsw b) > RHS. This is quite rare, but still possible situation. Normally we need to cast all {a, b, RHS} to their widest type. But we try to avoid creation of new SCEV that are not constants to avoid initiating recursive analysis that can take a lot of time and/or cache a bad value for iterations number. To deal with this, in this patch we reject this case and will not try to analyze it if the type of sum doesn't match with the type of RHS. In this situation we don't need to create any non-constant SCEVs. This patch also adds an assertion to the method IsProvedViaContext so that we could fail on it and not go further into range analysis etc (because in some situations these analyzes succeed even when the passed arguments have wrong types, what should not normally happen). The patch also contains a fix for a problem with too narrow scope of the analysis caused by wrong usage of predicates in recursive invocations. The regression test on the said failure: test/Analysis/ScalarEvolution/implied-via-addition.ll git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@298690 91177308-0d34-0410-b5e6-96231b3b80d8 Max Kazantsev 3 years ago
4 changed file(s) with 534 addition(s) and 16 deletion(s). Raw diff Collapse all Expand all
977977
978978 /// Test whether the condition described by Pred, LHS, and RHS is true
979979 /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
980 /// true. Here LHS is an operation that includes FoundLHS as one of its
981 /// arguments.
982 bool isImpliedViaOperations(ICmpInst::Predicate Pred,
983 const SCEV *LHS, const SCEV *RHS,
984 const SCEV *FoundLHS, const SCEV *FoundRHS,
985 unsigned Depth = 0);
986
987 /// Test whether the condition described by Pred, LHS, and RHS is true.
988 /// Use only simple non-recursive types of checks, such as range analysis etc.
989 bool isKnownViaSimpleReasoning(ICmpInst::Predicate Pred,
990 const SCEV *LHS, const SCEV *RHS);
991
992 /// Test whether the condition described by Pred, LHS, and RHS is true
993 /// whenever the condition described by Pred, FoundLHS, and FoundRHS is
980994 /// true.
981995 bool isImpliedCondOperandsHelper(ICmpInst::Predicate Pred, const SCEV *LHS,
982996 const SCEV *RHS, const SCEV *FoundLHS,
11211135 /// represents how SCEV will treat the given type, for which isSCEVable must
11221136 /// return true. For pointer types, this is the pointer-sized integer type.
11231137 Type *getEffectiveSCEVType(Type *Ty) const;
1138
1139 // Returns a wider type among {Ty1, Ty2}.
1140 Type *getWiderType(Type *Ty1, Type *Ty2) const;
11241141
11251142 /// Return true if the SCEV is a scAddRecExpr or it contains
11261143 /// scAddRecExpr. The result will be cached in HasRecMap.
135135 "scalar-evolution-max-scev-compare-depth", cl::Hidden,
136136 cl::desc("Maximum depth of recursive SCEV complexity comparisons"),
137137 cl::init(32));
138
139 static cl::opt MaxSCEVOperationsImplicationDepth(
140 "scalar-evolution-max-scev-operations-implication-depth", cl::Hidden,
141 cl::desc("Maximum depth of recursive SCEV operations implication analysis"),
142 cl::init(4));
138143
139144 static cl::opt MaxValueCompareDepth(
140145 "scalar-evolution-max-value-compare-depth", cl::Hidden,
34173422 return getDataLayout().getIntPtrType(Ty);
34183423 }
34193424
3425 Type *ScalarEvolution::getWiderType(Type *T1, Type *T2) const {
3426 return getTypeSizeInBits(T1) >= getTypeSizeInBits(T2) ? T1 : T2;
3427 }
3428
34203429 const SCEV *ScalarEvolution::getCouldNotCompute() {
34213430 return CouldNotCompute.get();
34223431 }
85588567 llvm_unreachable("covered switch fell through?!");
85598568 }
85608569
8570 bool ScalarEvolution::isImpliedViaOperations(ICmpInst::Predicate Pred,
8571 const SCEV *LHS, const SCEV *RHS,
8572 const SCEV *FoundLHS,
8573 const SCEV *FoundRHS,
8574 unsigned Depth) {
8575 // We want to avoid hurting the compile time with analysis of too big trees.
8576 if (Depth > MaxSCEVOperationsImplicationDepth)
8577 return false;
8578 // We only want to work with ICMP_SGT comparison so far.
8579 // TODO: Extend to ICMP_UGT?
8580 if (Pred == ICmpInst::ICMP_SLT) {
8581 Pred = ICmpInst::ICMP_SGT;
8582 std::swap(LHS, RHS);
8583 std::swap(FoundLHS, FoundRHS);
8584 }
8585 if (Pred != ICmpInst::ICMP_SGT)
8586 return false;
8587
8588 auto GetOpFromSExt = [&](const SCEV *S) {
8589 if (auto *Ext = dyn_cast(S))
8590 return Ext->getOperand();
8591 // TODO: If S is a SCEVConstant then you can cheaply "strip" the sext off
8592 // the constant in some cases.
8593 return S;
8594 };
8595
8596 // Acquire values from extensions.
8597 auto *OrigFoundLHS = FoundLHS;
8598 LHS = GetOpFromSExt(LHS);
8599 FoundLHS = GetOpFromSExt(FoundLHS);
8600
8601 // Is the SGT predicate can be proved trivially or using the found context.
8602 auto IsSGTViaContext = [&](const SCEV *S1, const SCEV *S2) {
8603 assert(S1->getType() == S2->getType() && "Proving for wrong types?");
8604 return isKnownViaSimpleReasoning(ICmpInst::ICMP_SGT, S1, S2) ||
8605 isImpliedViaOperations(ICmpInst::ICMP_SGT, S1, S2, OrigFoundLHS,
8606 FoundRHS, Depth + 1);
8607 };
8608
8609 if (auto *LHSAddExpr = dyn_cast(LHS)) {
8610 // We want to avoid creation of any new non-constant SCEV. Since we are
8611 // going to compare the operands to RHS, we should be certain that we don't
8612 // need any type conversions for this. So let's decline all cases when the
8613 // types of LHS and RHS do not match.
8614 // TODO: Maybe try to get RHS from sext to catch more cases?
8615 if (LHSAddExpr->getType() != RHS->getType())
8616 return false;
8617
8618 // Should not overflow.
8619 if (!LHSAddExpr->hasNoSignedWrap())
8620 return false;
8621
8622 auto *LL = LHSAddExpr->getOperand(0);
8623 auto *LR = LHSAddExpr->getOperand(1);
8624 auto *MinusOne = getNegativeSCEV(getOne(RHS->getType()));
8625
8626 // Checks that S1 >= 0 && S2 > RHS, trivially or using the found context.
8627 auto IsSumGreaterThanRHS = [&](const SCEV *S1, const SCEV *S2) {
8628 return IsSGTViaContext(S1, MinusOne) && IsSGTViaContext(S2, RHS);
8629 };
8630 // Try to prove the following rule:
8631 // (LHS = LL + LR) && (LL >= 0) && (LR > RHS) => (LHS > RHS).
8632 // (LHS = LL + LR) && (LR >= 0) && (LL > RHS) => (LHS > RHS).
8633 if (IsSumGreaterThanRHS(LL, LR) || IsSumGreaterThanRHS(LR, LL))
8634 return true;
8635 } else if (auto *LHSUnknownExpr = dyn_cast(LHS)) {
8636 Value *LL, *LR;
8637 // FIXME: Once we have SDiv implemented, we can get rid of this matching.
8638 using namespace llvm::PatternMatch;
8639 if (match(LHSUnknownExpr->getValue(), m_SDiv(m_Value(LL), m_Value(LR)))) {
8640 // Rules for division.
8641 // We are going to perform some comparisons with Denominator and its
8642 // derivative expressions. In general case, creating a SCEV for it may
8643 // lead to a complex analysis of the entire graph, and in particular it
8644 // can request trip count recalculation for the same loop. This would
8645 // cache as SCEVCouldNotCompute to avoid the infinite recursion. This is a
8646 // sad thing. To avoid this, we only want to create SCEVs that are
8647 // constants in this section. So we bail if Denominator is not a constant.
8648 if (!isa(LR))
8649 return false;
8650
8651 auto *Denominator = cast(getSCEV(LR));
8652
8653 // We want to make sure that LHS = FoundLHS / Denominator. If it is so,
8654 // then a SCEV for the numerator already exists and matches with FoundLHS.
8655 auto *Numerator = getExistingSCEV(LL);
8656
8657 // Make sure that it exists and has the same type.
8658 if (!Numerator || Numerator->getType() != FoundLHS->getType())
8659 return false;
8660
8661 // Make sure that the numerator matches with FoundLHs and the denominator
8662 // is positive.
8663 if (!HasSameValue(Numerator, FoundLHS) || !isKnownPositive(Denominator))
8664 return false;
8665
8666 // Given that:
8667 // FoundLHS > FoundRHS, LHS = FoundLHS / Denominator, Denominator > 0.
8668 auto *Ty2 = getWiderType(Denominator->getType(), FoundRHS->getType());
8669 auto *DenominatorExt = getNoopOrSignExtend(Denominator, Ty2);
8670 auto *FoundRHSExt = getNoopOrSignExtend(FoundRHS, Ty2);
8671
8672 // Try to prove the following rule:
8673 // (FoundRHS > Denominator - 2) && (RHS <= 0) => (LHS > RHS).
8674 // For example, given that FoundLHS > 2. It means that FoundLHS is at
8675 // least 3. If we divide it by Denominator < 4, we will have at least 1.
8676 auto *DenomMinusTwo = getMinusSCEV(DenominatorExt, getConstant(Ty2, 2));
8677 if (isKnownNonPositive(RHS) &&
8678 IsSGTViaContext(FoundRHSExt, DenomMinusTwo))
8679 return true;
8680
8681 // Try to prove the following rule:
8682 // (FoundRHS > -1 - Denominator) && (RHS < 0) => (LHS > RHS).
8683 // For example, given that FoundLHS > -3. Then FoundLHS is at least -2.
8684 // If we divide it by Denominator > 2, then:
8685 // 1. If FoundLHS is negative, then the result is 0.
8686 // 2. If FoundLHS is non-negative, then the result is non-negative.
8687 // Anyways, the result is non-negative.
8688 auto *MinusOne = getNegativeSCEV(getOne(Ty2));
8689 auto *NegDenomMinusOne = getMinusSCEV(MinusOne, DenominatorExt);
8690 if (isKnownNegative(RHS) &&
8691 IsSGTViaContext(FoundRHSExt, NegDenomMinusOne))
8692 return true;
8693 }
8694 }
8695
8696 return false;
8697 }
8698
8699 bool
8700 ScalarEvolution::isKnownViaSimpleReasoning(ICmpInst::Predicate Pred,
8701 const SCEV *LHS, const SCEV *RHS) {
8702 return isKnownPredicateViaConstantRanges(Pred, LHS, RHS) ||
8703 IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||
8704 IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS) ||
8705 isKnownPredicateViaNoOverflow(Pred, LHS, RHS);
8706 }
8707
85618708 bool
85628709 ScalarEvolution::isImpliedCondOperandsHelper(ICmpInst::Predicate Pred,
85638710 const SCEV *LHS, const SCEV *RHS,
85648711 const SCEV *FoundLHS,
85658712 const SCEV *FoundRHS) {
8566 auto IsKnownPredicateFull =
8567 [this](ICmpInst::Predicate Pred, const SCEV *LHS, const SCEV *RHS) {
8568 return isKnownPredicateViaConstantRanges(Pred, LHS, RHS) ||
8569 IsKnownPredicateViaMinOrMax(*this, Pred, LHS, RHS) ||
8570 IsKnownPredicateViaAddRecStart(*this, Pred, LHS, RHS) ||
8571 isKnownPredicateViaNoOverflow(Pred, LHS, RHS);
8572 };
8573
85748713 switch (Pred) {
85758714 default: llvm_unreachable("Unexpected ICmpInst::Predicate value!");
85768715 case ICmpInst::ICMP_EQ:
85808719 break;
85818720 case ICmpInst::ICMP_SLT:
85828721 case ICmpInst::ICMP_SLE:
8583 if (IsKnownPredicateFull(ICmpInst::ICMP_SLE, LHS, FoundLHS) &&
8584 IsKnownPredicateFull(ICmpInst::ICMP_SGE, RHS, FoundRHS))
8722 if (isKnownViaSimpleReasoning(ICmpInst::ICMP_SLE, LHS, FoundLHS) &&
8723 isKnownViaSimpleReasoning(ICmpInst::ICMP_SGE, RHS, FoundRHS))
85858724 return true;
85868725 break;
85878726 case ICmpInst::ICMP_SGT:
85888727 case ICmpInst::ICMP_SGE:
8589 if (IsKnownPredicateFull(ICmpInst::ICMP_SGE, LHS, FoundLHS) &&
8590 IsKnownPredicateFull(ICmpInst::ICMP_SLE, RHS, FoundRHS))
8728 if (isKnownViaSimpleReasoning(ICmpInst::ICMP_SGE, LHS, FoundLHS) &&
8729 isKnownViaSimpleReasoning(ICmpInst::ICMP_SLE, RHS, FoundRHS))
85918730 return true;
85928731 break;
85938732 case ICmpInst::ICMP_ULT:
85948733 case ICmpInst::ICMP_ULE:
8595 if (IsKnownPredicateFull(ICmpInst::ICMP_ULE, LHS, FoundLHS) &&
8596 IsKnownPredicateFull(ICmpInst::ICMP_UGE, RHS, FoundRHS))
8734 if (isKnownViaSimpleReasoning(ICmpInst::ICMP_ULE, LHS, FoundLHS) &&
8735 isKnownViaSimpleReasoning(ICmpInst::ICMP_UGE, RHS, FoundRHS))
85978736 return true;
85988737 break;
85998738 case ICmpInst::ICMP_UGT:
86008739 case ICmpInst::ICMP_UGE:
8601 if (IsKnownPredicateFull(ICmpInst::ICMP_UGE, LHS, FoundLHS) &&
8602 IsKnownPredicateFull(ICmpInst::ICMP_ULE, RHS, FoundRHS))
8740 if (isKnownViaSimpleReasoning(ICmpInst::ICMP_UGE, LHS, FoundLHS) &&
8741 isKnownViaSimpleReasoning(ICmpInst::ICMP_ULE, RHS, FoundRHS))
86038742 return true;
86048743 break;
86058744 }
8745
8746 // Maybe it can be proved via operations?
8747 if (isImpliedViaOperations(Pred, LHS, RHS, FoundLHS, FoundRHS))
8748 return true;
86068749
86078750 return false;
86088751 }
0 ; RUN: opt -indvars -S < %s | FileCheck %s
1
2 declare void @use(i1)
3
4 declare void @llvm.experimental.guard(i1, ...)
5
6 define void @test_01(i8 %t) {
7 ; CHECK-LABEL: test_01
8 entry:
9 %st = sext i8 %t to i16
10 %cmp1 = icmp slt i16 %st, 42
11 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
12 br label %loop
13
14 loop:
15 ; CHECK-LABEL: loop
16 %idx = phi i8 [ %t, %entry ], [ %idx.inc, %loop ]
17 %idx.inc = add i8 %idx, 1
18 %c = icmp slt i8 %idx, 42
19 ; CHECK: call void @use(i1 true)
20 call void @use(i1 %c)
21 %be = icmp slt i8 %idx.inc, 42
22 br i1 %be, label %loop, label %exit
23
24 exit:
25 ret void
26 }
0 ; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s
1
2 declare void @llvm.experimental.guard(i1, ...)
3
4 define void @test_1(i32 %n) nounwind {
5 ; Prove that (n > 1) ===> (n / 2 > 0).
6 ; CHECK: Determining loop execution counts for: @test_1
7 ; CHECK: Loop %header: backedge-taken count is (-1 + %n.div.2)
8 entry:
9 %cmp1 = icmp sgt i32 %n, 1
10 %n.div.2 = sdiv i32 %n, 2
11 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
12 br label %header
13
14 header:
15 %indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
16 %indvar.next = add i32 %indvar, 1
17 %exitcond = icmp sgt i32 %n.div.2, %indvar.next
18 br i1 %exitcond, label %header, label %exit
19
20 exit:
21 ret void
22 }
23
24 define void @test_1neg(i32 %n) nounwind {
25 ; Prove that (n > 0) =\=> (n / 2 > 0).
26 ; CHECK: Determining loop execution counts for: @test_1neg
27 ; CHECK: Loop %header: backedge-taken count is (-1 + (1 smax %n.div.2))
28 entry:
29 %cmp1 = icmp sgt i32 %n, 0
30 %n.div.2 = sdiv i32 %n, 2
31 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
32 br label %header
33
34 header:
35 %indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
36 %indvar.next = add i32 %indvar, 1
37 %exitcond = icmp sgt i32 %n.div.2, %indvar.next
38 br i1 %exitcond, label %header, label %exit
39
40 exit:
41 ret void
42 }
43
44 define void @test_2(i32 %n) nounwind {
45 ; Prove that (n >= 2) ===> (n / 2 > 0).
46 ; CHECK: Determining loop execution counts for: @test_2
47 ; CHECK: Loop %header: backedge-taken count is (-1 + %n.div.2)
48 entry:
49 %cmp1 = icmp sge i32 %n, 2
50 %n.div.2 = sdiv i32 %n, 2
51 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
52 br label %header
53
54 header:
55 %indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
56 %indvar.next = add i32 %indvar, 1
57 %exitcond = icmp sgt i32 %n.div.2, %indvar.next
58 br i1 %exitcond, label %header, label %exit
59
60 exit:
61 ret void
62 }
63
64 define void @test_2neg(i32 %n) nounwind {
65 ; Prove that (n >= 1) =\=> (n / 2 > 0).
66 ; CHECK: Determining loop execution counts for: @test_2neg
67 ; CHECK: Loop %header: backedge-taken count is (-1 + (1 smax %n.div.2))
68 entry:
69 %cmp1 = icmp sge i32 %n, 1
70 %n.div.2 = sdiv i32 %n, 2
71 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
72 br label %header
73
74 header:
75 %indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
76 %indvar.next = add i32 %indvar, 1
77 %exitcond = icmp sgt i32 %n.div.2, %indvar.next
78 br i1 %exitcond, label %header, label %exit
79
80 exit:
81 ret void
82 }
83
84 define void @test_3(i32 %n) nounwind {
85 ; Prove that (n > -2) ===> (n / 2 >= 0).
86 ; CHECK: Determining loop execution counts for: @test_3
87 ; CHECK: Loop %header: backedge-taken count is (1 + %n.div.2)
88 entry:
89 %cmp1 = icmp sgt i32 %n, -2
90 %n.div.2 = sdiv i32 %n, 2
91 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
92 br label %header
93
94 header:
95 %indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
96 %indvar.next = add i32 %indvar, 1
97 %exitcond = icmp sge i32 %n.div.2, %indvar
98 br i1 %exitcond, label %header, label %exit
99
100 exit:
101 ret void
102 }
103
104 define void @test_3neg(i32 %n) nounwind {
105 ; Prove that (n > -3) =\=> (n / 2 >= 0).
106 ; CHECK: Determining loop execution counts for: @test_3neg
107 ; CHECK: Loop %header: backedge-taken count is (0 smax (1 + %n.div.2))
108 entry:
109 %cmp1 = icmp sgt i32 %n, -3
110 %n.div.2 = sdiv i32 %n, 2
111 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
112 br label %header
113
114 header:
115 %indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
116 %indvar.next = add i32 %indvar, 1
117 %exitcond = icmp sge i32 %n.div.2, %indvar
118 br i1 %exitcond, label %header, label %exit
119
120 exit:
121 ret void
122 }
123
124 define void @test_4(i32 %n) nounwind {
125 ; Prove that (n >= -1) ===> (n / 2 >= 0).
126 ; CHECK: Determining loop execution counts for: @test_4
127 ; CHECK: Loop %header: backedge-taken count is (1 + %n.div.2)
128 entry:
129 %cmp1 = icmp sge i32 %n, -1
130 %n.div.2 = sdiv i32 %n, 2
131 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
132 br label %header
133
134 header:
135 %indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
136 %indvar.next = add i32 %indvar, 1
137 %exitcond = icmp sge i32 %n.div.2, %indvar
138 br i1 %exitcond, label %header, label %exit
139
140 exit:
141 ret void
142 }
143
144 define void @test_4neg(i32 %n) nounwind {
145 ; Prove that (n >= -2) =\=> (n / 2 >= 0).
146 ; CHECK: Determining loop execution counts for: @test_4neg
147 ; CHECK: Loop %header: backedge-taken count is (0 smax (1 + %n.div.2))
148 entry:
149 %cmp1 = icmp sge i32 %n, -2
150 %n.div.2 = sdiv i32 %n, 2
151 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
152 br label %header
153
154 header:
155 %indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
156 %indvar.next = add i32 %indvar, 1
157 %exitcond = icmp sge i32 %n.div.2, %indvar
158 br i1 %exitcond, label %header, label %exit
159
160 exit:
161 ret void
162 }
163
164 define void @test_ext_01(i32 %n) nounwind {
165 ; Prove that (n > 1) ===> (n / 2 > 0).
166 ; CHECK: Determining loop execution counts for: @test_ext_01
167 ; CHECK: Loop %header: backedge-taken count is (-1 + (sext i32 %n.div.2 to i64))
168 entry:
169 %cmp1 = icmp sgt i32 %n, 1
170 %n.div.2 = sdiv i32 %n, 2
171 %n.div.2.ext = sext i32 %n.div.2 to i64
172 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
173 br label %header
174
175 header:
176 %indvar = phi i64 [ %indvar.next, %header ], [ 0, %entry ]
177 %indvar.next = add i64 %indvar, 1
178 %exitcond = icmp sgt i64 %n.div.2.ext, %indvar.next
179 br i1 %exitcond, label %header, label %exit
180
181 exit:
182 ret void
183 }
184
185 define void @test_ext_01neg(i32 %n) nounwind {
186 ; Prove that (n > 0) =\=> (n / 2 > 0).
187 ; CHECK: Determining loop execution counts for: @test_ext_01neg
188 ; CHECK: Loop %header: backedge-taken count is (-1 + (1 smax (sext i32 %n.div.2 to i64)))
189 entry:
190 %cmp1 = icmp sgt i32 %n, 0
191 %n.div.2 = sdiv i32 %n, 2
192 %n.div.2.ext = sext i32 %n.div.2 to i64
193 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
194 br label %header
195
196 header:
197 %indvar = phi i64 [ %indvar.next, %header ], [ 0, %entry ]
198 %indvar.next = add i64 %indvar, 1
199 %exitcond = icmp sgt i64 %n.div.2.ext, %indvar.next
200 br i1 %exitcond, label %header, label %exit
201
202 exit:
203 ret void
204 }
205
206 define void @test_ext_02(i32 %n) nounwind {
207 ; Prove that (n >= 2) ===> (n / 2 > 0).
208 ; CHECK: Determining loop execution counts for: @test_ext_02
209 ; CHECK: Loop %header: backedge-taken count is (-1 + (sext i32 %n.div.2 to i64))
210 entry:
211 %cmp1 = icmp sge i32 %n, 2
212 %n.div.2 = sdiv i32 %n, 2
213 %n.div.2.ext = sext i32 %n.div.2 to i64
214 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
215 br label %header
216
217 header:
218 %indvar = phi i64 [ %indvar.next, %header ], [ 0, %entry ]
219 %indvar.next = add i64 %indvar, 1
220 %exitcond = icmp sgt i64 %n.div.2.ext, %indvar.next
221 br i1 %exitcond, label %header, label %exit
222
223 exit:
224 ret void
225 }
226
227 define void @test_ext_02neg(i32 %n) nounwind {
228 ; Prove that (n >= 1) =\=> (n / 2 > 0).
229 ; CHECK: Determining loop execution counts for: @test_ext_02neg
230 ; CHECK: Loop %header: backedge-taken count is (-1 + (1 smax (sext i32 %n.div.2 to i64)))
231 entry:
232 %cmp1 = icmp sge i32 %n, 1
233 %n.div.2 = sdiv i32 %n, 2
234 %n.div.2.ext = sext i32 %n.div.2 to i64
235 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
236 br label %header
237
238 header:
239 %indvar = phi i64 [ %indvar.next, %header ], [ 0, %entry ]
240 %indvar.next = add i64 %indvar, 1
241 %exitcond = icmp sgt i64 %n.div.2.ext, %indvar.next
242 br i1 %exitcond, label %header, label %exit
243
244 exit:
245 ret void
246 }
247
248 define void @test_ext_03(i32 %n) nounwind {
249 ; Prove that (n > -2) ===> (n / 2 >= 0).
250 ; CHECK: Determining loop execution counts for: @test_ext_03
251 ; CHECK: Loop %header: backedge-taken count is (1 + (sext i32 %n.div.2 to i64))
252 entry:
253 %cmp1 = icmp sgt i32 %n, -2
254 %n.div.2 = sdiv i32 %n, 2
255 %n.div.2.ext = sext i32 %n.div.2 to i64
256 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
257 br label %header
258
259 header:
260 %indvar = phi i64 [ %indvar.next, %header ], [ 0, %entry ]
261 %indvar.next = add i64 %indvar, 1
262 %exitcond = icmp sge i64 %n.div.2.ext, %indvar
263 br i1 %exitcond, label %header, label %exit
264
265 exit:
266 ret void
267 }
268
269 define void @test_ext_03neg(i32 %n) nounwind {
270 ; Prove that (n > -3) =\=> (n / 2 >= 0).
271 ; CHECK: Determining loop execution counts for: @test_ext_03neg
272 ; CHECK: Loop %header: backedge-taken count is (0 smax (1 + (sext i32 %n.div.2 to i64)))
273 entry:
274 %cmp1 = icmp sgt i32 %n, -3
275 %n.div.2 = sdiv i32 %n, 2
276 %n.div.2.ext = sext i32 %n.div.2 to i64
277 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
278 br label %header
279
280 header:
281 %indvar = phi i64 [ %indvar.next, %header ], [ 0, %entry ]
282 %indvar.next = add i64 %indvar, 1
283 %exitcond = icmp sge i64 %n.div.2.ext, %indvar
284 br i1 %exitcond, label %header, label %exit
285
286 exit:
287 ret void
288 }
289
290 define void @test_ext_04(i32 %n) nounwind {
291 ; Prove that (n >= -1) ===> (n / 2 >= 0).
292 ; CHECK: Determining loop execution counts for: @test_ext_04
293 ; CHECK: Loop %header: backedge-taken count is (1 + (sext i32 %n.div.2 to i64))
294 entry:
295 %cmp1 = icmp sge i32 %n, -1
296 %n.div.2 = sdiv i32 %n, 2
297 %n.div.2.ext = sext i32 %n.div.2 to i64
298 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
299 br label %header
300
301 header:
302 %indvar = phi i64 [ %indvar.next, %header ], [ 0, %entry ]
303 %indvar.next = add i64 %indvar, 1
304 %exitcond = icmp sge i64 %n.div.2.ext, %indvar
305 br i1 %exitcond, label %header, label %exit
306
307 exit:
308 ret void
309 }
310
311 define void @test_ext_04neg(i32 %n) nounwind {
312 ; Prove that (n >= -2) =\=> (n / 2 >= 0).
313 ; CHECK: Determining loop execution counts for: @test_ext_04neg
314 ; CHECK: Loop %header: backedge-taken count is (0 smax (1 + (sext i32 %n.div.2 to i64)))
315 entry:
316 %cmp1 = icmp sge i32 %n, -2
317 %n.div.2 = sdiv i32 %n, 2
318 %n.div.2.ext = sext i32 %n.div.2 to i64
319 call void(i1, ...) @llvm.experimental.guard(i1 %cmp1) [ "deopt"() ]
320 br label %header
321
322 header:
323 %indvar = phi i64 [ %indvar.next, %header ], [ 0, %entry ]
324 %indvar.next = add i64 %indvar, 1
325 %exitcond = icmp sge i64 %n.div.2.ext, %indvar
326 br i1 %exitcond, label %header, label %exit
327
328 exit:
329 ret void
330 }