diff options
Diffstat (limited to 'llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp')
| -rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp | 206 |
1 files changed, 110 insertions, 96 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp index 7fd4857c4490..86d161116e8c 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp @@ -30,15 +30,18 @@ #include "ObjCARC.h" #include "ProvenanceAnalysis.h" #include "llvm/ADT/Statistic.h" +#include "llvm/Analysis/AliasAnalysis.h" #include "llvm/Analysis/EHPersonalities.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/InlineAsm.h" #include "llvm/IR/InstIterator.h" #include "llvm/IR/Operator.h" +#include "llvm/IR/PassManager.h" #include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/ObjCARC.h" using namespace llvm; using namespace llvm::objcarc; @@ -53,59 +56,63 @@ STATISTIC(NumStoreStrongs, "Number objc_storeStrong calls formed"); //===----------------------------------------------------------------------===// namespace { - /// Late ARC optimizations - /// - /// These change the IR in a way that makes it difficult to be analyzed by - /// ObjCARCOpt, so it's run late. - class ObjCARCContract : public FunctionPass { - bool Changed; - AliasAnalysis *AA; - DominatorTree *DT; - ProvenanceAnalysis PA; - ARCRuntimeEntryPoints EP; +/// Late ARC optimizations +/// +/// These change the IR in a way that makes it difficult to be analyzed by +/// ObjCARCOpt, so it's run late. - /// A flag indicating whether this optimization pass should run. - bool Run; +class ObjCARCContract { + bool Changed; + AAResults *AA; + DominatorTree *DT; + ProvenanceAnalysis PA; + ARCRuntimeEntryPoints EP; - /// The inline asm string to insert between calls and RetainRV calls to make - /// the optimization work on targets which need it. - const MDString *RVInstMarker; + /// A flag indicating whether this optimization pass should run. + bool Run; - /// The set of inserted objc_storeStrong calls. If at the end of walking the - /// function we have found no alloca instructions, these calls can be marked - /// "tail". - SmallPtrSet<CallInst *, 8> StoreStrongCalls; + /// The inline asm string to insert between calls and RetainRV calls to make + /// the optimization work on targets which need it. + const MDString *RVInstMarker; - /// Returns true if we eliminated Inst. - bool tryToPeepholeInstruction( - Function &F, Instruction *Inst, inst_iterator &Iter, - SmallPtrSetImpl<Instruction *> &DepInsts, - SmallPtrSetImpl<const BasicBlock *> &Visited, - bool &TailOkForStoreStrong, - const DenseMap<BasicBlock *, ColorVector> &BlockColors); + /// The set of inserted objc_storeStrong calls. If at the end of walking the + /// function we have found no alloca instructions, these calls can be marked + /// "tail". + SmallPtrSet<CallInst *, 8> StoreStrongCalls; - bool optimizeRetainCall(Function &F, Instruction *Retain); + /// Returns true if we eliminated Inst. + bool tryToPeepholeInstruction( + Function &F, Instruction *Inst, inst_iterator &Iter, + bool &TailOkForStoreStrong, + const DenseMap<BasicBlock *, ColorVector> &BlockColors); - bool - contractAutorelease(Function &F, Instruction *Autorelease, - ARCInstKind Class, - SmallPtrSetImpl<Instruction *> &DependingInstructions, - SmallPtrSetImpl<const BasicBlock *> &Visited); + bool optimizeRetainCall(Function &F, Instruction *Retain); - void tryToContractReleaseIntoStoreStrong( - Instruction *Release, inst_iterator &Iter, - const DenseMap<BasicBlock *, ColorVector> &BlockColors); + bool contractAutorelease(Function &F, Instruction *Autorelease, + ARCInstKind Class); - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool doInitialization(Module &M) override; - bool runOnFunction(Function &F) override; + void tryToContractReleaseIntoStoreStrong( + Instruction *Release, inst_iterator &Iter, + const DenseMap<BasicBlock *, ColorVector> &BlockColors); - public: - static char ID; - ObjCARCContract() : FunctionPass(ID) { - initializeObjCARCContractPass(*PassRegistry::getPassRegistry()); - } - }; +public: + bool init(Module &M); + bool run(Function &F, AAResults *AA, DominatorTree *DT); +}; + +class ObjCARCContractLegacyPass : public FunctionPass { + ObjCARCContract OCARCC; + +public: + void getAnalysisUsage(AnalysisUsage &AU) const override; + bool doInitialization(Module &M) override; + bool runOnFunction(Function &F) override; + + static char ID; + ObjCARCContractLegacyPass() : FunctionPass(ID) { + initializeObjCARCContractLegacyPassPass(*PassRegistry::getPassRegistry()); + } +}; } //===----------------------------------------------------------------------===// @@ -149,32 +156,17 @@ bool ObjCARCContract::optimizeRetainCall(Function &F, Instruction *Retain) { } /// Merge an autorelease with a retain into a fused call. -bool ObjCARCContract::contractAutorelease( - Function &F, Instruction *Autorelease, ARCInstKind Class, - SmallPtrSetImpl<Instruction *> &DependingInstructions, - SmallPtrSetImpl<const BasicBlock *> &Visited) { +bool ObjCARCContract::contractAutorelease(Function &F, Instruction *Autorelease, + ARCInstKind Class) { const Value *Arg = GetArgRCIdentityRoot(Autorelease); // Check that there are no instructions between the retain and the autorelease // (such as an autorelease_pop) which may change the count. - CallInst *Retain = nullptr; - if (Class == ARCInstKind::AutoreleaseRV) - FindDependencies(RetainAutoreleaseRVDep, Arg, - Autorelease->getParent(), Autorelease, - DependingInstructions, Visited, PA); - else - FindDependencies(RetainAutoreleaseDep, Arg, - Autorelease->getParent(), Autorelease, - DependingInstructions, Visited, PA); - - Visited.clear(); - if (DependingInstructions.size() != 1) { - DependingInstructions.clear(); - return false; - } - - Retain = dyn_cast_or_null<CallInst>(*DependingInstructions.begin()); - DependingInstructions.clear(); + DependenceKind DK = Class == ARCInstKind::AutoreleaseRV + ? RetainAutoreleaseRVDep + : RetainAutoreleaseDep; + auto *Retain = dyn_cast_or_null<CallInst>( + findSingleDependency(DK, Arg, Autorelease->getParent(), Autorelease, PA)); if (!Retain || GetBasicARCInstKind(Retain) != ARCInstKind::Retain || GetArgRCIdentityRoot(Retain) != Arg) @@ -204,7 +196,7 @@ bool ObjCARCContract::contractAutorelease( static StoreInst *findSafeStoreForStoreStrongContraction(LoadInst *Load, Instruction *Release, ProvenanceAnalysis &PA, - AliasAnalysis *AA) { + AAResults *AA) { StoreInst *Store = nullptr; bool SawRelease = false; @@ -442,8 +434,7 @@ void ObjCARCContract::tryToContractReleaseIntoStoreStrong( bool ObjCARCContract::tryToPeepholeInstruction( Function &F, Instruction *Inst, inst_iterator &Iter, - SmallPtrSetImpl<Instruction *> &DependingInsts, - SmallPtrSetImpl<const BasicBlock *> &Visited, bool &TailOkForStoreStrongs, + bool &TailOkForStoreStrongs, const DenseMap<BasicBlock *, ColorVector> &BlockColors) { // Only these library routines return their argument. In particular, // objc_retainBlock does not necessarily return its argument. @@ -454,7 +445,7 @@ bool ObjCARCContract::tryToPeepholeInstruction( return false; case ARCInstKind::Autorelease: case ARCInstKind::AutoreleaseRV: - return contractAutorelease(F, Inst, Class, DependingInsts, Visited); + return contractAutorelease(F, Inst, Class); case ARCInstKind::Retain: // Attempt to convert retains to retainrvs if they are next to function // calls. @@ -485,7 +476,7 @@ bool ObjCARCContract::tryToPeepholeInstruction( --BBI; } while (IsNoopInstruction(&*BBI)); - if (&*BBI == GetArgRCIdentityRoot(Inst)) { + if (GetRCIdentityRoot(&*BBI) == GetArgRCIdentityRoot(Inst)) { LLVM_DEBUG(dbgs() << "Adding inline asm marker for the return value " "optimization.\n"); Changed = true; @@ -542,7 +533,22 @@ bool ObjCARCContract::tryToPeepholeInstruction( // Top Level Driver //===----------------------------------------------------------------------===// -bool ObjCARCContract::runOnFunction(Function &F) { +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)); + + return false; +} + +bool ObjCARCContract::run(Function &F, AAResults *A, DominatorTree *D) { if (!EnableARCOpts) return false; @@ -551,10 +557,9 @@ bool ObjCARCContract::runOnFunction(Function &F) { return false; Changed = false; - AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); - DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); - - PA.setAA(&getAnalysis<AAResultsWrapperPass>().getAAResults()); + AA = A; + DT = D; + PA.setAA(A); DenseMap<BasicBlock *, ColorVector> BlockColors; if (F.hasPersonalityFn() && @@ -574,9 +579,6 @@ bool ObjCARCContract::runOnFunction(Function &F) { // For ObjC library calls which return their argument, replace uses of the // argument with uses of the call return value, if it dominates the use. This // reduces register pressure. - SmallPtrSet<Instruction *, 4> DependingInstructions; - SmallPtrSet<const BasicBlock *, 4> Visited; - for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E;) { Instruction *Inst = &*I++; @@ -584,8 +586,8 @@ bool ObjCARCContract::runOnFunction(Function &F) { // 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, DependingInstructions, Visited, - TailOkForStoreStrongs, BlockColors)) + if (tryToPeepholeInstruction(F, Inst, I, TailOkForStoreStrongs, + BlockColors)) continue; // Otherwise, try to undo objc-arc-expand. @@ -720,33 +722,45 @@ bool ObjCARCContract::runOnFunction(Function &F) { // Misc Pass Manager //===----------------------------------------------------------------------===// -char ObjCARCContract::ID = 0; -INITIALIZE_PASS_BEGIN(ObjCARCContract, "objc-arc-contract", +char ObjCARCContractLegacyPass::ID = 0; +INITIALIZE_PASS_BEGIN(ObjCARCContractLegacyPass, "objc-arc-contract", "ObjC ARC contraction", false, false) INITIALIZE_PASS_DEPENDENCY(AAResultsWrapperPass) INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) -INITIALIZE_PASS_END(ObjCARCContract, "objc-arc-contract", +INITIALIZE_PASS_END(ObjCARCContractLegacyPass, "objc-arc-contract", "ObjC ARC contraction", false, false) -void ObjCARCContract::getAnalysisUsage(AnalysisUsage &AU) const { +void ObjCARCContractLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired<AAResultsWrapperPass>(); AU.addRequired<DominatorTreeWrapperPass>(); AU.setPreservesCFG(); } -Pass *llvm::createObjCARCContractPass() { return new ObjCARCContract(); } +Pass *llvm::createObjCARCContractPass() { + return new ObjCARCContractLegacyPass(); +} -bool ObjCARCContract::doInitialization(Module &M) { - // If nothing in the Module uses ARC, don't do anything. - Run = ModuleHasARC(M); - if (!Run) - return false; +bool ObjCARCContractLegacyPass::doInitialization(Module &M) { + return OCARCC.init(M); +} - EP.init(&M); +bool ObjCARCContractLegacyPass::runOnFunction(Function &F) { + auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults(); + auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); + return OCARCC.run(F, AA, DT); +} - // Initialize RVInstMarker. - const char *MarkerKey = "clang.arc.retainAutoreleasedReturnValueMarker"; - RVInstMarker = dyn_cast_or_null<MDString>(M.getModuleFlag(MarkerKey)); +PreservedAnalyses ObjCARCContractPass::run(Function &F, + FunctionAnalysisManager &AM) { + ObjCARCContract OCAC; + OCAC.init(*F.getParent()); - return false; + bool Changed = OCAC.run(F, &AM.getResult<AAManager>(F), + &AM.getResult<DominatorTreeAnalysis>(F)); + if (Changed) { + PreservedAnalyses PA; + PA.preserveSet<CFGAnalyses>(); + return PA; + } + return PreservedAnalyses::all(); } |
