/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/Transforms/ObjCARC/ObjCARCExpand.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===- ObjCARCExpand.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 | | /// This file defines ObjC ARC optimizations. ARC stands for Automatic |
10 | | /// Reference Counting and is a system for managing reference counts for objects |
11 | | /// in Objective C. |
12 | | /// |
13 | | /// This specific file deals with early optimizations which perform certain |
14 | | /// cleanup operations. |
15 | | /// |
16 | | /// WARNING: This file knows about certain library functions. It recognizes them |
17 | | /// by name, and hardwires knowledge of their semantics. |
18 | | /// |
19 | | /// WARNING: This file knows about how certain Objective-C library functions are |
20 | | /// used. Naive LLVM IR transformations which would otherwise be |
21 | | /// behavior-preserving may break these assumptions. |
22 | | /// |
23 | | //===----------------------------------------------------------------------===// |
24 | | |
25 | | #include "ObjCARC.h" |
26 | | #include "llvm/IR/Function.h" |
27 | | #include "llvm/IR/InstIterator.h" |
28 | | #include "llvm/IR/Instruction.h" |
29 | | #include "llvm/IR/Instructions.h" |
30 | | #include "llvm/IR/Value.h" |
31 | | #include "llvm/Pass.h" |
32 | | #include "llvm/PassAnalysisSupport.h" |
33 | | #include "llvm/PassRegistry.h" |
34 | | #include "llvm/PassSupport.h" |
35 | | #include "llvm/Support/Casting.h" |
36 | | #include "llvm/Support/Debug.h" |
37 | | #include "llvm/Support/raw_ostream.h" |
38 | | |
39 | | #define DEBUG_TYPE "objc-arc-expand" |
40 | | |
41 | | namespace llvm { |
42 | | class Module; |
43 | | } |
44 | | |
45 | | using namespace llvm; |
46 | | using namespace llvm::objcarc; |
47 | | |
48 | | namespace { |
49 | | /// Early ARC transformations. |
50 | | class ObjCARCExpand : public FunctionPass { |
51 | | void getAnalysisUsage(AnalysisUsage &AU) const override; |
52 | | bool doInitialization(Module &M) override; |
53 | | bool runOnFunction(Function &F) override; |
54 | | |
55 | | /// A flag indicating whether this optimization pass should run. |
56 | | bool Run; |
57 | | |
58 | | public: |
59 | | static char ID; |
60 | 8 | ObjCARCExpand() : FunctionPass(ID) { |
61 | 8 | initializeObjCARCExpandPass(*PassRegistry::getPassRegistry()); |
62 | 8 | } |
63 | | }; |
64 | | } |
65 | | |
66 | | char ObjCARCExpand::ID = 0; |
67 | | INITIALIZE_PASS(ObjCARCExpand, |
68 | | "objc-arc-expand", "ObjC ARC expansion", false, false) |
69 | | |
70 | 6 | Pass *llvm::createObjCARCExpandPass() { |
71 | 6 | return new ObjCARCExpand(); |
72 | 6 | } |
73 | | |
74 | 8 | void ObjCARCExpand::getAnalysisUsage(AnalysisUsage &AU) const { |
75 | 8 | AU.setPreservesCFG(); |
76 | 8 | } |
77 | | |
78 | 8 | bool ObjCARCExpand::doInitialization(Module &M) { |
79 | 8 | Run = ModuleHasARC(M); |
80 | 8 | return false; |
81 | 8 | } |
82 | | |
83 | 74 | bool ObjCARCExpand::runOnFunction(Function &F) { |
84 | 74 | if (!EnableARCOpts) |
85 | 0 | return false; |
86 | 74 | |
87 | 74 | // If nothing in the Module uses ARC, don't do anything. |
88 | 74 | if (!Run) |
89 | 3 | return false; |
90 | 71 | |
91 | 71 | bool Changed = false; |
92 | 71 | |
93 | 71 | LLVM_DEBUG(dbgs() << "ObjCARCExpand: Visiting Function: " << F.getName() |
94 | 71 | << "\n"); |
95 | 71 | |
96 | 2.05k | for (inst_iterator I = inst_begin(&F), E = inst_end(&F); I != E; ++I1.98k ) { |
97 | 1.98k | Instruction *Inst = &*I; |
98 | 1.98k | |
99 | 1.98k | LLVM_DEBUG(dbgs() << "ObjCARCExpand: Visiting: " << *Inst << "\n"); |
100 | 1.98k | |
101 | 1.98k | switch (GetBasicARCInstKind(Inst)) { |
102 | 1.98k | case ARCInstKind::Retain: |
103 | 50 | case ARCInstKind::RetainRV: |
104 | 50 | case ARCInstKind::Autorelease: |
105 | 50 | case ARCInstKind::AutoreleaseRV: |
106 | 50 | case ARCInstKind::FusedRetainAutorelease: |
107 | 50 | case ARCInstKind::FusedRetainAutoreleaseRV: { |
108 | 50 | // These calls return their argument verbatim, as a low-level |
109 | 50 | // optimization. However, this makes high-level optimizations |
110 | 50 | // harder. Undo any uses of this optimization that the front-end |
111 | 50 | // emitted here. We'll redo them in the contract pass. |
112 | 50 | Changed = true; |
113 | 50 | Value *Value = cast<CallInst>(Inst)->getArgOperand(0); |
114 | 50 | LLVM_DEBUG(dbgs() << "ObjCARCExpand: Old = " << *Inst |
115 | 50 | << "\n" |
116 | 50 | " New = " |
117 | 50 | << *Value << "\n"); |
118 | 50 | Inst->replaceAllUsesWith(Value); |
119 | 50 | break; |
120 | 50 | } |
121 | 1.93k | default: |
122 | 1.93k | break; |
123 | 1.98k | } |
124 | 1.98k | } |
125 | 71 | |
126 | 71 | LLVM_DEBUG(dbgs() << "ObjCARCExpand: Finished List.\n\n"); |
127 | 71 | |
128 | 71 | return Changed; |
129 | 71 | } |