[llvm-commits] [llvm] r148330 - in /llvm/trunk: include/llvm/InitializePasses.h include/llvm/LinkAllPasses.h include/llvm/Transforms/Scalar.h lib/Transforms/Scalar/ObjCARC.cpp lib/Transforms/Scalar/Scalar.cpp test/Transforms/ObjCARC/apelim.ll

Eli Friedman eli.friedman at gmail.com
Tue Jan 17 13:15:01 PST 2012


On Tue, Jan 17, 2012 at 12:52 PM, Dan Gohman <gohman at apple.com> wrote:
> Author: djg
> Date: Tue Jan 17 14:52:24 2012
> New Revision: 148330
>
> URL: http://llvm.org/viewvc/llvm-project?rev=148330&view=rev
> Log:
> Add a new ObjC ARC optimization pass to eliminate unneeded
> autorelease push+pop pairs.
>
> Added:
>    llvm/trunk/test/Transforms/ObjCARC/apelim.ll
> Modified:
>    llvm/trunk/include/llvm/InitializePasses.h
>    llvm/trunk/include/llvm/LinkAllPasses.h
>    llvm/trunk/include/llvm/Transforms/Scalar.h
>    llvm/trunk/lib/Transforms/Scalar/ObjCARC.cpp
>    llvm/trunk/lib/Transforms/Scalar/Scalar.cpp
>
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=148330&r1=148329&r2=148330&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Tue Jan 17 14:52:24 2012
> @@ -168,6 +168,7 @@
>  void initializeNoProfileInfoPass(PassRegistry&);
>  void initializeNoPathProfileInfoPass(PassRegistry&);
>  void initializeObjCARCAliasAnalysisPass(PassRegistry&);
> +void initializeObjCARCAPElimPass(PassRegistry&);
>  void initializeObjCARCExpandPass(PassRegistry&);
>  void initializeObjCARCContractPass(PassRegistry&);
>  void initializeObjCARCOptPass(PassRegistry&);
>
> Modified: llvm/trunk/include/llvm/LinkAllPasses.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/LinkAllPasses.h?rev=148330&r1=148329&r2=148330&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/LinkAllPasses.h (original)
> +++ llvm/trunk/include/llvm/LinkAllPasses.h Tue Jan 17 14:52:24 2012
> @@ -97,6 +97,7 @@
>       (void) llvm::createNoAAPass();
>       (void) llvm::createNoProfileInfoPass();
>       (void) llvm::createObjCARCAliasAnalysisPass();
> +      (void) llvm::createObjCARCAPElimPass();
>       (void) llvm::createObjCARCExpandPass();
>       (void) llvm::createObjCARCContractPass();
>       (void) llvm::createObjCARCOptPass();
>
> Modified: llvm/trunk/include/llvm/Transforms/Scalar.h
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Transforms/Scalar.h?rev=148330&r1=148329&r2=148330&view=diff
> ==============================================================================
> --- llvm/trunk/include/llvm/Transforms/Scalar.h (original)
> +++ llvm/trunk/include/llvm/Transforms/Scalar.h Tue Jan 17 14:52:24 2012
> @@ -327,6 +327,12 @@
>
>  //===----------------------------------------------------------------------===//
>  //
> +// ObjCARCAPElim - ObjC ARC autorelease pool elimination.
> +//
> +Pass *createObjCARCAPElimPass();
> +
> +//===----------------------------------------------------------------------===//
> +//
>  // ObjCARCExpand - ObjC ARC preliminary simplifications.
>  //
>  Pass *createObjCARCExpandPass();
>
> Modified: llvm/trunk/lib/Transforms/Scalar/ObjCARC.cpp
> URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/ObjCARC.cpp?rev=148330&r1=148329&r2=148330&view=diff
> ==============================================================================
> --- llvm/trunk/lib/Transforms/Scalar/ObjCARC.cpp (original)
> +++ llvm/trunk/lib/Transforms/Scalar/ObjCARC.cpp Tue Jan 17 14:52:24 2012
> @@ -375,7 +375,7 @@
>   }
>
>   // Otherwise, be conservative.
> -  return IC_User;
> +  return isa<InvokeInst>(V) ? IC_CallOrUser : IC_User;
>  }
>
>  /// IsRetain - Test if the the given class is objc_retain or
> @@ -884,6 +884,122 @@
>  }
>
>  //===----------------------------------------------------------------------===//
> +// ARC autorelease pool elimination.
> +//===----------------------------------------------------------------------===//
> +
> +namespace {
> +  /// ObjCARCAPElim - Autorelease pool elimination.
> +  class ObjCARCAPElim : public ModulePass {
> +    virtual void getAnalysisUsage(AnalysisUsage &AU) const;
> +    virtual bool runOnModule(Module &M);
> +
> +    bool MayAutorelease(CallSite CS);
> +    bool OptimizeBB(BasicBlock *BB);
> +
> +  public:
> +    static char ID;
> +    ObjCARCAPElim() : ModulePass(ID) {
> +      initializeObjCARCAPElimPass(*PassRegistry::getPassRegistry());
> +    }
> +  };
> +}
> +
> +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();
> +}
> +
> +/// MayAutorelease - Interprocedurally determine if calls made by the
> +/// given call site can possibly produce autoreleases.
> +bool ObjCARCAPElim::MayAutorelease(CallSite CS) {
> +  if (Function *Callee = CS.getCalledFunction()) {
> +    if (Callee->isDeclaration() || Callee->mayBeOverridden())
> +      return true;
> +    for (Function::iterator I = Callee->begin(), E = Callee->end();
> +         I != E; ++I) {
> +      BasicBlock *BB = I;
> +      for (BasicBlock::iterator J = BB->begin(), F = BB->end(); J != F; ++J)
> +        if (CallSite JCS = CallSite(J))
> +          if (!JCS.onlyReadsMemory() && MayAutorelease(JCS))
> +            return true;
> +    }
> +    return false;
> +  }
> +
> +  return true;
> +}
> +
> +bool ObjCARCAPElim::OptimizeBB(BasicBlock *BB) {
> +  bool Changed = false;
> +
> +  Instruction *Push = 0;
> +  for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ) {
> +    Instruction *Inst = I++;
> +    switch (GetBasicInstructionClass(Inst)) {
> +    case IC_AutoreleasepoolPush:
> +      Push = Inst;
> +      break;
> +    case IC_AutoreleasepoolPop:
> +      // If this pop matches a push and nothing in between can autorelease,
> +      // zap the pair.
> +      if (Push && cast<CallInst>(Inst)->getArgOperand(0) == Push) {
> +        Changed = true;
> +        Inst->eraseFromParent();
> +        Push->eraseFromParent();
> +      }
> +      Push = 0;
> +      break;
> +    case IC_CallOrUser:
> +      if (MayAutorelease(CallSite(Inst)))
> +        Push = 0;
> +      break;
> +    default:
> +      break;
> +    }
> +  }
> +
> +  return Changed;
> +}
> +
> +bool ObjCARCAPElim::runOnModule(Module &M) {
> +  if (!EnableARCOpts)
> +    return false;
> +
> +  // If nothing in the Module uses ARC, don't do anything.
> +  if (!ModuleHasARC(M))
> +    return false;
> +
> +  bool Changed = false;
> +
> +  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I) {
> +    Function *F = I;
> +    // Only look at function definitions.
> +    if (F->isDeclaration())
> +      continue;
> +    // Only look at global constructor functions. Unfortunately,
> +    // the name is the most convenient way to recognize them.
> +    if (!F->getName().startswith("_GLOBAL__I_"))
> +      continue;

This seems way more specialized than it needs to be; why not a more
general transformation that removes all redundant
objc_autoreleasePoolPush/objc_autoreleasePoolPop pairs?

Anyway, if you really only want global constructors, traversing
llvm.global_ctors seems like it would be more reliable.

-Eli




More information about the llvm-commits mailing list