From cfde93e5d6bebf7b63343ca0a15673a0ff3fa134 Mon Sep 17 00:00:00 2001 From: Arthur Eubanks Date: Wed, 15 Jul 2020 09:33:48 -0700 Subject: [PATCH] [ObjCARCOpt] Port objc-arc to NPM Since doInitialization() in the legacy pass modifies the module, the NPM pass is a Module pass. Reviewed By: ahatanak, ychen Differential Revision: https://reviews.llvm.org/D86178 --- llvm/include/llvm/InitializePasses.h | 2 +- llvm/include/llvm/Transforms/ObjCARC.h | 9 + llvm/lib/Passes/LLVMBuild.txt | 2 +- llvm/lib/Passes/PassBuilder.cpp | 1 + llvm/lib/Passes/PassRegistry.def | 1 + llvm/lib/Transforms/ObjCARC/ObjCARC.cpp | 2 +- llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 252 +++++++++++++---------- llvm/test/Transforms/ObjCARC/basic.ll | 1 + llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn | 1 + 9 files changed, 156 insertions(+), 115 deletions(-) diff --git a/llvm/include/llvm/InitializePasses.h b/llvm/include/llvm/InitializePasses.h index 48ee4c2..7e512ba 100644 --- a/llvm/include/llvm/InitializePasses.h +++ b/llvm/include/llvm/InitializePasses.h @@ -318,7 +318,7 @@ void initializeObjCARCAAWrapperPassPass(PassRegistry&); void initializeObjCARCAPElimPass(PassRegistry&); void initializeObjCARCContractPass(PassRegistry&); void initializeObjCARCExpandPass(PassRegistry&); -void initializeObjCARCOptPass(PassRegistry&); +void initializeObjCARCOptLegacyPassPass(PassRegistry &); void initializeOptimizationRemarkEmitterWrapperPassPass(PassRegistry&); void initializeOptimizePHIsPass(PassRegistry&); void initializePAEvalPass(PassRegistry&); diff --git a/llvm/include/llvm/Transforms/ObjCARC.h b/llvm/include/llvm/Transforms/ObjCARC.h index 2f114c7..03eaef5 100644 --- a/llvm/include/llvm/Transforms/ObjCARC.h +++ b/llvm/include/llvm/Transforms/ObjCARC.h @@ -14,6 +14,8 @@ #ifndef LLVM_TRANSFORMS_OBJCARC_H #define LLVM_TRANSFORMS_OBJCARC_H +#include "llvm/IR/PassManager.h" + namespace llvm { class Pass; @@ -42,6 +44,13 @@ Pass *createObjCARCContractPass(); // Pass *createObjCARCOptPass(); +class ObjCARCOptPass : public PassInfoMixin { +public: + ObjCARCOptPass() {} + + PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); +}; + } // End llvm namespace #endif diff --git a/llvm/lib/Passes/LLVMBuild.txt b/llvm/lib/Passes/LLVMBuild.txt index 4a26946..3e7a391 100644 --- a/llvm/lib/Passes/LLVMBuild.txt +++ b/llvm/lib/Passes/LLVMBuild.txt @@ -18,4 +18,4 @@ type = Library name = Passes parent = Libraries -required_libraries = AggressiveInstCombine Analysis Core Coroutines IPO InstCombine Scalar Support Target TransformUtils Vectorize Instrumentation +required_libraries = AggressiveInstCombine Analysis Core Coroutines IPO InstCombine ObjCARC Scalar Support Target TransformUtils Vectorize Instrumentation diff --git a/llvm/lib/Passes/PassBuilder.cpp b/llvm/lib/Passes/PassBuilder.cpp index 515aaea..3a6b736 100644 --- a/llvm/lib/Passes/PassBuilder.cpp +++ b/llvm/lib/Passes/PassBuilder.cpp @@ -118,6 +118,7 @@ #include "llvm/Transforms/Instrumentation/PoisonChecking.h" #include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/Transforms/Instrumentation/ThreadSanitizer.h" +#include "llvm/Transforms/ObjCARC.h" #include "llvm/Transforms/Scalar/ADCE.h" #include "llvm/Transforms/Scalar/AlignmentFromAssumptions.h" #include "llvm/Transforms/Scalar/BDCE.h" diff --git a/llvm/lib/Passes/PassRegistry.def b/llvm/lib/Passes/PassRegistry.def index 406a419..12e04ad 100644 --- a/llvm/lib/Passes/PassRegistry.def +++ b/llvm/lib/Passes/PassRegistry.def @@ -69,6 +69,7 @@ MODULE_PASS("lowertypetests", LowerTypeTestsPass(nullptr, nullptr)) MODULE_PASS("mergefunc", MergeFunctionsPass()) MODULE_PASS("name-anon-globals", NameAnonGlobalPass()) MODULE_PASS("no-op-module", NoOpModulePass()) +MODULE_PASS("objc-arc", ObjCARCOptPass()) MODULE_PASS("partial-inliner", PartialInlinerPass()) MODULE_PASS("pgo-icall-prom", PGOIndirectCallPromotion()) MODULE_PASS("pgo-instr-gen", PGOInstrumentationGen()) diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp index f4da516..ab5a8fb 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.cpp @@ -30,7 +30,7 @@ void llvm::initializeObjCARCOpts(PassRegistry &Registry) { initializeObjCARCAPElimPass(Registry); initializeObjCARCExpandPass(Registry); initializeObjCARCContractPass(Registry); - initializeObjCARCOptPass(Registry); + initializeObjCARCOptLegacyPassPass(Registry); initializePAEvalPass(Registry); } diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp index cb1fa80..450a07d 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -65,6 +65,7 @@ #include "llvm/Support/Debug.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Transforms/ObjCARC.h" #include #include #include @@ -480,123 +481,133 @@ raw_ostream &llvm::operator<<(raw_ostream &OS, BBState &BBInfo) { namespace { /// The main ARC optimization pass. - class ObjCARCOpt : public FunctionPass { - bool Changed; - ProvenanceAnalysis PA; - - /// A cache of references to runtime entry point constants. - ARCRuntimeEntryPoints EP; - - /// A cache of MDKinds that can be passed into other functions to propagate - /// MDKind identifiers. - ARCMDKindCache MDKindCache; - - /// A flag indicating whether this optimization pass should run. - bool Run; - - /// A flag indicating whether the optimization that removes or moves - /// retain/release pairs should be performed. - bool DisableRetainReleasePairing = false; - - /// Flags which determine whether each of the interesting runtime functions - /// is in fact used in the current function. - unsigned UsedInThisFunction; - - bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV); - void OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV, - ARCInstKind &Class); - void OptimizeIndividualCalls(Function &F); - - /// Optimize an individual call, optionally passing the - /// GetArgRCIdentityRoot if it has already been computed. - void OptimizeIndividualCallImpl( - Function &F, DenseMap &BlockColors, - Instruction *Inst, ARCInstKind Class, const Value *Arg); - - /// Try to optimize an AutoreleaseRV with a RetainRV or ClaimRV. If the - /// optimization occurs, returns true to indicate that the caller should - /// assume the instructions are dead. - bool OptimizeInlinedAutoreleaseRVCall( - Function &F, DenseMap &BlockColors, - Instruction *Inst, const Value *&Arg, ARCInstKind Class, - Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg); - - void CheckForCFGHazards(const BasicBlock *BB, - DenseMap &BBStates, - BBState &MyStates) const; - bool VisitInstructionBottomUp(Instruction *Inst, BasicBlock *BB, - BlotMapVector &Retains, - BBState &MyStates); - bool VisitBottomUp(BasicBlock *BB, - DenseMap &BBStates, - BlotMapVector &Retains); - bool VisitInstructionTopDown(Instruction *Inst, - DenseMap &Releases, - BBState &MyStates); - bool VisitTopDown(BasicBlock *BB, - DenseMap &BBStates, - DenseMap &Releases); - bool Visit(Function &F, DenseMap &BBStates, - BlotMapVector &Retains, - DenseMap &Releases); - - void MoveCalls(Value *Arg, RRInfo &RetainsToMove, RRInfo &ReleasesToMove, - BlotMapVector &Retains, - DenseMap &Releases, - SmallVectorImpl &DeadInsts, Module *M); - - bool - PairUpRetainsAndReleases(DenseMap &BBStates, - BlotMapVector &Retains, - DenseMap &Releases, Module *M, - Instruction * Retain, - SmallVectorImpl &DeadInsts, - RRInfo &RetainsToMove, RRInfo &ReleasesToMove, - Value *Arg, bool KnownSafe, - bool &AnyPairsCompletelyEliminated); - - bool PerformCodePlacement(DenseMap &BBStates, - BlotMapVector &Retains, - DenseMap &Releases, Module *M); - - void OptimizeWeakCalls(Function &F); - - bool OptimizeSequences(Function &F); - - void OptimizeReturns(Function &F); +class ObjCARCOpt { + bool Changed; + ProvenanceAnalysis PA; + + /// A cache of references to runtime entry point constants. + ARCRuntimeEntryPoints EP; + + /// A cache of MDKinds that can be passed into other functions to propagate + /// MDKind identifiers. + ARCMDKindCache MDKindCache; + + /// A flag indicating whether this optimization pass should run. + bool Run; + + /// A flag indicating whether the optimization that removes or moves + /// retain/release pairs should be performed. + bool DisableRetainReleasePairing = false; + + /// Flags which determine whether each of the interesting runtime functions + /// is in fact used in the current function. + unsigned UsedInThisFunction; + + bool OptimizeRetainRVCall(Function &F, Instruction *RetainRV); + void OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV, + ARCInstKind &Class); + void OptimizeIndividualCalls(Function &F); + + /// Optimize an individual call, optionally passing the + /// GetArgRCIdentityRoot if it has already been computed. + void OptimizeIndividualCallImpl( + Function &F, DenseMap &BlockColors, + Instruction *Inst, ARCInstKind Class, const Value *Arg); + + /// Try to optimize an AutoreleaseRV with a RetainRV or ClaimRV. If the + /// optimization occurs, returns true to indicate that the caller should + /// assume the instructions are dead. + bool OptimizeInlinedAutoreleaseRVCall( + Function &F, DenseMap &BlockColors, + Instruction *Inst, const Value *&Arg, ARCInstKind Class, + Instruction *AutoreleaseRV, const Value *&AutoreleaseRVArg); + + void CheckForCFGHazards(const BasicBlock *BB, + DenseMap &BBStates, + BBState &MyStates) const; + bool VisitInstructionBottomUp(Instruction *Inst, BasicBlock *BB, + BlotMapVector &Retains, + BBState &MyStates); + bool VisitBottomUp(BasicBlock *BB, + DenseMap &BBStates, + BlotMapVector &Retains); + bool VisitInstructionTopDown(Instruction *Inst, + DenseMap &Releases, + BBState &MyStates); + bool VisitTopDown(BasicBlock *BB, + DenseMap &BBStates, + DenseMap &Releases); + bool Visit(Function &F, DenseMap &BBStates, + BlotMapVector &Retains, + DenseMap &Releases); + + void MoveCalls(Value *Arg, RRInfo &RetainsToMove, RRInfo &ReleasesToMove, + BlotMapVector &Retains, + DenseMap &Releases, + SmallVectorImpl &DeadInsts, Module *M); + + bool PairUpRetainsAndReleases(DenseMap &BBStates, + BlotMapVector &Retains, + DenseMap &Releases, Module *M, + Instruction *Retain, + SmallVectorImpl &DeadInsts, + RRInfo &RetainsToMove, RRInfo &ReleasesToMove, + Value *Arg, bool KnownSafe, + bool &AnyPairsCompletelyEliminated); + + bool PerformCodePlacement(DenseMap &BBStates, + BlotMapVector &Retains, + DenseMap &Releases, Module *M); + + void OptimizeWeakCalls(Function &F); + + bool OptimizeSequences(Function &F); + + void OptimizeReturns(Function &F); #ifndef NDEBUG - void GatherStatistics(Function &F, bool AfterOptimization = false); + void GatherStatistics(Function &F, bool AfterOptimization = false); #endif - void getAnalysisUsage(AnalysisUsage &AU) const override; - bool doInitialization(Module &M) override; - bool runOnFunction(Function &F) override; - void releaseMemory() override; - public: - static char ID; - - ObjCARCOpt() : FunctionPass(ID) { - initializeObjCARCOptPass(*PassRegistry::getPassRegistry()); - } - }; + void init(Module &M); + bool run(Function &F, AAResults &AA); + void releaseMemory(); +}; + +/// 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().getAAResults()); + } + void releaseMemory() override { OCAO.releaseMemory(); } + static char ID; +private: + ObjCARCOpt OCAO; +}; } // end anonymous namespace -char ObjCARCOpt::ID = 0; +char ObjCARCOptLegacyPass::ID = 0; -INITIALIZE_PASS_BEGIN(ObjCARCOpt, - "objc-arc", "ObjC ARC optimization", false, false) +INITIALIZE_PASS_BEGIN(ObjCARCOptLegacyPass, "objc-arc", "ObjC ARC optimization", + false, false) INITIALIZE_PASS_DEPENDENCY(ObjCARCAAWrapperPass) -INITIALIZE_PASS_END(ObjCARCOpt, - "objc-arc", "ObjC ARC optimization", false, false) +INITIALIZE_PASS_END(ObjCARCOptLegacyPass, "objc-arc", "ObjC ARC optimization", + false, false) -Pass *llvm::createObjCARCOptPass() { - return new ObjCARCOpt(); -} +Pass *llvm::createObjCARCOptPass() { return new ObjCARCOptLegacyPass(); } -void ObjCARCOpt::getAnalysisUsage(AnalysisUsage &AU) const { +void ObjCARCOptLegacyPass::getAnalysisUsage(AnalysisUsage &AU) const { AU.addRequired(); AU.addRequired(); // ARC optimization doesn't currently split critical edges. @@ -2393,14 +2404,14 @@ ObjCARCOpt::GatherStatistics(Function &F, bool AfterOptimization) { } #endif -bool ObjCARCOpt::doInitialization(Module &M) { +void ObjCARCOpt::init(Module &M) { if (!EnableARCOpts) - return false; + return; // If nothing in the Module uses ARC, don't do anything. Run = ModuleHasARC(M); if (!Run) - return false; + return; // Intuitively, objc_retain and others are nocapture, however in practice // they are not, because they return their argument value. And objc_release @@ -2409,11 +2420,9 @@ bool ObjCARCOpt::doInitialization(Module &M) { // Initialize our runtime entry point cache. EP.init(&M); - - return false; } -bool ObjCARCOpt::runOnFunction(Function &F) { +bool ObjCARCOpt::run(Function &F, AAResults &AA) { if (!EnableARCOpts) return false; @@ -2427,7 +2436,7 @@ bool ObjCARCOpt::runOnFunction(Function &F) { << " >>>" "\n"); - PA.setAA(&getAnalysis().getAAResults()); + PA.setAA(&AA); #ifndef NDEBUG if (AreStatisticsEnabled()) { @@ -2484,3 +2493,22 @@ void ObjCARCOpt::releaseMemory() { /// @} /// + +PreservedAnalyses ObjCARCOptPass::run(Module &M, ModuleAnalysisManager &AM) { + ObjCARCOpt OCAO; + OCAO.init(M); + + auto &FAM = AM.getResult(M).getManager(); + bool Changed = false; + for (Function &F : M) { + if (F.isDeclaration()) + continue; + Changed |= OCAO.run(F, FAM.getResult(F)); + } + if (Changed) { + PreservedAnalyses PA; + PA.preserveSet(); + return PA; + } + return PreservedAnalyses::all(); +} diff --git a/llvm/test/Transforms/ObjCARC/basic.ll b/llvm/test/Transforms/ObjCARC/basic.ll index cc1120b..b25049c 100644 --- a/llvm/test/Transforms/ObjCARC/basic.ll +++ b/llvm/test/Transforms/ObjCARC/basic.ll @@ -1,4 +1,5 @@ ; RUN: opt -basic-aa -objc-arc -S < %s | FileCheck %s +; RUN: opt -aa-pipeline=basic-aa -passes=objc-arc -S < %s | FileCheck %s target datalayout = "e-p:64:64:64" diff --git a/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn index 5044fc1..9afe48d 100644 --- a/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/lib/Passes/BUILD.gn @@ -11,6 +11,7 @@ static_library("Passes") { "//llvm/lib/Transforms/IPO", "//llvm/lib/Transforms/InstCombine", "//llvm/lib/Transforms/Instrumentation", + "//llvm/lib/Transforms/ObjCARC", "//llvm/lib/Transforms/Scalar", "//llvm/lib/Transforms/Utils", "//llvm/lib/Transforms/Vectorize", -- 2.7.4