diff options
| -rw-r--r-- | llvm/include/llvm/Analysis/LoopPass.h | 9 | ||||
| -rw-r--r-- | llvm/lib/Analysis/LoopPass.cpp | 11 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/LICM.cpp | 13 | ||||
| -rw-r--r-- | llvm/test/Transforms/LICM/2014-09-10-doFinalizationAssert.ll | 30 | 
4 files changed, 63 insertions, 0 deletions
diff --git a/llvm/include/llvm/Analysis/LoopPass.h b/llvm/include/llvm/Analysis/LoopPass.h index 726e28636ac..8650000fcfb 100644 --- a/llvm/include/llvm/Analysis/LoopPass.h +++ b/llvm/include/llvm/Analysis/LoopPass.h @@ -82,6 +82,11 @@ public:    /// deleteAnalysisValue - Delete analysis info associated with value V.    virtual void deleteAnalysisValue(Value *V, Loop *L) {} +  /// Delete analysis info associated with Loop L. +  /// Called to notify a Pass that a loop has been deleted and any +  /// associated analysis values can be deleted. +  virtual void deleteAnalysisLoop(Loop *L) {} +  protected:    /// skipOptnoneFunction - Containing function has Attribute::OptimizeNone    /// and most transformation passes should skip it. @@ -152,6 +157,10 @@ public:    /// that implement simple analysis interface.    void deleteSimpleAnalysisValue(Value *V, Loop *L); +  /// Invoke deleteAnalysisLoop hook for all passes that implement simple +  /// analysis interface. +  void deleteSimpleAnalysisLoop(Loop *L); +  private:    std::deque<Loop *> LQ;    bool skipThisLoop; diff --git a/llvm/lib/Analysis/LoopPass.cpp b/llvm/lib/Analysis/LoopPass.cpp index 7bd866e73e1..190abc73fbb 100644 --- a/llvm/lib/Analysis/LoopPass.cpp +++ b/llvm/lib/Analysis/LoopPass.cpp @@ -76,6 +76,9 @@ void LPPassManager::deleteLoopFromQueue(Loop *L) {    LI->updateUnloop(L); +  // Notify passes that the loop is being deleted. +  deleteSimpleAnalysisLoop(L); +    // If L is current loop then skip rest of the passes and let    // runOnFunction remove L from LQ. Otherwise, remove L from LQ now    // and continue applying other passes on CurrentLoop. @@ -164,6 +167,14 @@ void LPPassManager::deleteSimpleAnalysisValue(Value *V, Loop *L) {    }  } +/// Invoke deleteAnalysisLoop hook for all passes. +void LPPassManager::deleteSimpleAnalysisLoop(Loop *L) { +  for (unsigned Index = 0; Index < getNumContainedPasses(); ++Index) { +    LoopPass *LP = getContainedPass(Index); +    LP->deleteAnalysisLoop(L); +  } +} +  // Recurse through all subloops and all loops  into LQ.  static void addLoopIntoQueue(Loop *L, std::deque<Loop *> &LQ) { diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index d387b56689a..4952a644ff2 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -130,6 +130,9 @@ namespace {      /// set.      void deleteAnalysisValue(Value *V, Loop *L) override; +    /// Simple Analysis hook. Delete loop L from alias set map. +    void deleteAnalysisLoop(Loop *L) override; +      /// SinkRegion - Walk the specified region of the CFG (defined by all blocks      /// dominated by the specified block, and that are in the current loop) in      /// reverse depth first order w.r.t the DominatorTree.  This allows us to @@ -943,3 +946,13 @@ void LICM::deleteAnalysisValue(Value *V, Loop *L) {    AST->deleteValue(V);  } + +/// Simple Analysis hook. Delete value L from alias set map. +void LICM::deleteAnalysisLoop(Loop *L) { +  AliasSetTracker *AST = LoopToAliasSetMap.lookup(L); +  if (!AST) +    return; + +  delete AST; +  LoopToAliasSetMap.erase(L); +} diff --git a/llvm/test/Transforms/LICM/2014-09-10-doFinalizationAssert.ll b/llvm/test/Transforms/LICM/2014-09-10-doFinalizationAssert.ll new file mode 100644 index 00000000000..17ae716dd47 --- /dev/null +++ b/llvm/test/Transforms/LICM/2014-09-10-doFinalizationAssert.ll @@ -0,0 +1,30 @@ +; RUN: opt < %s -scalar-evolution -licm -loop-unroll -disable-output +; Test triggered an assertion in doFinalization() because loop unroll was deleting +; the inner loop which caused the loop to not get removed from the +; LoopToAliasSetMap. +; Test case taken from test/Transforms/LoopUnroll/unloop.ll. + +declare i1 @check() nounwind +define void @skiplevelexit() nounwind { +entry: +  br label %outer + +outer: +  br label %inner + +inner: +  %iv = phi i32 [ 0, %outer ], [ %inc, %tail ] +  %inc = add i32 %iv, 1 +  call zeroext i1 @check() +  br i1 true, label %outer.backedge, label %tail + +tail: +  br i1 false, label %inner, label %exit + +outer.backedge: +  br label %outer + +exit: +  ret void +} +  | 

