[PATCH] D48470: [LegacyPM] Fix PR37888 by teaching the legacy loop pass manager how to clear out deleted loops from the current queue beyond just the current loop.

Chandler Carruth via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 21 19:07:07 PDT 2018


chandlerc created this revision.
chandlerc added a reviewer: sanjoy.
Herald added subscribers: hiraditya, mcrosier.

This is important because SimpleLoopUnswitch will now enqueue the same
loop to be re-processed. When it does this with the legacy PM, we don't
have a way of canceling the rest of the pipeline and so we can end up
deleting the loop before we reprocess it. =/

This change also makes it easy to support deleting other loops in the
queue to process, although I don't have any use cases for that.


Repository:
  rL LLVM

https://reviews.llvm.org/D48470

Files:
  llvm/lib/Analysis/LoopPass.cpp
  llvm/test/Transforms/SimpleLoopUnswitch/pr37888.ll


Index: llvm/test/Transforms/SimpleLoopUnswitch/pr37888.ll
===================================================================
--- /dev/null
+++ 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
+}
Index: llvm/lib/Analysis/LoopPass.cpp
===================================================================
--- llvm/lib/Analysis/LoopPass.cpp
+++ llvm/lib/Analysis/LoopPass.cpp
@@ -142,8 +142,17 @@
 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


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D48470.152421.patch
Type: text/x-patch
Size: 2189 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20180622/11404a8a/attachment.bin>


More information about the llvm-commits mailing list