summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Transforms/ObjCARC
diff options
context:
space:
mode:
authorSaleem Abdulrasool <compnerd@compnerd.org>2018-03-12 21:46:09 +0000
committerSaleem Abdulrasool <compnerd@compnerd.org>2018-03-12 21:46:09 +0000
commit8b342680bf62722e5099074e8bd23491c71d92b3 (patch)
tree5507c01b3b0e4a6ccf1ead1eee5d0a910fcf78b2 /llvm/lib/Transforms/ObjCARC
parent5b034c83d655f9dcc7a35bb82d34ac7a2b44db6f (diff)
downloadbcm5719-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.cpp37
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);
OpenPOWER on IntegriCloud