Index: include/llvm/Transforms/Utils/BasicBlockUtils.h =================================================================== --- include/llvm/Transforms/Utils/BasicBlockUtils.h +++ include/llvm/Transforms/Utils/BasicBlockUtils.h @@ -40,14 +40,18 @@ class Value; /// Delete the specified block, which must have no predecessors. -void DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU = nullptr); +void DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU = nullptr, + bool DontDeleteUselessPHIs = false); /// Delete the specified blocks from \p BB. The set of deleted blocks must have /// no predecessors that are not being deleted themselves. \p BBs must have no /// duplicating blocks. If there are loops among this set of blocks, all /// relevant loop info updates should be done before this function is called. +/// If \p DontDeleteUselessPHIs is true, one-input Phis in successors of blocks +/// being deleted will be preserved. void DeleteDeadBlocks(SmallVectorImpl &BBs, - DomTreeUpdater *DTU = nullptr); + DomTreeUpdater *DTU = nullptr, + bool DontDeleteUselessPHIs = false); /// We know that BB has one predecessor. If there are any single-entry PHI nodes /// in it, fold them away. This handles the case when all entries to the PHI Index: lib/Transforms/Scalar/LoopSimplifyCFG.cpp =================================================================== --- lib/Transforms/Scalar/LoopSimplifyCFG.cpp +++ lib/Transforms/Scalar/LoopSimplifyCFG.cpp @@ -422,7 +422,7 @@ LI.removeBlock(BB); } - DeleteDeadBlocks(DeadLoopBlocks, &DTU); + DeleteDeadBlocks(DeadLoopBlocks, &DTU, /*DontDeleteUselessPHIs */ true); NumLoopBlocksDeleted += DeadLoopBlocks.size(); } Index: lib/Transforms/Utils/BasicBlockUtils.cpp =================================================================== --- lib/Transforms/Utils/BasicBlockUtils.cpp +++ lib/Transforms/Utils/BasicBlockUtils.cpp @@ -47,13 +47,14 @@ using namespace llvm; -void llvm::DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU) { +void llvm::DeleteDeadBlock(BasicBlock *BB, DomTreeUpdater *DTU, + bool DontDeleteUselessPHIs) { SmallVector BBs = {BB}; - DeleteDeadBlocks(BBs, DTU); + DeleteDeadBlocks(BBs, DTU, DontDeleteUselessPHIs); } void llvm::DeleteDeadBlocks(SmallVectorImpl &BBs, - DomTreeUpdater *DTU) { + DomTreeUpdater *DTU, bool DontDeleteUselessPHIs) { #ifndef NDEBUG // Make sure that all predecessors of each dead block is also dead. SmallPtrSet Dead(BBs.begin(), BBs.end()); @@ -68,7 +69,7 @@ // Loop through all of our successors and make sure they know that one // of their predecessors is going away. for (BasicBlock *Succ : successors(BB)) { - Succ->removePredecessor(BB); + Succ->removePredecessor(BB, DontDeleteUselessPHIs); if (DTU) Updates.push_back({DominatorTree::Delete, BB, Succ}); } Index: test/Transforms/LoopSimplifyCFG/lcssa.ll =================================================================== --- test/Transforms/LoopSimplifyCFG/lcssa.ll +++ test/Transforms/LoopSimplifyCFG/lcssa.ll @@ -1,5 +1,4 @@ ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py -; XFAIL: * ; REQUIRES: asserts ; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -loop-simplifycfg -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s ; RUN: opt -S -enable-loop-simplifycfg-term-folding=true -passes='require,loop(simplify-cfg)' -verify-loop-info -verify-dom-info -verify-loop-lcssa < %s | FileCheck %s @@ -93,8 +92,31 @@ } define void @bar() { - -; CHECK-LABEL: @bar +; CHECK-LABEL: @bar( +; CHECK-NEXT: bb: +; CHECK-NEXT: switch i32 0, label [[BB_SPLIT:%.*]] [ +; CHECK-NEXT: i32 1, label [[BB10:%.*]] +; CHECK-NEXT: ] +; CHECK: bb-split: +; CHECK-NEXT: br label [[BB1:%.*]] +; CHECK: bb1: +; CHECK-NEXT: [[TMP:%.*]] = phi i32 [ [[TMP7:%.*]], [[BB6:%.*]] ], [ undef, [[BB_SPLIT]] ] +; CHECK-NEXT: switch i32 undef, label [[BB5:%.*]] [ +; CHECK-NEXT: i32 0, label [[BB6]] +; CHECK-NEXT: i32 1, label [[BB8:%.*]] +; CHECK-NEXT: ] +; CHECK: bb5: +; CHECK-NEXT: ret void +; CHECK: bb6: +; CHECK-NEXT: [[TMP7]] = add i32 undef, 123 +; CHECK-NEXT: br label [[BB1]] +; CHECK: bb8: +; CHECK-NEXT: [[TMP9:%.*]] = phi i32 [ [[TMP]], [[BB1]] ] +; CHECK-NEXT: [[USE:%.*]] = add i32 [[TMP9]], 1 +; CHECK-NEXT: ret void +; CHECK: bb10: +; CHECK-NEXT: ret void +; bb: br label %bb1 @@ -105,8 +127,8 @@ bb2: ; preds = %bb1 switch i32 undef, label %bb10 [ - i32 0, label %bb3 - i32 1, label %bb8 + i32 0, label %bb3 + i32 1, label %bb8 ] bb3: ; preds = %bb2 @@ -114,8 +136,8 @@ bb4: ; preds = %bb1 switch i32 undef, label %bb5 [ - i32 0, label %bb6 - i32 1, label %bb8 + i32 0, label %bb6 + i32 1, label %bb8 ] bb5: ; preds = %bb4