diff --git a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp index aecc681aad8e8d..35ab1e52ee2e4c 100644 --- a/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp +++ b/llvm/lib/Transforms/Scalar/SimplifyCFGPass.cpp @@ -77,9 +77,12 @@ STATISTIC(NumSimpl, "Number of blocks simplified"); /// If we have more than one empty (other than phi node) return blocks, /// merge them together to promote recursive block merging. -static bool mergeEmptyReturnBlocks(Function &F) { +static bool mergeEmptyReturnBlocks(Function &F, DomTreeUpdater *DTU) { bool Changed = false; + std::vector Updates; + SmallVector DeadBlocks; + BasicBlock *RetBlock = nullptr; // Scan all the blocks in the function, looking for empty return blocks. @@ -135,8 +138,15 @@ static bool mergeEmptyReturnBlocks(Function &F) { if (Ret->getNumOperands() == 0 || Ret->getOperand(0) == cast(RetBlock->getTerminator())->getOperand(0)) { + // All predecessors of BB should now branch to RetBlock instead. + if (DTU) { + for (auto *Predecessor : predecessors(&BB)) { + Updates.push_back({DominatorTree::Delete, Predecessor, &BB}); + Updates.push_back({DominatorTree::Insert, Predecessor, RetBlock}); + } + } BB.replaceAllUsesWith(RetBlock); - BB.eraseFromParent(); + DeadBlocks.emplace_back(&BB); continue; } @@ -160,6 +170,17 @@ static bool mergeEmptyReturnBlocks(Function &F) { RetBlockPHI->addIncoming(Ret->getOperand(0), &BB); BB.getTerminator()->eraseFromParent(); BranchInst::Create(RetBlock, &BB); + if (DTU) + Updates.push_back({DominatorTree::Insert, &BB, RetBlock}); + } + + if (DTU) { + DTU->applyUpdatesPermissive(Updates); + for (auto *BB : DeadBlocks) + DTU->deleteBB(BB); + } else { + for (auto *BB : DeadBlocks) + BB->eraseFromParent(); } return Changed; @@ -200,7 +221,7 @@ static bool simplifyFunctionCFGImpl(Function &F, const TargetTransformInfo &TTI, DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Eager); bool EverChanged = removeUnreachableBlocks(F, DT ? &DTU : nullptr); - EverChanged |= mergeEmptyReturnBlocks(F); + EverChanged |= mergeEmptyReturnBlocks(F, DT ? &DTU : nullptr); EverChanged |= iterativelySimplifyCFG(F, TTI, DT ? &DTU : nullptr, Options); // If neither pass changed anything, we're done. diff --git a/llvm/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll b/llvm/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll index c71f05bf0a358a..f224b6656de14a 100644 --- a/llvm/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll +++ b/llvm/test/Transforms/SimplifyCFG/2005-10-02-InvokeSimplify.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -simplifycfg -disable-output +; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -disable-output define i1 @foo() personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*) { %X = invoke i1 @foo( ) diff --git a/llvm/test/Transforms/SimplifyCFG/merge-empty-return-blocks.ll b/llvm/test/Transforms/SimplifyCFG/merge-empty-return-blocks.ll new file mode 100644 index 00000000000000..24baec0e45232e --- /dev/null +++ b/llvm/test/Transforms/SimplifyCFG/merge-empty-return-blocks.ll @@ -0,0 +1,48 @@ +; NOTE: Assertions have been autogenerated by utils/update_test_checks.py +; RUN: opt -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S < %s | FileCheck %s + +define void @t0(i1 %c) { +; CHECK-LABEL: @t0( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret void +; +entry: + br i1 %c, label %end0, label %end1 + +end0: + ret void + +end1: + ret void +} + +define i8 @t1(i1 %c, i8 %v) { +; CHECK-LABEL: @t1( +; CHECK-NEXT: entry: +; CHECK-NEXT: ret i8 [[V:%.*]] +; +entry: + br i1 %c, label %end0, label %end1 + +end0: + ret i8 %v + +end1: + ret i8 %v +} + +define i8 @t2(i1 %c, i8 %v0, i8 %v1) { +; CHECK-LABEL: @t2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[SPEC_SELECT:%.*]] = select i1 [[C:%.*]], i8 [[V0:%.*]], i8 [[V1:%.*]] +; CHECK-NEXT: ret i8 [[SPEC_SELECT]] +; +entry: + br i1 %c, label %end0, label %end1 + +end0: + ret i8 %v0 + +end1: + ret i8 %v1 +} diff --git a/llvm/test/Transforms/SimplifyCFG/return-merge.ll b/llvm/test/Transforms/SimplifyCFG/return-merge.ll index 977b6dff87cb7b..f65cf4925e6e73 100644 --- a/llvm/test/Transforms/SimplifyCFG/return-merge.ll +++ b/llvm/test/Transforms/SimplifyCFG/return-merge.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -simplifycfg -S | not grep br +; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | not grep br define i32 @test1(i1 %C) { entry: