41 using namespace llvm::objcarc;
43 #define DEBUG_TYPE "objc-arc-contract"
45 STATISTIC(NumPeeps,
"Number of calls peephole-optimized");
46 STATISTIC(NumStoreStrongs,
"Number objc_storeStrong calls formed");
81 bool &TailOkForStoreStrong);
95 bool doInitialization(
Module &M)
override;
132 DEBUG(
dbgs() <<
"Transforming objc_retain => "
133 "objc_retainAutoreleasedReturnValue since the operand is a "
134 "return value.\nOld: "<< *Retain <<
"\n");
139 cast<CallInst>(Retain)->setCalledFunction(Decl);
141 DEBUG(
dbgs() <<
"New: " << *Retain <<
"\n");
146 bool ObjCARCContract::contractAutorelease(
158 DependingInstructions, Visited, PA);
162 DependingInstructions, Visited, PA);
165 if (DependingInstructions.size() != 1) {
166 DependingInstructions.clear();
170 Retain = dyn_cast_or_null<CallInst>(*DependingInstructions.begin());
171 DependingInstructions.clear();
180 DEBUG(
dbgs() <<
" Fusing retain/autorelease!\n"
181 " Autorelease:" << *Autorelease <<
"\n"
182 " Retain: " << *Retain <<
"\n");
189 DEBUG(
dbgs() <<
" New RetainAutorelease: " << *Retain <<
"\n");
200 bool SawRelease =
false;
211 if (Store && SawRelease)
217 if (Inst == Release) {
240 if (!
CanUse(Inst, Load, PA, Class)) {
273 if (!Store || !SawRelease)
332 void ObjCARCContract::tryToContractReleaseIntoStoreStrong(
Instruction *Release,
341 if (
Load->getParent() != BB)
368 llvm::dbgs() <<
" Contracting retain, release into objc_storeStrong.\n"
370 <<
" Store: " << *Store <<
"\n"
371 <<
" Release: " << *Release <<
"\n"
372 <<
" Retain: " << *Retain <<
"\n"
373 <<
" Load: " << *
Load <<
"\n");
379 Value *Args[] = {
Load->getPointerOperand(), New };
380 if (Args[0]->
getType() != I8XX)
381 Args[0] =
new BitCastInst(Args[0], I8XX,
"", Store);
383 Args[1] =
new BitCastInst(Args[1], I8X,
"", Store);
392 StoreStrongCalls.insert(StoreStrong);
396 if (&*Iter == Store) ++Iter;
400 if (
Load->use_empty())
401 Load->eraseFromParent();
404 bool ObjCARCContract::tryToPeepholeInstruction(
408 bool &TailOkForStoreStrongs) {
418 return contractAutorelease(F, Inst, Class, DependingInsts, Visited);
422 if (!optimizeRetainCall(F, Inst))
439 if (&*BBI == InstParent->
begin()) {
442 goto decline_rv_optimization;
450 DEBUG(
dbgs() <<
"Adding inline asm marker for "
451 "retainAutoreleasedReturnValue optimization.\n");
456 RetainRVMarker->getString(),
460 decline_rv_optimization:
465 CallInst *CI = cast<CallInst>(Inst);
472 DEBUG(
dbgs() <<
"OBJCARCContract: Old = " << *CI <<
"\n"
473 <<
" New = " << *Null <<
"\n");
483 tryToContractReleaseIntoStoreStrong(Inst, Iter);
489 if (isa<AllocaInst>(Inst))
490 TailOkForStoreStrongs =
false;
505 bool ObjCARCContract::runOnFunction(
Function &F) {
514 AA = &getAnalysis<AliasAnalysis>();
515 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
517 PA.setAA(&getAnalysis<AliasAnalysis>());
526 bool TailOkForStoreStrongs =
537 DEBUG(
dbgs() <<
"Visiting: " << *Inst <<
"\n");
541 if (tryToPeepholeInstruction(F, Inst, I, DependingInstructions, Visited,
542 TailOkForStoreStrongs))
549 Value *Arg = cast<CallInst>(Inst)->getArgOperand(0);
554 if (!isa<Instruction>(Arg) && !isa<Argument>(Arg))
569 if (DT->isReachableFromEntry(U) && DT->dominates(Inst, U)) {
577 if (Replacement->
getType() != UseTy)
578 Replacement =
new BitCastInst(Replacement, UseTy,
"",
583 for (
unsigned i = 0, e =
PHI->getNumIncomingValues(); i != e; ++i)
584 if (
PHI->getIncomingBlock(i) == BB) {
590 PHI->setIncomingValue(i, Replacement);
593 if (Replacement->
getType() != UseTy)
594 Replacement =
new BitCastInst(Replacement, UseTy,
"",
595 cast<Instruction>(U.
getUser()));
602 if (
const BitCastInst *BI = dyn_cast<BitCastInst>(Arg))
603 Arg = BI->getOperand(0);
604 else if (isa<GEPOperator>(Arg) &&
605 cast<GEPOperator>(Arg)->hasAllZeroIndices())
607 else if (isa<GlobalAlias>(Arg) &&
608 !cast<GlobalAlias>(Arg)->mayBeOverridden())
609 Arg = cast<GlobalAlias>(Arg)->getAliasee();
617 if (TailOkForStoreStrongs)
618 for (
CallInst *CI : StoreStrongCalls)
620 StoreStrongCalls.clear();
631 "ObjC ARC contraction",
false,
false)
637 void ObjCARCContract::getAnalysisUsage(
AnalysisUsage &AU)
const {
640 AU.setPreservesCFG();
645 bool ObjCARCContract::doInitialization(
Module &M) {
654 RetainRVMarker =
nullptr;
657 if (NMD->getNumOperands() == 1) {
658 const MDNode *
N = NMD->getOperand(0);
Pass interface - Implemented by all 'passes'.
Value * getValueOperand()
iplist< Instruction >::iterator eraseFromParent()
eraseFromParent - This method unlinks 'this' from the containing basic block and deletes it...
use_iterator_impl< Use > use_iterator
This file declares special dependency analysis routines used in Objective C ARC Optimizations.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
const Instruction & back() const
This file contains a class ARCRuntimeEntryPoints for use in creating/managing references to entry poi...
STATISTIC(NumFunctions,"Total number of functions")
A Module instance is used to store all the information related to an LLVM module. ...
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 ...
Blocks objc_retainAutorelease.
unsigned getNumOperands() const
Return number of MDNode operands.
CallInst - This class represents a function call, abstracting a target machine's calling convention...
static ARCInstKind GetBasicARCInstKind(const Value *V)
Determine which objc runtime call instruction class V belongs to.
LoadInst - an instruction for reading from memory.
FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > Tys=None)
Return the function type for an intrinsic.
A templated base class for SmallPtrSet which provides the typesafe interface that is common across al...
iterator begin()
Instruction iterator methods.
static unsigned getOperandNumForIncomingValue(unsigned i)
#define INITIALIZE_PASS_DEPENDENCY(depName)
objc_autoreleaseReturnValue
static Value * getPointerOperand(Instruction &Inst)
inst_iterator inst_begin(Function *F)
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
A Use represents the edge between a Value definition and its users.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
void initializeObjCARCContractPass(PassRegistry &)
INITIALIZE_PASS_BEGIN(ObjCARCContract,"objc-arc-contract","ObjC ARC contraction", false, false) INITIALIZE_PASS_END(ObjCARCContract
objc_retainAutoreleasedReturnValue
Pass * createObjCARCContractPass()
bool EnableARCOpts
A handy option to enable/disable all ARC Optimizations.
This class represents a no-op cast from one type to another.
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
FunctionType::get - This static method is the primary way of constructing a FunctionType.
StoreInst - an instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
static StoreInst * findSafeStoreForStoreStrongContraction(LoadInst *Load, Instruction *Release, ProvenanceAnalysis &PA, AliasAnalysis *AA)
void setDebugLoc(DebugLoc Loc)
setDebugLoc - Set the debug location information for this instruction.
static ConstantPointerNull * get(PointerType *T)
get() - Static factory methods - Return objects of the specified value
unsigned getOperandNo() const
Return the operand # of this use in its User.
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
This is an important class for using LLVM in a threaded context.
This is an important base class in LLVM.
const DebugLoc & getDebugLoc() const
getDebugLoc - Return the debug location for this node as a DebugLoc.
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
User * getUser() const
Returns the User that contains this Use.
FunctionPass class - This class is used to implement most global optimizations.
static bool IsNoopInstruction(const Instruction *I)
static Instruction * findRetainForStoreStrongContraction(Value *New, StoreInst *Store, Instruction *Release, ProvenanceAnalysis &PA)
#define INITIALIZE_AG_DEPENDENCY(depName)
void setTailCall(bool isTC=true)
LLVMContext & getContext() const
All values hold a context through their type.
static unsigned getIncomingValueNumForOperand(unsigned i)
bool CanDecrementRefCount(ARCInstKind Kind)
Returns false if conservatively we can prove that any instruction mapped to this kind can not decreme...
const Value * Ptr
The address of the start of the location.
Representation for a specific memory location.
static Value * GetArgRCIdentityRoot(Value *Inst)
Assuming the given instruction is one of the special calls such as objc_retain or objc_release...
static void EraseInstruction(Instruction *CI)
Erase the given instruction.
objc arc ObjC ARC contraction
const MDOperand & getOperand(unsigned I) const
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements...
static PointerType * getUnqual(Type *ElementType)
PointerType::getUnqual - This constructs a pointer to an object of the specified type in the generic ...
static bool IsNullOrUndef(const Value *V)
This file declares a special form of Alias Analysis called ``Provenance Analysis''.
ARCInstKind
Equivalence classes of instructions in the ARC Model.
Type * getType() const
All values are typed, get the type of this value.
ModRefResult getModRefInfo(const Instruction *I)
getModRefInfo - Return information about whether or not an instruction may read or write memory (with...
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Value * getArgOperand(unsigned i) const
getArgOperand/setArgOperand - Return/set the i-th call argument.
BasicBlock * getSinglePredecessor()
Return the predecessor of this block if it has a single predecessor block.
LLVM_ATTRIBUTE_UNUSED_RESULT std::enable_if< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
objc_storeStrong (derived)
bool IsRetain(ARCInstKind Class)
Test if the given class is objc_retain or equivalent.
void setCalledFunction(Value *Fn)
setCalledFunction - Set the function called.
NamedMDNode * getNamedMetadata(const Twine &Name) const
Return the first NamedMDNode in the module with the specified name.
ImmutableCallSite - establish a view to a call site for examination.
Blocks objc_retainAutoreleaseReturnValue.
TerminatorInst * getTerminator()
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
bool callsFunctionThatReturnsTwice() const
callsFunctionThatReturnsTwice - Return true if the function has a call to setjmp or other function th...
Declarations for ObjC runtime functions and constants.
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT)
InlineAsm::get - Return the specified uniqued inline asm string.
static 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...
objc_retainAutoreleaseReturnValue
LLVM Value Representation.
This is similar to BasicAliasAnalysis, and it uses many of the same techniques, except it uses specia...
C - The default llvm calling convention, compatible with C.
inst_iterator inst_end(Function *F)
Legacy analysis pass which computes a DominatorTree.
bool isVarArg() const
isVarArg - Return true if this function takes a variable number of arguments.
void FindDependencies(DependenceKind Flavor, const Value *Arg, BasicBlock *StartBB, Instruction *StartInst, SmallPtrSetImpl< Instruction * > &DependingInstructions, SmallPtrSetImpl< const BasicBlock * > &Visited, ProvenanceAnalysis &PA)
Walk up the CFG from StartPos (which is in StartBB) and find local and non-local dependencies on Arg...
Value * getPointerOperand()
static IntegerType * getInt8Ty(LLVMContext &C)
const BasicBlock * getParent() const
static bool ModuleHasARC(const Module &M)
Test if the given module looks interesting to run ARC optimization on.