aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDan Gohman <gohman@apple.com>2010-08-11 00:12:36 +0000
committerDan Gohman <gohman@apple.com>2010-08-11 00:12:36 +0000
commit4ee87398e808534577ed1be52f2b48a6130b2c0e (patch)
tree3b7d7b376ae3bf2e509f3096354dd7664b74b823
parentf4452c37d03ab6cdcd2b23cb15b921c0bba591a7 (diff)
downloadexternal_llvm-4ee87398e808534577ed1be52f2b48a6130b2c0e.zip
external_llvm-4ee87398e808534577ed1be52f2b48a6130b2c0e.tar.gz
external_llvm-4ee87398e808534577ed1be52f2b48a6130b2c0e.tar.bz2
When analyzing loop exit conditions combined with and and or, don't
make any assumptions about when the two conditions will agree on when to permit the loop to exit. This fixes PR7845. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@110758 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r--lib/Analysis/ScalarEvolution.cpp26
-rw-r--r--test/Analysis/ScalarEvolution/max-trip-count.ll42
2 files changed, 52 insertions, 16 deletions
diff --git a/lib/Analysis/ScalarEvolution.cpp b/lib/Analysis/ScalarEvolution.cpp
index f5a762a..b3ddfc0 100644
--- a/lib/Analysis/ScalarEvolution.cpp
+++ b/lib/Analysis/ScalarEvolution.cpp
@@ -3854,14 +3854,13 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L,
else
MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max);
} else {
- // Both conditions must be true for the loop to exit.
+ // Both conditions must be true at the same time for the loop to exit.
+ // For now, be conservative.
assert(L->contains(FBB) && "Loop block has no successor in loop!");
- if (BTI0.Exact != getCouldNotCompute() &&
- BTI1.Exact != getCouldNotCompute())
- BECount = getUMaxFromMismatchedTypes(BTI0.Exact, BTI1.Exact);
- if (BTI0.Max != getCouldNotCompute() &&
- BTI1.Max != getCouldNotCompute())
- MaxBECount = getUMaxFromMismatchedTypes(BTI0.Max, BTI1.Max);
+ if (BTI0.Max == BTI1.Max)
+ MaxBECount = BTI0.Max;
+ if (BTI0.Exact == BTI1.Exact)
+ BECount = BTI0.Exact;
}
return BackedgeTakenInfo(BECount, MaxBECount);
@@ -3889,14 +3888,13 @@ ScalarEvolution::ComputeBackedgeTakenCountFromExitCond(const Loop *L,
else
MaxBECount = getUMinFromMismatchedTypes(BTI0.Max, BTI1.Max);
} else {
- // Both conditions must be false for the loop to exit.
+ // Both conditions must be false at the same time for the loop to exit.
+ // For now, be conservative.
assert(L->contains(TBB) && "Loop block has no successor in loop!");
- if (BTI0.Exact != getCouldNotCompute() &&
- BTI1.Exact != getCouldNotCompute())
- BECount = getUMaxFromMismatchedTypes(BTI0.Exact, BTI1.Exact);
- if (BTI0.Max != getCouldNotCompute() &&
- BTI1.Max != getCouldNotCompute())
- MaxBECount = getUMaxFromMismatchedTypes(BTI0.Max, BTI1.Max);
+ if (BTI0.Max == BTI1.Max)
+ MaxBECount = BTI0.Max;
+ if (BTI0.Exact == BTI1.Exact)
+ BECount = BTI0.Exact;
}
return BackedgeTakenInfo(BECount, MaxBECount);
diff --git a/test/Analysis/ScalarEvolution/max-trip-count.ll b/test/Analysis/ScalarEvolution/max-trip-count.ll
index a8966be..843fb07 100644
--- a/test/Analysis/ScalarEvolution/max-trip-count.ll
+++ b/test/Analysis/ScalarEvolution/max-trip-count.ll
@@ -1,8 +1,9 @@
-; RUN: opt < %s -analyze -scalar-evolution \
-; RUN: | grep {\{%d,+,\[^\{\}\]\*\}<%bb>}
+; RUN: opt < %s -analyze -scalar-evolution | FileCheck %s
; ScalarEvolution should be able to understand the loop and eliminate the casts.
+; CHECK: {%d,+,sizeof(i32)}
+
define void @foo(i32* nocapture %d, i32 %n) nounwind {
entry:
%0 = icmp sgt i32 %n, 0 ; <i1> [#uses=1]
@@ -32,3 +33,40 @@ bb1.return_crit_edge: ; preds = %bb1
return: ; preds = %bb1.return_crit_edge, %entry
ret void
}
+
+; ScalarEvolution should be able to find the maximum tripcount
+; of this multiple-exit loop, and if it doesn't know the exact
+; count, it should say so.
+
+; PR7845
+; CHECK: Loop %for.cond: <multiple exits> Unpredictable backedge-taken count.
+; CHECK: Loop %for.cond: max backedge-taken count is 5
+
+@.str = private constant [4 x i8] c"%d\0A\00" ; <[4 x i8]*> [#uses=2]
+
+define i32 @main() nounwind {
+entry:
+ br label %for.cond
+
+for.cond: ; preds = %for.inc, %entry
+ %g_4.0 = phi i32 [ 0, %entry ], [ %add, %for.inc ] ; <i32> [#uses=5]
+ %cmp = icmp slt i32 %g_4.0, 5 ; <i1> [#uses=1]
+ br i1 %cmp, label %for.body, label %for.end
+
+for.body: ; preds = %for.cond
+ %conv = trunc i32 %g_4.0 to i16 ; <i16> [#uses=1]
+ %tobool.not = icmp eq i16 %conv, 0 ; <i1> [#uses=1]
+ %tobool3 = icmp ne i32 %g_4.0, 0 ; <i1> [#uses=1]
+ %or.cond = and i1 %tobool.not, %tobool3 ; <i1> [#uses=1]
+ br i1 %or.cond, label %for.end, label %for.inc
+
+for.inc: ; preds = %for.body
+ %add = add nsw i32 %g_4.0, 1 ; <i32> [#uses=1]
+ br label %for.cond
+
+for.end: ; preds = %for.body, %for.cond
+ %call = call i32 (i8*, ...)* @printf(i8* getelementptr inbounds ([4 x i8]* @.str, i64 0, i64 0), i32 %g_4.0) nounwind ; <i32> [#uses=0]
+ ret i32 0
+}
+
+declare i32 @printf(i8*, ...)