LLVM 23.0.0git
ObjCARCInstKind.cpp
Go to the documentation of this file.
1//===- ARCInstKind.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 several utility functions used by various ARC
10/// optimizations which are IMHO too big to be in a header file.
11///
12/// WARNING: This file knows about certain library functions. It recognizes them
13/// by name, and hardwires knowledge of their semantics.
14///
15/// WARNING: This file knows about how certain Objective-C library functions are
16/// used. Naive LLVM IR transformations which would otherwise be
17/// behavior-preserving may break these assumptions.
18///
19//===----------------------------------------------------------------------===//
20
23#include "llvm/IR/Intrinsics.h"
24
25using namespace llvm;
26using namespace llvm::objcarc;
27
29 const ARCInstKind Class) {
30 switch (Class) {
32 return OS << "ARCInstKind::Retain";
34 return OS << "ARCInstKind::RetainRV";
36 return OS << "ARCInstKind::UnsafeClaimRV";
38 return OS << "ARCInstKind::RetainBlock";
40 return OS << "ARCInstKind::Release";
42 return OS << "ARCInstKind::Autorelease";
44 return OS << "ARCInstKind::AutoreleaseRV";
46 return OS << "ARCInstKind::AutoreleasepoolPush";
48 return OS << "ARCInstKind::AutoreleasepoolPop";
50 return OS << "ARCInstKind::NoopCast";
52 return OS << "ARCInstKind::FusedRetainAutorelease";
54 return OS << "ARCInstKind::FusedRetainAutoreleaseRV";
56 return OS << "ARCInstKind::LoadWeakRetained";
58 return OS << "ARCInstKind::StoreWeak";
60 return OS << "ARCInstKind::InitWeak";
62 return OS << "ARCInstKind::LoadWeak";
64 return OS << "ARCInstKind::MoveWeak";
66 return OS << "ARCInstKind::CopyWeak";
68 return OS << "ARCInstKind::DestroyWeak";
70 return OS << "ARCInstKind::StoreStrong";
72 return OS << "ARCInstKind::CallOrUser";
74 return OS << "ARCInstKind::Call";
76 return OS << "ARCInstKind::User";
78 return OS << "ARCInstKind::IntrinsicUser";
80 return OS << "ARCInstKind::None";
81 }
82 llvm_unreachable("Unknown instruction class!");
83}
84
86
87 Intrinsic::ID ID = F->getIntrinsicID();
88 switch (ID) {
89 default:
91 case Intrinsic::objc_autorelease:
93 case Intrinsic::objc_autoreleasePoolPop:
95 case Intrinsic::objc_autoreleasePoolPush:
97 case Intrinsic::objc_autoreleaseReturnValue:
99 case Intrinsic::objc_copyWeak:
101 case Intrinsic::objc_destroyWeak:
103 case Intrinsic::objc_initWeak:
105 case Intrinsic::objc_loadWeak:
107 case Intrinsic::objc_loadWeakRetained:
109 case Intrinsic::objc_moveWeak:
111 case Intrinsic::objc_release:
113 case Intrinsic::objc_retain:
114 return ARCInstKind::Retain;
115 case Intrinsic::objc_retainAutorelease:
117 case Intrinsic::objc_retainAutoreleaseReturnValue:
119 case Intrinsic::objc_retainAutoreleasedReturnValue:
121 case Intrinsic::objc_retainBlock:
123 case Intrinsic::objc_storeStrong:
125 case Intrinsic::objc_storeWeak:
127 case Intrinsic::objc_clang_arc_use:
129 case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
131 case Intrinsic::objc_retainedObject:
133 case Intrinsic::objc_unretainedObject:
135 case Intrinsic::objc_unretainedPointer:
137 case Intrinsic::objc_retain_autorelease:
139 case Intrinsic::objc_sync_enter:
140 return ARCInstKind::User;
141 case Intrinsic::objc_sync_exit:
142 return ARCInstKind::User;
143 case Intrinsic::objc_clang_arc_noop_use:
144 case Intrinsic::objc_arc_annotation_topdown_bbstart:
145 case Intrinsic::objc_arc_annotation_topdown_bbend:
146 case Intrinsic::objc_arc_annotation_bottomup_bbstart:
147 case Intrinsic::objc_arc_annotation_bottomup_bbend:
148 // Ignore annotation calls. This is important to stop the
149 // optimizer from treating annotations as uses which would
150 // make the state of the pointers they are attempting to
151 // elucidate to be incorrect.
152 return ARCInstKind::None;
153 }
154}
155
156// A list of intrinsics that we know do not use objc pointers or decrement
157// ref counts.
158static bool isInertIntrinsic(unsigned ID) {
159 // TODO: Make this into a covered switch.
160 switch (ID) {
161 case Intrinsic::returnaddress:
162 case Intrinsic::addressofreturnaddress:
163 case Intrinsic::frameaddress:
164 case Intrinsic::stacksave:
165 case Intrinsic::stackrestore:
166 case Intrinsic::vastart:
167 case Intrinsic::vacopy:
168 case Intrinsic::vaend:
169 case Intrinsic::objectsize:
170 case Intrinsic::prefetch:
171 case Intrinsic::stackprotector:
172 case Intrinsic::eh_return_i32:
173 case Intrinsic::eh_return_i64:
174 case Intrinsic::eh_typeid_for:
175 case Intrinsic::eh_dwarf_cfa:
176 case Intrinsic::eh_sjlj_lsda:
177 case Intrinsic::eh_sjlj_functioncontext:
178 case Intrinsic::init_trampoline:
179 case Intrinsic::adjust_trampoline:
180 case Intrinsic::lifetime_start:
181 case Intrinsic::lifetime_end:
182 case Intrinsic::invariant_start:
183 case Intrinsic::invariant_end:
184 // Don't let dbg info affect our results.
185 case Intrinsic::dbg_declare:
186 case Intrinsic::dbg_value:
187 case Intrinsic::dbg_label:
188 // Short cut: Some intrinsics obviously don't use ObjC pointers.
189 return true;
190 default:
191 return false;
192 }
193}
194
195// A list of intrinsics that we know do not use objc pointers or decrement
196// ref counts.
197static bool isUseOnlyIntrinsic(unsigned ID) {
198 // We are conservative and even though intrinsics are unlikely to touch
199 // reference counts, we white list them for safety.
200 //
201 // TODO: Expand this into a covered switch. There is a lot more here.
202 switch (ID) {
203 case Intrinsic::memcpy:
204 case Intrinsic::memmove:
205 case Intrinsic::memset:
206 return true;
207 default:
208 return false;
209 }
210}
211
212/// Determine what kind of construct V is.
214 if (const Instruction *I = dyn_cast<Instruction>(V)) {
215 // Any instruction other than bitcast and gep with a pointer operand have a
216 // use of an objc pointer. Bitcasts, GEPs, Selects, PHIs transfer a pointer
217 // to a subsequent use, rather than using it themselves, in this sense.
218 // As a short cut, several other opcodes are known to have no pointer
219 // operands of interest. And ret is never followed by a release, so it's
220 // not interesting to examine.
221 switch (I->getOpcode()) {
222 case Instruction::Call: {
223 const CallInst *CI = cast<CallInst>(I);
224 // See if we have a function that we know something about.
225 if (const Function *F = CI->getCalledFunction()) {
227 if (Class != ARCInstKind::CallOrUser)
228 return Class;
229 Intrinsic::ID ID = F->getIntrinsicID();
230 if (isInertIntrinsic(ID))
231 return ARCInstKind::None;
233 return ARCInstKind::User;
234 }
235
236 // Otherwise, be conservative.
237 return GetCallSiteClass(*CI);
238 }
239 case Instruction::Invoke:
240 // Otherwise, be conservative.
242 case Instruction::BitCast:
243 case Instruction::GetElementPtr:
244 case Instruction::Select:
245 case Instruction::PHI:
246 case Instruction::Ret:
247 case Instruction::UncondBr:
248 case Instruction::CondBr:
249 case Instruction::Switch:
250 case Instruction::IndirectBr:
251 case Instruction::Alloca:
252 case Instruction::VAArg:
253 case Instruction::Add:
254 case Instruction::FAdd:
255 case Instruction::Sub:
256 case Instruction::FSub:
257 case Instruction::Mul:
258 case Instruction::FMul:
259 case Instruction::SDiv:
260 case Instruction::UDiv:
261 case Instruction::FDiv:
262 case Instruction::SRem:
263 case Instruction::URem:
264 case Instruction::FRem:
265 case Instruction::Shl:
266 case Instruction::LShr:
267 case Instruction::AShr:
268 case Instruction::And:
269 case Instruction::Or:
270 case Instruction::Xor:
271 case Instruction::SExt:
272 case Instruction::ZExt:
273 case Instruction::Trunc:
274 case Instruction::IntToPtr:
275 case Instruction::FCmp:
276 case Instruction::FPTrunc:
277 case Instruction::FPExt:
278 case Instruction::FPToUI:
279 case Instruction::FPToSI:
280 case Instruction::UIToFP:
281 case Instruction::SIToFP:
282 case Instruction::InsertElement:
283 case Instruction::ExtractElement:
284 case Instruction::ShuffleVector:
285 case Instruction::ExtractValue:
286 break;
287 case Instruction::ICmp:
288 // Comparing a pointer with null, or any other constant, isn't an
289 // interesting use, because we don't care what the pointer points to, or
290 // about the values of any other dynamic reference-counted pointers.
291 if (IsPotentialRetainableObjPtr(I->getOperand(1)))
292 return ARCInstKind::User;
293 break;
294 default:
295 // For anything else, check all the operands.
296 // Note that this includes both operands of a Store: while the first
297 // operand isn't actually being dereferenced, it is being stored to
298 // memory where we can no longer track who might read it and dereference
299 // it, so we have to consider it potentially used.
300 for (const Use &U : I->operands())
302 return ARCInstKind::User;
303 }
304 }
305
306 // Otherwise, it's totally inert for ARC purposes.
307 return ARCInstKind::None;
308}
309
310/// Test if the given class is a kind of user.
343
344/// Test if the given class is objc_retain or equivalent.
346 switch (Class) {
349 return true;
350 // I believe we treat retain block as not a retain since it can copy its
351 // block.
375 return false;
376 }
377 llvm_unreachable("covered switch isn't covered?");
378}
379
380/// Test if the given class is objc_autorelease or equivalent.
413
414/// Test if the given class represents instructions which return their
415/// argument verbatim.
448
449/// Test if the given class represents instructions which do nothing if
450/// passed a null pointer.
483
484/// Test if the given class represents instructions which do nothing if
485/// passed a global variable.
518
519/// Test if the given class represents instructions which are always safe
520/// to mark with the "tail" keyword.
522 // ARCInstKind::RetainBlock may be given a stack argument.
523 switch (Class) {
528 return true;
550 return false;
551 }
552 llvm_unreachable("covered switch isn't covered?");
553}
554
555/// Test if the given class represents instructions which are never safe
556/// to mark with the "tail" keyword.
558 /// It is never safe to tail call objc_autorelease since by tail calling
559 /// objc_autorelease: fast autoreleasing causing our object to be potentially
560 /// reclaimed from the autorelease pool which violates the semantics of
561 /// __autoreleasing types in ARC.
562 switch (Class) {
564 return true;
589 return false;
590 }
591 llvm_unreachable("covered switch isn't covered?");
592}
593
594/// Test if the given class represents instructions which are always safe
595/// to mark with the nounwind attribute.
597 // objc_retainBlock is not nounwind because it calls user copy constructors
598 // which could theoretically throw.
599 switch (Class) {
608 return true;
626 return false;
627 }
628 llvm_unreachable("covered switch isn't covered?");
629}
630
631/// Test whether the given instruction can autorelease any pointer or cause an
632/// autoreleasepool pop.
633///
634/// This means that it *could* interrupt the RV optimization.
667
669 switch (Kind) {
680 return false;
681
682 // The cases below are conservative.
683
684 // RetainBlock can result in user defined copy constructors being called
685 // implying releases may occur.
701 return true;
702 }
703
704 llvm_unreachable("covered switch isn't covered?");
705}
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
This file defines common analysis utilities used by the ObjC ARC Optimizer.
static bool isInertIntrinsic(unsigned ID)
static bool isUseOnlyIntrinsic(unsigned ID)
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation or the function signa...
This class represents a function call, abstracting a target machine's calling convention.
A Use represents the edge between a Value definition and its users.
Definition Use.h:35
LLVM Value Representation.
Definition Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition raw_ostream.h:53
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition CallingConv.h:24
bool IsPotentialRetainableObjPtr(const Value *Op)
Test whether the given value is possible a retainable object pointer.
bool IsUser(ARCInstKind Class)
Test if the given class is a kind of user.
raw_ostream & operator<<(raw_ostream &OS, const ARCInstKind Class)
bool IsRetain(ARCInstKind Class)
Test if the given class is objc_retain or equivalent.
bool IsNeverTail(ARCInstKind Class)
Test if the given class represents instructions which are never safe to mark with the "tail" keyword.
bool IsAlwaysTail(ARCInstKind Class)
Test if the given class represents instructions which are always safe to mark with the "tail" keyword...
ARCInstKind GetCallSiteClass(const CallBase &CB)
Helper for GetARCInstKind.
bool IsAutorelease(ARCInstKind Class)
Test if the given class is objc_autorelease or equivalent.
ARCInstKind
Equivalence classes of instructions in the ARC Model.
@ DestroyWeak
objc_destroyWeak (derived)
@ FusedRetainAutorelease
objc_retainAutorelease
@ CallOrUser
could call objc_release and/or "use" pointers
@ StoreStrong
objc_storeStrong (derived)
@ LoadWeakRetained
objc_loadWeakRetained (primitive)
@ StoreWeak
objc_storeWeak (primitive)
@ AutoreleasepoolPop
objc_autoreleasePoolPop
@ AutoreleasepoolPush
objc_autoreleasePoolPush
@ InitWeak
objc_initWeak (derived)
@ Autorelease
objc_autorelease
@ LoadWeak
objc_loadWeak (derived)
@ None
anything that is inert from an ARC perspective.
@ MoveWeak
objc_moveWeak (derived)
@ User
could "use" a pointer
@ RetainRV
objc_retainAutoreleasedReturnValue
@ RetainBlock
objc_retainBlock
@ FusedRetainAutoreleaseRV
objc_retainAutoreleaseReturnValue
@ AutoreleaseRV
objc_autoreleaseReturnValue
@ Call
could call objc_release
@ CopyWeak
objc_copyWeak (derived)
@ NoopCast
objc_retainedObject, etc.
@ UnsafeClaimRV
objc_unsafeClaimAutoreleasedReturnValue
@ IntrinsicUser
llvm.objc.clang.arc.use
ARCInstKind GetFunctionClass(const Function *F)
Determine if F is one of the special known Functions.
bool IsForwarding(ARCInstKind Class)
Test if the given class represents instructions which return their argument verbatim.
ARCInstKind GetARCInstKind(const Value *V)
Map V to its ARCInstKind equivalence class.
bool CanInterruptRV(ARCInstKind Class)
Test whether the given instruction can autorelease any pointer or cause an autoreleasepool pop.
bool IsNoThrow(ARCInstKind Class)
Test if the given class represents instructions which are always safe to mark with the nounwind attri...
bool CanDecrementRefCount(ARCInstKind Kind)
Returns false if conservatively we can prove that any instruction mapped to this kind can not decreme...
bool IsNoopOnGlobal(ARCInstKind Class)
Test if the given class represents instructions which do nothing if passed a global variable.
bool IsNoopOnNull(ARCInstKind Class)
Test if the given class represents instructions which do nothing if passed a null pointer.
This is an optimization pass for GlobalISel generic memory operations.
Definition Types.h:26
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:643
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:559