diff options
| -rw-r--r-- | llvm/lib/Analysis/LoopPass.cpp | 11 | ||||
| -rw-r--r-- | llvm/test/Transforms/SimpleLoopUnswitch/pr37888.ll | 38 | 
2 files changed, 48 insertions, 1 deletions
diff --git a/llvm/lib/Analysis/LoopPass.cpp b/llvm/lib/Analysis/LoopPass.cpp index 00d88e8189e..c5ced03cfa8 100644 --- a/llvm/lib/Analysis/LoopPass.cpp +++ b/llvm/lib/Analysis/LoopPass.cpp @@ -142,8 +142,17 @@ void LPPassManager::getAnalysisUsage(AnalysisUsage &Info) const {  void LPPassManager::markLoopAsDeleted(Loop &L) {    assert((&L == CurrentLoop || CurrentLoop->contains(&L)) &&           "Must not delete loop outside the current loop tree!"); -  if (&L == CurrentLoop) +  // If this loop appears elsewhere within the queue, we also need to remove it +  // there. However, we have to be careful to not remove the back of the queue +  // as that is assumed to match the current loop. +  assert(LQ.back() == CurrentLoop && "Loop queue back isn't the current loop!"); +  LQ.erase(std::remove(LQ.begin(), LQ.end(), &L), LQ.end()); + +  if (&L == CurrentLoop) {      CurrentLoopDeleted = true; +    // Add this loop back onto the back of the queue to preserve our invariants. +    LQ.push_back(&L); +  }  }  /// run - Execute all of the passes scheduled for execution.  Keep track of diff --git a/llvm/test/Transforms/SimpleLoopUnswitch/pr37888.ll b/llvm/test/Transforms/SimpleLoopUnswitch/pr37888.ll new file mode 100644 index 00000000000..307706fc34a --- /dev/null +++ b/llvm/test/Transforms/SimpleLoopUnswitch/pr37888.ll @@ -0,0 +1,38 @@ +; RUN: opt -simple-loop-unswitch -loop-deletion -S < %s | FileCheck %s +; +; Check that when we do unswitching where we re-enqueue the loop to be processed +; again, but manage to delete the loop before ever getting to iterate on it, it +; doesn't crash the legacy pass manager. + +target triple = "x86_64-unknown-linux-gnu" + +define void @pr37888() { +; CHECK-LABEL: define void @pr37888() +entry: +  %tobool = icmp ne i16 undef, 0 +  br label %for.body +; CHECK:         %[[TOBOOL:.*]] = icmp ne +; CHECK-NEXT:    br i1 %[[TOBOOL]], label %if.then, label %[[ENTRY_SPLIT:.*]] +; +; CHECK:       [[ENTRY_SPLIT]]: +; CHECK-NEXT:    br label %for.end + +for.body: +  br i1 %tobool, label %if.then, label %if.end + +if.then: +  unreachable +; CHECK:       if.then: +; CHECK-NEXT:    unreachable + +if.end: +  br label %for.inc + +for.inc: +  br i1 undef, label %for.body, label %for.end + +for.end: +  ret void +; CHECK:       for.end: +; CHECK-NEXT:    ret void +}  | 

