Thanks to visit codestin.com
Credit goes to llvm.org

LLVM 22.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::Br:
248 case Instruction::Switch:
249 case Instruction::IndirectBr:
250 case Instruction::Alloca:
251 case Instruction::VAArg:
252 case Instruction::Add:
253 case Instruction::FAdd:
254 case Instruction::Sub:
255 case Instruction::FSub:
256 case Instruction::Mul:
257 case Instruction::FMul:
258 case Instruction::SDiv:
259 case Instruction::UDiv:
260 case Instruction::FDiv:
261 case Instruction::SRem:
262 case Instruction::URem:
263 case Instruction::FRem:
264 case Instruction::Shl:
265 case Instruction::LShr:
266 case Instruction::AShr:
267 case Instruction::And:
268 case Instruction::Or:
269 case Instruction::Xor:
270 case Instruction::SExt:
271 case Instruction::ZExt:
272 case Instruction::Trunc:
273 case Instruction::IntToPtr:
274 case Instruction::FCmp:
275 case Instruction::FPTrunc:
276 case Instruction::FPExt:
277 case Instruction::FPToUI:
278 case Instruction::FPToSI:
279 case Instruction::UIToFP:
280 case Instruction::SIToFP:
281 case Instruction::InsertElement:
282 case Instruction::ExtractElement:
283 case Instruction::ShuffleVector:
284 case Instruction::ExtractValue:
285 break;
286 case Instruction::ICmp:
287 // Comparing a pointer with null, or any other constant, isn't an
288 // interesting use, because we don't care what the pointer points to, or
289 // about the values of any other dynamic reference-counted pointers.
290 if (IsPotentialRetainableObjPtr(I->getOperand(1)))
291 return ARCInstKind::User;
292 break;
293 default:
294 // For anything else, check all the operands.
295 // Note that this includes both operands of a Store: while the first
296 // operand isn't actually being dereferenced, it is being stored to
297 // memory where we can no longer track who might read it and dereference
298 // it, so we have to consider it potentially used.
299 for (const Use &U : I->operands())
301 return ARCInstKind::User;
302 }
303 }
304
305 // Otherwise, it's totally inert for ARC purposes.
306 return ARCInstKind::None;
307}
308
309/// Test if the given class is a kind of user.
342
343/// Test if the given class is objc_retain or equivalent.
345 switch (Class) {
348 return true;
349 // I believe we treat retain block as not a retain since it can copy its
350 // block.
374 return false;
375 }
376 llvm_unreachable("covered switch isn't covered?");
377}
378
379/// Test if the given class is objc_autorelease or equivalent.
412
413/// Test if the given class represents instructions which return their
414/// argument verbatim.
447
448/// Test if the given class represents instructions which do nothing if
449/// passed a null pointer.
482
483/// Test if the given class represents instructions which do nothing if
484/// passed a global variable.
517
518/// Test if the given class represents instructions which are always safe
519/// to mark with the "tail" keyword.
521 // ARCInstKind::RetainBlock may be given a stack argument.
522 switch (Class) {
527 return true;
549 return false;
550 }
551 llvm_unreachable("covered switch isn't covered?");
552}
553
554/// Test if the given class represents instructions which are never safe
555/// to mark with the "tail" keyword.
557 /// It is never safe to tail call objc_autorelease since by tail calling
558 /// objc_autorelease: fast autoreleasing causing our object to be potentially
559 /// reclaimed from the autorelease pool which violates the semantics of
560 /// __autoreleasing types in ARC.
561 switch (Class) {
563 return true;
588 return false;
589 }
590 llvm_unreachable("covered switch isn't covered?");
591}
592
593/// Test if the given class represents instructions which are always safe
594/// to mark with the nounwind attribute.
596 // objc_retainBlock is not nounwind because it calls user copy constructors
597 // which could theoretically throw.
598 switch (Class) {
607 return true;
625 return false;
626 }
627 llvm_unreachable("covered switch isn't covered?");
628}
629
630/// Test whether the given instruction can autorelease any pointer or cause an
631/// autoreleasepool pop.
632///
633/// This means that it *could* interrupt the RV optimization.
666
668 switch (Kind) {
679 return false;
680
681 // The cases below are conservative.
682
683 // RetainBlock can result in user defined copy constructors being called
684 // implying releases may occur.
700 return true;
701 }
702
703 llvm_unreachable("covered switch isn't covered?");
704}
#define F(x, y, z)
Definition MD5.cpp:55
#define I(x, y, z)
Definition MD5.cpp:58
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.
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:649
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
Definition Casting.h:565