1 //===- ObjCARCAPElim.cpp - ObjC ARC Optimization --------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 /// \file 9 /// 10 /// This file defines ObjC ARC optimizations. ARC stands for Automatic 11 /// Reference Counting and is a system for managing reference counts for objects 12 /// in Objective C. 13 /// 14 /// This specific file implements optimizations which remove extraneous 15 /// autorelease pools. 16 /// 17 /// WARNING: This file knows about certain library functions. It recognizes them 18 /// by name, and hardwires knowledge of their semantics. 19 /// 20 /// WARNING: This file knows about how certain Objective-C library functions are 21 /// used. Naive LLVM IR transformations which would otherwise be 22 /// behavior-preserving may break these assumptions. 23 /// 24 //===----------------------------------------------------------------------===// 25 26 #include "ObjCARC.h" 27 #include "llvm/ADT/STLExtras.h" 28 #include "llvm/IR/Constants.h" 29 #include "llvm/IR/PassManager.h" 30 #include "llvm/InitializePasses.h" 31 #include "llvm/Support/Debug.h" 32 #include "llvm/Support/raw_ostream.h" 33 #include "llvm/Transforms/ObjCARC.h" 34 35 using namespace llvm; 36 using namespace llvm::objcarc; 37 38 #define DEBUG_TYPE "objc-arc-ap-elim" 39 40 namespace { 41 42 /// Interprocedurally determine if calls made by the given call site can 43 /// possibly produce autoreleases. 44 bool MayAutorelease(const CallBase &CB, unsigned Depth = 0) { 45 if (const Function *Callee = CB.getCalledFunction()) { 46 if (!Callee->hasExactDefinition()) 47 return true; 48 for (const BasicBlock &BB : *Callee) { 49 for (const Instruction &I : BB) 50 if (const CallBase *JCB = dyn_cast<CallBase>(&I)) 51 // This recursion depth limit is arbitrary. It's just great 52 // enough to cover known interesting testcases. 53 if (Depth < 3 && !JCB->onlyReadsMemory() && 54 MayAutorelease(*JCB, Depth + 1)) 55 return true; 56 } 57 return false; 58 } 59 60 return true; 61 } 62 63 bool OptimizeBB(BasicBlock *BB) { 64 bool Changed = false; 65 66 Instruction *Push = nullptr; 67 for (Instruction &Inst : llvm::make_early_inc_range(*BB)) { 68 switch (GetBasicARCInstKind(&Inst)) { 69 case ARCInstKind::AutoreleasepoolPush: 70 Push = &Inst; 71 break; 72 case ARCInstKind::AutoreleasepoolPop: 73 // If this pop matches a push and nothing in between can autorelease, 74 // zap the pair. 75 if (Push && cast<CallInst>(&Inst)->getArgOperand(0) == Push) { 76 Changed = true; 77 LLVM_DEBUG(dbgs() << "ObjCARCAPElim::OptimizeBB: Zapping push pop " 78 "autorelease pair:\n" 79 " Pop: " 80 << Inst << "\n" 81 << " Push: " << *Push 82 << "\n"); 83 Inst.eraseFromParent(); 84 Push->eraseFromParent(); 85 } 86 Push = nullptr; 87 break; 88 case ARCInstKind::CallOrUser: 89 if (MayAutorelease(cast<CallBase>(Inst))) 90 Push = nullptr; 91 break; 92 default: 93 break; 94 } 95 } 96 97 return Changed; 98 } 99 100 bool runImpl(Module &M) { 101 if (!EnableARCOpts) 102 return false; 103 104 // If nothing in the Module uses ARC, don't do anything. 105 if (!ModuleHasARC(M)) 106 return false; 107 // Find the llvm.global_ctors variable, as the first step in 108 // identifying the global constructors. In theory, unnecessary autorelease 109 // pools could occur anywhere, but in practice it's pretty rare. Global 110 // ctors are a place where autorelease pools get inserted automatically, 111 // so it's pretty common for them to be unnecessary, and it's pretty 112 // profitable to eliminate them. 113 GlobalVariable *GV = M.getGlobalVariable("llvm.global_ctors"); 114 if (!GV) 115 return false; 116 117 assert(GV->hasDefinitiveInitializer() && 118 "llvm.global_ctors is uncooperative!"); 119 120 bool Changed = false; 121 122 // Dig the constructor functions out of GV's initializer. 123 ConstantArray *Init = cast<ConstantArray>(GV->getInitializer()); 124 for (User::op_iterator OI = Init->op_begin(), OE = Init->op_end(); 125 OI != OE; ++OI) { 126 Value *Op = *OI; 127 // llvm.global_ctors is an array of three-field structs where the second 128 // members are constructor functions. 129 Function *F = dyn_cast<Function>(cast<ConstantStruct>(Op)->getOperand(1)); 130 // If the user used a constructor function with the wrong signature and 131 // it got bitcasted or whatever, look the other way. 132 if (!F) 133 continue; 134 // Only look at function definitions. 135 if (F->isDeclaration()) 136 continue; 137 // Only look at functions with one basic block. 138 if (std::next(F->begin()) != F->end()) 139 continue; 140 // Ok, a single-block constructor function definition. Try to optimize it. 141 Changed |= OptimizeBB(&F->front()); 142 } 143 144 return Changed; 145 } 146 147 /// Autorelease pool elimination. 148 class ObjCARCAPElim : public ModulePass { 149 void getAnalysisUsage(AnalysisUsage &AU) const override; 150 bool runOnModule(Module &M) override; 151 152 public: 153 static char ID; 154 ObjCARCAPElim() : ModulePass(ID) { 155 initializeObjCARCAPElimPass(*PassRegistry::getPassRegistry()); 156 } 157 }; 158 } // namespace 159 160 char ObjCARCAPElim::ID = 0; 161 INITIALIZE_PASS(ObjCARCAPElim, "objc-arc-apelim", 162 "ObjC ARC autorelease pool elimination", false, false) 163 164 Pass *llvm::createObjCARCAPElimPass() { return new ObjCARCAPElim(); } 165 166 void ObjCARCAPElim::getAnalysisUsage(AnalysisUsage &AU) const { 167 AU.setPreservesCFG(); 168 } 169 170 bool ObjCARCAPElim::runOnModule(Module &M) { 171 if (skipModule(M)) 172 return false; 173 return runImpl(M); 174 } 175 176 PreservedAnalyses ObjCARCAPElimPass::run(Module &M, ModuleAnalysisManager &AM) { 177 if (!runImpl(M)) 178 return PreservedAnalyses::all(); 179 PreservedAnalyses PA; 180 PA.preserveSet<CFGAnalyses>(); 181 return PA; 182 } 183