When forgetting SCEVs for loop PHIs, don't forget SCEVUnknown values.
authorDan Gohman <gohman@apple.com>
Tue, 12 May 2009 01:27:58 +0000 (01:27 +0000)
committerDan Gohman <gohman@apple.com>
Tue, 12 May 2009 01:27:58 +0000 (01:27 +0000)
These values aren't analyzable, so they don't care if more information
about the loop trip count can be had. Also, SCEVUnknown is used for
a PHI while the PHI itself is being analyzed, so it needs to be left
in the Scalars map. This fixes a variety of subtle issues.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@71533 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Analysis/ScalarEvolution.cpp
test/Transforms/IndVarSimplify/loop_evaluate_5.ll [new file with mode: 0644]

index 5cd9739e223f085cb1260c50919b01c4de88f006..a71db865cbf68b644416d9e961e51cf3ab5d1c08 100644 (file)
@@ -2309,10 +2309,20 @@ void ScalarEvolution::forgetLoopBackedgeTakenCount(const Loop *L) {
 void ScalarEvolution::forgetLoopPHIs(const Loop *L) {
   BasicBlock *Header = L->getHeader();
 
+  // Push all Loop-header PHIs onto the Worklist stack, except those
+  // that are presently represented via a SCEVUnknown. SCEVUnknown for
+  // a PHI either means that it has an unrecognized structure, or it's
+  // a PHI that's in the progress of being computed by createNodeForPHI.
+  // In the former case, additional loop trip count information isn't
+  // going to change anything. In the later case, createNodeForPHI will
+  // perform the necessary updates on its own when it gets to that point.
   SmallVector<Instruction *, 16> Worklist;
   for (BasicBlock::iterator I = Header->begin();
-       PHINode *PN = dyn_cast<PHINode>(I); ++I)
-    Worklist.push_back(PN);
+       PHINode *PN = dyn_cast<PHINode>(I); ++I) {
+    std::map<SCEVCallbackVH, SCEVHandle>::iterator It = Scalars.find((Value*)I);
+    if (It != Scalars.end() && !isa<SCEVUnknown>(It->second))
+      Worklist.push_back(PN);
+  }
 
   while (!Worklist.empty()) {
     Instruction *I = Worklist.pop_back_val();
diff --git a/test/Transforms/IndVarSimplify/loop_evaluate_5.ll b/test/Transforms/IndVarSimplify/loop_evaluate_5.ll
new file mode 100644 (file)
index 0000000..c6ce4a2
--- /dev/null
@@ -0,0 +1,32 @@
+; RUN: llvm-as < %s | opt -indvars | llvm-dis | grep {120, %bb2.bb3_crit_edge}
+target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64"
+target triple = "i686-pc-linux-gnu"
+
+; Indvars should be able to compute an exit value for %tmp1.
+
+define i32 @testcase(i5 zeroext %k) nounwind readnone {
+entry:
+       br i1 false, label %bb3, label %bb.nph
+
+bb.nph:                ; preds = %entry
+       br label %bb
+
+bb:            ; preds = %bb2, %bb.nph
+       %result2 = phi i32 [ %tmp1, %bb2 ], [ 0, %bb.nph ]              ; <i32> [#uses=1]
+       %k_01 = phi i5 [ %indvar_next1, %bb2 ], [ 0, %bb.nph ]          ; <i5> [#uses=2]
+       %tmp2 = zext i5 %k_01 to i32            ; <i32> [#uses=1]
+       %tmp1 = add i32 %tmp2, %result2         ; <i32> [#uses=2]
+       %indvar_next1 = add i5 %k_01, 1         ; <i5> [#uses=2]
+       br label %bb2
+
+bb2:           ; preds = %bb
+       %phitmp = icmp eq i5 %indvar_next1, -16         ; <i1> [#uses=1]
+       br i1 %phitmp, label %bb2.bb3_crit_edge, label %bb
+
+bb2.bb3_crit_edge:             ; preds = %bb2
+       br label %bb3
+
+bb3:           ; preds = %bb2.bb3_crit_edge, %entry
+       %result.lcssa = phi i32 [ %tmp1, %bb2.bb3_crit_edge ], [ 0, %entry ]            ; <i32> [#uses=1]
+       ret i32 %result.lcssa
+}