@@ -201,6 +201,46 @@ static bool canSplitCallSite(CallSite CS) {
201
201
return CallSiteBB->canSplitPredecessors ();
202
202
}
203
203
204
+ static Instruction *cloneInstForMustTail (Instruction *I, Instruction *Before,
205
+ Value *V) {
206
+ Instruction *Copy = I->clone ();
207
+ Copy->setName (I->getName ());
208
+ Copy->insertBefore (Before);
209
+ if (V)
210
+ Copy->setOperand (0 , V);
211
+ return Copy;
212
+ }
213
+
214
+ // / Copy mandatory `musttail` return sequence that follows original `CI`, and
215
+ // / link it up to `NewCI` value instead:
216
+ // /
217
+ // / * (optional) `bitcast NewCI to ...`
218
+ // / * `ret bitcast or NewCI`
219
+ // /
220
+ // / Insert this sequence right before `SplitBB`'s terminator, which will be
221
+ // / cleaned up later in `splitCallSite` below.
222
+ static void copyMustTailReturn (BasicBlock *SplitBB, Instruction *CI,
223
+ Instruction *NewCI) {
224
+ bool IsVoid = SplitBB->getParent ()->getReturnType ()->isVoidTy ();
225
+ auto II = std::next (CI->getIterator ());
226
+
227
+ BitCastInst *BCI = dyn_cast<BitCastInst>(&*II);
228
+ if (BCI)
229
+ ++II;
230
+
231
+ ReturnInst *RI = dyn_cast<ReturnInst>(&*II);
232
+ assert (RI && " `musttail` call must be followed by `ret` instruction" );
233
+
234
+ TerminatorInst *TI = SplitBB->getTerminator ();
235
+ Value *V = NewCI;
236
+ if (BCI)
237
+ V = cloneInstForMustTail (BCI, TI, V);
238
+ cloneInstForMustTail (RI, TI, IsVoid ? nullptr : V);
239
+
240
+ // FIXME: remove TI here, `DuplicateInstructionsInSplitBetween` has a bug
241
+ // that prevents doing this now.
242
+ }
243
+
204
244
// / Return true if the CS is split into its new predecessors which are directly
205
245
// / hooked to each of its original predecessors pointed by PredBB1 and PredBB2.
206
246
// / CallInst1 and CallInst2 will be the new call-sites placed in the new
@@ -245,6 +285,7 @@ static void splitCallSite(CallSite CS, BasicBlock *PredBB1, BasicBlock *PredBB2,
245
285
Instruction *CallInst1, Instruction *CallInst2) {
246
286
Instruction *Instr = CS.getInstruction ();
247
287
BasicBlock *TailBB = Instr->getParent ();
288
+ bool IsMustTailCall = CS.isMustTailCall ();
248
289
assert (Instr == (TailBB->getFirstNonPHIOrDbg ()) && " Unexpected call-site" );
249
290
250
291
BasicBlock *SplitBlock1 =
@@ -276,9 +317,14 @@ static void splitCallSite(CallSite CS, BasicBlock *PredBB1, BasicBlock *PredBB2,
276
317
++ArgNo;
277
318
}
278
319
}
320
+ // Clone and place bitcast and return instructions before `TI`
321
+ if (IsMustTailCall) {
322
+ copyMustTailReturn (SplitBlock1, CS.getInstruction (), CallInst1);
323
+ copyMustTailReturn (SplitBlock2, CS.getInstruction (), CallInst2);
324
+ }
279
325
280
326
// Replace users of the original call with a PHI mering call-sites split.
281
- if (Instr->getNumUses ()) {
327
+ if (!IsMustTailCall && Instr->getNumUses ()) {
282
328
PHINode *PN = PHINode::Create (Instr->getType (), 2 , " phi.call" ,
283
329
TailBB->getFirstNonPHI ());
284
330
PN->addIncoming (CallInst1, SplitBlock1);
@@ -290,8 +336,25 @@ static void splitCallSite(CallSite CS, BasicBlock *PredBB1, BasicBlock *PredBB2,
290
336
<< " \n " );
291
337
DEBUG (dbgs () << " " << *CallInst2 << " in " << SplitBlock2->getName ()
292
338
<< " \n " );
293
- Instr-> eraseFromParent ();
339
+
294
340
NumCallSiteSplit++;
341
+
342
+ // FIXME: remove TI in `copyMustTailReturn`
343
+ if (IsMustTailCall) {
344
+ // Remove superfluous `br` terminators from the end of the Split blocks
345
+ // NOTE: Removing terminator removes the SplitBlock from the TailBB's
346
+ // predecessors. Therefore we must get complete list of Splits before
347
+ // attempting removal.
348
+ SmallVector<BasicBlock *, 2 > Splits (predecessors ((TailBB)));
349
+ assert (Splits.size () == 2 && " Expected exactly 2 splits!" );
350
+ for (unsigned i = 0 ; i < Splits.size (); i++)
351
+ Splits[i]->getTerminator ()->eraseFromParent ();
352
+
353
+ // Erase the tail block once done with musttail patching
354
+ TailBB->eraseFromParent ();
355
+ return ;
356
+ }
357
+ Instr->eraseFromParent ();
295
358
}
296
359
297
360
// Return true if the call-site has an argument which is a PHI with only
@@ -369,7 +432,17 @@ static bool doCallSiteSplitting(Function &F, TargetLibraryInfo &TLI) {
369
432
Function *Callee = CS.getCalledFunction ();
370
433
if (!Callee || Callee->isDeclaration ())
371
434
continue ;
435
+
436
+ // Successful musttail call-site splits result in erased CI and erased BB.
437
+ // Check if such path is possible before attempting the splitting.
438
+ bool IsMustTail = CS.isMustTailCall ();
439
+
372
440
Changed |= tryToSplitCallSite (CS);
441
+
442
+ // There're no interesting instructions after this. The call site
443
+ // itself might have been erased on splitting.
444
+ if (IsMustTail)
445
+ break ;
373
446
}
374
447
}
375
448
return Changed;
0 commit comments