Completely short-circuit out ARC optimization if the ARC runtime
authorDan Gohman <gohman@apple.com>
Mon, 20 Jun 2011 23:20:43 +0000 (23:20 +0000)
committerDan Gohman <gohman@apple.com>
Mon, 20 Jun 2011 23:20:43 +0000 (23:20 +0000)
functions do not appear in the module.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@133478 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Scalar/ObjCARC.cpp

index 6cd35e5c9e7854f63cdd12230cecb616a6f2e5c2..89a451ef7ad7e77a6c097aa19dcadf17a1ed52f5 100644 (file)
@@ -33,6 +33,7 @@
 #include "llvm/Intrinsics.h"
 #include "llvm/GlobalVariable.h"
 #include "llvm/DerivedTypes.h"
+#include "llvm/Module.h"
 #include "llvm/Analysis/ValueTracking.h"
 #include "llvm/Transforms/Utils/Local.h"
 #include "llvm/Support/CallSite.h"
@@ -564,6 +565,29 @@ static const Value *FindSingleUseIdentifiedObject(const Value *Arg) {
   return 0;
 }
 
+/// ModuleHasARC - Test if the given module looks interesting to run ARC
+/// optimization on.
+static bool ModuleHasARC(const Module &M) {
+  return
+    M.getNamedValue("objc_retain") ||
+    M.getNamedValue("objc_release") ||
+    M.getNamedValue("objc_autorelease") ||
+    M.getNamedValue("objc_retainAutoreleasedReturnValue") ||
+    M.getNamedValue("objc_retainBlock") ||
+    M.getNamedValue("objc_autoreleaseReturnValue") ||
+    M.getNamedValue("objc_autoreleasePoolPush") ||
+    M.getNamedValue("objc_loadWeakRetained") ||
+    M.getNamedValue("objc_loadWeak") ||
+    M.getNamedValue("objc_destroyWeak") ||
+    M.getNamedValue("objc_storeWeak") ||
+    M.getNamedValue("objc_initWeak") ||
+    M.getNamedValue("objc_moveWeak") ||
+    M.getNamedValue("objc_copyWeak") ||
+    M.getNamedValue("objc_retainedObject") ||
+    M.getNamedValue("objc_unretainedObject") ||
+    M.getNamedValue("objc_unretainedPointer");
+}
+
 //===----------------------------------------------------------------------===//
 // ARC AliasAnalysis.
 //===----------------------------------------------------------------------===//
@@ -749,8 +773,12 @@ namespace {
   /// ObjCARCExpand - Early ARC transformations.
   class ObjCARCExpand : public FunctionPass {
     virtual void getAnalysisUsage(AnalysisUsage &AU) const;
+    virtual bool doInitialization(Module &M);
     virtual bool runOnFunction(Function &F);
 
+    /// Run - A flag indicating whether this optimization pass should run.
+    bool Run;
+
   public:
     static char ID;
     ObjCARCExpand() : FunctionPass(ID) {
@@ -771,10 +799,19 @@ void ObjCARCExpand::getAnalysisUsage(AnalysisUsage &AU) const {
   AU.setPreservesCFG();
 }
 
+bool ObjCARCExpand::doInitialization(Module &M) {
+  Run = ModuleHasARC(M);
+  return false;
+}
+
 bool ObjCARCExpand::runOnFunction(Function &F) {
   if (!EnableARCOpts)
     return false;
 
+  // If nothing in the Module uses ARC, don't do anything.
+  if (!Run)
+    return false;
+
   bool Changed = false;
 
   for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I) {
@@ -840,8 +877,9 @@ bool ObjCARCExpand::runOnFunction(Function &F) {
 // usually can't sink them past other calls, which would be the main
 // case where it would be useful.
 
+/// TODO: The pointer returned from objc_loadWeakRetained is retained.
+
 #include "llvm/GlobalAlias.h"
-#include "llvm/Module.h"
 #include "llvm/Constants.h"
 #include "llvm/LLVMContext.h"
 #include "llvm/Support/ErrorHandling.h"
@@ -1365,10 +1403,12 @@ namespace {
     bool Changed;
     ProvenanceAnalysis PA;
 
+    /// Run - A flag indicating whether this optimization pass should run.
+    bool Run;
+
     /// RetainFunc, RelaseFunc - Declarations for objc_retain,
     /// objc_retainBlock, and objc_release.
-    Function *RetainFunc, *RetainBlockFunc, *RetainRVFunc, *ReleaseFunc,
-             *AutoreleaseFunc;
+    Function *RetainFunc, *RetainBlockFunc, *RetainRVFunc, *ReleaseFunc;
 
     /// RetainRVCallee, etc. - Declarations for ObjC runtime
     /// functions, for use in creating calls to them. These are initialized
@@ -3069,6 +3109,10 @@ bool ObjCARCOpt::doInitialization(Module &M) {
   if (!EnableARCOpts)
     return false;
 
+  Run = ModuleHasARC(M);
+  if (!Run)
+    return false;
+
   // Identify the imprecise release metadata kind.
   ImpreciseReleaseMDKind =
     M.getContext().getMDKindID("clang.imprecise_release");
@@ -3078,7 +3122,6 @@ bool ObjCARCOpt::doInitialization(Module &M) {
   RetainBlockFunc = M.getFunction("objc_retainBlock");
   RetainRVFunc = M.getFunction("objc_retainAutoreleasedReturnValue");
   ReleaseFunc = M.getFunction("objc_release");
-  AutoreleaseFunc = M.getFunction("objc_autorelease");
 
   // Intuitively, objc_retain and others are nocapture, however in practice
   // they are not, because they return their argument value. And objc_release
@@ -3098,6 +3141,10 @@ bool ObjCARCOpt::runOnFunction(Function &F) {
   if (!EnableARCOpts)
     return false;
 
+  // If nothing in the Module uses ARC, don't do anything.
+  if (!Run)
+    return false;
+
   Changed = false;
 
   PA.setAA(&getAnalysis<AliasAnalysis>());
@@ -3162,6 +3209,9 @@ namespace {
     DominatorTree *DT;
     ProvenanceAnalysis PA;
 
+    /// Run - A flag indicating whether this optimization pass should run.
+    bool Run;
+
     /// StoreStrongCallee, etc. - Declarations for ObjC runtime
     /// functions, for use in creating calls to them. These are initialized
     /// lazily to avoid cluttering up the Module with unused declarations.
@@ -3384,6 +3434,10 @@ void ObjCARCContract::ContractRelease(Instruction *Release,
 }
 
 bool ObjCARCContract::doInitialization(Module &M) {
+  Run = ModuleHasARC(M);
+  if (!Run)
+    return false;
+
   // These are initialized lazily.
   StoreStrongCallee = 0;
   RetainAutoreleaseCallee = 0;
@@ -3407,6 +3461,10 @@ bool ObjCARCContract::runOnFunction(Function &F) {
   if (!EnableARCOpts)
     return false;
 
+  // If nothing in the Module uses ARC, don't do anything.
+  if (!Run)
+    return false;
+
   Changed = false;
   AA = &getAnalysis<AliasAnalysis>();
   DT = &getAnalysis<DominatorTree>();