[SCEV] Be more aggressive around proving no-wrap

... for AddRec's in loops for which SCEV is unable to compute a max
tripcount.  This is not a problem for "normal" loops[0] that don't have
guards or assumes, but helps in cases where we have guards or assumes in
the loop that can be used to constrain incoming values over the backedge.

This partially fixes PR27691 (we still don't handle the NUW case).

[0]: for "normal" loops, in the cases where we'd be able to prove
no-wrap via isKnownPredicate, we'd also be able to compute a max
tripcount.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@269211 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Sanjoy Das 2016-05-11 17:41:26 +00:00
parent 5c4ef289a9
commit 836f35c484
2 changed files with 81 additions and 4 deletions

View File

@ -1742,11 +1742,23 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
getZeroExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
}
}
}
// If the backedge is guarded by a comparison with the pre-inc value
// the addrec is safe. Also, if the entry is guarded by a comparison
// with the start value and the backedge is guarded by a comparison
// with the post-inc value, the addrec is safe.
// Normally, in the cases we can prove no-overflow via a
// backedge guarding condition, we can also compute a backedge
// taken count for the loop. The exceptions are assumptions and
// guards present in the loop -- SCEV is not great at exploiting
// these to compute max backedge taken counts, but can still use
// these to prove lack of overflow. Use this fact to avoid
// doing extra work that may not pay off.
if (!isa<SCEVCouldNotCompute>(MaxBECount) || HasGuards ||
!AC.assumptions().empty()) {
// If the backedge is guarded by a comparison with the pre-inc
// value the addrec is safe. Also, if the entry is guarded by
// a comparison with the start value and the backedge is
// guarded by a comparison with the post-inc value, the addrec
// is safe.
ICmpInst::Predicate Pred;
const SCEV *OverflowLimit =
getSignedOverflowLimitForStep(Step, &Pred, this);
@ -1762,6 +1774,7 @@ const SCEV *ScalarEvolution::getSignExtendExpr(const SCEV *Op,
getSignExtendExpr(Step, Ty), L, AR->getNoWrapFlags());
}
}
// If Start and Step are constants, check if we can apply this
// transformation:
// sext{C1,+,C2} --> C1 + sext{0,+,C2} if C1 < C2

View File

@ -0,0 +1,64 @@
; RUN: opt -analyze -scalar-evolution < %s | FileCheck %s
declare void @llvm.experimental.guard(i1, ...)
declare void @llvm.assume(i1)
define void @s_0(i32 %n, i1* %cond) {
; CHECK-LABEL: Classifying expressions for: @s_0
entry:
br label %loop
loop:
%iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
%iv.inc = add i32 %iv, 1
%iv.sext = sext i32 %iv to i64
; CHECK: %iv.sext = sext i32 %iv to i64
; CHECK-NEXT: --> {0,+,1}<nuw><nsw><%loop>
%cmp = icmp slt i32 %iv, %n
call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
%c = load volatile i1, i1* %cond
br i1 %c, label %loop, label %leave
leave:
ret void
}
define void @s_1(i1* %cond) {
; CHECK-LABEL: Classifying expressions for: @s_1
entry:
br label %loop
loop:
%iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
%iv.inc = add i32 %iv, 3
%iv.sext = sext i32 %iv to i64
; CHECK: %iv.sext = sext i32 %iv to i64
; CHECK-NEXT: --> {0,+,3}<nuw><nsw><%loop>
%cmp = icmp slt i32 %iv, 10000
call void(i1, ...) @llvm.experimental.guard(i1 %cmp) [ "deopt"() ]
%c = load volatile i1, i1* %cond
br i1 %c, label %loop, label %leave
leave:
ret void
}
define void @s_2(i1* %cond) {
; CHECK-LABEL: Classifying expressions for: @s_2
entry:
br label %loop
loop:
%iv = phi i32 [ 0, %entry ], [ %iv.inc, %loop ]
%iv.inc = add i32 %iv, 3
%iv.sext = sext i32 %iv to i64
%cmp = icmp slt i32 %iv, 10000
; CHECK: %iv.sext = sext i32 %iv to i64
; CHECK-NEXT: --> {0,+,3}<nuw><nsw><%loop>
call void @llvm.assume(i1 %cmp)
%c = load volatile i1, i1* %cond
br i1 %c, label %loop, label %leave
leave:
ret void
}