51#define DEBUG_TYPE "objc-arc-contract" 
   53STATISTIC(NumPeeps,       
"Number of calls peephole-optimized");
 
   54STATISTIC(NumStoreStrongs, 
"Number objc_storeStrong calls formed");
 
   57    "arc-contract-use-objc-claim-rv",
 
   59        "Enable generation of calls to objc_claimAutoreleasedReturnValue"));
 
   71class ObjCARCContract {
 
   73  bool CFGChanged = 
false;
 
   84  bool HasClaimRV = 
false;
 
   96  bool tryToPeepholeInstruction(
 
   98      bool &TailOkForStoreStrong,
 
  106  void tryToContractReleaseIntoStoreStrong(
 
  113  bool hasCFGChanged()
 const { 
return CFGChanged; }
 
  118  void getAnalysisUsage(AnalysisUsage &AU) 
const override;
 
  122  ObjCARCContractLegacyPass() : FunctionPass(ID) {
 
  154      dbgs() << 
"Transforming objc_retain => " 
  155                "objc_retainAutoreleasedReturnValue since the operand is a " 
  156                "return value.\nOld: " 
  161  Function *Decl = EP.
get(ARCRuntimeEntryPointKind::RetainRV);
 
  169bool ObjCARCContract::contractAutorelease(Function &
F, Instruction *
Autorelease,
 
  195  Function *Decl = EP.
get(Class == ARCInstKind::AutoreleaseRV
 
  196                              ? ARCRuntimeEntryPointKind::RetainAutoreleaseRV
 
  197                              : ARCRuntimeEntryPointKind::RetainAutorelease);
 
  211  bool SawRelease = 
false;
 
  215  auto *LocPtr = 
Loc.Ptr->stripPointerCasts();
 
  219            E = Load->getParent()->end();
 
  223    if (Store && SawRelease)
 
  245      if (!
CanUse(Inst, Load, PA, Class)) {
 
  274    if (!Store || !Store->isSimple())
 
  279    if (Store->getPointerOperand()->stripPointerCasts() == LocPtr)
 
  288  if (!Store || !SawRelease)
 
 
  347void ObjCARCContract::tryToContractReleaseIntoStoreStrong(
 
  349    const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
 
  352  if (!Load || !
Load->isSimple())
 
  357  if (
Load->getParent() != BB)
 
  384      llvm::dbgs() << 
"    Contracting retain, release into objc_storeStrong.\n" 
  386                   << 
"            Store:   " << *Store << 
"\n" 
  387                   << 
"            Release: " << *
Release << 
"\n" 
  388                   << 
"            Retain:  " << *
Retain << 
"\n" 
  389                   << 
"            Load:    " << *Load << 
"\n");
 
  392  Function *Decl = EP.
get(ARCRuntimeEntryPointKind::StoreStrong);
 
  394      Decl, Args, 
"", 
Store->getIterator(), BlockColors);
 
  406  if (&*Iter == 
Retain) ++Iter;
 
  407  if (&*Iter == Store) ++Iter;
 
  408  Store->eraseFromParent();
 
  411  if (
Load->use_empty())
 
  412    Load->eraseFromParent();
 
  415bool ObjCARCContract::tryToPeepholeInstruction(
 
  417    bool &TailOkForStoreStrongs,
 
  418    const DenseMap<BasicBlock *, ColorVector> &BlockColors) {
 
  423  case ARCInstKind::FusedRetainAutorelease:
 
  424  case ARCInstKind::FusedRetainAutoreleaseRV:
 
  426  case ARCInstKind::Autorelease:
 
  427  case ARCInstKind::AutoreleaseRV:
 
  428    return contractAutorelease(
F, Inst, Class);
 
  429  case ARCInstKind::Retain:
 
  432    if (!optimizeRetainCall(
F, Inst))
 
  436  case ARCInstKind::RetainRV:
 
  437  case ARCInstKind::UnsafeClaimRV: {
 
  459      if (BBI == InstParent->
begin()) {
 
  462          goto decline_rv_optimization;
 
  470      LLVM_DEBUG(
dbgs() << 
"Adding inline asm marker for the return value " 
  482  decline_rv_optimization:
 
  485  case ARCInstKind::InitWeak: {
 
  494                        << 
"                 New = " << *
Null << 
"\n");
 
  501  case ARCInstKind::Release:
 
  504    tryToContractReleaseIntoStoreStrong(Inst, Iter, BlockColors);
 
  506  case ARCInstKind::User:
 
  511      TailOkForStoreStrongs = 
false;
 
  513  case ARCInstKind::IntrinsicUser:
 
  535  Triple TT(M.getTargetTriple());
 
  542  unsigned Major = TT.getOSMajorVersion();
 
  543  switch (TT.getOS()) {
 
 
  566bool ObjCARCContract::init(
Module &M) {
 
  581bool ObjCARCContract::run(Function &
F, AAResults *
A, DominatorTree *
D) {
 
  592  BundledRetainClaimRVs BRV(EP, 
true, HasClaimRV);
 
  597  CFGChanged |= 
R.second;
 
  599  DenseMap<BasicBlock *, ColorVector> BlockColors;
 
  600  if (
F.hasPersonalityFn() &&
 
  611  bool TailOkForStoreStrongs =
 
  612      !
F.isVarArg() && !
F.callsFunctionThatReturnsTwice();
 
  631    if (tryToPeepholeInstruction(
F, Inst, 
I, TailOkForStoreStrongs,
 
  641    auto ReplaceArgUses = [Inst, 
this](
Value *Arg) {
 
  651        unsigned OperandNo = 
U.getOperandNo();
 
  664        Type *UseTy = 
U.get()->getType();
 
  669          if (Replacement->
getType() != UseTy) {
 
  679                   "Invalid insertion point for bitcast");
 
  680            Replacement = 
new BitCastInst(Replacement, UseTy, 
"",
 
  687          for (
unsigned i = 0, e = 
PHI->getNumIncomingValues(); i != e; ++i)
 
  688            if (
PHI->getIncomingBlock(i) == IncomingBB) {
 
  694              PHI->setIncomingValue(i, Replacement);
 
  697          if (Replacement->
getType() != UseTy)
 
  699                new BitCastInst(Replacement, UseTy, 
"",
 
  714        Arg = BI->getOperand(0);
 
  737  if (TailOkForStoreStrongs)
 
  738    for (CallInst *CI : StoreStrongCalls)
 
  740  StoreStrongCalls.clear();
 
  749char ObjCARCContractLegacyPass::ID = 0;
 
  751                      "ObjC ARC contraction", 
false, 
false)
 
  757void ObjCARCContractLegacyPass::getAnalysisUsage(
AnalysisUsage &AU)
 const {
 
  766  return new ObjCARCContractLegacyPass();
 
 
  769bool ObjCARCContractLegacyPass::runOnFunction(
Function &
F) {
 
  770  ObjCARCContract OCARCC;
 
  771  OCARCC.init(*
F.getParent());
 
  772  auto *
AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
 
  773  auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
 
  774  return OCARCC.run(
F, 
AA, DT);
 
  779  ObjCARCContract OCAC;
 
  780  OCAC.init(*
F.getParent());
 
  784  bool CFGChanged = OCAC.hasCFGChanged();
 
 
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
This file contains a class ARCRuntimeEntryPoints for use in creating/managing references to entry poi...
This is the interface for LLVM's primary stateless and local alias analysis.
static GCRegistry::Add< ErlangGC > A("erlang", "erlang-compatible garbage collector")
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file declares special dependency analysis routines used in Objective C ARC Optimizations.
static bool runOnFunction(Function &F, bool PostInlining)
This header defines various interfaces for pass management in LLVM.
Machine Check Debug Module
static StoreInst * findSafeStoreForStoreStrongContraction(LoadInst *Load, Instruction *Release, ProvenanceAnalysis &PA, AAResults *AA)
static bool useClaimRuntimeCall(Module &M)
Should we use objc_claimAutoreleasedReturnValue?
static Instruction * findRetainForStoreStrongContraction(Value *New, StoreInst *Store, Instruction *Release, ProvenanceAnalysis &PA)
static cl::opt< cl::boolOrDefault > UseObjCClaimRV("arc-contract-use-objc-claim-rv", cl::desc("Enable generation of calls to objc_claimAutoreleasedReturnValue"))
This file defines ARC utility functions which are used by various parts of the compiler.
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
This file declares a special form of Alias Analysis called Provenance / Analysis''.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
void setAA(AAResults *aa)
A manager for alias analyses.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
Legacy wrapper pass to provide the BasicAAResult object.
iterator begin()
Instruction iterator methods.
const Instruction & back() const
LLVM_ABI InstListType::const_iterator getFirstNonPHIIt() const
Returns an iterator to the first instruction in this block that is not a PHINode instruction.
InstListType::const_iterator const_iterator
LLVM_ABI const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
InstListType::iterator iterator
Instruction iterators...
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Represents analyses that only rely on functions' control flow.
Value * getArgOperand(unsigned i) const
LLVM_ABI Intrinsic::ID getIntrinsicID() const
Returns the intrinsic ID of the intrinsic called or Intrinsic::not_intrinsic if the called function i...
void setCalledFunction(Function *Fn)
Sets the function called, including updating the function type.
void setTailCall(bool IsTc=true)
static LLVM_ABI ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
DomTreeNodeBase * getIDom() const
Analysis pass which computes a DominatorTree.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
Legacy analysis pass which computes a DominatorTree.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
LLVM_ABI bool isReachableFromEntry(const Use &U) const
Provide an overload for a Use.
LLVM_ABI bool dominates(const BasicBlock *BB, const Use &U) const
Return true if the (end of the) basic block BB dominates the use U.
FunctionPass class - This class is used to implement most global optimizations.
static LLVM_ABI InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT, bool canThrow=false)
InlineAsm::get - Return the specified uniqued inline asm string.
LLVM_ABI InstListType::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
An instruction for reading from memory.
LLVM_ABI StringRef getString() const
Representation for a specific memory location.
static LLVM_ABI MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
A Module instance is used to store all the information related to an LLVM module.
static unsigned getOperandNumForIncomingValue(unsigned i)
static unsigned getIncomingValueNumForOperand(unsigned i)
static LLVM_ABI PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
Pass interface - Implemented by all 'passes'.
A set of analyses that are preserved following a run of a transformation pass.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses & preserveSet()
Mark an analysis set as preserved.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
An instruction for storing to memory.
Triple - Helper class for working with autoconf configuration names.
LLVM Value Representation.
Type * getType() const
All values are typed, get the type of this value.
LLVM_ABI void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
LLVM_ABI LLVMContext & getContext() const
All values hold a context through their type.
const ParentTy * getParent() const
self_iterator getIterator()
Declarations for ObjC runtime functions and constants.
Function * get(ARCRuntimeEntryPointKind kind)
bool contains(const Instruction *I) const
See if an instruction is a bundled retainRV/claimRV call.
std::pair< bool, bool > insertAfterInvokes(Function &F, DominatorTree *DT)
Insert a retainRV/claimRV call to the normal destination blocks of invokes with operand bundle "clang...
CallInst * insertRVCallWithColors(BasicBlock::iterator InsertPt, CallBase *AnnotatedCall, const DenseMap< BasicBlock *, ColorVector > &BlockColors)
Insert a retainRV/claimRV call with colors.
CallInst * Autorelease
Look for an `‘autorelease’' instruction dependent on Arg such that there are / no instructions depend...
Abstract Attribute helper functions.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
@ BasicBlock
Various leaf nodes.
bool ModuleHasARC(const Module &M)
Test if the given module looks interesting to run ARC optimization on.
bool IsRetain(ARCInstKind Class)
Test if the given class is objc_retain or equivalent.
DependenceKind
Defines different dependence kinds among various ARC constructs.
@ RetainAutoreleaseDep
Blocks objc_retainAutorelease.
@ RetainAutoreleaseRVDep
Blocks objc_retainAutoreleaseReturnValue.
bool IsNullOrUndef(const Value *V)
ARCInstKind
Equivalence classes of instructions in the ARC Model.
@ StoreStrong
objc_storeStrong (derived)
bool EnableARCOpts
A handy option to enable/disable all ARC Optimizations.
CallInst * createCallInstWithColors(FunctionCallee Func, ArrayRef< Value * > Args, const Twine &NameStr, BasicBlock::iterator InsertBefore, const DenseMap< BasicBlock *, ColorVector > &BlockColors)
Create a call instruction with the correct funclet token.
void getEquivalentPHIs(PHINodeTy &PN, VectorTy &PHIList)
Return the list of PHI nodes that are equivalent to PN.
bool IsNoopInstruction(const Instruction *I)
llvm::Instruction * findSingleDependency(DependenceKind Flavor, const Value *Arg, BasicBlock *StartBB, Instruction *StartInst, ProvenanceAnalysis &PA)
Find dependent instructions.
ARCInstKind GetBasicARCInstKind(const Value *V)
Determine which objc runtime call instruction class V belongs to.
Value * GetArgRCIdentityRoot(Value *Inst)
Assuming the given instruction is one of the special calls such as objc_retain or objc_release,...
bool CanDecrementRefCount(ARCInstKind Kind)
Returns false if conservatively we can prove that any instruction mapped to this kind can not decreme...
const Value * GetRCIdentityRoot(const Value *V)
The RCIdentity root of a value V is a dominating value U for which retaining or releasing U is equiva...
static MDString * getRVInstMarker(Module &M)
bool hasAttachedCallOpBundle(const CallBase *CB)
bool CanUse(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, ARCInstKind Class)
Test whether the given instruction can "use" the given pointer's object in a way that requires the re...
static void EraseInstruction(Instruction *CI)
Erase the given instruction.
NodeAddr< UseNode * > Use
friend class Instruction
Iterator for Instructions in a `BasicBlock.
This is an optimization pass for GlobalISel generic memory operations.
FunctionAddr VTableAddr Value
InstIterator< SymbolTableList< BasicBlock >, Function::iterator, BasicBlock::iterator, Instruction > inst_iterator
decltype(auto) dyn_cast(const From &Val)
dyn_cast<X> - Return the argument parameter cast to the specified type.
LLVM_ABI DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
LLVM_ABI void initializeObjCARCContractLegacyPassPass(PassRegistry &)
inst_iterator inst_begin(Function *F)
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
auto dyn_cast_or_null(const Y &Val)
bool isModSet(const ModRefInfo MRI)
LLVM_ABI raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
LLVM_ABI EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
bool isa(const From &Val)
isa<X> - Return true if the parameter to the template is an instance of one of the template type argu...
inst_iterator inst_end(Function *F)
decltype(auto) cast(const From &Val)
cast<X> - Return the argument parameter cast to the specified type.
AnalysisManager< Function > FunctionAnalysisManager
Convenience typedef for the Function analysis manager.
LLVM_ABI Pass * createObjCARCContractPass()
LLVM_ABI PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)