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