[SimplifyCFG] Drop support for duplicating ret's into uncond predecessors

This functionality existed only under a default-off flag,
and simplifycfg nowadays prefers to not increase the count of ret's.
This commit is contained in:
Roman Lebedev 2021-07-26 23:08:36 +03:00
parent 20555a15a5
commit 7c5f104e45
No known key found for this signature in database
GPG Key ID: 083C3EBB4A1689E0
4 changed files with 21 additions and 92 deletions

View File

@ -113,10 +113,6 @@ static cl::opt<unsigned> TwoEntryPHINodeFoldingThreshold(
"to speculatively execute to fold a 2-entry PHI node into a "
"select (default = 4)"));
static cl::opt<bool> DupRet(
"simplifycfg-dup-ret", cl::Hidden, cl::init(false),
cl::desc("Duplicate return instructions into unconditional branches"));
static cl::opt<bool>
HoistCommon("simplifycfg-hoist-common", cl::Hidden, cl::init(true),
cl::desc("Hoist common instructions up to the parent block"));
@ -4638,33 +4634,13 @@ bool SimplifyCFGOpt::simplifyReturn(ReturnInst *RI, IRBuilder<> &Builder) {
return false;
// Find predecessors that end with branches.
SmallVector<BasicBlock *, 8> UncondBranchPreds;
SmallVector<BranchInst *, 8> CondBranchPreds;
for (BasicBlock *P : predecessors(BB)) {
Instruction *PTI = P->getTerminator();
if (BranchInst *BI = dyn_cast<BranchInst>(PTI)) {
if (BI->isUnconditional())
UncondBranchPreds.push_back(P);
else
if (BranchInst *BI = dyn_cast<BranchInst>(PTI))
if (BI->isConditional())
CondBranchPreds.push_back(BI);
}
}
// If we found some, do the transformation!
if (!UncondBranchPreds.empty() && DupRet) {
while (!UncondBranchPreds.empty()) {
BasicBlock *Pred = UncondBranchPreds.pop_back_val();
LLVM_DEBUG(dbgs() << "FOLDING: " << *BB
<< "INTO UNCOND BRANCH PRED: " << *Pred);
(void)FoldReturnIntoUncondBranch(RI, BB, Pred, DTU);
}
// If we eliminated all predecessors of the block, delete the block now.
if (pred_empty(BB))
DeleteDeadBlock(BB, DTU);
return true;
}
// Check out all of the conditional branches going to this return
// instruction. If any of them just select between returns, change the

View File

@ -1,31 +0,0 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -simplifycfg-dup-ret -S | FileCheck %s
declare void @bar()
declare void @baz()
define void @foo(i1 %c) {
; CHECK-LABEL: @foo(
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[C:%.*]], label [[TRUE:%.*]], label [[FALSE:%.*]]
; CHECK: true:
; CHECK-NEXT: call void @bar()
; CHECK-NEXT: ret void
; CHECK: false:
; CHECK-NEXT: call void @baz()
; CHECK-NEXT: ret void
;
entry:
br i1 %c, label %true, label %false
true:
call void @bar()
br label %end
false:
call void @baz()
br label %end
end:
ret void
}

View File

@ -1,5 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -simplifycfg-dup-ret -S | FileCheck %s
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck %s
declare void @bar()
declare void @baz()

View File

@ -1,6 +1,5 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck --check-prefixes=CHECK,NODUPRET %s
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -simplifycfg-dup-ret -S | FileCheck --check-prefixes=CHECK,DUPRET %s
; RUN: opt < %s -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck --check-prefixes=CHECK %s
; RUN: opt < %s -debugify -simplifycfg -simplifycfg-require-and-preserve-domtree=1 -S | FileCheck --check-prefixes=DBGINFO %s
define i32 @test1(i1 %C) {
@ -24,12 +23,9 @@ F: ; preds = %entry
}
define void @test2(i1 %C) {
; NODUPRET-LABEL: @test2(
; NODUPRET-NEXT: common.ret:
; NODUPRET-NEXT: ret void
;
; DUPRET-LABEL: @test2(
; DUPRET-NEXT: ret void
; CHECK-LABEL: @test2(
; CHECK-NEXT: common.ret:
; CHECK-NEXT: ret void
;
; DBGINFO-LABEL: @test2(
; DBGINFO-NEXT: common.ret:
@ -48,32 +44,20 @@ declare void @sideeffect1()
declare void @sideeffect2()
define i32 @test3(i1 %C0, i1 %C1, i32 %v0, i32 %v1, i32 %v2) {
; NODUPRET-LABEL: @test3(
; NODUPRET-NEXT: entry:
; NODUPRET-NEXT: call void @sideeffect0()
; NODUPRET-NEXT: br i1 [[C0:%.*]], label [[T:%.*]], label [[F:%.*]]
; NODUPRET: end:
; NODUPRET-NEXT: [[R:%.*]] = phi i32 [ [[V2:%.*]], [[F]] ], [ [[SPEC_SELECT:%.*]], [[T]] ]
; NODUPRET-NEXT: ret i32 [[R]]
; NODUPRET: T:
; NODUPRET-NEXT: call void @sideeffect1()
; NODUPRET-NEXT: [[SPEC_SELECT]] = select i1 [[C1:%.*]], i32 [[V0:%.*]], i32 [[V1:%.*]]
; NODUPRET-NEXT: br label [[END:%.*]]
; NODUPRET: F:
; NODUPRET-NEXT: call void @sideeffect2()
; NODUPRET-NEXT: br label [[END]]
;
; DUPRET-LABEL: @test3(
; DUPRET-NEXT: entry:
; DUPRET-NEXT: call void @sideeffect0()
; DUPRET-NEXT: br i1 [[C0:%.*]], label [[T:%.*]], label [[F:%.*]]
; DUPRET: T:
; DUPRET-NEXT: call void @sideeffect1()
; DUPRET-NEXT: [[RETVAL:%.*]] = select i1 [[C1:%.*]], i32 [[V0:%.*]], i32 [[V1:%.*]]
; DUPRET-NEXT: ret i32 [[RETVAL]]
; DUPRET: F:
; DUPRET-NEXT: call void @sideeffect2()
; DUPRET-NEXT: ret i32 [[V2:%.*]]
; CHECK-LABEL: @test3(
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @sideeffect0()
; CHECK-NEXT: br i1 [[C0:%.*]], label [[T:%.*]], label [[F:%.*]]
; CHECK: end:
; CHECK-NEXT: [[R:%.*]] = phi i32 [ [[V2:%.*]], [[F]] ], [ [[SPEC_SELECT:%.*]], [[T]] ]
; CHECK-NEXT: ret i32 [[R]]
; CHECK: T:
; CHECK-NEXT: call void @sideeffect1()
; CHECK-NEXT: [[SPEC_SELECT]] = select i1 [[C1:%.*]], i32 [[V0:%.*]], i32 [[V1:%.*]]
; CHECK-NEXT: br label [[END:%.*]]
; CHECK: F:
; CHECK-NEXT: call void @sideeffect2()
; CHECK-NEXT: br label [[END]]
;
; DBGINFO-LABEL: @test3(
; DBGINFO-NEXT: entry: