[llvm] r330576 - [LoopSimplify] Fix incorrect SCEV invalidation

Max Kazantsev via llvm-commits llvm-commits at lists.llvm.org
Mon Apr 23 03:32:37 PDT 2018


Author: mkazantsev
Date: Mon Apr 23 03:32:37 2018
New Revision: 330576

URL: http://llvm.org/viewvc/llvm-project?rev=330576&view=rev
Log:
[LoopSimplify] Fix incorrect SCEV invalidation

In the function `simplifyOneLoop` we optimistically assume that changes in the
inner loop only affect this very loop and have no impact on its parents. In fact,
after rL329047 has been merged, we can now calculate exit counts for outer
loops which may depend on inner loops. Thus, we need to invalidate all parents
when we do something to a loop.

There is an evidence of incorrect behavior of `simplifyOneLoop`: when we insert
`SE->verify()` check in the end of this funciton, it fails on a bunch of existing
test, in particular:

    LLVM :: Transforms/LoopUnroll/peel-loop-not-forced.ll
    LLVM :: Transforms/LoopUnroll/peel-loop-pgo.ll
    LLVM :: Transforms/LoopUnroll/peel-loop.ll
    LLVM :: Transforms/LoopUnroll/peel-loop2.ll

Note that previously we have fixed issues of this variety, see rL328483.
This patch makes this function invalidate the outermost loop properly.

Differential Revision: https://reviews.llvm.org/D45937
Reviewed By: chandlerc

Modified:
    llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
    llvm/trunk/lib/Analysis/ScalarEvolution.cpp
    llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp
    llvm/trunk/test/Transforms/LoopSimplify/preserve-scev.ll

Modified: llvm/trunk/include/llvm/Analysis/ScalarEvolution.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Analysis/ScalarEvolution.h?rev=330576&r1=330575&r2=330576&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Analysis/ScalarEvolution.h (original)
+++ llvm/trunk/include/llvm/Analysis/ScalarEvolution.h Mon Apr 23 03:32:37 2018
@@ -764,6 +764,12 @@ public:
   /// loop bodies.
   void forgetLoop(const Loop *L);
 
+  // This method invokes forgetLoop for the outermost loop of the given loop
+  // \p L, making ScalarEvolution forget about all this subtree. This needs to
+  // be done whenever we make a transform that may affect the parameters of the
+  // outer loop, such as exit counts for branches.
+  void forgetTopmostLoop(const Loop *L);
+
   /// This method should be called by the client when it has changed a value
   /// in a way that may effect its value, or which may disconnect it from a
   /// def-use chain linking it to a loop.

Modified: llvm/trunk/lib/Analysis/ScalarEvolution.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ScalarEvolution.cpp?rev=330576&r1=330575&r2=330576&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ScalarEvolution.cpp (original)
+++ llvm/trunk/lib/Analysis/ScalarEvolution.cpp Mon Apr 23 03:32:37 2018
@@ -6620,6 +6620,12 @@ void ScalarEvolution::forgetLoop(const L
   }
 }
 
+void ScalarEvolution::forgetTopmostLoop(const Loop *L) {
+  while (Loop *Parent = L->getParentLoop())
+    L = Parent;
+  forgetLoop(L);
+}
+
 void ScalarEvolution::forgetValue(Value *V) {
   Instruction *I = dyn_cast<Instruction>(V);
   if (!I) return;

Modified: llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp?rev=330576&r1=330575&r2=330576&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp (original)
+++ llvm/trunk/lib/Transforms/Utils/LoopSimplify.cpp Mon Apr 23 03:32:37 2018
@@ -510,10 +510,6 @@ ReprocessLoop:
           BI->setCondition(ConstantInt::get(Cond->getType(),
                                             !L->contains(BI->getSuccessor(0))));
 
-          // This may make the loop analyzable, force SCEV recomputation.
-          if (SE)
-            SE->forgetLoop(L);
-
           Changed = true;
         }
       }
@@ -651,13 +647,6 @@ ReprocessLoop:
       DEBUG(dbgs() << "LoopSimplify: Eliminating exiting block "
                    << ExitingBlock->getName() << "\n");
 
-      // Notify ScalarEvolution before deleting this block. Currently assume the
-      // parent loop doesn't change (spliting edges doesn't count). If blocks,
-      // CFG edges, or other values in the parent loop change, then we need call
-      // to forgetLoop() for the parent instead.
-      if (SE)
-        SE->forgetLoop(L);
-
       assert(pred_begin(ExitingBlock) == pred_end(ExitingBlock));
       Changed = true;
       LI->removeBlock(ExitingBlock);
@@ -679,6 +668,18 @@ ReprocessLoop:
     }
   }
 
+  // Changing exit conditions for blocks may affect exit counts of this loop and
+  // any of its paretns, so we must invalidate the entire subtree if we've made
+  // any changes.
+  if (Changed && SE)
+    SE->forgetTopmostLoop(L);
+
+#ifndef NDEBUG
+  // Make sure that after all our transforms SE is correct.
+  if (SE)
+    SE->verify();
+#endif
+
   return Changed;
 }
 

Modified: llvm/trunk/test/Transforms/LoopSimplify/preserve-scev.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LoopSimplify/preserve-scev.ll?rev=330576&r1=330575&r2=330576&view=diff
==============================================================================
--- llvm/trunk/test/Transforms/LoopSimplify/preserve-scev.ll (original)
+++ llvm/trunk/test/Transforms/LoopSimplify/preserve-scev.ll Mon Apr 23 03:32:37 2018
@@ -95,7 +95,7 @@ declare void @foo() nounwind
 ; CHECK: Loop %while.cond191: max backedge-taken count is 0
 ; CHECK: Loop %while.cond191: Predicated backedge-taken count is 0
 ; CHECK: Loop %while.cond191.outer: <multiple exits> Unpredictable backedge-taken count.
-; CHECK: Loop %while.cond191.outer: Unpredictable max backedge-taken count.
+; CHECK: Loop %while.cond191.outer: max backedge-taken count is false
 ; CHECK: Loop %while.cond191.outer: Unpredictable predicated backedge-taken count.
 define void @mergeExit(i32 %MapAttrCount) nounwind uwtable ssp {
 entry:




More information about the llvm-commits mailing list