diff --git a/llvm/lib/Transforms/Utils/FixIrreducible.cpp b/llvm/lib/Transforms/Utils/FixIrreducible.cpp --- a/llvm/lib/Transforms/Utils/FixIrreducible.cpp +++ b/llvm/lib/Transforms/Utils/FixIrreducible.cpp @@ -138,10 +138,18 @@ // not be necessary if we can retain such backedges. if (Headers.count(Child->getHeader())) { for (auto BB : Child->blocks()) { + if (LI.getLoopFor(BB) != Child) + continue; LI.changeLoopFor(BB, NewLoop); LLVM_DEBUG(dbgs() << "moved block from child: " << BB->getName() << "\n"); } + std::vector GrandChildLoops; + std::swap(GrandChildLoops, Child->getSubLoopsVector()); + for (auto GrandChildLoop : GrandChildLoops) { + GrandChildLoop->setParentLoop(nullptr); + NewLoop->addChildLoop(GrandChildLoop); + } LI.destroy(Child); LLVM_DEBUG(dbgs() << "subsumed child loop (common header)\n"); continue; diff --git a/llvm/test/Transforms/FixIrreducible/issue55099.ll b/llvm/test/Transforms/FixIrreducible/issue55099.ll new file mode 100644 --- /dev/null +++ b/llvm/test/Transforms/FixIrreducible/issue55099.ll @@ -0,0 +1,39 @@ +; RUN: opt %s -fix-irreducible -S -o - | FileCheck %s + +define dso_local void @foo(i1 %a) { +; CHECK-LABEL: @foo( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label %irr.guard +; CHECK: block1: +; CHECK-NEXT: br label %irr.guard +; CHECK: block2: +; CHECK-NEXT: br label %body +; CHECK: body: +; CHECK-NEXT: br i1 %a, label %latch, label %inner_body +; CHECK: inner_body: +; CHECK-NEXT: br label %body +; CHECK: latch: +; CHECK-NEXT: br label %irr.guard +; CHECK: irr.guard: +; CHECK-NEXT: [[GUARD:%.*]] = phi i1 [ %a, %latch ], [ %a, %block1 ], [ %a, %entry ] +; CHECK-NEXT: br i1 [[GUARD]], label %block1, label %block2 +; +entry: + br i1 %a, label %block1, label %block2 + +block1: + br i1 %a, label %block1, label %block2 + +block2: + br label %body + +body: + br i1 %a, label %latch, label %inner_body + +inner_body: + br label %body + +latch: + br i1 %a, label %block1, label %block2 + +}