Skip to content

Commit f066d75

Browse files
dtcxzywartagnon
andauthored
[Reland][SCEV] teach isImpliedViaOperations about samesign (llvm#133711)
This patch relands llvm#124270. Closes llvm#126409. The root cause is that we incorrectly preserve the samesign flag after truncating operands of an icmp: https://alive2.llvm.org/ce/z/4NE9gS --------- Co-authored-by: Ramkumar Ramachandra <[email protected]>
1 parent ef56b53 commit f066d75

File tree

5 files changed

+201
-61
lines changed

5 files changed

+201
-61
lines changed

llvm/lib/Analysis/ScalarEvolution.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -11791,8 +11791,10 @@ bool ScalarEvolution::isImpliedCond(CmpPredicate Pred, const SCEV *LHS,
1179111791
MaxValue)) {
1179211792
const SCEV *TruncFoundLHS = getTruncateExpr(FoundLHS, NarrowType);
1179311793
const SCEV *TruncFoundRHS = getTruncateExpr(FoundRHS, NarrowType);
11794-
if (isImpliedCondBalancedTypes(Pred, LHS, RHS, FoundPred, TruncFoundLHS,
11795-
TruncFoundRHS, CtxI))
11794+
// We cannot preserve samesign after truncation.
11795+
if (isImpliedCondBalancedTypes(
11796+
Pred, LHS, RHS, static_cast<ICmpInst::Predicate>(FoundPred),
11797+
TruncFoundLHS, TruncFoundRHS, CtxI))
1179611798
return true;
1179711799
}
1179811800
}
@@ -11849,15 +11851,13 @@ bool ScalarEvolution::isImpliedCondBalancedTypes(
1184911851
}
1185011852

1185111853
// Check whether the found predicate is the same as the desired predicate.
11852-
// FIXME: use CmpPredicate::getMatching here.
11853-
if (FoundPred == static_cast<CmpInst::Predicate>(Pred))
11854-
return isImpliedCondOperands(Pred, LHS, RHS, FoundLHS, FoundRHS, CtxI);
11854+
if (auto P = CmpPredicate::getMatching(FoundPred, Pred))
11855+
return isImpliedCondOperands(*P, LHS, RHS, FoundLHS, FoundRHS, CtxI);
1185511856

1185611857
// Check whether swapping the found predicate makes it the same as the
1185711858
// desired predicate.
11858-
// FIXME: use CmpPredicate::getMatching here.
11859-
if (ICmpInst::getSwappedCmpPredicate(FoundPred) ==
11860-
static_cast<CmpInst::Predicate>(Pred)) {
11859+
if (auto P = CmpPredicate::getMatching(
11860+
ICmpInst::getSwappedCmpPredicate(FoundPred), Pred)) {
1186111861
// We can write the implication
1186211862
// 0. LHS Pred RHS <- FoundLHS SwapPred FoundRHS
1186311863
// using one of the following ways:
@@ -11868,22 +11868,23 @@ bool ScalarEvolution::isImpliedCondBalancedTypes(
1186811868
// Forms 1. and 2. require swapping the operands of one condition. Don't
1186911869
// do this if it would break canonical constant/addrec ordering.
1187011870
if (!isa<SCEVConstant>(RHS) && !isa<SCEVAddRecExpr>(LHS))
11871-
return isImpliedCondOperands(FoundPred, RHS, LHS, FoundLHS, FoundRHS,
11872-
CtxI);
11871+
return isImpliedCondOperands(ICmpInst::getSwappedCmpPredicate(*P), RHS,
11872+
LHS, FoundLHS, FoundRHS, CtxI);
1187311873
if (!isa<SCEVConstant>(FoundRHS) && !isa<SCEVAddRecExpr>(FoundLHS))
11874-
return isImpliedCondOperands(Pred, LHS, RHS, FoundRHS, FoundLHS, CtxI);
11874+
return isImpliedCondOperands(*P, LHS, RHS, FoundRHS, FoundLHS, CtxI);
1187511875

1187611876
// There's no clear preference between forms 3. and 4., try both. Avoid
1187711877
// forming getNotSCEV of pointer values as the resulting subtract is
1187811878
// not legal.
1187911879
if (!LHS->getType()->isPointerTy() && !RHS->getType()->isPointerTy() &&
11880-
isImpliedCondOperands(FoundPred, getNotSCEV(LHS), getNotSCEV(RHS),
11881-
FoundLHS, FoundRHS, CtxI))
11880+
isImpliedCondOperands(ICmpInst::getSwappedCmpPredicate(*P),
11881+
getNotSCEV(LHS), getNotSCEV(RHS), FoundLHS,
11882+
FoundRHS, CtxI))
1188211883
return true;
1188311884

1188411885
if (!FoundLHS->getType()->isPointerTy() &&
1188511886
!FoundRHS->getType()->isPointerTy() &&
11886-
isImpliedCondOperands(Pred, LHS, RHS, getNotSCEV(FoundLHS),
11887+
isImpliedCondOperands(*P, LHS, RHS, getNotSCEV(FoundLHS),
1188711888
getNotSCEV(FoundRHS), CtxI))
1188811889
return true;
1188911890

@@ -12559,14 +12560,16 @@ bool ScalarEvolution::isImpliedViaOperations(CmpPredicate Pred, const SCEV *LHS,
1255912560
return false;
1256012561

1256112562
// We only want to work with GT comparison so far.
12562-
if (Pred == ICmpInst::ICMP_ULT || Pred == ICmpInst::ICMP_SLT) {
12563+
if (ICmpInst::isLT(Pred)) {
1256312564
Pred = ICmpInst::getSwappedCmpPredicate(Pred);
1256412565
std::swap(LHS, RHS);
1256512566
std::swap(FoundLHS, FoundRHS);
1256612567
}
1256712568

12569+
CmpInst::Predicate P = Pred.getPreferredSignedPredicate();
12570+
1256812571
// For unsigned, try to reduce it to corresponding signed comparison.
12569-
if (Pred == ICmpInst::ICMP_UGT)
12572+
if (P == ICmpInst::ICMP_UGT)
1257012573
// We can replace unsigned predicate with its signed counterpart if all
1257112574
// involved values are non-negative.
1257212575
// TODO: We could have better support for unsigned.
@@ -12579,10 +12582,10 @@ bool ScalarEvolution::isImpliedViaOperations(CmpPredicate Pred, const SCEV *LHS,
1257912582
FoundRHS) &&
1258012583
isImpliedCondOperands(ICmpInst::ICMP_SGT, RHS, MinusOne, FoundLHS,
1258112584
FoundRHS))
12582-
Pred = ICmpInst::ICMP_SGT;
12585+
P = ICmpInst::ICMP_SGT;
1258312586
}
1258412587

12585-
if (Pred != ICmpInst::ICMP_SGT)
12588+
if (P != ICmpInst::ICMP_SGT)
1258612589
return false;
1258712590

1258812591
auto GetOpFromSExt = [&](const SCEV *S) {

llvm/test/Analysis/ScalarEvolution/exit-count-samesign.ll

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,9 @@
55
define i32 @exit_count_samesign(i32 %iter.count, ptr %ptr) {
66
; CHECK-LABEL: 'exit_count_samesign'
77
; CHECK-NEXT: Determining loop execution counts for: @exit_count_samesign
8-
; CHECK-NEXT: Loop %inner.loop: backedge-taken count is (-1 + (1 smax {(-1 + %iter.count)<nsw>,+,-1}<nsw><%outer.loop>))<nsw>
8+
; CHECK-NEXT: Loop %inner.loop: backedge-taken count is {(-2 + %iter.count),+,-1}<nw><%outer.loop>
99
; CHECK-NEXT: Loop %inner.loop: constant max backedge-taken count is i32 2147483646
10-
; CHECK-NEXT: Loop %inner.loop: symbolic max backedge-taken count is (-1 + (1 smax {(-1 + %iter.count)<nsw>,+,-1}<nsw><%outer.loop>))<nsw>
10+
; CHECK-NEXT: Loop %inner.loop: symbolic max backedge-taken count is {(-2 + %iter.count),+,-1}<nw><%outer.loop>
1111
; CHECK-NEXT: Loop %inner.loop: Trip multiple is 1
1212
; CHECK-NEXT: Loop %outer.loop: <multiple exits> Unpredictable backedge-taken count.
1313
; CHECK-NEXT: Loop %outer.loop: Unpredictable constant max backedge-taken count.

llvm/test/Analysis/ScalarEvolution/implied-via-division.ll

Lines changed: 131 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,10 @@
22
; RUN: opt < %s -disable-output -passes="print<scalar-evolution>" \
33
; RUN: -scalar-evolution-classify-expressions=0 2>&1 | FileCheck %s
44

5-
declare void @llvm.experimental.guard(i1, ...)
6-
7-
define void @test_1(i32 %n) nounwind {
8-
; Prove that (n > 1) ===> (n / 2 > 0).
9-
; CHECK-LABEL: 'test_1'
10-
; CHECK-NEXT: Determining loop execution counts for: @test_1
5+
define void @implied1(i32 %n) {
6+
; Prove that (n s> 1) ===> (n / 2 s> 0).
7+
; CHECK-LABEL: 'implied1'
8+
; CHECK-NEXT: Determining loop execution counts for: @implied1
119
; CHECK-NEXT: Loop %header: backedge-taken count is (-1 + %n.div.2)<nsw>
1210
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741822
1311
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (-1 + %n.div.2)<nsw>
@@ -29,10 +27,35 @@ exit:
2927
ret void
3028
}
3129

32-
define void @test_1neg(i32 %n) nounwind {
33-
; Prove that (n > 0) =\=> (n / 2 > 0).
34-
; CHECK-LABEL: 'test_1neg'
35-
; CHECK-NEXT: Determining loop execution counts for: @test_1neg
30+
define void @implied1_samesign(i32 %n) {
31+
; Prove that (n > 1) ===> (n / 2 s> 0).
32+
; CHECK-LABEL: 'implied1_samesign'
33+
; CHECK-NEXT: Determining loop execution counts for: @implied1_samesign
34+
; CHECK-NEXT: Loop %header: backedge-taken count is (-1 + %n.div.2)<nsw>
35+
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741822
36+
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (-1 + %n.div.2)<nsw>
37+
; CHECK-NEXT: Loop %header: Trip multiple is 1
38+
;
39+
entry:
40+
%cmp1 = icmp samesign ugt i32 %n, 1
41+
%n.div.2 = sdiv i32 %n, 2
42+
call void @llvm.assume(i1 %cmp1)
43+
br label %header
44+
45+
header:
46+
%indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
47+
%indvar.next = add i32 %indvar, 1
48+
%exitcond = icmp sgt i32 %n.div.2, %indvar.next
49+
br i1 %exitcond, label %header, label %exit
50+
51+
exit:
52+
ret void
53+
}
54+
55+
define void @implied1_neg(i32 %n) {
56+
; Prove that (n s> 0) =\=> (n / 2 s> 0).
57+
; CHECK-LABEL: 'implied1_neg'
58+
; CHECK-NEXT: Determining loop execution counts for: @implied1_neg
3659
; CHECK-NEXT: Loop %header: backedge-taken count is (-1 + (1 smax %n.div.2))<nsw>
3760
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741822
3861
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (-1 + (1 smax %n.div.2))<nsw>
@@ -54,10 +77,10 @@ exit:
5477
ret void
5578
}
5679

57-
define void @test_2(i32 %n) nounwind {
58-
; Prove that (n >= 2) ===> (n / 2 > 0).
59-
; CHECK-LABEL: 'test_2'
60-
; CHECK-NEXT: Determining loop execution counts for: @test_2
80+
define void @implied2(i32 %n) {
81+
; Prove that (n s>= 2) ===> (n / 2 s> 0).
82+
; CHECK-LABEL: 'implied2'
83+
; CHECK-NEXT: Determining loop execution counts for: @implied2
6184
; CHECK-NEXT: Loop %header: backedge-taken count is (-1 + %n.div.2)<nsw>
6285
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741822
6386
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (-1 + %n.div.2)<nsw>
@@ -79,10 +102,35 @@ exit:
79102
ret void
80103
}
81104

82-
define void @test_2neg(i32 %n) nounwind {
83-
; Prove that (n >= 1) =\=> (n / 2 > 0).
84-
; CHECK-LABEL: 'test_2neg'
85-
; CHECK-NEXT: Determining loop execution counts for: @test_2neg
105+
define void @implied2_samesign(i32 %n) {
106+
; Prove that (n >= 2) ===> (n / 2 s> 0).
107+
; CHECK-LABEL: 'implied2_samesign'
108+
; CHECK-NEXT: Determining loop execution counts for: @implied2_samesign
109+
; CHECK-NEXT: Loop %header: backedge-taken count is (-1 + (1 smax %n.div.2))<nsw>
110+
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741822
111+
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (-1 + (1 smax %n.div.2))<nsw>
112+
; CHECK-NEXT: Loop %header: Trip multiple is 1
113+
;
114+
entry:
115+
%cmp1 = icmp samesign uge i32 %n, 2
116+
%n.div.2 = sdiv i32 %n, 2
117+
call void @llvm.assume(i1 %cmp1)
118+
br label %header
119+
120+
header:
121+
%indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
122+
%indvar.next = add i32 %indvar, 1
123+
%exitcond = icmp sgt i32 %n.div.2, %indvar.next
124+
br i1 %exitcond, label %header, label %exit
125+
126+
exit:
127+
ret void
128+
}
129+
130+
define void @implied2_neg(i32 %n) {
131+
; Prove that (n s>= 1) =\=> (n / 2 s> 0).
132+
; CHECK-LABEL: 'implied2_neg'
133+
; CHECK-NEXT: Determining loop execution counts for: @implied2_neg
86134
; CHECK-NEXT: Loop %header: backedge-taken count is (-1 + (1 smax %n.div.2))<nsw>
87135
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741822
88136
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (-1 + (1 smax %n.div.2))<nsw>
@@ -104,10 +152,10 @@ exit:
104152
ret void
105153
}
106154

107-
define void @test_3(i32 %n) nounwind {
108-
; Prove that (n > -2) ===> (n / 2 >= 0).
109-
; CHECK-LABEL: 'test_3'
110-
; CHECK-NEXT: Determining loop execution counts for: @test_3
155+
define void @implied3(i32 %n) {
156+
; Prove that (n s> -2) ===> (n / 2 s>= 0).
157+
; CHECK-LABEL: 'implied3'
158+
; CHECK-NEXT: Determining loop execution counts for: @implied3
111159
; CHECK-NEXT: Loop %header: backedge-taken count is (1 + %n.div.2)<nsw>
112160
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741824
113161
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (1 + %n.div.2)<nsw>
@@ -129,10 +177,35 @@ exit:
129177
ret void
130178
}
131179

132-
define void @test_3neg(i32 %n) nounwind {
180+
define void @implied3_samesign(i32 %n) {
181+
; Prove that (n > -2) ===> (n / 2 s>= 0).
182+
; CHECK-LABEL: 'implied3_samesign'
183+
; CHECK-NEXT: Determining loop execution counts for: @implied3_samesign
184+
; CHECK-NEXT: Loop %header: backedge-taken count is (1 + %n.div.2)<nsw>
185+
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1
186+
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (1 + %n.div.2)<nsw>
187+
; CHECK-NEXT: Loop %header: Trip multiple is 1
188+
;
189+
entry:
190+
%cmp1 = icmp samesign ugt i32 %n, -2
191+
%n.div.2 = sdiv i32 %n, 2
192+
call void @llvm.assume(i1 %cmp1)
193+
br label %header
194+
195+
header:
196+
%indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
197+
%indvar.next = add i32 %indvar, 1
198+
%exitcond = icmp sge i32 %n.div.2, %indvar
199+
br i1 %exitcond, label %header, label %exit
200+
201+
exit:
202+
ret void
203+
}
204+
205+
define void @implied3_neg(i32 %n) {
133206
; Prove that (n > -3) =\=> (n / 2 >= 0).
134-
; CHECK-LABEL: 'test_3neg'
135-
; CHECK-NEXT: Determining loop execution counts for: @test_3neg
207+
; CHECK-LABEL: 'implied3_neg'
208+
; CHECK-NEXT: Determining loop execution counts for: @implied3_neg
136209
; CHECK-NEXT: Loop %header: backedge-taken count is (0 smax (1 + %n.div.2)<nsw>)
137210
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741824
138211
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (0 smax (1 + %n.div.2)<nsw>)
@@ -154,10 +227,10 @@ exit:
154227
ret void
155228
}
156229

157-
define void @test_4(i32 %n) nounwind {
158-
; Prove that (n >= -1) ===> (n / 2 >= 0).
159-
; CHECK-LABEL: 'test_4'
160-
; CHECK-NEXT: Determining loop execution counts for: @test_4
230+
define void @implied4(i32 %n) {
231+
; Prove that (n s>= -1) ===> (n / 2 s>= 0).
232+
; CHECK-LABEL: 'implied4'
233+
; CHECK-NEXT: Determining loop execution counts for: @implied4
161234
; CHECK-NEXT: Loop %header: backedge-taken count is (1 + %n.div.2)<nsw>
162235
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741824
163236
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (1 + %n.div.2)<nsw>
@@ -179,10 +252,35 @@ exit:
179252
ret void
180253
}
181254

182-
define void @test_4neg(i32 %n) nounwind {
183-
; Prove that (n >= -2) =\=> (n / 2 >= 0).
184-
; CHECK-LABEL: 'test_4neg'
185-
; CHECK-NEXT: Determining loop execution counts for: @test_4neg
255+
define void @implied4_samesign(i32 %n) {
256+
; Prove that (n >= -1) ===> (n / 2 s>= 0).
257+
; CHECK-LABEL: 'implied4_samesign'
258+
; CHECK-NEXT: Determining loop execution counts for: @implied4_samesign
259+
; CHECK-NEXT: Loop %header: backedge-taken count is (1 + %n.div.2)<nsw>
260+
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1
261+
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (1 + %n.div.2)<nsw>
262+
; CHECK-NEXT: Loop %header: Trip multiple is 1
263+
;
264+
entry:
265+
%cmp1 = icmp samesign uge i32 %n, -1
266+
%n.div.2 = sdiv i32 %n, 2
267+
call void @llvm.assume(i1 %cmp1)
268+
br label %header
269+
270+
header:
271+
%indvar = phi i32 [ %indvar.next, %header ], [ 0, %entry ]
272+
%indvar.next = add i32 %indvar, 1
273+
%exitcond = icmp sge i32 %n.div.2, %indvar
274+
br i1 %exitcond, label %header, label %exit
275+
276+
exit:
277+
ret void
278+
}
279+
280+
define void @implied4_neg(i32 %n) {
281+
; Prove that (n s>= -2) =\=> (n / 2 s>= 0).
282+
; CHECK-LABEL: 'implied4_neg'
283+
; CHECK-NEXT: Determining loop execution counts for: @implied4_neg
186284
; CHECK-NEXT: Loop %header: backedge-taken count is (0 smax (1 + %n.div.2)<nsw>)
187285
; CHECK-NEXT: Loop %header: constant max backedge-taken count is i32 1073741824
188286
; CHECK-NEXT: Loop %header: symbolic max backedge-taken count is (0 smax (1 + %n.div.2)<nsw>)

0 commit comments

Comments
 (0)