1 | //===- ObjCARC.h - ObjC ARC Optimization --------------*- C++ -*-----------===// |
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 common definitions/declarations used by the ObjC ARC |
10 | /// Optimizer. ARC stands for Automatic Reference Counting and is a system for |
11 | /// managing reference counts for objects in Objective C. |
12 | /// |
13 | /// WARNING: This file knows about certain library functions. It recognizes them |
14 | /// by name, and hardwires knowledge of their semantics. |
15 | /// |
16 | /// WARNING: This file knows about how certain Objective-C library functions are |
17 | /// used. Naive LLVM IR transformations which would otherwise be |
18 | /// behavior-preserving may break these assumptions. |
19 | /// |
20 | //===----------------------------------------------------------------------===// |
21 | |
22 | #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H |
23 | #define LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H |
24 | |
25 | #include "llvm/Analysis/ObjCARCAnalysisUtils.h" |
26 | #include "llvm/Analysis/ObjCARCUtil.h" |
27 | #include "llvm/IR/EHPersonalities.h" |
28 | #include "llvm/Transforms/Utils/Local.h" |
29 | |
30 | namespace llvm { |
31 | namespace objcarc { |
32 | |
33 | /// Erase the given instruction. |
34 | /// |
35 | /// Many ObjC calls return their argument verbatim, |
36 | /// so if it's such a call and the return value has users, replace them with the |
37 | /// argument value. |
38 | /// |
39 | static inline void EraseInstruction(Instruction *CI) { |
40 | Value *OldArg = cast<CallInst>(Val: CI)->getArgOperand(i: 0); |
41 | |
42 | bool Unused = CI->use_empty(); |
43 | |
44 | if (!Unused) { |
45 | // Replace the return value with the argument. |
46 | assert((IsForwarding(GetBasicARCInstKind(CI)) || |
47 | (IsNoopOnNull(GetBasicARCInstKind(CI)) && |
48 | IsNullOrUndef(OldArg->stripPointerCasts()))) && |
49 | "Can't delete non-forwarding instruction with users!" ); |
50 | CI->replaceAllUsesWith(V: OldArg); |
51 | } |
52 | |
53 | CI->eraseFromParent(); |
54 | |
55 | if (Unused) |
56 | RecursivelyDeleteTriviallyDeadInstructions(V: OldArg); |
57 | } |
58 | |
59 | /// If Inst is a ReturnRV and its operand is a call or invoke, return the |
60 | /// operand. Otherwise return null. |
61 | static inline const Instruction *getreturnRVOperand(const Instruction &Inst, |
62 | ARCInstKind Class) { |
63 | if (Class != ARCInstKind::RetainRV) |
64 | return nullptr; |
65 | |
66 | const auto *Opnd = Inst.getOperand(i: 0)->stripPointerCasts(); |
67 | if (const auto *C = dyn_cast<CallInst>(Val: Opnd)) |
68 | return C; |
69 | return dyn_cast<InvokeInst>(Val: Opnd); |
70 | } |
71 | |
72 | /// Return the list of PHI nodes that are equivalent to PN. |
73 | template<class PHINodeTy, class VectorTy> |
74 | void getEquivalentPHIs(PHINodeTy &PN, VectorTy &PHIList) { |
75 | auto *BB = PN.getParent(); |
76 | for (auto &P : BB->phis()) { |
77 | if (&P == &PN) // Do not add PN to the list. |
78 | continue; |
79 | unsigned I = 0, E = PN.getNumIncomingValues(); |
80 | for (; I < E; ++I) { |
81 | auto *BB = PN.getIncomingBlock(I); |
82 | auto *PNOpnd = PN.getIncomingValue(I)->stripPointerCasts(); |
83 | auto *POpnd = P.getIncomingValueForBlock(BB)->stripPointerCasts(); |
84 | if (PNOpnd != POpnd) |
85 | break; |
86 | } |
87 | if (I == E) |
88 | PHIList.push_back(&P); |
89 | } |
90 | } |
91 | |
92 | static inline MDString *getRVInstMarker(Module &M) { |
93 | const char *MarkerKey = getRVMarkerModuleFlagStr(); |
94 | return dyn_cast_or_null<MDString>(Val: M.getModuleFlag(Key: MarkerKey)); |
95 | } |
96 | |
97 | /// Create a call instruction with the correct funclet token. This should be |
98 | /// called instead of calling CallInst::Create directly unless the call is |
99 | /// going to be removed from the IR before WinEHPrepare. |
100 | CallInst *createCallInstWithColors( |
101 | FunctionCallee Func, ArrayRef<Value *> Args, const Twine &NameStr, |
102 | BasicBlock::iterator InsertBefore, |
103 | const DenseMap<BasicBlock *, ColorVector> &BlockColors); |
104 | |
105 | class BundledRetainClaimRVs { |
106 | public: |
107 | BundledRetainClaimRVs(bool ContractPass) : ContractPass(ContractPass) {} |
108 | ~BundledRetainClaimRVs(); |
109 | |
110 | /// Insert a retainRV/claimRV call to the normal destination blocks of invokes |
111 | /// with operand bundle "clang.arc.attachedcall". If the edge to the normal |
112 | /// destination block is a critical edge, split it. |
113 | std::pair<bool, bool> insertAfterInvokes(Function &F, DominatorTree *DT); |
114 | |
115 | /// Insert a retainRV/claimRV call. |
116 | CallInst *insertRVCall(BasicBlock::iterator InsertPt, |
117 | CallBase *AnnotatedCall); |
118 | |
119 | /// Insert a retainRV/claimRV call with colors. |
120 | CallInst *insertRVCallWithColors( |
121 | BasicBlock::iterator InsertPt, CallBase *AnnotatedCall, |
122 | const DenseMap<BasicBlock *, ColorVector> &BlockColors); |
123 | |
124 | /// See if an instruction is a bundled retainRV/claimRV call. |
125 | bool contains(const Instruction *I) const { |
126 | if (auto *CI = dyn_cast<CallInst>(Val: I)) |
127 | return RVCalls.count(Val: CI); |
128 | return false; |
129 | } |
130 | |
131 | /// Remove a retainRV/claimRV call entirely. |
132 | void eraseInst(CallInst *CI) { |
133 | auto It = RVCalls.find(Val: CI); |
134 | if (It != RVCalls.end()) { |
135 | // Remove call to @llvm.objc.clang.arc.noop.use. |
136 | for (User *U : It->second->users()) |
137 | if (auto *CI = dyn_cast<CallInst>(Val: U)) |
138 | if (CI->getIntrinsicID() == Intrinsic::objc_clang_arc_noop_use) { |
139 | CI->eraseFromParent(); |
140 | break; |
141 | } |
142 | |
143 | auto *NewCall = CallBase::removeOperandBundle( |
144 | CB: It->second, ID: LLVMContext::OB_clang_arc_attachedcall, |
145 | InsertPt: It->second->getIterator()); |
146 | NewCall->copyMetadata(SrcInst: *It->second); |
147 | It->second->replaceAllUsesWith(V: NewCall); |
148 | It->second->eraseFromParent(); |
149 | RVCalls.erase(I: It); |
150 | } |
151 | EraseInstruction(CI); |
152 | } |
153 | |
154 | private: |
155 | /// A map of inserted retainRV/claimRV calls to annotated calls/invokes. |
156 | DenseMap<CallInst *, CallBase *> RVCalls; |
157 | |
158 | bool ContractPass; |
159 | }; |
160 | |
161 | } // end namespace objcarc |
162 | } // end namespace llvm |
163 | |
164 | #endif |
165 | |