diff --git a/llvm/lib/Transforms/Utils/LoopSimplify.cpp b/llvm/lib/Transforms/Utils/LoopSimplify.cpp index 26b59ad57df9..36e2fea63dc5 100644 --- a/llvm/lib/Transforms/Utils/LoopSimplify.cpp +++ b/llvm/lib/Transforms/Utils/LoopSimplify.cpp @@ -622,8 +622,10 @@ ReprocessLoop: (PN = dyn_cast(I++)); ) if (Value *V = SimplifyInstruction(PN, DL, nullptr, DT, AC)) { if (SE) SE->forgetValue(PN); - PN->replaceAllUsesWith(V); - PN->eraseFromParent(); + if (!PreserveLCSSA || LI->replacementPreservesLCSSAForm(PN, V)) { + PN->replaceAllUsesWith(V); + PN->eraseFromParent(); + } } // If this loop has multiple exits and the exits all go to the same diff --git a/llvm/test/Transforms/LoopUnroll/rebuild_lcssa.ll b/llvm/test/Transforms/LoopUnroll/rebuild_lcssa.ll index 9de638ce4f80..98a8b91a0e6e 100644 --- a/llvm/test/Transforms/LoopUnroll/rebuild_lcssa.ll +++ b/llvm/test/Transforms/LoopUnroll/rebuild_lcssa.ll @@ -151,3 +151,40 @@ L1_latch: exit: ret i8 0 } + +; CHECK-LABEL: @foo5 +define void @foo5() { +entry: + br label %outer + +outer: + br label %inner1 + +; CHECK: inner1: +; CHECK-NOT: br i1 true +; CHECK: br label %inner2_indirect_exit +inner1: + br i1 true, label %inner2_indirect_exit.preheader, label %inner1 + +inner2_indirect_exit.preheader: + br label %inner2_indirect_exit + +inner2_indirect_exit: + %a = phi i32 [ %b, %inner2_latch ], [ undef, %inner2_indirect_exit.preheader ] + indirectbr i8* undef, [label %inner2_latch, label %inner3, label %outer_latch] + +inner2_latch: + %b = load i32, i32* undef, align 8 + br label %inner2_indirect_exit + +inner3: + %a.lcssa = phi i32 [ %a.lcssa, %inner3 ], [ %a, %inner2_indirect_exit ] + br i1 true, label %outer_latch.loopexit, label %inner3 + +outer_latch.loopexit: + %a.lcssa.lcssa = phi i32 [ %a.lcssa, %inner3 ] + br label %outer_latch + +outer_latch: + br label %outer +}