forked from OSchip/llvm-project
[SCEV] Reapply 'Teach isLoopBackedgeGuardedByCond to exploit trip counts'
Summary: If the trip count of a specific backedge is `N`, then we know that backedge is effectively guarded by the condition `{0,+,1} u< N`. This change teaches SCEV to use this condition to prove things in `isLoopBackedgeGuardedByCond`. Depends on D12948 Depends on D12949 The original checkin, r248608 had to be backed out due to an issue with a ObjCXX unit test. That issue is now fixed, so re-landing. Reviewers: atrick, reames, majnemer, hfinkel Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D12950 llvm-svn: 248638
This commit is contained in:
parent
96709c4854
commit
b174f9a316
|
@ -6994,6 +6994,22 @@ ScalarEvolution::isLoopBackedgeGuardedByCond(const Loop *L,
|
|||
|
||||
SaveAndRestore<bool> ClearOnExit(WalkingBEDominatingConds, true);
|
||||
|
||||
// See if we can exploit a trip count to prove the predicate.
|
||||
const auto &BETakenInfo = getBackedgeTakenInfo(L);
|
||||
const SCEV *LatchBECount = BETakenInfo.getExact(Latch, this);
|
||||
if (LatchBECount != getCouldNotCompute()) {
|
||||
// We know that Latch branches back to the loop header exactly
|
||||
// LatchBECount times. This means the backdege condition at Latch is
|
||||
// equivalent to "{0,+,1} u< LatchBECount".
|
||||
Type *Ty = LatchBECount->getType();
|
||||
auto NoWrapFlags = SCEV::NoWrapFlags(SCEV::FlagNUW | SCEV::FlagNW);
|
||||
const SCEV *LoopCounter =
|
||||
getAddRecExpr(getZero(Ty), getOne(Ty), L, NoWrapFlags);
|
||||
if (isImpliedCond(Pred, LHS, RHS, ICmpInst::ICMP_ULT, LoopCounter,
|
||||
LatchBECount))
|
||||
return true;
|
||||
}
|
||||
|
||||
// Check conditions due to any @llvm.assume intrinsics.
|
||||
for (auto &AssumeVH : AC.assumptions()) {
|
||||
if (!AssumeVH)
|
||||
|
|
|
@ -10,7 +10,7 @@ bb.i: ; preds = %bb1.i, %bb.nph
|
|||
|
||||
; This cast shouldn't be folded into the addrec.
|
||||
; CHECK: %tmp = zext i8 %l_95.0.i1 to i16
|
||||
; CHECK: --> (zext i8 {0,+,-1}<%bb.i> to i16){{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: 2
|
||||
; CHECK: --> (zext i8 {0,+,-1}<nw><%bb.i> to i16){{ U: [^ ]+ S: [^ ]+}}{{ *}}Exits: 2
|
||||
|
||||
%tmp = zext i8 %l_95.0.i1 to i16
|
||||
|
||||
|
|
|
@ -356,5 +356,42 @@ define void @func_17(i32* %len.ptr) {
|
|||
ret void
|
||||
}
|
||||
|
||||
!0 = !{i32 0, i32 2147483647}
|
||||
define i1 @func_18(i16* %tmp20, i32* %len.addr) {
|
||||
; CHECK-LABEL: @func_18(
|
||||
entry:
|
||||
%len = load i32, i32* %len.addr, !range !0
|
||||
%tmp18 = icmp eq i32 %len, 0
|
||||
br i1 %tmp18, label %bb2, label %bb0.preheader
|
||||
|
||||
bb0.preheader:
|
||||
br label %bb0
|
||||
|
||||
bb0:
|
||||
; CHECK: bb0:
|
||||
%var_0.in = phi i32 [ %var_0, %bb1 ], [ %len, %bb0.preheader ]
|
||||
%var_1 = phi i32 [ %tmp30, %bb1 ], [ 0, %bb0.preheader ]
|
||||
%var_0 = add nsw i32 %var_0.in, -1
|
||||
%tmp23 = icmp ult i32 %var_1, %len
|
||||
; CHECK: br i1 true, label %stay, label %bb2.loopexit
|
||||
br i1 %tmp23, label %stay, label %bb2
|
||||
|
||||
stay:
|
||||
; CHECK: stay:
|
||||
%tmp25 = getelementptr inbounds i16, i16* %tmp20, i32 %var_1
|
||||
%tmp26 = load i16, i16* %tmp25
|
||||
%tmp29 = icmp eq i16 %tmp26, 0
|
||||
br i1 %tmp29, label %bb1, label %bb2
|
||||
|
||||
bb1:
|
||||
%tmp30 = add i32 %var_1, 1
|
||||
%tmp31 = icmp eq i32 %var_0, 0
|
||||
br i1 %tmp31, label %bb3, label %bb0
|
||||
|
||||
bb2:
|
||||
ret i1 false
|
||||
|
||||
bb3:
|
||||
ret i1 true
|
||||
}
|
||||
|
||||
!0 = !{i32 0, i32 2147483647}
|
||||
|
|
Loading…
Reference in New Issue