diff options
Diffstat (limited to 'llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp')
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp | 83 |
1 files changed, 37 insertions, 46 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp index 86d161116e8c..62161b5b6b40 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp @@ -32,6 +32,7 @@ #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/EHPersonalities.h" +#include "llvm/Analysis/ObjCARCUtil.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstIterator.h" @@ -63,13 +64,12 @@ namespace { class ObjCARCContract { bool Changed; + bool CFGChanged; AAResults *AA; DominatorTree *DT; ProvenanceAnalysis PA; ARCRuntimeEntryPoints EP; - - /// A flag indicating whether this optimization pass should run. - bool Run; + BundledRetainClaimRVs *BundledInsts = nullptr; /// The inline asm string to insert between calls and RetainRV calls to make /// the optimization work on targets which need it. @@ -98,6 +98,7 @@ class ObjCARCContract { public: bool init(Module &M); bool run(Function &F, AAResults *AA, DominatorTree *DT); + bool hasCFGChanged() const { return CFGChanged; } }; class ObjCARCContractLegacyPass : public FunctionPass { @@ -304,32 +305,6 @@ findRetainForStoreStrongContraction(Value *New, StoreInst *Store, return Retain; } -/// Create a call instruction with the correct funclet token. Should be used -/// instead of calling CallInst::Create directly. -static CallInst * -createCallInst(FunctionType *FTy, Value *Func, ArrayRef<Value *> Args, - const Twine &NameStr, Instruction *InsertBefore, - const DenseMap<BasicBlock *, ColorVector> &BlockColors) { - SmallVector<OperandBundleDef, 1> OpBundles; - if (!BlockColors.empty()) { - const ColorVector &CV = BlockColors.find(InsertBefore->getParent())->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(FTy, Func, Args, OpBundles, NameStr, InsertBefore); -} - -static CallInst * -createCallInst(FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr, - Instruction *InsertBefore, - const DenseMap<BasicBlock *, ColorVector> &BlockColors) { - return createCallInst(Func.getFunctionType(), Func.getCallee(), Args, NameStr, - InsertBefore, BlockColors); -} - /// Attempt to merge an objc_release with a store, load, and objc_retain to form /// an objc_storeStrong. An objc_storeStrong: /// @@ -411,7 +386,8 @@ void ObjCARCContract::tryToContractReleaseIntoStoreStrong( if (Args[1]->getType() != I8X) Args[1] = new BitCastInst(Args[1], I8X, "", Store); Function *Decl = EP.get(ARCRuntimeEntryPointKind::StoreStrong); - CallInst *StoreStrong = createCallInst(Decl, Args, "", Store, BlockColors); + CallInst *StoreStrong = + objcarc::createCallInstWithColors(Decl, Args, "", Store, BlockColors); StoreStrong->setDoesNotThrow(); StoreStrong->setDebugLoc(Store->getDebugLoc()); @@ -456,9 +432,14 @@ bool ObjCARCContract::tryToPeepholeInstruction( case ARCInstKind::RetainRV: case ARCInstKind::ClaimRV: { // If we're compiling for a target which needs a special inline-asm - // marker to do the return value optimization, insert it now. + // marker to do the return value optimization and the retainRV/claimRV call + // wasn't bundled with a call, insert the marker now. if (!RVInstMarker) return false; + + if (BundledInsts->contains(Inst)) + return false; + BasicBlock::iterator BBI = Inst->getIterator(); BasicBlock *InstParent = Inst->getParent(); @@ -486,7 +467,7 @@ bool ObjCARCContract::tryToPeepholeInstruction( RVInstMarker->getString(), /*Constraints=*/"", /*hasSideEffects=*/true); - createCallInst(IA, None, "", Inst, BlockColors); + objcarc::createCallInstWithColors(IA, None, "", Inst, BlockColors); } decline_rv_optimization: return false; @@ -525,6 +506,12 @@ bool ObjCARCContract::tryToPeepholeInstruction( Inst->eraseFromParent(); return true; default: + if (auto *CI = dyn_cast<CallInst>(Inst)) + if (CI->getIntrinsicID() == Intrinsic::objc_clang_arc_noop_use) { + // Remove calls to @llvm.objc.clang.arc.noop.use(...). + Changed = true; + CI->eraseFromParent(); + } return true; } } @@ -534,16 +521,10 @@ bool ObjCARCContract::tryToPeepholeInstruction( //===----------------------------------------------------------------------===// bool ObjCARCContract::init(Module &M) { - // If nothing in the Module uses ARC, don't do anything. - Run = ModuleHasARC(M); - if (!Run) - return false; - EP.init(&M); // Initialize RVInstMarker. - const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker"; - RVInstMarker = dyn_cast_or_null<MDString>(M.getModuleFlag(MarkerKey)); + RVInstMarker = getRVInstMarker(M); return false; } @@ -552,14 +533,16 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) { if (!EnableARCOpts) return false; - // If nothing in the Module uses ARC, don't do anything. - if (!Run) - return false; - - Changed = false; + Changed = CFGChanged = false; AA = A; DT = D; PA.setAA(A); + BundledRetainClaimRVs BRV(EP, true); + BundledInsts = &BRV; + + std::pair<bool, bool> R = BundledInsts->insertAfterInvokes(F, DT); + Changed |= R.first; + CFGChanged |= R.second; DenseMap<BasicBlock *, ColorVector> BlockColors; if (F.hasPersonalityFn() && @@ -584,6 +567,13 @@ bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) { LLVM_DEBUG(dbgs() << "Visiting: " << *Inst << "\n"); + if (auto *CI = dyn_cast<CallInst>(Inst)) + if (objcarc::hasAttachedCallOpBundle(CI)) { + BundledInsts->insertRVCallWithColors(&*I, CI, BlockColors); + --I; + Changed = true; + } + // First try to peephole Inst. If there is nothing further we can do in // terms of undoing objc-arc-expand, process the next inst. if (tryToPeepholeInstruction(F, Inst, I, TailOkForStoreStrongs, @@ -733,7 +723,6 @@ INITIALIZE_PASS_END(ObjCARCContractLegacyPass, "objc-arc-contract", void ObjCARCContractLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<AAResultsWrapperPass>(); AU.addRequired<DominatorTreeWrapperPass>(); - AU.setPreservesCFG(); } Pass *llvm::createObjCARCContractPass() { @@ -757,9 +746,11 @@ PreservedAnalyses ObjCARCContractPass::run(Function &F, bool Changed = OCAC.run(F, &AM.getResult<AAManager>(F), &AM.getResult<DominatorTreeAnalysis>(F)); + bool CFGChanged = OCAC.hasCFGChanged(); if (Changed) { PreservedAnalyses PA; - PA.preserveSet<CFGAnalyses>(); + if (!CFGChanged) + PA.preserveSet<CFGAnalyses>(); return PA; } return PreservedAnalyses::all(); |