@@ -1052,15 +1052,14 @@ static void setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ) {
10521052// Replaces all uses of OldPred with the NewPred block in all PHINodes in a
10531053// block.
10541054static void updatePhiNodes (BasicBlock *DestBB, BasicBlock *OldPred,
1055- BasicBlock *NewPred,
1056- PHINode *LandingPadReplacement) {
1055+ BasicBlock *NewPred, PHINode *Until = nullptr ) {
10571056 unsigned BBIdx = 0 ;
10581057 for (BasicBlock::iterator I = DestBB->begin (); isa<PHINode>(I); ++I) {
10591058 PHINode *PN = cast<PHINode>(I);
10601059
10611060 // We manually update the LandingPadReplacement PHINode and it is the last
10621061 // PHI Node. So, if we find it, we are done.
1063- if (LandingPadReplacement == PN)
1062+ if (Until == PN)
10641063 break ;
10651064
10661065 // Reuse the previous value of BBIdx if it lines up. In cases where we
@@ -1109,6 +1108,102 @@ static BasicBlock *ehAwareSplitEdge(BasicBlock *BB, BasicBlock *Succ,
11091108 return NewBB;
11101109}
11111110
1111+ // Moves the values in the PHIs in SuccBB that correspong to PredBB into a new
1112+ // PHI in InsertedBB.
1113+ static void movePHIValuesToInsertedBlock (BasicBlock *SuccBB,
1114+ BasicBlock *InsertedBB,
1115+ BasicBlock *PredBB,
1116+ PHINode *UntilPHI = nullptr ) {
1117+ auto *PN = cast<PHINode>(&SuccBB->front ());
1118+ do {
1119+ int Index = PN->getBasicBlockIndex (InsertedBB);
1120+ Value *V = PN->getIncomingValue (Index);
1121+ PHINode *InputV = PHINode::Create (
1122+ V->getType (), 1 , V->getName () + Twine (" ." ) + SuccBB->getName (),
1123+ &InsertedBB->front ());
1124+ InputV->addIncoming (V, PredBB);
1125+ PN->setIncomingValue (Index, InputV);
1126+ PN = dyn_cast<PHINode>(PN->getNextNode ());
1127+ } while (PN != UntilPHI);
1128+ }
1129+
1130+ // Rewrites the PHI Nodes in a cleanuppad.
1131+ static void rewritePHIsForCleanupPad (BasicBlock *CleanupPadBB,
1132+ CleanupPadInst *CleanupPad) {
1133+ // For every incoming edge to a CleanupPad we will create a new block holding
1134+ // all incoming values in single-value PHI nodes. We will then create another
1135+ // block to act as a dispather (as all unwind edges for related EH blocks
1136+ // must be the same).
1137+ //
1138+ // cleanuppad:
1139+ // %2 = phi i32[%0, %catchswitch], [%1, %catch.1]
1140+ // %3 = cleanuppad within none []
1141+ //
1142+ // It will create:
1143+ //
1144+ // cleanuppad.corodispatch
1145+ // %2 = phi i8[0, %catchswitch], [1, %catch.1]
1146+ // %3 = cleanuppad within none []
1147+ // switch i8 % 2, label %unreachable
1148+ // [i8 0, label %cleanuppad.from.catchswitch
1149+ // i8 1, label %cleanuppad.from.catch.1]
1150+ // cleanuppad.from.catchswitch:
1151+ // %4 = phi i32 [%0, %catchswitch]
1152+ // br %label cleanuppad
1153+ // cleanuppad.from.catch.1:
1154+ // %6 = phi i32 [%1, %catch.1]
1155+ // br %label cleanuppad
1156+ // cleanuppad:
1157+ // %8 = phi i32 [%4, %cleanuppad.from.catchswitch],
1158+ // [%6, %cleanuppad.from.catch.1]
1159+
1160+ // Unreachable BB, in case switching on an invalid value in the dispatcher.
1161+ auto *UnreachBB = BasicBlock::Create (
1162+ CleanupPadBB->getContext (), " unreachable" , CleanupPadBB->getParent ());
1163+ IRBuilder<> Builder (UnreachBB);
1164+ Builder.CreateUnreachable ();
1165+
1166+ // Create a new cleanuppad which will be the dispatcher.
1167+ auto *NewCleanupPadBB =
1168+ BasicBlock::Create (CleanupPadBB->getContext (),
1169+ CleanupPadBB->getName () + Twine (" .corodispatch" ),
1170+ CleanupPadBB->getParent (), CleanupPadBB);
1171+ Builder.SetInsertPoint (NewCleanupPadBB);
1172+ auto *SwitchType = Builder.getInt8Ty ();
1173+ auto *SetDispatchValuePN =
1174+ Builder.CreatePHI (SwitchType, pred_size (CleanupPadBB));
1175+ CleanupPad->removeFromParent ();
1176+ CleanupPad->insertAfter (SetDispatchValuePN);
1177+ auto *SwitchOnDispatch = Builder.CreateSwitch (SetDispatchValuePN, UnreachBB,
1178+ pred_size (CleanupPadBB));
1179+
1180+ int SwitchIndex = 0 ;
1181+ SmallVector<BasicBlock *, 8 > Preds (pred_begin (CleanupPadBB),
1182+ pred_end (CleanupPadBB));
1183+ for (BasicBlock *Pred : Preds) {
1184+ // Create a new cleanuppad and move the PHI values to there.
1185+ auto *CaseBB = BasicBlock::Create (CleanupPadBB->getContext (),
1186+ CleanupPadBB->getName () +
1187+ Twine (" .from." ) + Pred->getName (),
1188+ CleanupPadBB->getParent (), CleanupPadBB);
1189+ updatePhiNodes (CleanupPadBB, Pred, CaseBB);
1190+ CaseBB->setName (CleanupPadBB->getName () + Twine (" .from." ) +
1191+ Pred->getName ());
1192+ Builder.SetInsertPoint (CaseBB);
1193+ Builder.CreateBr (CleanupPadBB);
1194+ movePHIValuesToInsertedBlock (CleanupPadBB, CaseBB, NewCleanupPadBB);
1195+
1196+ // Update this Pred to the new unwind point.
1197+ setUnwindEdgeTo (Pred->getTerminator (), NewCleanupPadBB);
1198+
1199+ // Setup the switch in the dispatcher.
1200+ auto *SwitchConstant = ConstantInt::get (SwitchType, SwitchIndex);
1201+ SetDispatchValuePN->addIncoming (SwitchConstant, Pred);
1202+ SwitchOnDispatch->addCase (SwitchConstant, CaseBB);
1203+ SwitchIndex++;
1204+ }
1205+ }
1206+
11121207static void rewritePHIs (BasicBlock &BB) {
11131208 // For every incoming edge we will create a block holding all
11141209 // incoming values in a single PHI nodes.
@@ -1131,6 +1226,23 @@ static void rewritePHIs(BasicBlock &BB) {
11311226 // TODO: Simplify PHINodes in the basic block to remove duplicate
11321227 // predecessors.
11331228
1229+ // Special case for CleanupPad: all EH blocks must have the same unwind edge
1230+ // so we need to create an additional "dispatcher" block.
1231+ if (auto *CleanupPad =
1232+ dyn_cast_or_null<CleanupPadInst>(BB.getFirstNonPHI ())) {
1233+ SmallVector<BasicBlock *, 8 > Preds (pred_begin (&BB), pred_end (&BB));
1234+ for (BasicBlock *Pred : Preds) {
1235+ if (CatchSwitchInst *CS =
1236+ dyn_cast<CatchSwitchInst>(Pred->getTerminator ())) {
1237+ // CleanupPad with a CatchSwitch predecessor: therefore this is an
1238+ // unwind destination that needs to be handle specially.
1239+ assert (CS->getUnwindDest () == &BB);
1240+ rewritePHIsForCleanupPad (&BB, CleanupPad);
1241+ return ;
1242+ }
1243+ }
1244+ }
1245+
11341246 LandingPadInst *LandingPad = nullptr ;
11351247 PHINode *ReplPHI = nullptr ;
11361248 if ((LandingPad = dyn_cast_or_null<LandingPadInst>(BB.getFirstNonPHI ()))) {
@@ -1148,18 +1260,10 @@ static void rewritePHIs(BasicBlock &BB) {
11481260 for (BasicBlock *Pred : Preds) {
11491261 auto *IncomingBB = ehAwareSplitEdge (Pred, &BB, LandingPad, ReplPHI);
11501262 IncomingBB->setName (BB.getName () + Twine (" .from." ) + Pred->getName ());
1151- auto *PN = cast<PHINode>(&BB.front ());
1152- do {
1153- int Index = PN->getBasicBlockIndex (IncomingBB);
1154- Value *V = PN->getIncomingValue (Index);
1155- PHINode *InputV = PHINode::Create (
1156- V->getType (), 1 , V->getName () + Twine (" ." ) + BB.getName (),
1157- &IncomingBB->front ());
1158- InputV->addIncoming (V, Pred);
1159- PN->setIncomingValue (Index, InputV);
1160- PN = dyn_cast<PHINode>(PN->getNextNode ());
1161- } while (PN != ReplPHI); // ReplPHI is either null or the PHI that replaced
1162- // the landing pad.
1263+
1264+ // Stop the moving of values at ReplPHI, as this is either null or the PHI
1265+ // that replaced the landing pad.
1266+ movePHIValuesToInsertedBlock (&BB, IncomingBB, Pred, ReplPHI);
11631267 }
11641268
11651269 if (LandingPad) {
0 commit comments