diff --git a/include/llvm/Transforms/Utils/BasicBlockUtils.h b/include/llvm/Transforms/Utils/BasicBlockUtils.h index 867b9e43849..2f9dc54541b 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 7e485b8113d..930980f528a 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 0de3befa4e4..6b04e3d17b9 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 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(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(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 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(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 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 00000000000..261876df2aa --- /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}