[llvm] r262108 - [LICM] Teach LICM how to handle cases where the alias set tracker was

Chandler Carruth via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 26 20:34:07 PST 2016


Author: chandlerc
Date: Fri Feb 26 22:34:07 2016
New Revision: 262108

URL: http://llvm.org/viewvc/llvm-project?rev=262108&view=rev
Log:
[LICM] Teach LICM how to handle cases where the alias set tracker was
merged into a loop that was subsequently unrolled (or otherwise nuked).

In this case it can't merge in the ASTs for any remaining nested loops,
it needs to re-add their instructions dircetly.

The fix is very isolated, but I've pulled the code for merging blocks
into the AST into a single place in the process. The only behavior
change is in the case which would have crashed before.

This fixes a crash reported by Mikael Holmen on the list after r261316
restored much of the loop pass pipelining and allowed us to actually do
this kind of nested transformation sequenc. I've taken that test case
and further reduced it into the somewhat twisty maze of loops in the
included test case. This does in fact trigger the bug even in this
reduced form.

Added:
    llvm/trunk/test/Transforms/LICM/alias-set-tracker-loss.ll
Modified:
    llvm/trunk/lib/Transforms/Scalar/LICM.cpp

Modified: llvm/trunk/lib/Transforms/Scalar/LICM.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/LICM.cpp?rev=262108&r1=262107&r2=262108&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/LICM.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/LICM.cpp Fri Feb 26 22:34:07 2016
@@ -154,10 +154,7 @@ namespace {
     /// Simple Analysis hook. Delete loop L from alias set map.
     void deleteAnalysisLoop(Loop *L) override;
 
-    /// Returns an owning pointer to an alias set which incorporates aliasing
-    /// info from all subloops of L, but does not include instructions in L
-    /// itself.
-    AliasSetTracker *collectAliasInfoFromSubLoops(Loop *L);
+    AliasSetTracker *collectAliasInfoForLoop(Loop *L);
   };
 }
 
@@ -188,22 +185,13 @@ bool LICM::runOnLoop(Loop *L, LPPassMana
 
   assert(L->isLCSSAForm(*DT) && "Loop is not in LCSSA form.");
 
-  CurAST = collectAliasInfoFromSubLoops(L);
+  CurAST = collectAliasInfoForLoop(L);
 
   CurLoop = L;
 
   // Get the preheader block to move instructions into...
   Preheader = L->getLoopPreheader();
 
-  // Loop over the body of this loop, looking for calls, invokes, and stores.
-  // Because subloops have already been incorporated into AST, we skip blocks in
-  // subloops.
-  //
-  for (BasicBlock *BB : L->blocks()) {
-    if (LI->getLoopFor(BB) == L)        // Ignore blocks in subloops.
-      CurAST->add(*BB);                 // Incorporate the specified basic block
-  }
-
   // Compute loop safety information.
   LICMSafetyInfo SafetyInfo;
   computeLICMSafetyInfo(&SafetyInfo, CurLoop);
@@ -1039,13 +1027,20 @@ bool llvm::promoteLoopAccessesToScalars(
 }
 
 /// Returns an owning pointer to an alias set which incorporates aliasing info
-/// from all subloops of L, but does not include instructions in L itself.
-///
-AliasSetTracker *LICM::collectAliasInfoFromSubLoops(Loop *L) {
+/// from L and all subloops of L.
+AliasSetTracker *LICM::collectAliasInfoForLoop(Loop *L) {
   AliasSetTracker *CurAST = nullptr;
+  SmallVector<Loop *, 4> RecomputeLoops;
   for (Loop *InnerL : L->getSubLoops()) {
-    AliasSetTracker *InnerAST = LoopToAliasSetMap[InnerL];
-    assert(InnerAST && "Where is my AST?");
+    auto MapI = LoopToAliasSetMap.find(InnerL);
+    // If the AST for this inner loop is missing it may have been merged into
+    // some other loop's AST and then that loop unrolled, and so we need to
+    // recompute it.
+    if (MapI == LoopToAliasSetMap.end()) {
+      RecomputeLoops.push_back(InnerL);
+      continue;
+    }
+    AliasSetTracker *InnerAST = MapI->second;
 
     if (CurAST != nullptr) {
       // What if InnerLoop was modified by other passes ?
@@ -1057,10 +1052,27 @@ AliasSetTracker *LICM::collectAliasInfoF
     } else {
       CurAST = InnerAST;
     }
-    LoopToAliasSetMap.erase(InnerL);
+    LoopToAliasSetMap.erase(MapI);
   }
   if (CurAST == nullptr)
     CurAST = new AliasSetTracker(*AA);
+
+  auto mergeLoop = [&](Loop *L) {
+    // Loop over the body of this loop, looking for calls, invokes, and stores.
+    // Because subloops have already been incorporated into AST, we skip blocks
+    // in subloops.
+    for (BasicBlock *BB : L->blocks())
+      if (LI->getLoopFor(BB) == L) // Ignore blocks in subloops.
+        CurAST->add(*BB);          // Incorporate the specified basic block
+  };
+
+  // Add everything from the sub loops that are no longer directly available.
+  for (Loop *InnerL : RecomputeLoops)
+    mergeLoop(InnerL);
+
+  // And merge in this loop.
+  mergeLoop(L);
+
   return CurAST;
 }
 

Added: llvm/trunk/test/Transforms/LICM/alias-set-tracker-loss.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/LICM/alias-set-tracker-loss.ll?rev=262108&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/LICM/alias-set-tracker-loss.ll (added)
+++ llvm/trunk/test/Transforms/LICM/alias-set-tracker-loss.ll Fri Feb 26 22:34:07 2016
@@ -0,0 +1,39 @@
+; RUN: opt -S -licm -loop-unroll < %s
+;
+; This test contains a carefully rotated set of three nested loops. The middle
+; loop can be unrolled leaving one copy of the inner loop inside the outer
+; loop. Because of how LICM works, when this middle loop is unrolled and
+; removed, its alias set tracker is destroyed and no longer available when LICM
+; runs on the outer loop.
+
+define void @f() {
+entry:
+  br label %l1
+
+l2.l1.loopexit_crit_edge:
+  br label %l1.loopexit
+
+l1.loopexit:
+  br label %l1.backedge
+
+l1:
+  br i1 undef, label %l1.backedge, label %l2.preheader
+
+l1.backedge:
+  br label %l1
+
+l2.preheader:
+  br i1 true, label %l1.loopexit, label %l3.preheader.lr.ph
+
+l3.preheader.lr.ph:
+  br label %l3.preheader
+
+l2.loopexit:
+  br i1 true, label %l2.l1.loopexit_crit_edge, label %l3.preheader
+
+l3.preheader:
+  br label %l3
+
+l3:
+  br i1 true, label %l3, label %l2.loopexit
+}




More information about the llvm-commits mailing list