LoopUnrollRuntime: Check for overflow in the trip count calculation.

Fixes PR19823.

llvm-svn: 211436
This commit is contained in:
Benjamin Kramer 2014-06-21 13:46:25 +00:00
parent b7f5fb5751
commit 0bf086f80f
2 changed files with 17 additions and 10 deletions

View File

@ -280,17 +280,17 @@ bool llvm::UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI,
SCEVExpander Expander(*SE, "loop-unroll");
Value *TripCount = Expander.expandCodeFor(TripCountSC, TripCountSC->getType(),
PreHeaderBR);
Type *CountTy = TripCount->getType();
BinaryOperator *ModVal =
BinaryOperator::CreateURem(TripCount,
ConstantInt::get(CountTy, Count),
"xtraiter");
ModVal->insertBefore(PreHeaderBR);
// Check if for no extra iterations, then jump to unrolled loop
Value *BranchVal = new ICmpInst(PreHeaderBR,
ICmpInst::ICMP_NE, ModVal,
ConstantInt::get(CountTy, 0), "lcmp");
IRBuilder<> B(PreHeaderBR);
Value *ModVal = B.CreateAnd(TripCount, Count - 1, "xtraiter");
// Check if for no extra iterations, then jump to unrolled loop. We have to
// check that the trip count computation didn't overflow when adding one to
// the backedge taken count.
Value *LCmp = B.CreateIsNotNull(ModVal, "lcmp.mod");
Value *OverflowCheck = B.CreateIsNull(TripCount, "lcmp.overflow");
Value *BranchVal = B.CreateOr(OverflowCheck, LCmp, "lcmp.or");
// Branch to either the extra iterations or the unrolled loop
// We will fix up the true branch label when adding loop body copies
BranchInst::Create(PEnd, PEnd, BranchVal, PreHeaderBR);
@ -344,6 +344,7 @@ bool llvm::UnrollRuntimeLoopProlog(Loop *L, unsigned Count, LoopInfo *LI,
}
// The comparison w/ the extra iteration value and branch
Type *CountTy = TripCount->getType();
Value *BranchVal = new ICmpInst(*NewBB, ICmpInst::ICMP_EQ, ModVal,
ConstantInt::get(CountTy, leftOverIters),
"un.tmp");

View File

@ -2,6 +2,12 @@
; Tests for unrolling loops with run-time trip counts
; CHECK: %xtraiter = and i32 %n
; CHECK: %lcmp.mod = icmp ne i32 %xtraiter, 0
; CHECK: %lcmp.overflow = icmp eq i32 %n, 0
; CHECK: %lcmp.or = or i1 %lcmp.overflow, %lcmp.mod
; CHECK: br i1 %lcmp.or, label %unr.cmp
; CHECK: unr.cmp{{.*}}:
; CHECK: for.body.unr{{.*}}:
; CHECK: for.body: