[SCEV] Improve Scalar Evolution's use of no {un,}signed wrap flags

In a case where we have a no {un,}signed wrap flag on the increment, if
RHS - Start is constant then we can avoid inserting a max operation bewteen
the two, since we can statically determine which is greater.

This allows us to unroll loops such as:

 void testcase3(int v) {
   for (int i=v; i<=v+1; ++i)
     f(i);
 }


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@220960 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bradley Smith 2014-10-31 11:40:32 +00:00
parent 8a9c531e9a
commit 8cff277de2
3 changed files with 79 additions and 8 deletions

View File

@ -6964,9 +6964,19 @@ ScalarEvolution::HowManyLessThans(const SCEV *LHS, const SCEV *RHS,
: ICmpInst::ICMP_ULT;
const SCEV *Start = IV->getStart();
const SCEV *End = RHS;
if (!isLoopEntryGuardedByCond(L, Cond, getMinusSCEV(Start, Stride), RHS))
End = IsSigned ? getSMaxExpr(RHS, Start)
: getUMaxExpr(RHS, Start);
if (!isLoopEntryGuardedByCond(L, Cond, getMinusSCEV(Start, Stride), RHS)) {
const SCEV *Diff = getMinusSCEV(RHS, Start);
// If we have NoWrap set, then we can assume that the increment won't
// overflow, in which case if RHS - Start is a constant, we don't need to
// do a max operation since we can just figure it out statically
if (NoWrap && isa<SCEVConstant>(Diff)) {
APInt D = dyn_cast<const SCEVConstant>(Diff)->getValue()->getValue();
if (D.isNegative())
End = Start;
} else
End = IsSigned ? getSMaxExpr(RHS, Start)
: getUMaxExpr(RHS, Start);
}
const SCEV *BECount = computeBECount(getMinusSCEV(End, Start), Stride, false);
@ -7035,9 +7045,19 @@ ScalarEvolution::HowManyGreaterThans(const SCEV *LHS, const SCEV *RHS,
const SCEV *Start = IV->getStart();
const SCEV *End = RHS;
if (!isLoopEntryGuardedByCond(L, Cond, getAddExpr(Start, Stride), RHS))
End = IsSigned ? getSMinExpr(RHS, Start)
: getUMinExpr(RHS, Start);
if (!isLoopEntryGuardedByCond(L, Cond, getAddExpr(Start, Stride), RHS)) {
const SCEV *Diff = getMinusSCEV(RHS, Start);
// If we have NoWrap set, then we can assume that the increment won't
// overflow, in which case if RHS - Start is a constant, we don't need to
// do a max operation since we can just figure it out statically
if (NoWrap && isa<SCEVConstant>(Diff)) {
APInt D = dyn_cast<const SCEVConstant>(Diff)->getValue()->getValue();
if (!D.isNegative())
End = Start;
} else
End = IsSigned ? getSMinExpr(RHS, Start)
: getUMinExpr(RHS, Start);
}
const SCEV *BECount = computeBECount(getMinusSCEV(Start, End), Stride, false);

View File

@ -123,9 +123,8 @@ exit:
ret i32 %result
}
; TODO: This could fold down to '1'
; CHECK-LABEL: PR12375
; CHECK: --> {(4 + %arg),+,4}<nuw><%bb1> Exits: (4 + (4 * ((-1 + (-1 * %arg) + ((4 + %arg) umax (8 + %arg)<nsw>)) /u 4)) + %arg)
; CHECK: --> {(4 + %arg),+,4}<nuw><%bb1> Exits: (8 + %arg)<nsw>
define i32 @PR12375(i32* readnone %arg) {
bb:
%tmp = getelementptr inbounds i32* %arg, i64 2
@ -158,3 +157,23 @@ bb2: ; preds = %bb2, %bb
bb5: ; preds = %bb2
ret void
}
declare void @f(i32)
; CHECK-LABEL: nswnowrap
; CHECK: --> {(1 + %v),+,1}<nsw><%for.body> Exits: (2 + %v)
define void @nswnowrap(i32 %v) {
entry:
%add = add nsw i32 %v, 1
br label %for.body
for.body:
%i.04 = phi i32 [ %v, %entry ], [ %inc, %for.body ]
%inc = add nsw i32 %i.04, 1
tail call void @f(i32 %i.04)
%cmp = icmp slt i32 %i.04, %add
br i1 %cmp, label %for.body, label %for.end
for.end:
ret void
}

View File

@ -0,0 +1,32 @@
; RUN: opt -loop-unroll -S %s | FileCheck %s
; extern void f(int);
; void test1(int v) {
; for (int i=v; i<=v+1; ++i)
; f(i);
; }
;
; We can use the nsw information to see that the tripcount will be 2, so the
; loop should be unrolled as this is always beneficial
declare void @f(i32)
; CHECK-LABEL: @test1
define void @test1(i32 %v) {
entry:
%add = add nsw i32 %v, 1
br label %for.body
for.body:
%i.04 = phi i32 [ %v, %entry ], [ %inc, %for.body ]
tail call void @f(i32 %i.04)
%inc = add nsw i32 %i.04, 1
%cmp = icmp slt i32 %i.04, %add
br i1 %cmp, label %for.body, label %for.end
; CHECK: call void @f
; CHECK-NOT: br i1
; CHECK: call void @f
for.end:
ret void
}