diff options
Diffstat (limited to 'llvm/lib/Transforms/ObjCARC')
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARC.cpp | 21 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARC.h | 4 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp | 29 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp | 26 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 172 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp | 70 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h | 1 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp | 38 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/PtrState.cpp | 4 |
11 files changed, 124 insertions, 252 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp index de0f5803b4c7..0fea6bcc4882 100644 --- a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp +++ b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp @@ -48,10 +48,10 @@ bool llvm::objcarc::CanAlterRefCount(const Instruction *Inst, const Value *Ptr, const auto *Call = cast<CallBase>(Inst); // See if AliasAnalysis can help us with the call. - FunctionModRefBehavior MRB = PA.getAA()->getModRefBehavior(Call); - if (AliasAnalysis::onlyReadsMemory(MRB)) + MemoryEffects ME = PA.getAA()->getMemoryEffects(Call); + if (ME.onlyReadsMemory()) return false; - if (AliasAnalysis::onlyAccessesArgPointees(MRB)) { + if (ME.onlyAccessesArgPointees()) { for (const Value *Op : Call->args()) { if (IsPotentialRetainableObjPtr(Op, *PA.getAA()) && PA.related(Ptr, Op)) return true; diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp index 70f150c9461a..02f9db719e26 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp @@ -13,35 +13,14 @@ //===----------------------------------------------------------------------===// #include "ObjCARC.h" -#include "llvm-c/Initialization.h" #include "llvm/Analysis/ObjCARCUtil.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" -#include "llvm/InitializePasses.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" -namespace llvm { - class PassRegistry; -} - using namespace llvm; using namespace llvm::objcarc; -/// initializeObjCARCOptsPasses - Initialize all passes linked into the -/// ObjCARCOpts library. -void llvm::initializeObjCARCOpts(PassRegistry &Registry) { - initializeObjCARCAAWrapperPassPass(Registry); - initializeObjCARCAPElimPass(Registry); - initializeObjCARCExpandPass(Registry); - initializeObjCARCContractLegacyPassPass(Registry); - initializeObjCARCOptLegacyPassPass(Registry); - initializePAEvalPass(Registry); -} - -void LLVMInitializeObjCARCOpts(LLVMPassRegistryRef R) { - initializeObjCARCOpts(*unwrap(R)); -} - CallInst *objcarc::createCallInstWithColors( FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr, Instruction *InsertBefore, diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.h b/llvm/lib/Transforms/ObjCARC/ObjCARC.h index 2bc0c8f87d77..d4570ff908f1 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARC.h +++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.h @@ -132,8 +132,8 @@ public: auto It = RVCalls.find(CI); if (It != RVCalls.end()) { // Remove call to @llvm.objc.clang.arc.noop.use. - for (auto U = It->second->user_begin(), E = It->second->user_end(); U != E; ++U) - if (auto *CI = dyn_cast<CallInst>(*U)) + for (User *U : It->second->users()) + if (auto *CI = dyn_cast<CallInst>(U)) if (CI->getIntrinsicID() == Intrinsic::objc_clang_arc_noop_use) { CI->eraseFromParent(); break; diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp index 03e5fb18d5ac..dceb2ebb1863 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCAPElim.cpp @@ -29,8 +29,6 @@ #include "llvm/IR/Constants.h" #include "llvm/IR/InstrTypes.h" #include "llvm/IR/PassManager.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/ObjCARC.h" @@ -147,35 +145,8 @@ bool runImpl(Module &M) { return Changed; } -/// Autorelease pool elimination. -class ObjCARCAPElim : public ModulePass { - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnModule(Module &M) override; - -public: - static char ID; - ObjCARCAPElim() : ModulePass(ID) { - initializeObjCARCAPElimPass(*PassRegistry::getPassRegistry()); - } -}; } // namespace -char ObjCARCAPElim::ID = 0; -INITIALIZE_PASS(ObjCARCAPElim, "objc-arc-apelim", - "ObjC ARC autorelease pool elimination", false, false) - -Pass *llvm::createObjCARCAPElimPass() { return new ObjCARCAPElim(); } - -void ObjCARCAPElim::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); -} - -bool ObjCARCAPElim::runOnModule(Module &M) { - if (skipModule(M)) - return false; - return runImpl(M); -} - PreservedAnalyses ObjCARCAPElimPass::run(Module &M, ModuleAnalysisManager &AM) { if (!runImpl(M)) return PreservedAnalyses::all(); diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp index f64c26ef2bed..ab90ef090ae0 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp @@ -428,7 +428,7 @@ bool ObjCARCContract::tryToPeepholeInstruction( if (!optimizeRetainCall(F, Inst)) return false; // If we succeed in our optimization, fall through. - LLVM_FALLTHROUGH; + [[fallthrough]]; case ARCInstKind::RetainRV: case ARCInstKind::UnsafeClaimRV: { // Return true if this is a bundled retainRV/claimRV call, which is always @@ -472,7 +472,8 @@ bool ObjCARCContract::tryToPeepholeInstruction( RVInstMarker->getString(), /*Constraints=*/"", /*hasSideEffects=*/true); - objcarc::createCallInstWithColors(IA, None, "", Inst, BlockColors); + objcarc::createCallInstWithColors(IA, std::nullopt, "", Inst, + BlockColors); } decline_rv_optimization: return false; diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp index efcdc51ef5e3..bb0a01b78a96 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp @@ -29,9 +29,6 @@ #include "llvm/IR/Instructions.h" #include "llvm/IR/PassManager.h" #include "llvm/IR/Value.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" -#include "llvm/PassRegistry.h" #include "llvm/Support/Casting.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" @@ -89,31 +86,8 @@ static bool runImpl(Function &F) { return Changed; } -/// Early ARC transformations. -class ObjCARCExpand : public FunctionPass { - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnFunction(Function &F) override; - -public: - static char ID; - ObjCARCExpand() : FunctionPass(ID) { - initializeObjCARCExpandPass(*PassRegistry::getPassRegistry()); - } -}; } // namespace -char ObjCARCExpand::ID = 0; -INITIALIZE_PASS(ObjCARCExpand, "objc-arc-expand", "ObjC ARC expansion", false, - false) - -Pass *llvm::createObjCARCExpandPass() { return new ObjCARCExpand(); } - -void ObjCARCExpand::getAnalysisUsage(AnalysisUsage &AU) const { - AU.setPreservesCFG(); -} - -bool ObjCARCExpand::runOnFunction(Function &F) { return runImpl(F); } - PreservedAnalyses ObjCARCExpandPass::run(Function &F, FunctionAnalysisManager &AM) { if (!runImpl(F)) diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp index e1a000b31cf9..a374958f9707 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -31,7 +31,6 @@ #include "ProvenanceAnalysis.h" #include "PtrState.h" #include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/None.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/ADT/SmallVector.h" @@ -58,8 +57,6 @@ #include "llvm/IR/Type.h" #include "llvm/IR/User.h" #include "llvm/IR/Value.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" @@ -483,8 +480,8 @@ namespace { /// The main ARC optimization pass. class ObjCARCOpt { - bool Changed; - bool CFGChanged; + bool Changed = false; + bool CFGChanged = false; ProvenanceAnalysis PA; /// A cache of references to runtime entry point constants. @@ -504,6 +501,8 @@ class ObjCARCOpt { /// is in fact used in the current function. unsigned UsedInThisFunction; + DenseMap<BasicBlock *, ColorVector> BlockEHColors; + bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV); void OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV, ARCInstKind &Class); @@ -511,17 +510,16 @@ class ObjCARCOpt { /// Optimize an individual call, optionally passing the /// GetArgRCIdentityRoot if it has already been computed. - void OptimizeIndividualCallImpl( - Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors, - Instruction *Inst, ARCInstKind Class, const Value *Arg); + void OptimizeIndividualCallImpl(Function &F, Instruction *Inst, + ARCInstKind Class, const Value *Arg); /// Try to optimize an AutoreleaseRV with a RetainRV or UnsafeClaimRV. If the /// optimization occurs, returns true to indicate that the caller should /// assume the instructions are dead. - bool OptimizeInlinedAutoreleaseRVCall( - Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors, - Instruction *Inst, const Value *&Arg, ARCInstKind Class, - Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg); + bool OptimizeInlinedAutoreleaseRVCall(Function &F, Instruction *Inst, + const Value *&Arg, ARCInstKind Class, + Instruction *AutoreleaseRV, + const Value *&AutoreleaseRVArg); void CheckForCFGHazards(const BasicBlock *BB, DenseMap<const BasicBlock *, BBState> &BBStates, @@ -569,54 +567,41 @@ class ObjCARCOpt { void OptimizeReturns(Function &F); + template <typename PredicateT> + static void cloneOpBundlesIf(CallBase *CI, + SmallVectorImpl<OperandBundleDef> &OpBundles, + PredicateT Predicate) { + for (unsigned I = 0, E = CI->getNumOperandBundles(); I != E; ++I) { + OperandBundleUse B = CI->getOperandBundleAt(I); + if (Predicate(B)) + OpBundles.emplace_back(B); + } + } + + void addOpBundleForFunclet(BasicBlock *BB, + SmallVectorImpl<OperandBundleDef> &OpBundles) { + if (!BlockEHColors.empty()) { + const ColorVector &CV = BlockEHColors.find(BB)->second; + assert(CV.size() > 0 && "Uncolored block"); + for (BasicBlock *EHPadBB : CV) + if (auto *EHPad = dyn_cast<FuncletPadInst>(EHPadBB->getFirstNonPHI())) { + OpBundles.emplace_back("funclet", EHPad); + return; + } + } + } + #ifndef NDEBUG void GatherStatistics(Function &F, bool AfterOptimization = false); #endif public: - void init(Module &M); + void init(Function &F); bool run(Function &F, AAResults &AA); - void releaseMemory(); bool hasCFGChanged() const { return CFGChanged; } }; - -/// The main ARC optimization pass. -class ObjCARCOptLegacyPass : public FunctionPass { -public: - ObjCARCOptLegacyPass() : FunctionPass(ID) { - initializeObjCARCOptLegacyPassPass(*PassRegistry::getPassRegistry()); - } - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool doInitialization(Module &M) override { - OCAO.init(M); - return false; - } - bool runOnFunction(Function &F) override { - return OCAO.run(F, getAnalysis<AAResultsWrapperPass>().getAAResults()); - } - void releaseMemory() override { OCAO.releaseMemory(); } - static char ID; - -private: - ObjCARCOpt OCAO; -}; } // end anonymous namespace -char ObjCARCOptLegacyPass::ID = 0; - -INITIALIZE_PASS_BEGIN(ObjCARCOptLegacyPass, "objc-arc", "ObjC ARC optimization", - false, false) -INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass) -INITIALIZE_PASS_END(ObjCARCOptLegacyPass, "objc-arc", "ObjC ARC optimization", - false, false) - -Pass *llvm::createObjCARCOptPass() { return new ObjCARCOptLegacyPass(); } - -void ObjCARCOptLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<ObjCARCAAWrapperPass>(); - AU.addRequired<AAResultsWrapperPass>(); -} - /// Turn objc_retainAutoreleasedReturnValue into objc_retain if the operand is /// not a return value. bool @@ -664,8 +649,7 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) { } bool ObjCARCOpt::OptimizeInlinedAutoreleaseRVCall( - Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors, - Instruction *Inst, const Value *&Arg, ARCInstKind Class, + Function &F, Instruction *Inst, const Value *&Arg, ARCInstKind Class, Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg) { if (BundledInsts->contains(Inst)) return false; @@ -718,8 +702,7 @@ bool ObjCARCOpt::OptimizeInlinedAutoreleaseRVCall( EraseInstruction(Inst); // Run the normal optimizations on Release. - OptimizeIndividualCallImpl(F, BlockColors, Release, ARCInstKind::Release, - Arg); + OptimizeIndividualCallImpl(F, Release, ARCInstKind::Release, Arg); return true; } @@ -772,31 +755,6 @@ void ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, LLVM_DEBUG(dbgs() << "New: " << *AutoreleaseRV << "\n"); } -namespace { -Instruction * -CloneCallInstForBB(CallInst &CI, BasicBlock &BB, - const DenseMap<BasicBlock *, ColorVector> &BlockColors) { - 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) { @@ -804,11 +762,6 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { // Reset all the flags in preparation for recomputing them. UsedInThisFunction = 0; - DenseMap<BasicBlock *, ColorVector> BlockColors; - if (F.hasPersonalityFn() && - isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) - BlockColors = colorEHFunclets(F); - // Store any delayed AutoreleaseRV intrinsics, so they can be easily paired // with RetainRV and UnsafeClaimRV. Instruction *DelayedAutoreleaseRV = nullptr; @@ -821,7 +774,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { auto optimizeDelayedAutoreleaseRV = [&]() { if (!DelayedAutoreleaseRV) return; - OptimizeIndividualCallImpl(F, BlockColors, DelayedAutoreleaseRV, + OptimizeIndividualCallImpl(F, DelayedAutoreleaseRV, ARCInstKind::AutoreleaseRV, DelayedAutoreleaseRVArg); setDelayedAutoreleaseRV(nullptr); @@ -884,7 +837,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { case ARCInstKind::UnsafeClaimRV: if (DelayedAutoreleaseRV) { // We have a potential RV pair. Check if they cancel out. - if (OptimizeInlinedAutoreleaseRVCall(F, BlockColors, Inst, Arg, Class, + if (OptimizeInlinedAutoreleaseRVCall(F, Inst, Arg, Class, DelayedAutoreleaseRV, DelayedAutoreleaseRVArg)) { setDelayedAutoreleaseRV(nullptr); @@ -895,7 +848,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { break; } - OptimizeIndividualCallImpl(F, BlockColors, Inst, Class, Arg); + OptimizeIndividualCallImpl(F, Inst, Class, Arg); } // Catch the final delayed AutoreleaseRV. @@ -929,9 +882,9 @@ static bool isInertARCValue(Value *V, SmallPtrSet<Value *, 1> &VisitedPhis) { return false; } -void ObjCARCOpt::OptimizeIndividualCallImpl( - Function &F, DenseMap<BasicBlock *, ColorVector> &BlockColors, - Instruction *Inst, ARCInstKind Class, const Value *Arg) { +void ObjCARCOpt::OptimizeIndividualCallImpl(Function &F, Instruction *Inst, + ARCInstKind Class, + const Value *Arg) { LLVM_DEBUG(dbgs() << "Visiting: Class: " << Class << "; " << *Inst << "\n"); // We can delete this call if it takes an inert value. @@ -1038,7 +991,7 @@ void ObjCARCOpt::OptimizeIndividualCallImpl( CallInst *NewCall = CallInst::Create(Decl, Call->getArgOperand(0), "", Call); NewCall->setMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease), - MDNode::get(C, None)); + MDNode::get(C, std::nullopt)); LLVM_DEBUG(dbgs() << "Replacing autorelease{,RV}(x) with objc_release(x) " "since x is otherwise unused.\nOld: " @@ -1189,8 +1142,12 @@ void ObjCARCOpt::OptimizeIndividualCallImpl( continue; Value *Op = PN->getIncomingValue(i); Instruction *InsertPos = &PN->getIncomingBlock(i)->back(); - CallInst *Clone = cast<CallInst>( - CloneCallInstForBB(*CInst, *InsertPos->getParent(), BlockColors)); + SmallVector<OperandBundleDef, 1> OpBundles; + cloneOpBundlesIf(CInst, OpBundles, [](const OperandBundleUse &B) { + return B.getTagID() != LLVMContext::OB_funclet; + }); + addOpBundleForFunclet(InsertPos->getParent(), OpBundles); + CallInst *Clone = CallInst::Create(CInst, OpBundles); if (Op->getType() != ParamTy) Op = new BitCastInst(Op, ParamTy, "", InsertPos); Clone->setArgOperand(0, Op); @@ -1503,7 +1460,7 @@ static void collectReleaseInsertPts( const BlotMapVector<Value *, RRInfo> &Retains, DenseMap<const Instruction *, SmallPtrSet<const Value *, 2>> &ReleaseInsertPtToRCIdentityRoots) { - for (auto &P : Retains) { + for (const auto &P : Retains) { // Retains is a map from an objc_retain call to a RRInfo of the RC identity // root of the call. Get the RC identity root of the objc_retain call. Instruction *Retain = cast<Instruction>(P.first); @@ -1541,7 +1498,7 @@ bool ObjCARCOpt::VisitInstructionTopDown( if (const SmallPtrSet<const Value *, 2> *Roots = getRCIdentityRootsFromReleaseInsertPt( Inst, ReleaseInsertPtToRCIdentityRoots)) - for (auto *Root : *Roots) { + for (const auto *Root : *Roots) { TopDownPtrState &S = MyStates.getPtrTopDownState(Root); // Disable code motion if the current position is S_Retain to prevent // moving the objc_retain call past objc_release calls. If it's @@ -1812,7 +1769,9 @@ void ObjCARCOpt::MoveCalls(Value *Arg, RRInfo &RetainsToMove, Value *MyArg = ArgTy == ParamTy ? Arg : new BitCastInst(Arg, ParamTy, "", InsertPt); Function *Decl = EP.get(ARCRuntimeEntryPointKind::Retain); - CallInst *Call = CallInst::Create(Decl, MyArg, "", InsertPt); + SmallVector<OperandBundleDef, 1> BundleList; + addOpBundleForFunclet(InsertPt->getParent(), BundleList); + CallInst *Call = CallInst::Create(Decl, MyArg, BundleList, "", InsertPt); Call->setDoesNotThrow(); Call->setTailCall(); @@ -1825,7 +1784,9 @@ void ObjCARCOpt::MoveCalls(Value *Arg, RRInfo &RetainsToMove, Value *MyArg = ArgTy == ParamTy ? Arg : new BitCastInst(Arg, ParamTy, "", InsertPt); Function *Decl = EP.get(ARCRuntimeEntryPointKind::Release); - CallInst *Call = CallInst::Create(Decl, MyArg, "", InsertPt); + SmallVector<OperandBundleDef, 1> BundleList; + addOpBundleForFunclet(InsertPt->getParent(), BundleList); + CallInst *Call = CallInst::Create(Decl, MyArg, BundleList, "", InsertPt); // Attach a clang.imprecise_release metadata tag, if appropriate. if (MDNode *M = ReleasesToMove.ReleaseMetadata) Call->setMetadata(MDKindCache.get(ARCMDKindID::ImpreciseRelease), M); @@ -2441,17 +2402,22 @@ ObjCARCOpt::GatherStatistics(Function &F, bool AfterOptimization) { } #endif -void ObjCARCOpt::init(Module &M) { +void ObjCARCOpt::init(Function &F) { if (!EnableARCOpts) return; // Intuitively, objc_retain and others are nocapture, however in practice // they are not, because they return their argument value. And objc_release // calls finalizers which can have arbitrary side effects. - MDKindCache.init(&M); + MDKindCache.init(F.getParent()); // Initialize our runtime entry point cache. - EP.init(&M); + EP.init(F.getParent()); + + // Compute which blocks are in which funclet. + if (F.hasPersonalityFn() && + isScopedEHPersonality(classifyEHPersonality(F.getPersonalityFn()))) + BlockEHColors = colorEHFunclets(F); } bool ObjCARCOpt::run(Function &F, AAResults &AA) { @@ -2521,17 +2487,13 @@ bool ObjCARCOpt::run(Function &F, AAResults &AA) { return Changed; } -void ObjCARCOpt::releaseMemory() { - PA.clear(); -} - /// @} /// PreservedAnalyses ObjCARCOptPass::run(Function &F, FunctionAnalysisManager &AM) { ObjCARCOpt OCAO; - OCAO.init(*F.getParent()); + OCAO.init(F); bool Changed = OCAO.run(F, AM.getResult<AAManager>(F)); bool CFGChanged = OCAO.hasCFGChanged(); diff --git a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp index 6731b841771c..2fa25a79ae9d 100644 --- a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp +++ b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.cpp @@ -42,21 +42,40 @@ bool ProvenanceAnalysis::relatedSelect(const SelectInst *A, const Value *B) { // If the values are Selects with the same condition, we can do a more precise // check: just check for relations between the values on corresponding arms. - if (const SelectInst *SB = dyn_cast<SelectInst>(B)) + if (const SelectInst *SB = dyn_cast<SelectInst>(B)) { if (A->getCondition() == SB->getCondition()) return related(A->getTrueValue(), SB->getTrueValue()) || related(A->getFalseValue(), SB->getFalseValue()); + // Check both arms of B individually. Return false if neither arm is related + // to A. + if (!(related(SB->getTrueValue(), A) || related(SB->getFalseValue(), A))) + return false; + } + // Check both arms of the Select node individually. return related(A->getTrueValue(), B) || related(A->getFalseValue(), B); } bool ProvenanceAnalysis::relatedPHI(const PHINode *A, const Value *B) { - // If the values are PHIs in the same block, we can do a more precise as well - // as efficient check: just check for relations between the values on - // corresponding edges. - if (const PHINode *PNB = dyn_cast<PHINode>(B)) + + auto comparePHISources = [this](const PHINode *PNA, const Value *B) -> bool { + // Check each unique source of the PHI node against B. + SmallPtrSet<const Value *, 4> UniqueSrc; + for (Value *PV1 : PNA->incoming_values()) { + if (UniqueSrc.insert(PV1).second && related(PV1, B)) + return true; + } + + // All of the arms checked out. + return false; + }; + + if (const PHINode *PNB = dyn_cast<PHINode>(B)) { + // If the values are PHIs in the same block, we can do a more precise as + // well as efficient check: just check for relations between the values on + // corresponding edges. if (PNB->getParent() == A->getParent()) { for (unsigned i = 0, e = A->getNumIncomingValues(); i != e; ++i) if (related(A->getIncomingValue(i), @@ -65,15 +84,11 @@ bool ProvenanceAnalysis::relatedPHI(const PHINode *A, return false; } - // Check each unique source of the PHI node against B. - SmallPtrSet<const Value *, 4> UniqueSrc; - for (Value *PV1 : A->incoming_values()) { - if (UniqueSrc.insert(PV1).second && related(PV1, B)) - return true; + if (!comparePHISources(PNB, A)) + return false; } - // All of the arms checked out. - return false; + return comparePHISources(A, B); } /// Test if the value of P, or any value covered by its provenance, is ever @@ -125,22 +140,19 @@ bool ProvenanceAnalysis::relatedCheck(const Value *A, const Value *B) { bool BIsIdentified = IsObjCIdentifiedObject(B); // An ObjC-Identified object can't alias a load if it is never locally stored. - if (AIsIdentified) { - // Check for an obvious escape. - if (isa<LoadInst>(B)) - return IsStoredObjCPointer(A); - if (BIsIdentified) { - // Check for an obvious escape. - if (isa<LoadInst>(A)) - return IsStoredObjCPointer(B); - // Both pointers are identified and escapes aren't an evident problem. - return false; - } - } else if (BIsIdentified) { - // Check for an obvious escape. - if (isa<LoadInst>(A)) - return IsStoredObjCPointer(B); - } + + // Check for an obvious escape. + if ((AIsIdentified && isa<LoadInst>(B) && !IsStoredObjCPointer(A)) || + (BIsIdentified && isa<LoadInst>(A) && !IsStoredObjCPointer(B))) + return false; + + if ((AIsIdentified && isa<LoadInst>(B)) || + (BIsIdentified && isa<LoadInst>(A))) + return true; + + // Both pointers are identified and escapes aren't an evident problem. + if (AIsIdentified && BIsIdentified && !isa<LoadInst>(A) && !isa<LoadInst>(B)) + return false; // Special handling for PHI and Select. if (const PHINode *PN = dyn_cast<PHINode>(A)) @@ -174,6 +186,8 @@ bool ProvenanceAnalysis::related(const Value *A, const Value *B) { return Pair.first->second; bool Result = relatedCheck(A, B); + assert(relatedCheck(B, A) == Result && + "relatedCheck result depending on order of parameters!"); CachedResults[ValuePairTy(A, B)] = Result; return Result; } diff --git a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h index 1624cf26094a..bc946fac4544 100644 --- a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h +++ b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysis.h @@ -26,6 +26,7 @@ #define LLVM_LIB_TRANSFORMS_OBJCARC_PROVENANCEANALYSIS_H #include "llvm/ADT/DenseMap.h" +#include "llvm/IR/PassManager.h" #include "llvm/IR/ValueHandle.h" #include <utility> diff --git a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp index fe637ee066a4..9f15772f2fa1 100644 --- a/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp +++ b/llvm/lib/Transforms/ObjCARC/ProvenanceAnalysisEvaluator.cpp @@ -7,38 +7,16 @@ //===----------------------------------------------------------------------===// #include "ProvenanceAnalysis.h" +#include "llvm/Transforms/ObjCARC.h" #include "llvm/ADT/SetVector.h" #include "llvm/Analysis/AliasAnalysis.h" -#include "llvm/Analysis/Passes.h" #include "llvm/IR/Function.h" #include "llvm/IR/InstIterator.h" -#include "llvm/IR/InstrTypes.h" -#include "llvm/IR/Module.h" -#include "llvm/InitializePasses.h" -#include "llvm/Pass.h" #include "llvm/Support/raw_ostream.h" using namespace llvm; using namespace llvm::objcarc; -namespace { -class PAEval : public FunctionPass { - -public: - static char ID; - PAEval(); - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool runOnFunction(Function &F) override; -}; -} - -char PAEval::ID = 0; -PAEval::PAEval() : FunctionPass(ID) {} - -void PAEval::getAnalysisUsage(AnalysisUsage &AU) const { - AU.addRequired<AAResultsWrapperPass>(); -} - static StringRef getName(Value *V) { StringRef Name = V->getName(); if (Name.startswith("\1")) @@ -52,7 +30,7 @@ static void insertIfNamed(SetVector<Value *> &Values, Value *V) { Values.insert(V); } -bool PAEval::runOnFunction(Function &F) { +PreservedAnalyses PAEvalPass::run(Function &F, FunctionAnalysisManager &AM) { SetVector<Value *> Values; for (auto &Arg : F.args()) @@ -66,7 +44,7 @@ bool PAEval::runOnFunction(Function &F) { } ProvenanceAnalysis PA; - PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults()); + PA.setAA(&AM.getResult<AAManager>(F)); for (Value *V1 : Values) { StringRef NameV1 = getName(V1); @@ -82,13 +60,5 @@ bool PAEval::runOnFunction(Function &F) { } } - return false; + return PreservedAnalyses::all(); } - -FunctionPass *llvm::createPAEvalPass() { return new PAEval(); } - -INITIALIZE_PASS_BEGIN(PAEval, "pa-eval", - "Evaluate ProvenanceAnalysis on all pairs", false, true) -INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) -INITIALIZE_PASS_END(PAEval, "pa-eval", - "Evaluate ProvenanceAnalysis on all pairs", false, true) diff --git a/llvm/lib/Transforms/ObjCARC/PtrState.cpp b/llvm/lib/Transforms/ObjCARC/PtrState.cpp index d10d5851d5ea..e9b2dbeb62e6 100644 --- a/llvm/lib/Transforms/ObjCARC/PtrState.cpp +++ b/llvm/lib/Transforms/ObjCARC/PtrState.cpp @@ -212,7 +212,7 @@ bool BottomUpPtrState::MatchWithRetain() { // imprecise release, clear our reverse insertion points. if (OldSeq != S_Use || IsTrackingImpreciseReleases()) ClearReverseInsertPts(); - LLVM_FALLTHROUGH; + [[fallthrough]]; case S_CanRelease: return true; case S_None: @@ -360,7 +360,7 @@ bool TopDownPtrState::MatchWithRelease(ARCMDKindCache &Cache, case S_CanRelease: if (OldSeq == S_Retain || ReleaseMetadata != nullptr) ClearReverseInsertPts(); - LLVM_FALLTHROUGH; + [[fallthrough]]; case S_Use: SetReleaseMetadata(ReleaseMetadata); SetTailCallRelease(cast<CallInst>(Release)->isTailCall()); |