diff options
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/lib/Analysis/MustExecute.cpp | 7 | ||||
-rw-r--r-- | llvm/test/Transforms/LICM/preheader-safe.ll | 43 |
2 files changed, 45 insertions, 5 deletions
diff --git a/llvm/lib/Analysis/MustExecute.cpp b/llvm/lib/Analysis/MustExecute.cpp index ece4a1695cf..1e922fd44c4 100644 --- a/llvm/lib/Analysis/MustExecute.cpp +++ b/llvm/lib/Analysis/MustExecute.cpp @@ -109,8 +109,11 @@ bool llvm::isGuaranteedToExecute(const Instruction &Inst, // is a common case, and can save some work, check it now. if (Inst.getParent() == CurLoop->getHeader()) // If there's a throw in the header block, we can't guarantee we'll reach - // Inst. - return !SafetyInfo->HeaderMayThrow; + // Inst unless we can prove that Inst comes before the potential implicit + // exit. At the moment, we use a (cheap) hack for the common case where + // the instruction of interest is the first one in the block. + return !SafetyInfo->HeaderMayThrow || + Inst.getParent()->getFirstNonPHI() == &Inst; // Somewhere in this loop there is an instruction which may throw and make us // exit the loop. diff --git a/llvm/test/Transforms/LICM/preheader-safe.ll b/llvm/test/Transforms/LICM/preheader-safe.ll index 8f82d1c68bb..9aa8e00bcfa 100644 --- a/llvm/test/Transforms/LICM/preheader-safe.ll +++ b/llvm/test/Transforms/LICM/preheader-safe.ll @@ -3,6 +3,7 @@ declare void @use_nothrow(i64 %a) nounwind declare void @use(i64 %a) +declare void @maythrow() define void @nothrow(i64 %x, i64 %y, i1* %cond) { ; CHECK-LABEL: nothrow @@ -21,9 +22,44 @@ loop2: call void @use_nothrow(i64 %div) br label %loop } + +; The udiv is guarantee to execute if the loop is +define void @throw_header_after(i64 %x, i64 %y, i1* %cond) { +; CHECK-LABEL: throw_header_after +; CHECK: %div = udiv i64 %x, %y +; CHECK-LABEL: loop +; CHECK: call void @use(i64 %div) +entry: + br label %loop + +loop: ; preds = %entry, %for.inc + %div = udiv i64 %x, %y + call void @use(i64 %div) + br label %loop +} +define void @throw_header_after_rec(i64* %xp, i64* %yp, i1* %cond) { +; CHECK-LABEL: throw_header_after_rec +; CHECK: %x = load i64, i64* %xp +; CHECK: %y = load i64, i64* %yp +; CHECK: %div = udiv i64 %x, %y +; CHECK-LABEL: loop +; CHECK: call void @use(i64 %div) +entry: + br label %loop + +loop: ; preds = %entry, %for.inc + %x = load i64, i64* %xp + %y = load i64, i64* %yp + %div = udiv i64 %x, %y + call void @use(i64 %div) readonly + br label %loop +} + + + ; Negative test -define void @throw_header(i64 %x, i64 %y, i1* %cond) { -; CHECK-LABEL: throw_header +define void @throw_header_before(i64 %x, i64 %y, i1* %cond) { +; CHECK-LABEL: throw_header_before ; CHECK-LABEL: loop ; CHECK: %div = udiv i64 %x, %y ; CHECK: call void @use(i64 %div) @@ -31,6 +67,7 @@ entry: br label %loop loop: ; preds = %entry, %for.inc + call void @maythrow() %div = udiv i64 %x, %y call void @use(i64 %div) br label %loop @@ -43,7 +80,7 @@ define void @nothrow_header(i64 %x, i64 %y, i1 %cond) { ; CHECK-LABEL: entry ; CHECK: %div = udiv i64 %x, %y ; CHECK-LABEL: loop -; CHECK: call void @use(i64 %div) + ; CHECK: call void @use(i64 %div) entry: br label %loop loop: ; preds = %entry, %for.inc |