@@ -1052,15 +1052,14 @@ static void setUnwindEdgeTo(Instruction *TI, BasicBlock *Succ) {
1052
1052
// Replaces all uses of OldPred with the NewPred block in all PHINodes in a
1053
1053
// block.
1054
1054
static void updatePhiNodes (BasicBlock *DestBB, BasicBlock *OldPred,
1055
- BasicBlock *NewPred,
1056
- PHINode *LandingPadReplacement) {
1055
+ BasicBlock *NewPred, PHINode *Until = nullptr ) {
1057
1056
unsigned BBIdx = 0 ;
1058
1057
for (BasicBlock::iterator I = DestBB->begin (); isa<PHINode>(I); ++I) {
1059
1058
PHINode *PN = cast<PHINode>(I);
1060
1059
1061
1060
// We manually update the LandingPadReplacement PHINode and it is the last
1062
1061
// PHI Node. So, if we find it, we are done.
1063
- if (LandingPadReplacement == PN)
1062
+ if (Until == PN)
1064
1063
break ;
1065
1064
1066
1065
// 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,
1109
1108
return NewBB;
1110
1109
}
1111
1110
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
+
1112
1207
static void rewritePHIs (BasicBlock &BB) {
1113
1208
// For every incoming edge we will create a block holding all
1114
1209
// incoming values in a single PHI nodes.
@@ -1131,6 +1226,23 @@ static void rewritePHIs(BasicBlock &BB) {
1131
1226
// TODO: Simplify PHINodes in the basic block to remove duplicate
1132
1227
// predecessors.
1133
1228
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
+
1134
1246
LandingPadInst *LandingPad = nullptr ;
1135
1247
PHINode *ReplPHI = nullptr ;
1136
1248
if ((LandingPad = dyn_cast_or_null<LandingPadInst>(BB.getFirstNonPHI ()))) {
@@ -1148,18 +1260,10 @@ static void rewritePHIs(BasicBlock &BB) {
1148
1260
for (BasicBlock *Pred : Preds) {
1149
1261
auto *IncomingBB = ehAwareSplitEdge (Pred, &BB, LandingPad, ReplPHI);
1150
1262
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);
1163
1267
}
1164
1268
1165
1269
if (LandingPad) {
0 commit comments