Skip to content

Instantly share code, notes, and snippets.

@indutny

indutny/1.diff Secret

Created February 24, 2018 07:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save indutny/240c33522563ebd633613a903479d5e6 to your computer and use it in GitHub Desktop.
Save indutny/240c33522563ebd633613a903479d5e6 to your computer and use it in GitHub Desktop.
diff --git a/lib/Transforms/Scalar/CallSiteSplitting.cpp b/lib/Transforms/Scalar/CallSiteSplitting.cpp
index 2e841b2ac94..6ea74218886 100644
--- a/lib/Transforms/Scalar/CallSiteSplitting.cpp
+++ b/lib/Transforms/Scalar/CallSiteSplitting.cpp
@@ -209,8 +209,6 @@ static bool canSplitCallSite(CallSite CS, TargetTransformInfo &TTI) {
return CallSiteBB->canSplitPredecessors();
}
-/// Return true if the CS is split into its new predecessors.
-///
/// For each (predecessor, conditions from predecessors) pair, it will split the
/// basic block containing the call site, hook it up to the predecessor and
/// replace the call instruction with new call instructions, which contain
@@ -255,12 +253,25 @@ static bool canSplitCallSite(CallSite CS, TargetTransformInfo &TTI) {
static void splitCallSite(
CallSite CS,
const SmallVectorImpl<std::pair<BasicBlock *, ConditionsTy>> &Preds) {
+ bool IsMustTail = CS.isMustTailCall();
Instruction *Instr = CS.getInstruction();
BasicBlock *TailBB = Instr->getParent();
PHINode *CallPN = nullptr;
- if (Instr->getNumUses())
+
+ Instruction *StopAt;
+ if (IsMustTail) {
+ // We need to copy everything including the terminator of the Tail block,
+ // since musttail must be followed by optional bitcast and ret.
+ //
+ StopAt = new UnreachableInst(TailBB->getContext(), TailBB);
+
+ // musttail call results are used just once - no need to create phi.
+ } else if (Instr->getNumUses()) {
CallPN = PHINode::Create(Instr->getType(), Preds.size(), "phi.call");
+ StopAt = &*std::next(Instr->getIterator());
+ }
+
DEBUG(dbgs() << "split call-site : " << *Instr << " into \n");
@@ -271,11 +282,17 @@ static void splitCallSite(
for (unsigned i = 0; i < Preds.size(); i++) {
BasicBlock *PredBB = Preds[i].first;
BasicBlock *SplitBlock = DuplicateInstructionsInSplitBetween(
- TailBB, PredBB, &*std::next(Instr->getIterator()), ValueToValueMaps[i]);
+ TailBB, PredBB, StopAt, ValueToValueMaps[i]);
assert(SplitBlock && "Unexpected new basic block split.");
- Instruction *NewCI =
- &*std::prev(SplitBlock->getTerminator()->getIterator());
+ Instruction *NewCI;
+
+ if (IsMustTail) {
+ NewCI = dyn_cast<Instruction>(&*ValueToValueMaps[i][Instr]);
+ SplitBlock->getTerminator()->removeFromParent();
+ } else {
+ NewCI = &*std::prev(SplitBlock->getTerminator()->getIterator());
+ }
CallSite NewCS(NewCI);
addConditions(NewCS, Preds[i].second);
@@ -309,7 +326,7 @@ static void splitCallSite(
// instruction, so we do not end up deleting them. By using reverse-order, we
// do not introduce unnecessary PHI nodes for def-use chains from the call
// instruction to the beginning of the block.
- auto I = Instr->getReverseIterator();
+ auto I = (&*std::prev(StopAt->getIterator()))->getReverseIterator();
while (I != TailBB->rend()) {
Instruction *CurrentI = &*I++;
if (!CurrentI->use_empty()) {
@@ -330,6 +347,9 @@ static void splitCallSite(
break;
}
+ if (IsMustTail)
+ TailBB->eraseFromParent();
+
NumCallSiteSplit++;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment