Second attempt at PR12573:

Allow the "SplitCriticalEdge" function to split the edge to a landing pad. If
the pass is *sure* that it thinks it knows what it's doing, then it may go ahead
and specify that the landing pad can have its critical edge split. The loop
unswitch pass is one of these passes. It will split the critical edges of all
edges coming from a loop to a landing pad not within the loop. Doing so will
retain important loop analysis information, such as loop simplify.


git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@155817 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Bill Wendling 2012-04-30 10:44:54 +00:00
parent 38da2a8cc1
commit bfbab99b58
4 changed files with 131 additions and 14 deletions

View File

@ -110,7 +110,8 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
/// ///
BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
Pass *P = 0, bool MergeIdenticalEdges = false, Pass *P = 0, bool MergeIdenticalEdges = false,
bool DontDeleteUselessPHIs = false); bool DontDeleteUselessPHIs = false,
bool SplitLandingPads = false);
inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI, inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
Pass *P = 0) { Pass *P = 0) {

View File

@ -687,8 +687,8 @@ void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
// If either edge is critical, split it. This helps preserve LoopSimplify // If either edge is critical, split it. This helps preserve LoopSimplify
// form for enclosing loops. // form for enclosing loops.
SplitCriticalEdge(BI, 0, this); SplitCriticalEdge(BI, 0, this, false, false, true);
SplitCriticalEdge(BI, 1, this); SplitCriticalEdge(BI, 1, this, false, false, true);
} }
/// UnswitchTrivialCondition - Given a loop that has a trivial unswitchable /// UnswitchTrivialCondition - Given a loop that has a trivial unswitchable

View File

@ -126,24 +126,29 @@ static void createPHIsForSplitLoopExit(ArrayRef<BasicBlock *> Preds,
BasicBlock *SplitBB, BasicBlock *SplitBB,
BasicBlock *DestBB) { BasicBlock *DestBB) {
// SplitBB shouldn't have anything non-trivial in it yet. // SplitBB shouldn't have anything non-trivial in it yet.
assert(SplitBB->getFirstNonPHI() == SplitBB->getTerminator() && assert((SplitBB->getFirstNonPHI() == SplitBB->getTerminator() ||
"SplitBB has non-PHI nodes!"); SplitBB->isLandingPad()) && "SplitBB has non-PHI nodes!");
// For each PHI in the destination block... // For each PHI in the destination block.
for (BasicBlock::iterator I = DestBB->begin(); for (BasicBlock::iterator I = DestBB->begin();
PHINode *PN = dyn_cast<PHINode>(I); ++I) { PHINode *PN = dyn_cast<PHINode>(I); ++I) {
unsigned Idx = PN->getBasicBlockIndex(SplitBB); unsigned Idx = PN->getBasicBlockIndex(SplitBB);
Value *V = PN->getIncomingValue(Idx); Value *V = PN->getIncomingValue(Idx);
// If the input is a PHI which already satisfies LCSSA, don't create // If the input is a PHI which already satisfies LCSSA, don't create
// a new one. // a new one.
if (const PHINode *VP = dyn_cast<PHINode>(V)) if (const PHINode *VP = dyn_cast<PHINode>(V))
if (VP->getParent() == SplitBB) if (VP->getParent() == SplitBB)
continue; continue;
// Otherwise a new PHI is needed. Create one and populate it. // Otherwise a new PHI is needed. Create one and populate it.
PHINode *NewPN = PHINode::Create(PN->getType(), Preds.size(), "split", PHINode *NewPN =
SplitBB->getTerminator()); PHINode::Create(PN->getType(), Preds.size(), "split",
SplitBB->isLandingPad() ?
SplitBB->begin() : SplitBB->getTerminator());
for (unsigned i = 0, e = Preds.size(); i != e; ++i) for (unsigned i = 0, e = Preds.size(); i != e; ++i)
NewPN->addIncoming(V, Preds[i]); NewPN->addIncoming(V, Preds[i]);
// Update the original PHI. // Update the original PHI.
PN->setIncomingValue(Idx, NewPN); PN->setIncomingValue(Idx, NewPN);
} }
@ -168,7 +173,8 @@ static void createPHIsForSplitLoopExit(ArrayRef<BasicBlock *> Preds,
/// ///
BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum, BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
Pass *P, bool MergeIdenticalEdges, Pass *P, bool MergeIdenticalEdges,
bool DontDeleteUselessPhis) { bool DontDeleteUselessPhis,
bool SplitLandingPads) {
if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return 0; if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return 0;
assert(!isa<IndirectBrInst>(TI) && assert(!isa<IndirectBrInst>(TI) &&
@ -368,10 +374,19 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
// getUniqueExitBlocks above because that depends on LoopSimplify // getUniqueExitBlocks above because that depends on LoopSimplify
// form, which we're in the process of restoring! // form, which we're in the process of restoring!
if (!Preds.empty() && HasPredOutsideOfLoop) { if (!Preds.empty() && HasPredOutsideOfLoop) {
if (!Exit->isLandingPad()) {
BasicBlock *NewExitBB = BasicBlock *NewExitBB =
SplitBlockPredecessors(Exit, Preds, "split", P); SplitBlockPredecessors(Exit, Preds, "split", P);
if (P->mustPreserveAnalysisID(LCSSAID)) if (P->mustPreserveAnalysisID(LCSSAID))
createPHIsForSplitLoopExit(Preds, NewExitBB, Exit); createPHIsForSplitLoopExit(Preds, NewExitBB, Exit);
} else if (SplitLandingPads) {
SmallVector<BasicBlock*, 8> NewBBs;
SplitLandingPadPredecessors(Exit, Preds,
".split1", ".split2",
P, NewBBs);
if (P->mustPreserveAnalysisID(LCSSAID))
createPHIsForSplitLoopExit(Preds, NewBBs[0], Exit);
}
} }
} }
} }

View File

@ -0,0 +1,101 @@
; RUN: opt < %s -basicaa -instcombine -inline -functionattrs -licm -loop-unswitch -gvn -verify
; PR12573
target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64-S128"
target triple = "x86_64-apple-macosx10.7.0"
%class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379 = type { %class.C.23.43.67.103.139.159.179.199.239.243.247.251.263.295.303.339.347.376*, %class.B.21.41.65.101.137.157.177.197.237.241.245.249.261.293.301.337.345.378 }
%class.C.23.43.67.103.139.159.179.199.239.243.247.251.263.295.303.339.347.376 = type { %class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379* }
%class.B.21.41.65.101.137.157.177.197.237.241.245.249.261.293.301.337.345.378 = type { %class.A.20.40.64.100.136.156.176.196.236.240.244.248.260.292.300.336.344.377* }
%class.A.20.40.64.100.136.156.176.196.236.240.244.248.260.292.300.336.344.377 = type { i8 }
define void @_Z23get_reconstruction_pathv() uwtable ssp {
entry:
%c = alloca %class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379, align 8
br label %for.cond
for.cond: ; preds = %for.end, %entry
invoke void @_ZN1DptEv(%class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379* %c)
to label %invoke.cont unwind label %lpad
invoke.cont: ; preds = %for.cond
invoke void @_ZN1C3endEv()
to label %for.cond3 unwind label %lpad
for.cond3: ; preds = %invoke.cont6, %invoke.cont
invoke void @_ZN1DptEv(%class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379* %c)
to label %invoke.cont4 unwind label %lpad
invoke.cont4: ; preds = %for.cond3
invoke void @_ZN1C3endEv()
to label %invoke.cont6 unwind label %lpad
invoke.cont6: ; preds = %invoke.cont4
br i1 undef, label %for.cond3, label %for.end
lpad: ; preds = %for.end, %invoke.cont4, %for.cond3, %invoke.cont, %for.cond
%0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_v0 to i8*)
cleanup
resume { i8*, i32 } undef
for.end: ; preds = %invoke.cont6
invoke void @_ZN1C13_M_insert_auxER1D()
to label %for.cond unwind label %lpad
}
define void @_ZN1DptEv(%class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379* %this) uwtable ssp align 2 {
entry:
%this.addr = alloca %class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379*, align 8
store %class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379* %this, %class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379** %this.addr, align 8, !tbaa !0
%this1 = load %class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379** %this.addr
%px = getelementptr inbounds %class.D.22.42.66.102.138.158.178.198.238.242.246.250.262.294.302.338.346.379* %this1, i32 0, i32 0
%0 = load %class.C.23.43.67.103.139.159.179.199.239.243.247.251.263.295.303.339.347.376** %px, align 8, !tbaa !0
%tobool = icmp ne %class.C.23.43.67.103.139.159.179.199.239.243.247.251.263.295.303.339.347.376* %0, null
br i1 %tobool, label %cond.end, label %cond.false
cond.false: ; preds = %entry
call void @_Z10__assert13v() noreturn
unreachable
cond.end: ; preds = %entry
ret void
}
declare i32 @__gxx_personality_v0(...)
declare void @_ZN1C3endEv()
define void @_ZN1C13_M_insert_auxER1D() uwtable ssp align 2 {
entry:
ret void
}
define void @_ZN1DD1Ev() unnamed_addr uwtable inlinehint ssp align 2 {
entry:
ret void
}
define void @_ZN1DD2Ev() unnamed_addr uwtable inlinehint ssp align 2 {
entry:
ret void
}
define void @_ZN1BD1Ev() unnamed_addr uwtable ssp align 2 {
entry:
ret void
}
define void @_ZN1BD2Ev() unnamed_addr uwtable ssp align 2 {
entry:
ret void
}
define void @_ZN1BaSERS_() uwtable ssp align 2 {
entry:
unreachable
}
declare void @_Z10__assert13v() noreturn
!0 = metadata !{metadata !"any pointer", metadata !1}
!1 = metadata !{metadata !"omnipotent char", metadata !2}
!2 = metadata !{metadata !"Simple C/C++ TBAA", null}