Skip to content

Commit d81d9e8

Browse files
author
Sidharth Baveja
committed
[SplitEdge] Update SplitCriticalEdge to return a nullptr only when the edge is not critical
Summary: The function SplitCriticalEdge (called by SplitEdge) can return a nullptr in cases where the edge is a critical. SplitEdge uses SplitCriticalEdge assuming it can always split all critical edges, which is an incorrect assumption. The three cases where the function SplitCriticalEdge will return a nullptr is: 1. DestBB is an exception block 2. Options.IgnoreUnreachableDests is set to true and isa(DestBB->getFirstNonPHIOrDbgOrLifetime()) is not equal to a nullptr 3. LoopSimplify form must be preserved (Options.PreserveLoopSimplify is true) and it cannot be maintained for a loop due to indirect branches For each of these situations they are handled in the following way: 1. Modified the function ehAwareSplitEdge originally from llvm/lib/Transforms/Coroutines/CoroFrame.cpp to handle the cases when the DestBB is an exception block. This function is called directly in SplitEdge. SplitEdge does not call SplitCriticalEdge in this case 2. Options.IgnoreUnreachableDests is set to false by default, so this situation does not apply. 3. Return a nullptr in this situation since the SplitCriticalEdge also returned nullptr. Nothing we can do in this case. Reviewed By: asbirlea Differential Revision:https://reviews.llvm.org/D94619
1 parent c060945 commit d81d9e8

File tree

5 files changed

+351
-111
lines changed

5 files changed

+351
-111
lines changed

llvm/include/llvm/Transforms/Utils/BasicBlockUtils.h

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,13 @@ struct CriticalEdgeSplittingOptions {
179179
}
180180
};
181181

182+
/// When a loop exit edge is split, LCSSA form may require new PHIs in the new
183+
/// exit block. This function inserts the new PHIs, as needed. Preds is a list
184+
/// of preds inside the loop, SplitBB is the new loop exit block, and DestBB is
185+
/// the old loop exit, now the successor of SplitBB.
186+
void createPHIsForSplitLoopExit(ArrayRef<BasicBlock *> Preds,
187+
BasicBlock *SplitBB, BasicBlock *DestBB);
188+
182189
/// If this edge is a critical edge, insert a new node to split the critical
183190
/// edge. This will update the analyses passed in through the option struct.
184191
/// This returns the new block if the edge was split, null otherwise.
@@ -200,6 +207,13 @@ BasicBlock *SplitCriticalEdge(Instruction *TI, unsigned SuccNum,
200207
CriticalEdgeSplittingOptions(),
201208
const Twine &BBName = "");
202209

210+
/// If it is known that an edge is critical, SplitKnownCriticalEdge can be
211+
/// called directly, rather than calling SplitCriticalEdge first.
212+
BasicBlock *SplitKnownCriticalEdge(Instruction *TI, unsigned SuccNum,
213+
const CriticalEdgeSplittingOptions &Options =
214+
CriticalEdgeSplittingOptions(),
215+
const Twine &BBName = "");
216+
203217
inline BasicBlock *
204218
SplitCriticalEdge(BasicBlock *BB, succ_iterator SI,
205219
const CriticalEdgeSplittingOptions &Options =
@@ -253,6 +267,23 @@ BasicBlock *SplitEdge(BasicBlock *From, BasicBlock *To,
253267
MemorySSAUpdater *MSSAU = nullptr,
254268
const Twine &BBName = "");
255269

270+
/// Sets the unwind edge of an instruction to a particular successor.
271+
void setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ);
272+
273+
/// Replaces all uses of OldPred with the NewPred block in all PHINodes in a
274+
/// block.
275+
void updatePhiNodes(BasicBlock *DestBB, BasicBlock *OldPred,
276+
BasicBlock *NewPred, PHINode *Until = nullptr);
277+
278+
/// Split the edge connect the specficed blocks in the case that \p Succ is an
279+
/// Exception Handling Block
280+
BasicBlock *ehAwareSplitEdge(BasicBlock *BB, BasicBlock *Succ,
281+
LandingPadInst *OriginalPad = nullptr,
282+
PHINode *LandingPadReplacement = nullptr,
283+
const CriticalEdgeSplittingOptions &Options =
284+
CriticalEdgeSplittingOptions(),
285+
const Twine &BBName = "");
286+
256287
/// Split the specified block at the specified instruction.
257288
///
258289
/// If \p Before is true, splitBlockBefore handles the block

llvm/lib/Transforms/Coroutines/CoroFrame.cpp

Lines changed: 0 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -1358,77 +1358,6 @@ static Instruction *insertSpills(const FrameDataInfo &FrameData,
13581358
return FramePtr;
13591359
}
13601360

1361-
// Sets the unwind edge of an instruction to a particular successor.
1362-
static void setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ) {
1363-
if (auto *II = dyn_cast<InvokeInst>(TI))
1364-
II->setUnwindDest(Succ);
1365-
else if (auto *CS = dyn_cast<CatchSwitchInst>(TI))
1366-
CS->setUnwindDest(Succ);
1367-
else if (auto *CR = dyn_cast<CleanupReturnInst>(TI))
1368-
CR->setUnwindDest(Succ);
1369-
else
1370-
llvm_unreachable("unexpected terminator instruction");
1371-
}
1372-
1373-
// Replaces all uses of OldPred with the NewPred block in all PHINodes in a
1374-
// block.
1375-
static void updatePhiNodes(BasicBlock *DestBB, BasicBlock *OldPred,
1376-
BasicBlock *NewPred, PHINode *Until = nullptr) {
1377-
unsigned BBIdx = 0;
1378-
for (BasicBlock::iterator I = DestBB->begin(); isa<PHINode>(I); ++I) {
1379-
PHINode *PN = cast<PHINode>(I);
1380-
1381-
// We manually update the LandingPadReplacement PHINode and it is the last
1382-
// PHI Node. So, if we find it, we are done.
1383-
if (Until == PN)
1384-
break;
1385-
1386-
// Reuse the previous value of BBIdx if it lines up. In cases where we
1387-
// have multiple phi nodes with *lots* of predecessors, this is a speed
1388-
// win because we don't have to scan the PHI looking for TIBB. This
1389-
// happens because the BB list of PHI nodes are usually in the same
1390-
// order.
1391-
if (PN->getIncomingBlock(BBIdx) != OldPred)
1392-
BBIdx = PN->getBasicBlockIndex(OldPred);
1393-
1394-
assert(BBIdx != (unsigned)-1 && "Invalid PHI Index!");
1395-
PN->setIncomingBlock(BBIdx, NewPred);
1396-
}
1397-
}
1398-
1399-
// Uses SplitEdge unless the successor block is an EHPad, in which case do EH
1400-
// specific handling.
1401-
static BasicBlock *ehAwareSplitEdge(BasicBlock *BB, BasicBlock *Succ,
1402-
LandingPadInst *OriginalPad,
1403-
PHINode *LandingPadReplacement) {
1404-
auto *PadInst = Succ->getFirstNonPHI();
1405-
if (!LandingPadReplacement && !PadInst->isEHPad())
1406-
return SplitEdge(BB, Succ);
1407-
1408-
auto *NewBB = BasicBlock::Create(BB->getContext(), "", BB->getParent(), Succ);
1409-
setUnwindEdgeTo(BB->getTerminator(), NewBB);
1410-
updatePhiNodes(Succ, BB, NewBB, LandingPadReplacement);
1411-
1412-
if (LandingPadReplacement) {
1413-
auto *NewLP = OriginalPad->clone();
1414-
auto *Terminator = BranchInst::Create(Succ, NewBB);
1415-
NewLP->insertBefore(Terminator);
1416-
LandingPadReplacement->addIncoming(NewLP, NewBB);
1417-
return NewBB;
1418-
}
1419-
Value *ParentPad = nullptr;
1420-
if (auto *FuncletPad = dyn_cast<FuncletPadInst>(PadInst))
1421-
ParentPad = FuncletPad->getParentPad();
1422-
else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(PadInst))
1423-
ParentPad = CatchSwitch->getParentPad();
1424-
else
1425-
llvm_unreachable("handling for other EHPads not implemented yet");
1426-
1427-
auto *NewCleanupPad = CleanupPadInst::Create(ParentPad, {}, "", NewBB);
1428-
CleanupReturnInst::Create(NewCleanupPad, Succ, NewBB);
1429-
return NewBB;
1430-
}
1431-
14321361
// Moves the values in the PHIs in SuccBB that correspong to PredBB into a new
14331362
// PHI in InsertedBB.
14341363
static void movePHIValuesToInsertedBlock(BasicBlock *SuccBB,

llvm/lib/Transforms/Utils/BasicBlockUtils.cpp

Lines changed: 225 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -501,13 +501,20 @@ BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, DominatorTree *DT,
501501
const Twine &BBName) {
502502
unsigned SuccNum = GetSuccessorNumber(BB, Succ);
503503

504-
// If this is a critical edge, let SplitCriticalEdge do it.
505504
Instruction *LatchTerm = BB->getTerminator();
506-
if (SplitCriticalEdge(
507-
LatchTerm, SuccNum,
508-
CriticalEdgeSplittingOptions(DT, LI, MSSAU).setPreserveLCSSA(),
509-
BBName))
510-
return LatchTerm->getSuccessor(SuccNum);
505+
506+
CriticalEdgeSplittingOptions Options =
507+
CriticalEdgeSplittingOptions(DT, LI, MSSAU).setPreserveLCSSA();
508+
509+
if ((isCriticalEdge(LatchTerm, SuccNum, Options.MergeIdenticalEdges))) {
510+
// If it is a critical edge, and the succesor is an exception block, handle
511+
// the split edge logic in this specific function
512+
if (Succ->isEHPad())
513+
return ehAwareSplitEdge(BB, Succ, nullptr, nullptr, Options, BBName);
514+
515+
// If this is a critical edge, let SplitKnownCriticalEdge do it.
516+
return SplitKnownCriticalEdge(LatchTerm, SuccNum, Options, BBName);
517+
}
511518

512519
// If the edge isn't critical, then BB has a single successor or Succ has a
513520
// single pred. Split the block.
@@ -527,6 +534,218 @@ BasicBlock *llvm::SplitEdge(BasicBlock *BB, BasicBlock *Succ, DominatorTree *DT,
527534
return SplitBlock(BB, BB->getTerminator(), DT, LI, MSSAU, BBName);
528535
}
529536

537+
void llvm::setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ) {
538+
if (auto *II = dyn_cast<InvokeInst>(TI))
539+
II->setUnwindDest(Succ);
540+
else if (auto *CS = dyn_cast<CatchSwitchInst>(TI))
541+
CS->setUnwindDest(Succ);
542+
else if (auto *CR = dyn_cast<CleanupReturnInst>(TI))
543+
CR->setUnwindDest(Succ);
544+
else
545+
llvm_unreachable("unexpected terminator instruction");
546+
}
547+
548+
void llvm::updatePhiNodes(BasicBlock *DestBB, BasicBlock *OldPred,
549+
BasicBlock *NewPred, PHINode *Until) {
550+
int BBIdx = 0;
551+
for (PHINode &PN : DestBB->phis()) {
552+
// We manually update the LandingPadReplacement PHINode and it is the last
553+
// PHI Node. So, if we find it, we are done.
554+
if (Until == &PN)
555+
break;
556+
557+
// Reuse the previous value of BBIdx if it lines up. In cases where we
558+
// have multiple phi nodes with *lots* of predecessors, this is a speed
559+
// win because we don't have to scan the PHI looking for TIBB. This
560+
// happens because the BB list of PHI nodes are usually in the same
561+
// order.
562+
if (PN.getIncomingBlock(BBIdx) != OldPred)
563+
BBIdx = PN.getBasicBlockIndex(OldPred);
564+
565+
assert(BBIdx != -1 && "Invalid PHI Index!");
566+
PN.setIncomingBlock(BBIdx, NewPred);
567+
}
568+
}
569+
570+
BasicBlock *llvm::ehAwareSplitEdge(BasicBlock *BB, BasicBlock *Succ,
571+
LandingPadInst *OriginalPad,
572+
PHINode *LandingPadReplacement,
573+
const CriticalEdgeSplittingOptions &Options,
574+
const Twine &BBName) {
575+
576+
auto *PadInst = Succ->getFirstNonPHI();
577+
if (!LandingPadReplacement && !PadInst->isEHPad())
578+
return SplitEdge(BB, Succ, Options.DT, Options.LI, Options.MSSAU, BBName);
579+
580+
auto *LI = Options.LI;
581+
SmallVector<BasicBlock *, 4> LoopPreds;
582+
// Check if extra modifications will be required to preserve loop-simplify
583+
// form after splitting. If it would require splitting blocks with IndirectBr
584+
// terminators, bail out if preserving loop-simplify form is requested.
585+
if (Options.PreserveLoopSimplify && LI) {
586+
if (Loop *BBLoop = LI->getLoopFor(BB)) {
587+
588+
// The only way that we can break LoopSimplify form by splitting a
589+
// critical edge is when there exists some edge from BBLoop to Succ *and*
590+
// the only edge into Succ from outside of BBLoop is that of NewBB after
591+
// the split. If the first isn't true, then LoopSimplify still holds,
592+
// NewBB is the new exit block and it has no non-loop predecessors. If the
593+
// second isn't true, then Succ was not in LoopSimplify form prior to
594+
// the split as it had a non-loop predecessor. In both of these cases,
595+
// the predecessor must be directly in BBLoop, not in a subloop, or again
596+
// LoopSimplify doesn't hold.
597+
for (BasicBlock *P : predecessors(Succ)) {
598+
if (P == BB)
599+
continue; // The new block is known.
600+
if (LI->getLoopFor(P) != BBLoop) {
601+
// Loop is not in LoopSimplify form, no need to re simplify after
602+
// splitting edge.
603+
LoopPreds.clear();
604+
break;
605+
}
606+
LoopPreds.push_back(P);
607+
}
608+
// Loop-simplify form can be preserved, if we can split all in-loop
609+
// predecessors.
610+
if (any_of(LoopPreds, [](BasicBlock *Pred) {
611+
return isa<IndirectBrInst>(Pred->getTerminator());
612+
})) {
613+
return nullptr;
614+
}
615+
}
616+
}
617+
618+
auto *NewBB =
619+
BasicBlock::Create(BB->getContext(), BBName, BB->getParent(), Succ);
620+
setUnwindEdgeTo(BB->getTerminator(), NewBB);
621+
updatePhiNodes(Succ, BB, NewBB, LandingPadReplacement);
622+
623+
if (LandingPadReplacement) {
624+
auto *NewLP = OriginalPad->clone();
625+
auto *Terminator = BranchInst::Create(Succ, NewBB);
626+
NewLP->insertBefore(Terminator);
627+
LandingPadReplacement->addIncoming(NewLP, NewBB);
628+
} else {
629+
Value *ParentPad = nullptr;
630+
if (auto *FuncletPad = dyn_cast<FuncletPadInst>(PadInst))
631+
ParentPad = FuncletPad->getParentPad();
632+
else if (auto *CatchSwitch = dyn_cast<CatchSwitchInst>(PadInst))
633+
ParentPad = CatchSwitch->getParentPad();
634+
else if (auto *CleanupPad = dyn_cast<CleanupPadInst>(PadInst))
635+
ParentPad = CleanupPad->getParentPad();
636+
else if (auto *LandingPad = dyn_cast<LandingPadInst>(PadInst))
637+
ParentPad = LandingPad->getParent();
638+
else
639+
llvm_unreachable("handling for other EHPads not implemented yet");
640+
641+
auto *NewCleanupPad = CleanupPadInst::Create(ParentPad, {}, BBName, NewBB);
642+
CleanupReturnInst::Create(NewCleanupPad, Succ, NewBB);
643+
}
644+
645+
auto *DT = Options.DT;
646+
auto *MSSAU = Options.MSSAU;
647+
if (!DT && !LI)
648+
return NewBB;
649+
650+
if (DT) {
651+
DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
652+
SmallVector<DominatorTree::UpdateType, 3> Updates;
653+
654+
Updates.push_back({DominatorTree::Insert, BB, NewBB});
655+
Updates.push_back({DominatorTree::Insert, NewBB, Succ});
656+
Updates.push_back({DominatorTree::Delete, BB, Succ});
657+
658+
DTU.applyUpdates(Updates);
659+
DTU.flush();
660+
661+
if (MSSAU) {
662+
MSSAU->applyUpdates(Updates, *DT);
663+
if (VerifyMemorySSA)
664+
MSSAU->getMemorySSA()->verifyMemorySSA();
665+
}
666+
}
667+
668+
if (LI) {
669+
if (Loop *BBLoop = LI->getLoopFor(BB)) {
670+
// If one or the other blocks were not in a loop, the new block is not
671+
// either, and thus LI doesn't need to be updated.
672+
if (Loop *SuccLoop = LI->getLoopFor(Succ)) {
673+
if (BBLoop == SuccLoop) {
674+
// Both in the same loop, the NewBB joins loop.
675+
SuccLoop->addBasicBlockToLoop(NewBB, *LI);
676+
} else if (BBLoop->contains(SuccLoop)) {
677+
// Edge from an outer loop to an inner loop. Add to the outer loop.
678+
BBLoop->addBasicBlockToLoop(NewBB, *LI);
679+
} else if (SuccLoop->contains(BBLoop)) {
680+
// Edge from an inner loop to an outer loop. Add to the outer loop.
681+
SuccLoop->addBasicBlockToLoop(NewBB, *LI);
682+
} else {
683+
// Edge from two loops with no containment relation. Because these
684+
// are natural loops, we know that the destination block must be the
685+
// header of its loop (adding a branch into a loop elsewhere would
686+
// create an irreducible loop).
687+
assert(SuccLoop->getHeader() == Succ &&
688+
"Should not create irreducible loops!");
689+
if (Loop *P = SuccLoop->getParentLoop())
690+
P->addBasicBlockToLoop(NewBB, *LI);
691+
}
692+
}
693+
694+
// If BB is in a loop and Succ is outside of that loop, we may need to
695+
// update LoopSimplify form and LCSSA form.
696+
if (!BBLoop->contains(Succ)) {
697+
assert(!BBLoop->contains(NewBB) &&
698+
"Split point for loop exit is contained in loop!");
699+
700+
// Update LCSSA form in the newly created exit block.
701+
if (Options.PreserveLCSSA) {
702+
createPHIsForSplitLoopExit(BB, NewBB, Succ);
703+
}
704+
705+
if (!LoopPreds.empty()) {
706+
BasicBlock *NewExitBB = SplitBlockPredecessors(
707+
Succ, LoopPreds, "split", DT, LI, MSSAU, Options.PreserveLCSSA);
708+
if (Options.PreserveLCSSA)
709+
createPHIsForSplitLoopExit(LoopPreds, NewExitBB, Succ);
710+
}
711+
}
712+
}
713+
}
714+
715+
return NewBB;
716+
}
717+
718+
void llvm::createPHIsForSplitLoopExit(ArrayRef<BasicBlock *> Preds,
719+
BasicBlock *SplitBB, BasicBlock *DestBB) {
720+
// SplitBB shouldn't have anything non-trivial in it yet.
721+
assert((SplitBB->getFirstNonPHI() == SplitBB->getTerminator() ||
722+
SplitBB->isLandingPad()) &&
723+
"SplitBB has non-PHI nodes!");
724+
725+
// For each PHI in the destination block.
726+
for (PHINode &PN : DestBB->phis()) {
727+
int Idx = PN.getBasicBlockIndex(SplitBB);
728+
assert(Idx >= 0 && "Invalid Block Index");
729+
Value *V = PN.getIncomingValue(Idx);
730+
731+
// If the input is a PHI which already satisfies LCSSA, don't create
732+
// a new one.
733+
if (const PHINode *VP = dyn_cast<PHINode>(V))
734+
if (VP->getParent() == SplitBB)
735+
continue;
736+
737+
// Otherwise a new PHI is needed. Create one and populate it.
738+
PHINode *NewPN = PHINode::Create(
739+
PN.getType(), Preds.size(), "split",
740+
SplitBB->isLandingPad() ? &SplitBB->front() : SplitBB->getTerminator());
741+
for (BasicBlock *BB : Preds)
742+
NewPN->addIncoming(V, BB);
743+
744+
// Update the original PHI.
745+
PN.setIncomingValue(Idx, NewPN);
746+
}
747+
}
748+
530749
unsigned
531750
llvm::SplitAllCriticalEdges(Function &F,
532751
const CriticalEdgeSplittingOptions &Options) {

0 commit comments

Comments
 (0)