summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBill Wendling <isanbard@gmail.com>2012-04-30 10:44:54 +0000
committerBill Wendling <isanbard@gmail.com>2012-04-30 10:44:54 +0000
commitbfbab99b58aa530d5d6aa886ef66be42a047c756 (patch)
tree3d4df04901c7bcdba3f3684492c94e74ebd35a6f
parent38da2a8cc1a41147efac423cb97caf3db90f73e7 (diff)
downloadllvm-bfbab99b58aa530d5d6aa886ef66be42a047c756.tar.gz
llvm-bfbab99b58aa530d5d6aa886ef66be42a047c756.tar.bz2
llvm-bfbab99b58aa530d5d6aa886ef66be42a047c756.tar.xz
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
-rw-r--r--include/llvm/Transforms/Utils/BasicBlockUtils.h3
-rw-r--r--lib/Transforms/Scalar/LoopUnswitch.cpp4
-rw-r--r--lib/Transforms/Utils/BreakCriticalEdges.cpp37
-rw-r--r--test/Transforms/LoopUnswitch/2012-04-30-LoopUnswitch-LPad-Crash.ll101
4 files changed, 131 insertions, 14 deletions
diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h
index 867b9e4384..2f9dc54541 100644
--- a/include/llvm/Transforms/Utils/BasicBlockUtils.h
+++ b/include/llvm/Transforms/Utils/BasicBlockUtils.h
@@ -110,7 +110,8 @@ bool isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
///
BasicBlock *SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
Pass *P = 0, bool MergeIdenticalEdges = false,
- bool DontDeleteUselessPHIs = false);
+ bool DontDeleteUselessPHIs = false,
+ bool SplitLandingPads = false);
inline BasicBlock *SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
Pass *P = 0) {
diff --git a/lib/Transforms/Scalar/LoopUnswitch.cpp b/lib/Transforms/Scalar/LoopUnswitch.cpp
index 7e485b8113..930980f528 100644
--- a/lib/Transforms/Scalar/LoopUnswitch.cpp
+++ b/lib/Transforms/Scalar/LoopUnswitch.cpp
@@ -687,8 +687,8 @@ void LoopUnswitch::EmitPreheaderBranchOnCondition(Value *LIC, Constant *Val,
// If either edge is critical, split it. This helps preserve LoopSimplify
// form for enclosing loops.
- SplitCriticalEdge(BI, 0, this);
- SplitCriticalEdge(BI, 1, this);
+ SplitCriticalEdge(BI, 0, this, false, false, true);
+ SplitCriticalEdge(BI, 1, this, false, false, true);
}
/// UnswitchTrivialCondition - Given a loop that has a trivial unswitchable
diff --git a/lib/Transforms/Utils/BreakCriticalEdges.cpp b/lib/Transforms/Utils/BreakCriticalEdges.cpp
index 0de3befa4e..6b04e3d17b 100644
--- a/lib/Transforms/Utils/BreakCriticalEdges.cpp
+++ b/lib/Transforms/Utils/BreakCriticalEdges.cpp
@@ -119,31 +119,36 @@ bool llvm::isCriticalEdge(const TerminatorInst *TI, unsigned SuccNum,
/// createPHIsForSplitLoopExit - When a loop exit edge is split, LCSSA form
/// may require new PHIs in the new exit block. This function inserts the
-/// new PHIs, as needed. Preds is a list of preds inside the loop, SplitBB
+/// new PHIs, as needed. Preds is a list of preds inside the loop, SplitBB
/// is the new loop exit block, and DestBB is the old loop exit, now the
/// successor of SplitBB.
static void createPHIsForSplitLoopExit(ArrayRef<BasicBlock *> Preds,
BasicBlock *SplitBB,
BasicBlock *DestBB) {
// SplitBB shouldn't have anything non-trivial in it yet.
- assert(SplitBB->getFirstNonPHI() == SplitBB->getTerminator() &&
- "SplitBB has non-PHI nodes!");
+ assert((SplitBB->getFirstNonPHI() == SplitBB->getTerminator() ||
+ 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();
PHINode *PN = dyn_cast<PHINode>(I); ++I) {
unsigned Idx = PN->getBasicBlockIndex(SplitBB);
Value *V = PN->getIncomingValue(Idx);
+
// If the input is a PHI which already satisfies LCSSA, don't create
// a new one.
if (const PHINode *VP = dyn_cast<PHINode>(V))
if (VP->getParent() == SplitBB)
continue;
+
// Otherwise a new PHI is needed. Create one and populate it.
- PHINode *NewPN = PHINode::Create(PN->getType(), Preds.size(), "split",
- SplitBB->getTerminator());
+ PHINode *NewPN =
+ PHINode::Create(PN->getType(), Preds.size(), "split",
+ SplitBB->isLandingPad() ?
+ SplitBB->begin() : SplitBB->getTerminator());
for (unsigned i = 0, e = Preds.size(); i != e; ++i)
NewPN->addIncoming(V, Preds[i]);
+
// Update the original PHI.
PN->setIncomingValue(Idx, NewPN);
}
@@ -168,7 +173,8 @@ static void createPHIsForSplitLoopExit(ArrayRef<BasicBlock *> Preds,
///
BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
Pass *P, bool MergeIdenticalEdges,
- bool DontDeleteUselessPhis) {
+ bool DontDeleteUselessPhis,
+ bool SplitLandingPads) {
if (!isCriticalEdge(TI, SuccNum, MergeIdenticalEdges)) return 0;
assert(!isa<IndirectBrInst>(TI) &&
@@ -368,10 +374,19 @@ BasicBlock *llvm::SplitCriticalEdge(TerminatorInst *TI, unsigned SuccNum,
// getUniqueExitBlocks above because that depends on LoopSimplify
// form, which we're in the process of restoring!
if (!Preds.empty() && HasPredOutsideOfLoop) {
- BasicBlock *NewExitBB =
- SplitBlockPredecessors(Exit, Preds, "split", P);
- if (P->mustPreserveAnalysisID(LCSSAID))
- createPHIsForSplitLoopExit(Preds, NewExitBB, Exit);
+ if (!Exit->isLandingPad()) {
+ BasicBlock *NewExitBB =
+ SplitBlockPredecessors(Exit, Preds, "split", P);
+ if (P->mustPreserveAnalysisID(LCSSAID))
+ 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);
+ }
}
}
}
diff --git a/test/Transforms/LoopUnswitch/2012-04-30-LoopUnswitch-LPad-Crash.ll b/test/Transforms/LoopUnswitch/2012-04-30-LoopUnswitch-LPad-Crash.ll
new file mode 100644
index 0000000000..261876df2a
--- /dev/null
+++ b/test/Transforms/LoopUnswitch/2012-04-30-LoopUnswitch-LPad-Crash.ll
@@ -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}