/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ObjCARCExpand.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 | | /// 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 deals with early optimizations which perform certain |
15 | | /// cleanup operations. |
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/IR/Function.h" |
28 | | #include "llvm/IR/InstIterator.h" |
29 | | #include "llvm/IR/Instruction.h" |
30 | | #include "llvm/IR/Instructions.h" |
31 | | #include "llvm/IR/Value.h" |
32 | | #include "llvm/Pass.h" |
33 | | #include "llvm/PassAnalysisSupport.h" |
34 | | #include "llvm/PassRegistry.h" |
35 | | #include "llvm/PassSupport.h" |
36 | | #include "llvm/Support/Casting.h" |
37 | | #include "llvm/Support/Debug.h" |
38 | | #include "llvm/Support/raw_ostream.h" |
39 | | |
40 | | #define DEBUG_TYPE "objc-arc-expand" |
41 | | |
42 | | namespace llvm { |
43 | | class Module; |
44 | | } |
45 | | |
46 | | using namespace llvm; |
47 | | using namespace llvm::objcarc; |
48 | | |
49 | | namespace { |
50 | | /// \brief Early ARC transformations. |
51 | | class ObjCARCExpand : public FunctionPass { |
52 | | void getAnalysisUsage(AnalysisUsage &AU) const override; |
53 | | bool doInitialization(Module &M) override; |
54 | | bool runOnFunction(Function &F) override; |
55 | | |
56 | | /// A flag indicating whether this optimization pass should run. |
57 | | bool Run; |
58 | | |
59 | | public: |
60 | | static char ID; |
61 | 6 | ObjCARCExpand() : FunctionPass(ID) { |
62 | 6 | initializeObjCARCExpandPass(*PassRegistry::getPassRegistry()); |
63 | 6 | } |
64 | | }; |
65 | | } |
66 | | |
67 | | char ObjCARCExpand::ID = 0; |
68 | | INITIALIZE_PASS(ObjCARCExpand, |
69 | | "objc-arc-expand", "ObjC ARC expansion", false, false) |
70 | | |
71 | 4 | Pass *llvm::createObjCARCExpandPass() { |
72 | 4 | return new ObjCARCExpand(); |
73 | 4 | } |
74 | | |
75 | 6 | void ObjCARCExpand::getAnalysisUsage(AnalysisUsage &AU) const { |
76 | 6 | AU.setPreservesCFG(); |
77 | 6 | } |
78 | | |
79 | 6 | bool ObjCARCExpand::doInitialization(Module &M) { |
80 | 6 | Run = ModuleHasARC(M); |
81 | 6 | return false; |
82 | 6 | } |
83 | | |
84 | 31 | bool ObjCARCExpand::runOnFunction(Function &F) { |
85 | 31 | if (!EnableARCOpts) |
86 | 0 | return false; |
87 | 31 | |
88 | 31 | // If nothing in the Module uses ARC, don't do anything. |
89 | 31 | if (31 !Run31 ) |
90 | 0 | return false; |
91 | 31 | |
92 | 31 | bool Changed = false; |
93 | 31 | |
94 | 31 | DEBUG(dbgs() << "ObjCARCExpand: Visiting Function: " << F.getName() << "\n"); |
95 | 31 | |
96 | 674 | for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E674 ; ++I643 ) { |
97 | 643 | Instruction *Inst = &*I; |
98 | 643 | |
99 | 643 | DEBUG(dbgs() << "ObjCARCExpand: Visiting: " << *Inst << "\n"); |
100 | 643 | |
101 | 643 | switch (GetBasicARCInstKind(Inst)) { |
102 | 24 | case ARCInstKind::Retain: |
103 | 24 | case ARCInstKind::RetainRV: |
104 | 24 | case ARCInstKind::Autorelease: |
105 | 24 | case ARCInstKind::AutoreleaseRV: |
106 | 24 | case ARCInstKind::FusedRetainAutorelease: |
107 | 24 | case ARCInstKind::FusedRetainAutoreleaseRV: { |
108 | 24 | // These calls return their argument verbatim, as a low-level |
109 | 24 | // optimization. However, this makes high-level optimizations |
110 | 24 | // harder. Undo any uses of this optimization that the front-end |
111 | 24 | // emitted here. We'll redo them in the contract pass. |
112 | 24 | Changed = true; |
113 | 24 | Value *Value = cast<CallInst>(Inst)->getArgOperand(0); |
114 | 24 | DEBUG(dbgs() << "ObjCARCExpand: Old = " << *Inst << "\n" |
115 | 24 | " New = " << *Value << "\n"); |
116 | 24 | Inst->replaceAllUsesWith(Value); |
117 | 24 | break; |
118 | 24 | } |
119 | 619 | default: |
120 | 619 | break; |
121 | 643 | } |
122 | 643 | } |
123 | 31 | |
124 | 31 | DEBUG31 (dbgs() << "ObjCARCExpand: Finished List.\n\n"); |
125 | 31 | |
126 | 31 | return Changed; |
127 | 31 | } |