LLVM  14.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 
25 using namespace llvm;
26 using 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::ClaimRV";
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";
73  case ARCInstKind::Call:
74  return OS << "ARCInstKind::Call";
75  case ARCInstKind::User:
76  return OS << "ARCInstKind::User";
78  return OS << "ARCInstKind::IntrinsicUser";
79  case ARCInstKind::None:
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:
100  return ARCInstKind::CopyWeak;
101  case Intrinsic::objc_destroyWeak:
103  case Intrinsic::objc_initWeak:
104  return ARCInstKind::InitWeak;
105  case Intrinsic::objc_loadWeak:
106  return ARCInstKind::LoadWeak;
107  case Intrinsic::objc_loadWeakRetained:
109  case Intrinsic::objc_moveWeak:
110  return ARCInstKind::MoveWeak;
111  case Intrinsic::objc_release:
112  return ARCInstKind::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:
120  return ARCInstKind::RetainRV;
121  case Intrinsic::objc_retainBlock:
123  case Intrinsic::objc_storeStrong:
125  case Intrinsic::objc_storeWeak:
126  return ARCInstKind::StoreWeak;
127  case Intrinsic::objc_clang_arc_use:
129  case Intrinsic::objc_unsafeClaimAutoreleasedReturnValue:
130  return ARCInstKind::ClaimRV;
131  case Intrinsic::objc_retainedObject:
132  return ARCInstKind::NoopCast;
133  case Intrinsic::objc_unretainedObject:
134  return ARCInstKind::NoopCast;
135  case Intrinsic::objc_unretainedPointer:
136  return ARCInstKind::NoopCast;
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.
158 static 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.
197 static 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()) {
226  ARCInstKind Class = GetFunctionClass(F);
227  if (Class != ARCInstKind::CallOrUser)
228  return Class;
229  Intrinsic::ID ID = F->getIntrinsicID();
230  if (isInertIntrinsic(ID))
231  return ARCInstKind::None;
232  if (isUseOnlyIntrinsic(ID))
233  return ARCInstKind::User;
234  }
235 
236  // Otherwise, be conservative.
237  return GetCallSiteClass(*CI);
238  }
239  case Instruction::Invoke:
240  // Otherwise, be conservative.
241  return GetCallSiteClass(cast<InvokeInst>(*I));
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.
311  switch (Class) {
312  case ARCInstKind::User:
315  return true;
316  case ARCInstKind::Retain:
335  case ARCInstKind::Call:
336  case ARCInstKind::None:
338  return false;
339  }
340  llvm_unreachable("covered switch isn't covered?");
341 }
342 
343 /// Test if the given class is objc_retain or equivalent.
345  switch (Class) {
346  case ARCInstKind::Retain:
348  return true;
349  // I believe we treat retain block as not a retain since it can copy its
350  // block.
370  case ARCInstKind::Call:
371  case ARCInstKind::User:
372  case ARCInstKind::None:
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.
381  switch (Class) {
384  return true;
385  case ARCInstKind::Retain:
405  case ARCInstKind::Call:
406  case ARCInstKind::User:
407  case ARCInstKind::None:
408  return false;
409  }
410  llvm_unreachable("covered switch isn't covered?");
411 }
412 
413 /// Test if the given class represents instructions which return their
414 /// argument verbatim.
416  switch (Class) {
417  case ARCInstKind::Retain:
423  return true;
440  case ARCInstKind::Call:
441  case ARCInstKind::User:
442  case ARCInstKind::None:
443  return false;
444  }
445  llvm_unreachable("covered switch isn't covered?");
446 }
447 
448 /// Test if the given class represents instructions which do nothing if
449 /// passed a null pointer.
451  switch (Class) {
452  case ARCInstKind::Retain:
459  return true;
474  case ARCInstKind::Call:
475  case ARCInstKind::User:
476  case ARCInstKind::None:
478  return false;
479  }
480  llvm_unreachable("covered switch isn't covered?");
481 }
482 
483 /// Test if the given class represents instructions which do nothing if
484 /// passed a global variable.
486  switch (Class) {
487  case ARCInstKind::Retain:
496  return true;
509  case ARCInstKind::Call:
510  case ARCInstKind::User:
511  case ARCInstKind::None:
513  return false;
514  }
515  llvm_unreachable("covered switch isn't covered?");
516 }
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) {
523  case ARCInstKind::Retain:
527  return true;
545  case ARCInstKind::Call:
546  case ARCInstKind::User:
547  case ARCInstKind::None:
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;
564  case ARCInstKind::Retain:
584  case ARCInstKind::Call:
585  case ARCInstKind::User:
586  case ARCInstKind::None:
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) {
599  case ARCInstKind::Retain:
607  return true;
621  case ARCInstKind::Call:
622  case ARCInstKind::User:
623  case ARCInstKind::None:
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.
635  switch (Class) {
638  case ARCInstKind::Call:
643  return true;
644  case ARCInstKind::Retain:
659  case ARCInstKind::User:
660  case ARCInstKind::None:
662  return false;
663  }
664  llvm_unreachable("covered switch isn't covered?");
665 }
666 
668  switch (Kind) {
669  case ARCInstKind::Retain:
677  case ARCInstKind::User:
678  case ARCInstKind::None:
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.
698  case ARCInstKind::Call:
700  return true;
701  }
702 
703  llvm_unreachable("covered switch isn't covered?");
704 }
llvm::objcarc::ARCInstKind::User
@ User
could "use" a pointer
llvm::objcarc::operator<<
raw_ostream & operator<<(raw_ostream &OS, const ARCInstKind Class)
Definition: ObjCARCInstKind.cpp:28
llvm
This is an optimization pass for GlobalISel generic memory operations.
Definition: AllocatorList.h:23
llvm::Function
Definition: Function.h:62
llvm::objcarc::ARCInstKind::RetainBlock
@ RetainBlock
objc_retainBlock
llvm::objcarc::GetFunctionClass
ARCInstKind GetFunctionClass(const Function *F)
Determine if F is one of the special known Functions.
Definition: ObjCARCInstKind.cpp:85
llvm::objcarc::IsNeverTail
bool IsNeverTail(ARCInstKind Class)
Test if the given class represents instructions which are never safe to mark with the "tail" keyword.
Definition: ObjCARCInstKind.cpp:556
llvm::objcarc::ARCInstKind::LoadWeak
@ LoadWeak
objc_loadWeak (derived)
llvm::objcarc::ARCInstKind::Call
@ Call
could call objc_release
isInertIntrinsic
static bool isInertIntrinsic(unsigned ID)
Definition: ObjCARCInstKind.cpp:158
llvm::objcarc::ARCInstKind::MoveWeak
@ MoveWeak
objc_moveWeak (derived)
llvm::MipsISD::Ret
@ Ret
Definition: MipsISelLowering.h:116
llvm::objcarc::GetARCInstKind
ARCInstKind GetARCInstKind(const Value *V)
Map V to its ARCInstKind equivalence class.
Definition: ObjCARCInstKind.cpp:213
llvm::objcarc::IsAutorelease
bool IsAutorelease(ARCInstKind Class)
Test if the given class is objc_autorelease or equivalent.
Definition: ObjCARCInstKind.cpp:380
llvm::objcarc::ARCInstKind::Autorelease
@ Autorelease
objc_autorelease
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::objcarc::CanInterruptRV
bool CanInterruptRV(ARCInstKind Class)
Test whether the given instruction can autorelease any pointer or cause an autoreleasepool pop.
Definition: ObjCARCInstKind.cpp:634
llvm::objcarc::IsPotentialRetainableObjPtr
bool IsPotentialRetainableObjPtr(const Value *Op)
Test whether the given value is possible a retainable object pointer.
Definition: ObjCARCAnalysisUtils.h:146
llvm::objcarc::ARCInstKind::InitWeak
@ InitWeak
objc_initWeak (derived)
isUseOnlyIntrinsic
static bool isUseOnlyIntrinsic(unsigned ID)
Definition: ObjCARCInstKind.cpp:197
Intrinsics.h
llvm::objcarc::ARCInstKind::CallOrUser
@ CallOrUser
could call objc_release and/or "use" pointers
llvm::objcarc::IsNoopOnGlobal
bool IsNoopOnGlobal(ARCInstKind Class)
Test if the given class represents instructions which do nothing if passed a global variable.
Definition: ObjCARCInstKind.cpp:485
llvm::CallBase::getCalledFunction
Function * getCalledFunction() const
Returns the function called, or null if this is an indirect function invocation.
Definition: InstrTypes.h:1398
llvm::objcarc::ARCInstKind::Release
@ Release
objc_release
llvm::objcarc::ARCInstKind::RetainRV
@ RetainRV
objc_retainAutoreleasedReturnValue
llvm::objcarc::ARCInstKind::NoopCast
@ NoopCast
objc_retainedObject, etc.
llvm::objcarc::ARCInstKind::CopyWeak
@ CopyWeak
objc_copyWeak (derived)
llvm::Instruction
Definition: Instruction.h:45
llvm::raw_ostream
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
llvm::objcarc::ARCInstKind::IntrinsicUser
@ IntrinsicUser
llvm.objc.clang.arc.use
llvm::MCID::Call
@ Call
Definition: MCInstrDesc.h:153
llvm::lltok::Kind
Kind
Definition: LLToken.h:18
llvm::objcarc::ARCInstKind
ARCInstKind
Definition: ObjCARCInstKind.h:28
llvm::objcarc::IsAlwaysTail
bool IsAlwaysTail(ARCInstKind Class)
Test if the given class represents instructions which are always safe to mark with the "tail" keyword...
Definition: ObjCARCInstKind.cpp:520
llvm::objcarc::ARCInstKind::AutoreleasepoolPop
@ AutoreleasepoolPop
objc_autoreleasePoolPop
llvm::objcarc::IsNoThrow
bool IsNoThrow(ARCInstKind Class)
Test if the given class represents instructions which are always safe to mark with the nounwind attri...
Definition: ObjCARCInstKind.cpp:595
llvm::objcarc::ARCInstKind::FusedRetainAutorelease
@ FusedRetainAutorelease
objc_retainAutorelease
I
#define I(x, y, z)
Definition: MD5.cpp:59
ObjCARCInstKind.h
memcpy
<%struct.s * > cast struct s *S to sbyte *< sbyte * > sbyte uint cast struct s *agg result to sbyte *< sbyte * > sbyte uint cast struct s *memtmp to sbyte *< sbyte * > sbyte uint ret void llc ends up issuing two memcpy or custom lower memcpy(of small size) to be ldmia/stmia. I think option 2 is better but the current register allocator cannot allocate a chunk of registers at a time. A feasible temporary solution is to use specific physical registers at the lowering time for small(<
llvm::objcarc::IsRetain
bool IsRetain(ARCInstKind Class)
Test if the given class is objc_retain or equivalent.
Definition: ObjCARCInstKind.cpp:344
llvm::objcarc
Definition: ObjCARCAliasAnalysis.h:29
prefetch
loop data prefetch
Definition: LoopDataPrefetch.cpp:152
llvm_unreachable
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
Definition: ErrorHandling.h:134
ObjCARCAnalysisUtils.h
llvm::objcarc::ARCInstKind::AutoreleasepoolPush
@ AutoreleasepoolPush
objc_autoreleasePoolPush
llvm::MCID::Select
@ Select
Definition: MCInstrDesc.h:162
llvm::objcarc::ARCInstKind::StoreWeak
@ StoreWeak
objc_storeWeak (primitive)
llvm::objcarc::ARCInstKind::FusedRetainAutoreleaseRV
@ FusedRetainAutoreleaseRV
objc_retainAutoreleaseReturnValue
llvm::objcarc::ARCInstKind::DestroyWeak
@ DestroyWeak
objc_destroyWeak (derived)
llvm::MCID::Add
@ Add
Definition: MCInstrDesc.h:183
llvm::objcarc::GetCallSiteClass
ARCInstKind GetCallSiteClass(const CallBase &CB)
Helper for GetARCInstKind.
Definition: ObjCARCAnalysisUtils.h:173
llvm::objcarc::ARCInstKind::StoreStrong
@ StoreStrong
objc_storeStrong (derived)
llvm::objcarc::CanDecrementRefCount
bool CanDecrementRefCount(ARCInstKind Kind)
Returns false if conservatively we can prove that any instruction mapped to this kind can not decreme...
Definition: ObjCARCInstKind.cpp:667
llvm::objcarc::ARCInstKind::ClaimRV
@ ClaimRV
objc_unsafeClaimAutoreleasedReturnValue
llvm::objcarc::ARCInstKind::None
@ None
anything that is inert from an ARC perspective.
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1487
llvm::Value
LLVM Value Representation.
Definition: Value.h:74
llvm::objcarc::ARCInstKind::Retain
@ Retain
objc_retain
llvm::objcarc::IsForwarding
bool IsForwarding(ARCInstKind Class)
Test if the given class represents instructions which return their argument verbatim.
Definition: ObjCARCInstKind.cpp:415
llvm::objcarc::IsNoopOnNull
bool IsNoopOnNull(ARCInstKind Class)
Test if the given class represents instructions which do nothing if passed a null pointer.
Definition: ObjCARCInstKind.cpp:450
llvm::objcarc::ARCInstKind::LoadWeakRetained
@ LoadWeakRetained
objc_loadWeakRetained (primitive)
llvm::Use
A Use represents the edge between a Value definition and its users.
Definition: Use.h:44
llvm::objcarc::IsUser
bool IsUser(ARCInstKind Class)
Test if the given class is a kind of user.
Definition: ObjCARCInstKind.cpp:310
llvm::objcarc::ARCInstKind::AutoreleaseRV
@ AutoreleaseRV
objc_autoreleaseReturnValue
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:38