Line data Source code
1 : //===- ARCInstKind.cpp - ObjC ARC Optimization ----------------------------===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : /// \file
10 : /// This file defines several utility functions used by various ARC
11 : /// optimizations which are IMHO too big to be in a header file.
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 : #include "llvm/Analysis/ObjCARCInstKind.h"
23 : #include "llvm/ADT/StringSwitch.h"
24 : #include "llvm/Analysis/ObjCARCAnalysisUtils.h"
25 : #include "llvm/IR/Intrinsics.h"
26 :
27 : using namespace llvm;
28 : using namespace llvm::objcarc;
29 :
30 0 : raw_ostream &llvm::objcarc::operator<<(raw_ostream &OS,
31 : const ARCInstKind Class) {
32 0 : switch (Class) {
33 0 : case ARCInstKind::Retain:
34 0 : return OS << "ARCInstKind::Retain";
35 0 : case ARCInstKind::RetainRV:
36 0 : return OS << "ARCInstKind::RetainRV";
37 0 : case ARCInstKind::ClaimRV:
38 0 : return OS << "ARCInstKind::ClaimRV";
39 0 : case ARCInstKind::RetainBlock:
40 0 : return OS << "ARCInstKind::RetainBlock";
41 0 : case ARCInstKind::Release:
42 0 : return OS << "ARCInstKind::Release";
43 0 : case ARCInstKind::Autorelease:
44 0 : return OS << "ARCInstKind::Autorelease";
45 0 : case ARCInstKind::AutoreleaseRV:
46 0 : return OS << "ARCInstKind::AutoreleaseRV";
47 0 : case ARCInstKind::AutoreleasepoolPush:
48 0 : return OS << "ARCInstKind::AutoreleasepoolPush";
49 0 : case ARCInstKind::AutoreleasepoolPop:
50 0 : return OS << "ARCInstKind::AutoreleasepoolPop";
51 0 : case ARCInstKind::NoopCast:
52 0 : return OS << "ARCInstKind::NoopCast";
53 0 : case ARCInstKind::FusedRetainAutorelease:
54 0 : return OS << "ARCInstKind::FusedRetainAutorelease";
55 0 : case ARCInstKind::FusedRetainAutoreleaseRV:
56 0 : return OS << "ARCInstKind::FusedRetainAutoreleaseRV";
57 0 : case ARCInstKind::LoadWeakRetained:
58 0 : return OS << "ARCInstKind::LoadWeakRetained";
59 0 : case ARCInstKind::StoreWeak:
60 0 : return OS << "ARCInstKind::StoreWeak";
61 0 : case ARCInstKind::InitWeak:
62 0 : return OS << "ARCInstKind::InitWeak";
63 0 : case ARCInstKind::LoadWeak:
64 0 : return OS << "ARCInstKind::LoadWeak";
65 0 : case ARCInstKind::MoveWeak:
66 0 : return OS << "ARCInstKind::MoveWeak";
67 0 : case ARCInstKind::CopyWeak:
68 0 : return OS << "ARCInstKind::CopyWeak";
69 0 : case ARCInstKind::DestroyWeak:
70 0 : return OS << "ARCInstKind::DestroyWeak";
71 0 : case ARCInstKind::StoreStrong:
72 0 : return OS << "ARCInstKind::StoreStrong";
73 0 : case ARCInstKind::CallOrUser:
74 0 : return OS << "ARCInstKind::CallOrUser";
75 0 : case ARCInstKind::Call:
76 0 : return OS << "ARCInstKind::Call";
77 0 : case ARCInstKind::User:
78 0 : return OS << "ARCInstKind::User";
79 0 : case ARCInstKind::IntrinsicUser:
80 0 : return OS << "ARCInstKind::IntrinsicUser";
81 0 : case ARCInstKind::None:
82 0 : return OS << "ARCInstKind::None";
83 : }
84 0 : llvm_unreachable("Unknown instruction class!");
85 : }
86 :
87 10021 : ARCInstKind llvm::objcarc::GetFunctionClass(const Function *F) {
88 : Function::const_arg_iterator AI = F->arg_begin(), AE = F->arg_end();
89 :
90 : // No (mandatory) arguments.
91 10021 : if (AI == AE)
92 3120 : return StringSwitch<ARCInstKind>(F->getName())
93 : .Case("objc_autoreleasePoolPush", ARCInstKind::AutoreleasepoolPush)
94 : .Case("clang.arc.use", ARCInstKind::IntrinsicUser)
95 : .Default(ARCInstKind::CallOrUser);
96 :
97 : // One argument.
98 8461 : const Argument *A0 = &*AI++;
99 8461 : if (AI == AE) {
100 : // Argument is a pointer.
101 5950 : PointerType *PTy = dyn_cast<PointerType>(A0->getType());
102 : if (!PTy)
103 : return ARCInstKind::CallOrUser;
104 :
105 5923 : Type *ETy = PTy->getElementType();
106 : // Argument is i8*.
107 5923 : if (ETy->isIntegerTy(8))
108 10670 : return StringSwitch<ARCInstKind>(F->getName())
109 : .Case("objc_retain", ARCInstKind::Retain)
110 : .Case("objc_retainAutoreleasedReturnValue", ARCInstKind::RetainRV)
111 : .Case("objc_unsafeClaimAutoreleasedReturnValue", ARCInstKind::ClaimRV)
112 : .Case("objc_retainBlock", ARCInstKind::RetainBlock)
113 : .Case("objc_release", ARCInstKind::Release)
114 : .Case("objc_autorelease", ARCInstKind::Autorelease)
115 : .Case("objc_autoreleaseReturnValue", ARCInstKind::AutoreleaseRV)
116 : .Case("objc_autoreleasePoolPop", ARCInstKind::AutoreleasepoolPop)
117 : .Case("objc_retainedObject", ARCInstKind::NoopCast)
118 : .Case("objc_unretainedObject", ARCInstKind::NoopCast)
119 : .Case("objc_unretainedPointer", ARCInstKind::NoopCast)
120 : .Case("objc_retain_autorelease", ARCInstKind::FusedRetainAutorelease)
121 : .Case("objc_retainAutorelease", ARCInstKind::FusedRetainAutorelease)
122 : .Case("objc_retainAutoreleaseReturnValue",
123 : ARCInstKind::FusedRetainAutoreleaseRV)
124 : .Case("objc_sync_enter", ARCInstKind::User)
125 : .Case("objc_sync_exit", ARCInstKind::User)
126 : .Default(ARCInstKind::CallOrUser);
127 :
128 : // Argument is i8**
129 : if (PointerType *Pte = dyn_cast<PointerType>(ETy))
130 368 : if (Pte->getElementType()->isIntegerTy(8))
131 708 : return StringSwitch<ARCInstKind>(F->getName())
132 : .Case("objc_loadWeakRetained", ARCInstKind::LoadWeakRetained)
133 : .Case("objc_loadWeak", ARCInstKind::LoadWeak)
134 : .Case("objc_destroyWeak", ARCInstKind::DestroyWeak)
135 : .Default(ARCInstKind::CallOrUser);
136 :
137 : // Anything else with one argument.
138 234 : return ARCInstKind::CallOrUser;
139 : }
140 :
141 : // Two arguments, first is i8**.
142 2511 : const Argument *A1 = &*AI++;
143 2511 : if (AI == AE)
144 2311 : if (PointerType *PTy = dyn_cast<PointerType>(A0->getType()))
145 2124 : if (PointerType *Pte = dyn_cast<PointerType>(PTy->getElementType()))
146 207 : if (Pte->getElementType()->isIntegerTy(8))
147 207 : if (PointerType *PTy1 = dyn_cast<PointerType>(A1->getType())) {
148 207 : Type *ETy1 = PTy1->getElementType();
149 : // Second argument is i8*
150 207 : if (ETy1->isIntegerTy(8))
151 282 : return StringSwitch<ARCInstKind>(F->getName())
152 : .Case("objc_storeWeak", ARCInstKind::StoreWeak)
153 : .Case("objc_initWeak", ARCInstKind::InitWeak)
154 : .Case("objc_storeStrong", ARCInstKind::StoreStrong)
155 : .Default(ARCInstKind::CallOrUser);
156 : // Second argument is i8**.
157 : if (PointerType *Pte1 = dyn_cast<PointerType>(ETy1))
158 66 : if (Pte1->getElementType()->isIntegerTy(8))
159 132 : return StringSwitch<ARCInstKind>(F->getName())
160 : .Case("objc_moveWeak", ARCInstKind::MoveWeak)
161 : .Case("objc_copyWeak", ARCInstKind::CopyWeak)
162 : // Ignore annotation calls. This is important to stop the
163 : // optimizer from treating annotations as uses which would
164 : // make the state of the pointers they are attempting to
165 : // elucidate to be incorrect.
166 : .Case("llvm.arc.annotation.topdown.bbstart",
167 : ARCInstKind::None)
168 : .Case("llvm.arc.annotation.topdown.bbend",
169 : ARCInstKind::None)
170 : .Case("llvm.arc.annotation.bottomup.bbstart",
171 : ARCInstKind::None)
172 : .Case("llvm.arc.annotation.bottomup.bbend",
173 : ARCInstKind::None)
174 : .Default(ARCInstKind::CallOrUser);
175 : }
176 :
177 : // Anything else.
178 : return ARCInstKind::CallOrUser;
179 : }
180 :
181 : // A whitelist of intrinsics that we know do not use objc pointers or decrement
182 : // ref counts.
183 690 : static bool isInertIntrinsic(unsigned ID) {
184 : // TODO: Make this into a covered switch.
185 690 : switch (ID) {
186 : case Intrinsic::returnaddress:
187 : case Intrinsic::addressofreturnaddress:
188 : case Intrinsic::frameaddress:
189 : case Intrinsic::stacksave:
190 : case Intrinsic::stackrestore:
191 : case Intrinsic::vastart:
192 : case Intrinsic::vacopy:
193 : case Intrinsic::vaend:
194 : case Intrinsic::objectsize:
195 : case Intrinsic::prefetch:
196 : case Intrinsic::stackprotector:
197 : case Intrinsic::eh_return_i32:
198 : case Intrinsic::eh_return_i64:
199 : case Intrinsic::eh_typeid_for:
200 : case Intrinsic::eh_dwarf_cfa:
201 : case Intrinsic::eh_sjlj_lsda:
202 : case Intrinsic::eh_sjlj_functioncontext:
203 : case Intrinsic::init_trampoline:
204 : case Intrinsic::adjust_trampoline:
205 : case Intrinsic::lifetime_start:
206 : case Intrinsic::lifetime_end:
207 : case Intrinsic::invariant_start:
208 : case Intrinsic::invariant_end:
209 : // Don't let dbg info affect our results.
210 : case Intrinsic::dbg_declare:
211 : case Intrinsic::dbg_value:
212 : case Intrinsic::dbg_label:
213 : // Short cut: Some intrinsics obviously don't use ObjC pointers.
214 : return true;
215 646 : default:
216 646 : return false;
217 : }
218 : }
219 :
220 : // A whitelist of intrinsics that we know do not use objc pointers or decrement
221 : // ref counts.
222 : static bool isUseOnlyIntrinsic(unsigned ID) {
223 : // We are conservative and even though intrinsics are unlikely to touch
224 : // reference counts, we white list them for safety.
225 : //
226 : // TODO: Expand this into a covered switch. There is a lot more here.
227 : switch (ID) {
228 : case Intrinsic::memcpy:
229 : case Intrinsic::memmove:
230 : case Intrinsic::memset:
231 : return true;
232 : default:
233 : return false;
234 : }
235 : }
236 :
237 : /// Determine what kind of construct V is.
238 8076 : ARCInstKind llvm::objcarc::GetARCInstKind(const Value *V) {
239 : if (const Instruction *I = dyn_cast<Instruction>(V)) {
240 : // Any instruction other than bitcast and gep with a pointer operand have a
241 : // use of an objc pointer. Bitcasts, GEPs, Selects, PHIs transfer a pointer
242 : // to a subsequent use, rather than using it themselves, in this sense.
243 : // As a short cut, several other opcodes are known to have no pointer
244 : // operands of interest. And ret is never followed by a release, so it's
245 : // not interesting to examine.
246 8076 : switch (I->getOpcode()) {
247 : case Instruction::Call: {
248 : const CallInst *CI = cast<CallInst>(I);
249 : // See if we have a function that we know something about.
250 : if (const Function *F = CI->getCalledFunction()) {
251 2175 : ARCInstKind Class = GetFunctionClass(F);
252 2175 : if (Class != ARCInstKind::CallOrUser)
253 : return Class;
254 690 : Intrinsic::ID ID = F->getIntrinsicID();
255 690 : if (isInertIntrinsic(ID))
256 : return ARCInstKind::None;
257 : if (isUseOnlyIntrinsic(ID))
258 : return ARCInstKind::User;
259 : }
260 :
261 : // Otherwise, be conservative.
262 728 : return GetCallSiteClass(CI);
263 : }
264 : case Instruction::Invoke:
265 : // Otherwise, be conservative.
266 439 : return GetCallSiteClass(cast<InvokeInst>(I));
267 : case Instruction::BitCast:
268 : case Instruction::GetElementPtr:
269 : case Instruction::Select:
270 : case Instruction::PHI:
271 : case Instruction::Ret:
272 : case Instruction::Br:
273 : case Instruction::Switch:
274 : case Instruction::IndirectBr:
275 : case Instruction::Alloca:
276 : case Instruction::VAArg:
277 : case Instruction::Add:
278 : case Instruction::FAdd:
279 : case Instruction::Sub:
280 : case Instruction::FSub:
281 : case Instruction::Mul:
282 : case Instruction::FMul:
283 : case Instruction::SDiv:
284 : case Instruction::UDiv:
285 : case Instruction::FDiv:
286 : case Instruction::SRem:
287 : case Instruction::URem:
288 : case Instruction::FRem:
289 : case Instruction::Shl:
290 : case Instruction::LShr:
291 : case Instruction::AShr:
292 : case Instruction::And:
293 : case Instruction::Or:
294 : case Instruction::Xor:
295 : case Instruction::SExt:
296 : case Instruction::ZExt:
297 : case Instruction::Trunc:
298 : case Instruction::IntToPtr:
299 : case Instruction::FCmp:
300 : case Instruction::FPTrunc:
301 : case Instruction::FPExt:
302 : case Instruction::FPToUI:
303 : case Instruction::FPToSI:
304 : case Instruction::UIToFP:
305 : case Instruction::SIToFP:
306 : case Instruction::InsertElement:
307 : case Instruction::ExtractElement:
308 : case Instruction::ShuffleVector:
309 : case Instruction::ExtractValue:
310 : break;
311 263 : case Instruction::ICmp:
312 : // Comparing a pointer with null, or any other constant, isn't an
313 : // interesting use, because we don't care what the pointer points to, or
314 : // about the values of any other dynamic reference-counted pointers.
315 526 : if (IsPotentialRetainableObjPtr(I->getOperand(1)))
316 23 : return ARCInstKind::User;
317 : break;
318 1433 : default:
319 : // For anything else, check all the operands.
320 : // Note that this includes both operands of a Store: while the first
321 : // operand isn't actually being dereferenced, it is being stored to
322 : // memory where we can no longer track who might read it and dereference
323 : // it, so we have to consider it potentially used.
324 2077 : for (User::const_op_iterator OI = I->op_begin(), OE = I->op_end();
325 2077 : OI != OE; ++OI)
326 1403 : if (IsPotentialRetainableObjPtr(*OI))
327 674 : return ARCInstKind::User;
328 : }
329 : }
330 :
331 : // Otherwise, it's totally inert for ARC purposes.
332 : return ARCInstKind::None;
333 : }
334 :
335 : /// Test if the given class is a kind of user.
336 45 : bool llvm::objcarc::IsUser(ARCInstKind Class) {
337 : switch (Class) {
338 : case ARCInstKind::User:
339 : case ARCInstKind::CallOrUser:
340 : case ARCInstKind::IntrinsicUser:
341 : return true;
342 : case ARCInstKind::Retain:
343 : case ARCInstKind::RetainRV:
344 : case ARCInstKind::RetainBlock:
345 : case ARCInstKind::Release:
346 : case ARCInstKind::Autorelease:
347 : case ARCInstKind::AutoreleaseRV:
348 : case ARCInstKind::AutoreleasepoolPush:
349 : case ARCInstKind::AutoreleasepoolPop:
350 : case ARCInstKind::NoopCast:
351 : case ARCInstKind::FusedRetainAutorelease:
352 : case ARCInstKind::FusedRetainAutoreleaseRV:
353 : case ARCInstKind::LoadWeakRetained:
354 : case ARCInstKind::StoreWeak:
355 : case ARCInstKind::InitWeak:
356 : case ARCInstKind::LoadWeak:
357 : case ARCInstKind::MoveWeak:
358 : case ARCInstKind::CopyWeak:
359 : case ARCInstKind::DestroyWeak:
360 : case ARCInstKind::StoreStrong:
361 : case ARCInstKind::Call:
362 : case ARCInstKind::None:
363 : case ARCInstKind::ClaimRV:
364 : return false;
365 : }
366 0 : llvm_unreachable("covered switch isn't covered?");
367 : }
368 :
369 : /// Test if the given class is objc_retain or equivalent.
370 46 : bool llvm::objcarc::IsRetain(ARCInstKind Class) {
371 46 : switch (Class) {
372 : case ARCInstKind::Retain:
373 : case ARCInstKind::RetainRV:
374 : return true;
375 : // I believe we treat retain block as not a retain since it can copy its
376 : // block.
377 33 : case ARCInstKind::RetainBlock:
378 : case ARCInstKind::Release:
379 : case ARCInstKind::Autorelease:
380 : case ARCInstKind::AutoreleaseRV:
381 : case ARCInstKind::AutoreleasepoolPush:
382 : case ARCInstKind::AutoreleasepoolPop:
383 : case ARCInstKind::NoopCast:
384 : case ARCInstKind::FusedRetainAutorelease:
385 : case ARCInstKind::FusedRetainAutoreleaseRV:
386 : case ARCInstKind::LoadWeakRetained:
387 : case ARCInstKind::StoreWeak:
388 : case ARCInstKind::InitWeak:
389 : case ARCInstKind::LoadWeak:
390 : case ARCInstKind::MoveWeak:
391 : case ARCInstKind::CopyWeak:
392 : case ARCInstKind::DestroyWeak:
393 : case ARCInstKind::StoreStrong:
394 : case ARCInstKind::IntrinsicUser:
395 : case ARCInstKind::CallOrUser:
396 : case ARCInstKind::Call:
397 : case ARCInstKind::User:
398 : case ARCInstKind::None:
399 : case ARCInstKind::ClaimRV:
400 33 : return false;
401 : }
402 0 : llvm_unreachable("covered switch isn't covered?");
403 : }
404 :
405 : /// Test if the given class is objc_autorelease or equivalent.
406 4096 : bool llvm::objcarc::IsAutorelease(ARCInstKind Class) {
407 : switch (Class) {
408 : case ARCInstKind::Autorelease:
409 : case ARCInstKind::AutoreleaseRV:
410 : return true;
411 : case ARCInstKind::Retain:
412 : case ARCInstKind::RetainRV:
413 : case ARCInstKind::ClaimRV:
414 : case ARCInstKind::RetainBlock:
415 : case ARCInstKind::Release:
416 : case ARCInstKind::AutoreleasepoolPush:
417 : case ARCInstKind::AutoreleasepoolPop:
418 : case ARCInstKind::NoopCast:
419 : case ARCInstKind::FusedRetainAutorelease:
420 : case ARCInstKind::FusedRetainAutoreleaseRV:
421 : case ARCInstKind::LoadWeakRetained:
422 : case ARCInstKind::StoreWeak:
423 : case ARCInstKind::InitWeak:
424 : case ARCInstKind::LoadWeak:
425 : case ARCInstKind::MoveWeak:
426 : case ARCInstKind::CopyWeak:
427 : case ARCInstKind::DestroyWeak:
428 : case ARCInstKind::StoreStrong:
429 : case ARCInstKind::IntrinsicUser:
430 : case ARCInstKind::CallOrUser:
431 : case ARCInstKind::Call:
432 : case ARCInstKind::User:
433 : case ARCInstKind::None:
434 : return false;
435 : }
436 0 : llvm_unreachable("covered switch isn't covered?");
437 : }
438 :
439 : /// Test if the given class represents instructions which return their
440 : /// argument verbatim.
441 12589 : bool llvm::objcarc::IsForwarding(ARCInstKind Class) {
442 : switch (Class) {
443 : case ARCInstKind::Retain:
444 : case ARCInstKind::RetainRV:
445 : case ARCInstKind::ClaimRV:
446 : case ARCInstKind::Autorelease:
447 : case ARCInstKind::AutoreleaseRV:
448 : case ARCInstKind::NoopCast:
449 : return true;
450 : case ARCInstKind::RetainBlock:
451 : case ARCInstKind::Release:
452 : case ARCInstKind::AutoreleasepoolPush:
453 : case ARCInstKind::AutoreleasepoolPop:
454 : case ARCInstKind::FusedRetainAutorelease:
455 : case ARCInstKind::FusedRetainAutoreleaseRV:
456 : case ARCInstKind::LoadWeakRetained:
457 : case ARCInstKind::StoreWeak:
458 : case ARCInstKind::InitWeak:
459 : case ARCInstKind::LoadWeak:
460 : case ARCInstKind::MoveWeak:
461 : case ARCInstKind::CopyWeak:
462 : case ARCInstKind::DestroyWeak:
463 : case ARCInstKind::StoreStrong:
464 : case ARCInstKind::IntrinsicUser:
465 : case ARCInstKind::CallOrUser:
466 : case ARCInstKind::Call:
467 : case ARCInstKind::User:
468 : case ARCInstKind::None:
469 : return false;
470 : }
471 0 : llvm_unreachable("covered switch isn't covered?");
472 : }
473 :
474 : /// Test if the given class represents instructions which do nothing if
475 : /// passed a null pointer.
476 4067 : bool llvm::objcarc::IsNoopOnNull(ARCInstKind Class) {
477 4067 : switch (Class) {
478 : case ARCInstKind::Retain:
479 : case ARCInstKind::RetainRV:
480 : case ARCInstKind::ClaimRV:
481 : case ARCInstKind::Release:
482 : case ARCInstKind::Autorelease:
483 : case ARCInstKind::AutoreleaseRV:
484 : case ARCInstKind::RetainBlock:
485 : return true;
486 3340 : case ARCInstKind::AutoreleasepoolPush:
487 : case ARCInstKind::AutoreleasepoolPop:
488 : case ARCInstKind::FusedRetainAutorelease:
489 : case ARCInstKind::FusedRetainAutoreleaseRV:
490 : case ARCInstKind::LoadWeakRetained:
491 : case ARCInstKind::StoreWeak:
492 : case ARCInstKind::InitWeak:
493 : case ARCInstKind::LoadWeak:
494 : case ARCInstKind::MoveWeak:
495 : case ARCInstKind::CopyWeak:
496 : case ARCInstKind::DestroyWeak:
497 : case ARCInstKind::StoreStrong:
498 : case ARCInstKind::IntrinsicUser:
499 : case ARCInstKind::CallOrUser:
500 : case ARCInstKind::Call:
501 : case ARCInstKind::User:
502 : case ARCInstKind::None:
503 : case ARCInstKind::NoopCast:
504 3340 : return false;
505 : }
506 0 : llvm_unreachable("covered switch isn't covered?");
507 : }
508 :
509 : /// Test if the given class represents instructions which are always safe
510 : /// to mark with the "tail" keyword.
511 4067 : bool llvm::objcarc::IsAlwaysTail(ARCInstKind Class) {
512 : // ARCInstKind::RetainBlock may be given a stack argument.
513 : switch (Class) {
514 : case ARCInstKind::Retain:
515 : case ARCInstKind::RetainRV:
516 : case ARCInstKind::ClaimRV:
517 : case ARCInstKind::AutoreleaseRV:
518 : return true;
519 : case ARCInstKind::Release:
520 : case ARCInstKind::Autorelease:
521 : case ARCInstKind::RetainBlock:
522 : case ARCInstKind::AutoreleasepoolPush:
523 : case ARCInstKind::AutoreleasepoolPop:
524 : case ARCInstKind::FusedRetainAutorelease:
525 : case ARCInstKind::FusedRetainAutoreleaseRV:
526 : case ARCInstKind::LoadWeakRetained:
527 : case ARCInstKind::StoreWeak:
528 : case ARCInstKind::InitWeak:
529 : case ARCInstKind::LoadWeak:
530 : case ARCInstKind::MoveWeak:
531 : case ARCInstKind::CopyWeak:
532 : case ARCInstKind::DestroyWeak:
533 : case ARCInstKind::StoreStrong:
534 : case ARCInstKind::IntrinsicUser:
535 : case ARCInstKind::CallOrUser:
536 : case ARCInstKind::Call:
537 : case ARCInstKind::User:
538 : case ARCInstKind::None:
539 : case ARCInstKind::NoopCast:
540 : return false;
541 : }
542 0 : llvm_unreachable("covered switch isn't covered?");
543 : }
544 :
545 : /// Test if the given class represents instructions which are never safe
546 : /// to mark with the "tail" keyword.
547 4067 : bool llvm::objcarc::IsNeverTail(ARCInstKind Class) {
548 : /// It is never safe to tail call objc_autorelease since by tail calling
549 : /// objc_autorelease: fast autoreleasing causing our object to be potentially
550 : /// reclaimed from the autorelease pool which violates the semantics of
551 : /// __autoreleasing types in ARC.
552 : switch (Class) {
553 : case ARCInstKind::Autorelease:
554 : return true;
555 : case ARCInstKind::Retain:
556 : case ARCInstKind::RetainRV:
557 : case ARCInstKind::ClaimRV:
558 : case ARCInstKind::AutoreleaseRV:
559 : case ARCInstKind::Release:
560 : case ARCInstKind::RetainBlock:
561 : case ARCInstKind::AutoreleasepoolPush:
562 : case ARCInstKind::AutoreleasepoolPop:
563 : case ARCInstKind::FusedRetainAutorelease:
564 : case ARCInstKind::FusedRetainAutoreleaseRV:
565 : case ARCInstKind::LoadWeakRetained:
566 : case ARCInstKind::StoreWeak:
567 : case ARCInstKind::InitWeak:
568 : case ARCInstKind::LoadWeak:
569 : case ARCInstKind::MoveWeak:
570 : case ARCInstKind::CopyWeak:
571 : case ARCInstKind::DestroyWeak:
572 : case ARCInstKind::StoreStrong:
573 : case ARCInstKind::IntrinsicUser:
574 : case ARCInstKind::CallOrUser:
575 : case ARCInstKind::Call:
576 : case ARCInstKind::User:
577 : case ARCInstKind::None:
578 : case ARCInstKind::NoopCast:
579 : return false;
580 : }
581 0 : llvm_unreachable("covered switch isn't covered?");
582 : }
583 :
584 : /// Test if the given class represents instructions which are always safe
585 : /// to mark with the nounwind attribute.
586 4067 : bool llvm::objcarc::IsNoThrow(ARCInstKind Class) {
587 : // objc_retainBlock is not nounwind because it calls user copy constructors
588 : // which could theoretically throw.
589 : switch (Class) {
590 : case ARCInstKind::Retain:
591 : case ARCInstKind::RetainRV:
592 : case ARCInstKind::ClaimRV:
593 : case ARCInstKind::Release:
594 : case ARCInstKind::Autorelease:
595 : case ARCInstKind::AutoreleaseRV:
596 : case ARCInstKind::AutoreleasepoolPush:
597 : case ARCInstKind::AutoreleasepoolPop:
598 : return true;
599 : case ARCInstKind::RetainBlock:
600 : case ARCInstKind::FusedRetainAutorelease:
601 : case ARCInstKind::FusedRetainAutoreleaseRV:
602 : case ARCInstKind::LoadWeakRetained:
603 : case ARCInstKind::StoreWeak:
604 : case ARCInstKind::InitWeak:
605 : case ARCInstKind::LoadWeak:
606 : case ARCInstKind::MoveWeak:
607 : case ARCInstKind::CopyWeak:
608 : case ARCInstKind::DestroyWeak:
609 : case ARCInstKind::StoreStrong:
610 : case ARCInstKind::IntrinsicUser:
611 : case ARCInstKind::CallOrUser:
612 : case ARCInstKind::Call:
613 : case ARCInstKind::User:
614 : case ARCInstKind::None:
615 : case ARCInstKind::NoopCast:
616 : return false;
617 : }
618 0 : llvm_unreachable("covered switch isn't covered?");
619 : }
620 :
621 : /// Test whether the given instruction can autorelease any pointer or cause an
622 : /// autoreleasepool pop.
623 : ///
624 : /// This means that it *could* interrupt the RV optimization.
625 4 : bool llvm::objcarc::CanInterruptRV(ARCInstKind Class) {
626 : switch (Class) {
627 : case ARCInstKind::AutoreleasepoolPop:
628 : case ARCInstKind::CallOrUser:
629 : case ARCInstKind::Call:
630 : case ARCInstKind::Autorelease:
631 : case ARCInstKind::AutoreleaseRV:
632 : case ARCInstKind::FusedRetainAutorelease:
633 : case ARCInstKind::FusedRetainAutoreleaseRV:
634 : return true;
635 : case ARCInstKind::Retain:
636 : case ARCInstKind::RetainRV:
637 : case ARCInstKind::ClaimRV:
638 : case ARCInstKind::Release:
639 : case ARCInstKind::AutoreleasepoolPush:
640 : case ARCInstKind::RetainBlock:
641 : case ARCInstKind::LoadWeakRetained:
642 : case ARCInstKind::StoreWeak:
643 : case ARCInstKind::InitWeak:
644 : case ARCInstKind::LoadWeak:
645 : case ARCInstKind::MoveWeak:
646 : case ARCInstKind::CopyWeak:
647 : case ARCInstKind::DestroyWeak:
648 : case ARCInstKind::StoreStrong:
649 : case ARCInstKind::IntrinsicUser:
650 : case ARCInstKind::User:
651 : case ARCInstKind::None:
652 : case ARCInstKind::NoopCast:
653 : return false;
654 : }
655 0 : llvm_unreachable("covered switch isn't covered?");
656 : }
657 :
658 39 : bool llvm::objcarc::CanDecrementRefCount(ARCInstKind Kind) {
659 : switch (Kind) {
660 : case ARCInstKind::Retain:
661 : case ARCInstKind::RetainRV:
662 : case ARCInstKind::Autorelease:
663 : case ARCInstKind::AutoreleaseRV:
664 : case ARCInstKind::NoopCast:
665 : case ARCInstKind::FusedRetainAutorelease:
666 : case ARCInstKind::FusedRetainAutoreleaseRV:
667 : case ARCInstKind::IntrinsicUser:
668 : case ARCInstKind::User:
669 : case ARCInstKind::None:
670 : return false;
671 :
672 : // The cases below are conservative.
673 :
674 : // RetainBlock can result in user defined copy constructors being called
675 : // implying releases may occur.
676 : case ARCInstKind::RetainBlock:
677 : case ARCInstKind::Release:
678 : case ARCInstKind::AutoreleasepoolPush:
679 : case ARCInstKind::AutoreleasepoolPop:
680 : case ARCInstKind::LoadWeakRetained:
681 : case ARCInstKind::StoreWeak:
682 : case ARCInstKind::InitWeak:
683 : case ARCInstKind::LoadWeak:
684 : case ARCInstKind::MoveWeak:
685 : case ARCInstKind::CopyWeak:
686 : case ARCInstKind::DestroyWeak:
687 : case ARCInstKind::StoreStrong:
688 : case ARCInstKind::CallOrUser:
689 : case ARCInstKind::Call:
690 : case ARCInstKind::ClaimRV:
691 : return true;
692 : }
693 :
694 0 : llvm_unreachable("covered switch isn't covered?");
695 : }
|