diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp index be3902c99f4..d731a2c1a34 100644 --- a/lib/Analysis/ScalarEvolution.cpp +++ b/lib/Analysis/ScalarEvolution.cpp @@ -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(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 diff --git a/test/Analysis/ScalarEvolution/no-wrap-unknown-becount.ll b/test/Analysis/ScalarEvolution/no-wrap-unknown-becount.ll new file mode 100644 index 00000000000..cad3cb524e9 --- /dev/null +++ b/test/Analysis/ScalarEvolution/no-wrap-unknown-becount.ll @@ -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}<%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}<%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}<%loop> + call void @llvm.assume(i1 %cmp) + %c = load volatile i1, i1* %cond + br i1 %c, label %loop, label %leave + +leave: + ret void +}