diff options
author | Saleem Abdulrasool <compnerd@compnerd.org> | 2018-03-12 21:46:09 +0000 |
---|---|---|
committer | Saleem Abdulrasool <compnerd@compnerd.org> | 2018-03-12 21:46:09 +0000 |
commit | 8b342680bf62722e5099074e8bd23491c71d92b3 (patch) | |
tree | 5507c01b3b0e4a6ccf1ead1eee5d0a910fcf78b2 /llvm/lib/Transforms/ObjCARC | |
parent | 5b034c83d655f9dcc7a35bb82d34ac7a2b44db6f (diff) | |
download | bcm5719-llvm-8b342680bf62722e5099074e8bd23491c71d92b3.tar.gz bcm5719-llvm-8b342680bf62722e5099074e8bd23491c71d92b3.zip |
ObjCARC: teach the cloner about funclets
In the case that the CallInst that is being moved has an associated
operand bundle which is a funclet, the move will construct an invalid
instruction. The new site will have a different token and needs to be
reassociated with the new instruction.
Unfortunately, there is no way to alter the bundle after the
construction of the instruction. Replace the call instruction cloning
with a custom helper to clone the instruction and reassociate the
funclet token.
llvm-svn: 327336
Diffstat (limited to 'llvm/lib/Transforms/ObjCARC')
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 37 |
1 files changed, 36 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp index ecec85444b1..52a31a3c7fb 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -38,6 +38,7 @@ #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" +#include "llvm/Analysis/EHPersonalities.h" #include "llvm/Analysis/ObjCARCAliasAnalysis.h" #include "llvm/Analysis/ObjCARCAnalysisUtils.h" #include "llvm/Analysis/ObjCARCInstKind.h" @@ -684,6 +685,34 @@ void ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, DEBUG(dbgs() << "New: " << *AutoreleaseRV << "\n"); } +namespace { +Instruction * +CloneCallInstForBB(Instruction &I, BasicBlock &BB, + DenseMap<BasicBlock *, ColorVector> &BlockColors) { + auto *CI = dyn_cast<CallInst>(&I); + assert(CI && "CloneCallInst must receive a CallInst"); + + SmallVector<OperandBundleDef, 1> OpBundles; + for (unsigned I = 0, E = CI->getNumOperandBundles(); I != E; ++I) { + auto Bundle = CI->getOperandBundleAt(I); + // funclets will be reassociated in the future + if (Bundle.getTagID() == LLVMContext::OB_funclet) + continue; + OpBundles.emplace_back(Bundle); + } + + if (!BlockColors.empty()) { + const ColorVector &CV = BlockColors.find(&BB)->second; + assert(CV.size() == 1 && "non-unique color for block!"); + Instruction *EHPad = CV.front()->getFirstNonPHI(); + if (EHPad->isEHPad()) + OpBundles.emplace_back("funclet", EHPad); + } + + return CallInst::Create(CI, OpBundles); +} +} + /// Visit each call, one at a time, and make simplifications without doing any /// additional analysis. void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { @@ -691,6 +720,11 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { // Reset all the flags in preparation for recomputing them. UsedInThisFunction = 0; + DenseMap<BasicBlock *, ColorVector> BlockColors; + if (F.hasPersonalityFn() && + isFuncletEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) + BlockColors = colorEHFunclets(F); + // Visit all objc_* calls in F. for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ) { Instruction *Inst = &*I++; @@ -927,9 +961,10 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { Value *Incoming = GetRCIdentityRoot(PN->getIncomingValue(i)); if (!IsNullOrUndef(Incoming)) { - CallInst *Clone = cast<CallInst>(CInst->clone()); Value *Op = PN->getIncomingValue(i); Instruction *InsertPos = &PN->getIncomingBlock(i)->back(); + CallInst *Clone = cast<CallInst>(CloneCallInstForBB( + *CInst, *InsertPos->getParent(), BlockColors)); if (Op->getType() != ParamTy) Op = new BitCastInst(Op, ParamTy, "", InsertPos); Clone->setArgOperand(0, Op); |