mirror of
https://github.com/RPCS3/llvm.git
synced 2025-02-15 00:16:42 +00:00
[SimplifyCFG] Merge together cleanuppads
Cleanuppads may be merged together if one is the only predecessor of the other in which case a simple transform can be performed: replace the a cleanupret with a branch and remove an unnecessary cleanuppad. Differential Revision: http://reviews.llvm.org/D17459 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@261390 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
7ed6f01c5d
commit
1f296bf0b8
@ -3371,7 +3371,7 @@ bool SimplifyCFGOpt::SimplifySingleResume(ResumeInst *RI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) {
|
||||
static bool removeEmptyCleanup(CleanupReturnInst *RI) {
|
||||
// If this is a trivial cleanup pad that executes no instructions, it can be
|
||||
// eliminated. If the cleanup pad continues to the caller, any predecessor
|
||||
// that is an EH pad will be updated to continue to the caller and any
|
||||
@ -3489,6 +3489,49 @@ bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Try to merge two cleanuppads together.
|
||||
static bool mergeCleanupPad(CleanupReturnInst *RI) {
|
||||
// Skip any cleanuprets which unwind to caller, there is nothing to merge
|
||||
// with.
|
||||
BasicBlock *UnwindDest = RI->getUnwindDest();
|
||||
if (!UnwindDest)
|
||||
return false;
|
||||
|
||||
// This cleanupret isn't the only predecessor of this cleanuppad, it wouldn't
|
||||
// be safe to merge without code duplication.
|
||||
if (UnwindDest->getSinglePredecessor() != RI->getParent())
|
||||
return false;
|
||||
|
||||
// Verify that our cleanuppad's unwind destination is another cleanuppad.
|
||||
auto *SuccessorCleanupPad = dyn_cast<CleanupPadInst>(&UnwindDest->front());
|
||||
if (!SuccessorCleanupPad)
|
||||
return false;
|
||||
|
||||
CleanupPadInst *PredecessorCleanupPad = RI->getCleanupPad();
|
||||
// Replace any uses of the successor cleanupad with the predecessor pad
|
||||
// The only cleanuppad uses should be this cleanupret, it's cleanupret and
|
||||
// funclet bundle operands.
|
||||
SuccessorCleanupPad->replaceAllUsesWith(PredecessorCleanupPad);
|
||||
// Remove the old cleanuppad.
|
||||
SuccessorCleanupPad->eraseFromParent();
|
||||
// Now, we simply replace the cleanupret with a branch to the unwind
|
||||
// destination.
|
||||
BranchInst::Create(UnwindDest, RI->getParent());
|
||||
RI->eraseFromParent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SimplifyCFGOpt::SimplifyCleanupReturn(CleanupReturnInst *RI) {
|
||||
if (removeEmptyCleanup(RI))
|
||||
return true;
|
||||
|
||||
if (mergeCleanupPad(RI))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool SimplifyCFGOpt::SimplifyReturn(ReturnInst *RI, IRBuilder<> &Builder) {
|
||||
BasicBlock *BB = RI->getParent();
|
||||
if (!BB->getFirstNonPHIOrDbg()->isTerminator()) return false;
|
||||
@ -4978,7 +5021,7 @@ static bool TryToMergeLandingPad(LandingPadInst *LPad, BranchInst *BI,
|
||||
if (!BI2 || !BI2->isIdenticalTo(BI))
|
||||
continue;
|
||||
|
||||
// We've found an identical block. Update our predeccessors to take that
|
||||
// We've found an identical block. Update our predecessors to take that
|
||||
// path instead and make ourselves dead.
|
||||
SmallSet<BasicBlock *, 16> Preds;
|
||||
Preds.insert(pred_begin(BB), pred_end(BB));
|
||||
|
39
test/Transforms/SimplifyCFG/merge-cleanuppads.ll
Normal file
39
test/Transforms/SimplifyCFG/merge-cleanuppads.ll
Normal file
@ -0,0 +1,39 @@
|
||||
; RUN: opt -S -simplifycfg < %s | FileCheck %s
|
||||
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
|
||||
target triple = "x86_64-pc-windows-msvc18.0.0"
|
||||
|
||||
; Function Attrs: uwtable
|
||||
define void @test1() #0 personality i32 (...)* @__CxxFrameHandler3 {
|
||||
entry:
|
||||
invoke void @may_throw(i32 3)
|
||||
to label %invoke.cont unwind label %ehcleanup
|
||||
|
||||
invoke.cont: ; preds = %entry
|
||||
tail call void @may_throw(i32 2) #2
|
||||
tail call void @may_throw(i32 1) #2
|
||||
ret void
|
||||
|
||||
ehcleanup: ; preds = %entry
|
||||
%cp = cleanuppad within none []
|
||||
tail call void @may_throw(i32 2) #2 [ "funclet"(token %cp) ]
|
||||
cleanupret from %cp unwind label %ehcleanup2
|
||||
|
||||
ehcleanup2:
|
||||
%cp2 = cleanuppad within none []
|
||||
tail call void @may_throw(i32 1) #2 [ "funclet"(token %cp2) ]
|
||||
cleanupret from %cp2 unwind to caller
|
||||
}
|
||||
|
||||
; CHECK-LABEL: define void @test1(
|
||||
; CHECK: %[[cp:.*]] = cleanuppad within none []
|
||||
; CHECK: tail call void @may_throw(i32 2) #2 [ "funclet"(token %[[cp]]) ]
|
||||
; CHECK: tail call void @may_throw(i32 1) #2 [ "funclet"(token %[[cp]]) ]
|
||||
; CHECK: cleanupret from %[[cp]] unwind to caller
|
||||
|
||||
declare void @may_throw(i32) #1
|
||||
|
||||
declare i32 @__CxxFrameHandler3(...)
|
||||
|
||||
attributes #0 = { uwtable "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
attributes #1 = { "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+fxsr,+mmx,+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
|
||||
attributes #2 = { nounwind }
|
Loading…
x
Reference in New Issue
Block a user