[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

Dan Gohman gohman at apple.com
Tue Jan 17 13:40:36 PST 2012


On Jan 17, 2012, at 1:15 PM, Eli Friedman wrote:

> 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?

Compile time. It's less likely that any other autorelease pairs will be
easily removable, or as profitable to remove. Also, this pass has to be
interprocedural in order to achieve the desired optimization, so it can
be slow. As it is, I still need to add more safeguards to keep it from
getting out of control.

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


Good idea; I'll do that.

Dan




More information about the llvm-commits mailing list