//===- ObjCARC.h - ObjC ARC Optimization --------------*- C++ -*-----------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// /// \file /// This file defines common definitions/declarations used by the ObjC ARC /// Optimizer. ARC stands for Automatic Reference Counting and is a system for /// managing reference counts for objects in Objective C. /// /// WARNING: This file knows about certain library functions. It recognizes them /// by name, and hardwires knowledge of their semantics. /// /// WARNING: This file knows about how certain Objective-C library functions are /// used. Naive LLVM IR transformations which would otherwise be /// behavior-preserving may break these assumptions. /// //===----------------------------------------------------------------------===// #ifndef LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H #define LLVM_LIB_TRANSFORMS_OBJCARC_OBJCARC_H #include "llvm/Analysis/ObjCARCAnalysisUtils.h" #include "llvm/Transforms/Utils/Local.h" namespace llvm { namespace objcarc { /// Erase the given instruction. /// /// Many ObjC calls return their argument verbatim, /// so if it's such a call and the return value has users, replace them with the /// argument value. /// static inline void EraseInstruction(Instruction *CI) { Value *OldArg = cast(CI)->getArgOperand(0); bool Unused = CI->use_empty(); if (!Unused) { // Replace the return value with the argument. assert((IsForwarding(GetBasicARCInstKind(CI)) || (IsNoopOnNull(GetBasicARCInstKind(CI)) && IsNullOrUndef(OldArg->stripPointerCasts()))) && "Can't delete non-forwarding instruction with users!"); CI->replaceAllUsesWith(OldArg); } CI->eraseFromParent(); if (Unused) RecursivelyDeleteTriviallyDeadInstructions(OldArg); } /// If Inst is a ReturnRV and its operand is a call or invoke, return the /// operand. Otherwise return null. static inline const Instruction *getreturnRVOperand(const Instruction &Inst, ARCInstKind Class) { if (Class != ARCInstKind::RetainRV) return nullptr; const auto *Opnd = Inst.getOperand(0)->stripPointerCasts(); if (const auto *C = dyn_cast(Opnd)) return C; return dyn_cast(Opnd); } /// Return the list of PHI nodes that are equivalent to PN. template void getEquivalentPHIs(PHINodeTy &PN, VectorTy &PHIList) { auto *BB = PN.getParent(); for (auto &P : BB->phis()) { if (&P == &PN) // Do not add PN to the list. continue; unsigned I = 0, E = PN.getNumIncomingValues(); for (; I < E; ++I) { auto *BB = PN.getIncomingBlock(I); auto *PNOpnd = PN.getIncomingValue(I)->stripPointerCasts(); auto *POpnd = P.getIncomingValueForBlock(BB)->stripPointerCasts(); if (PNOpnd != POpnd) break; } if (I == E) PHIList.push_back(&P); } } } // end namespace objcarc } // end namespace llvm #endif