text: //===- ObjCARC.h - ObjC ARC Optimization --------------*- C++ -*-----------===//
  //
  //                     The LLVM Compiler Infrastructure
  //
  // This file is distributed under the University of Illinois Open Source
  // License. See LICENSE.TXT for details.
  //
  //===----------------------------------------------------------------------===//
  /// \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/ADT/StringSwitch.h"
  #include "llvm/Analysis/AliasAnalysis.h"
  #include "llvm/Analysis/ObjCARCAnalysisUtils.h"
  #include "llvm/Analysis/ObjCARCInstKind.h"
  #include "llvm/Analysis/Passes.h"
  #include "llvm/Analysis/ValueTracking.h"
  #include "llvm/IR/CallSite.h"
  #include "llvm/IR/InstIterator.h"
  #include "llvm/IR/Module.h"
  #include "llvm/Pass.h"
  #include "llvm/Transforms/ObjCARC.h"
  #include "llvm/Transforms/Utils/Local.h"
  
  namespace llvm {
  class raw_ostream;
  }
  
  namespace llvm {
  namespace objcarc {
  
  /// \brief 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<CallInst>(CI)->getArgOperand(0);
  
    bool Unused = CI->use_empty();
  
    if (!Unused) {
      // Replace the return value with the argument.
      assert((IsForwarding(GetBasicARCInstKind(CI)) ||
              (IsNoopOnNull(GetBasicARCInstKind(CI)) &&
               isa<ConstantPointerNull>(OldArg))) &&
             "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<CallInst>(Opnd))
      return C;
    return dyn_cast<InvokeInst>(Opnd);
  }
  
  } // end namespace objcarc
  } // end namespace llvm
  
  #endif
  