29 #define DEBUG_TYPE "objc-arc-contract"
41 using namespace llvm::objcarc;
43 STATISTIC(NumPeeps,
"Number of calls peephole-optimized");
44 STATISTIC(NumStoreStrongs,
"Number objc_storeStrong calls formed");
75 &DependingInstructions,
83 virtual bool doInitialization(
Module &M);
96 "objc-arc-contract",
"ObjC ARC contraction",
false,
false)
103 return new ObjCARCContract();
106 void ObjCARCContract::getAnalysisUsage(
AnalysisUsage &AU)
const {
135 DEBUG(
dbgs() <<
"Transforming objc_retain => "
136 "objc_retainAutoreleasedReturnValue since the operand is a "
137 "return value.\nOld: "<< *Retain <<
"\n");
142 cast<CallInst>(Retain)->setCalledFunction(Decl);
144 DEBUG(
dbgs() <<
"New: " << *Retain <<
"\n");
153 &DependingInstructions,
164 DependingInstructions, Visited, PA);
168 DependingInstructions, Visited, PA);
171 if (DependingInstructions.size() != 1) {
172 DependingInstructions.clear();
176 Retain = dyn_cast_or_null<CallInst>(*DependingInstructions.begin());
177 DependingInstructions.clear();
187 DEBUG(
dbgs() <<
"ObjCARCContract::ContractAutorelease: Fusing "
188 "retain/autorelease. Erasing: " << *Autorelease <<
"\n"
211 if (!Load || !Load->
isSimple())
return;
222 bool SawRelease =
false;
223 for (; !Store || !SawRelease; ++
I) {
228 if (Inst == Release) {
242 if (
CanUse(Inst, Load, PA, Class))
248 if (!Store || !Store->
isSimple())
return;
272 if (Args[0]->
getType() != I8XX)
273 Args[0] =
new BitCastInst(Args[0], I8XX,
"", Store);
275 Args[1] =
new BitCastInst(Args[1], I8X,
"", Store);
284 StoreStrongCalls.insert(StoreStrong);
286 if (&*Iter == Store) ++Iter;
294 bool ObjCARCContract::doInitialization(
Module &M) {
306 if (NMD->getNumOperands() == 1) {
307 const MDNode *
N = NMD->getOperand(0);
316 bool ObjCARCContract::runOnFunction(
Function &F) {
325 AA = &getAnalysis<AliasAnalysis>();
326 DT = &getAnalysis<DominatorTree>();
328 PA.setAA(&getAnalysis<AliasAnalysis>());
335 bool TailOkForStoreStrongs = !F.
isVarArg() &&
346 DEBUG(
dbgs() <<
"ObjCARCContract: Visiting: " << *Inst <<
"\n");
357 if (ContractAutorelease(F, Inst, Class, DependingInstructions, Visited))
363 if (!OptimizeRetainCall(F, Inst))
380 if (&*BBI == InstParent->
begin()) {
383 goto decline_rv_optimization;
391 DEBUG(
dbgs() <<
"ObjCARCContract: Adding inline asm marker for "
392 "retainAutoreleasedReturnValue optimization.\n");
397 RetainRVMarker->getString(),
401 decline_rv_optimization:
406 CallInst *CI = cast<CallInst>(Inst);
413 DEBUG(
dbgs() <<
"OBJCARCContract: Old = " << *CI <<
"\n"
414 <<
" New = " << *Null <<
"\n");
422 ContractRelease(Inst, I);
428 if (isa<AllocaInst>(Inst))
429 TailOkForStoreStrongs =
false;
439 DEBUG(
dbgs() <<
"ObjCARCContract: Finished List.\n\n");
443 const Value *Arg = cast<CallInst>(Inst)->getArgOperand(0);
446 if (!isa<Instruction>(Arg) && !isa<Argument>(Arg))
451 Use &U = UI.getUse();
452 unsigned OperandNo = UI.getOperandNo();
461 if (DT->isReachableFromEntry(U) && DT->dominates(Inst, U)) {
469 if (Replacement->
getType() != UseTy)
470 Replacement =
new BitCastInst(Replacement, UseTy,
"",
475 for (
unsigned i = 0, e =
PHI->getNumIncomingValues(); i != e; ++i)
476 if (
PHI->getIncomingBlock(i) == BB) {
478 if (&
PHI->getOperandUse(
482 PHI->setIncomingValue(i, Replacement);
485 if (Replacement->
getType() != UseTy)
486 Replacement =
new BitCastInst(Replacement, UseTy,
"",
487 cast<Instruction>(U.
getUser()));
494 if (
const BitCastInst *BI = dyn_cast<BitCastInst>(Arg))
495 Arg = BI->getOperand(0);
496 else if (isa<GEPOperator>(Arg) &&
497 cast<GEPOperator>(Arg)->hasAllZeroIndices())
499 else if (isa<GlobalAlias>(Arg) &&
500 !cast<GlobalAlias>(Arg)->mayBeOverridden())
501 Arg = cast<GlobalAlias>(Arg)->getAliasee();
509 if (TailOkForStoreStrongs)
511 E = StoreStrongCalls.end(); I != E; ++
I)
513 StoreStrongCalls.clear();
Value * getValueOperand()
static PassRegistry * getPassRegistry()
const Instruction & back() const
The main container class for the LLVM Intermediate Representation.
static Value * GetObjCArg(Value *Inst)
Assuming the given instruction is one of the special calls such as objc_retain or objc_release...
Blocks objc_retainAutorelease.
enable_if_c<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
unsigned getNumOperands() const
getNumOperands - Return number of MDNode operands.
static InstructionClass GetBasicInstructionClass(const Value *V)
Determine which objc runtime call instruction class V belongs to.
MDNode - a tuple of other values.
FunctionType * getType(LLVMContext &Context, ID id, ArrayRef< Type * > Tys=None)
STATISTIC(NumPeeps,"Number of calls peephole-optimized")
void setDebugLoc(const DebugLoc &Loc)
setDebugLoc - Set the debug location information for this instruction.
Value * getOperand(unsigned i) const LLVM_READONLY
getOperand - Return specified operand.
static unsigned getOperandNumForIncomingValue(unsigned i)
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
static Value * getPointerOperand(Instruction &Inst)
inst_iterator inst_begin(Function *F)
static const Value * StripPointerCastsAndObjCCalls(const Value *V)
This is a wrapper around Value::stripPointerCasts which also knows how to look through objc_retain an...
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
void initializeObjCARCContractPass(PassRegistry &)
ID
LLVM Calling Convention Representation.
INITIALIZE_PASS_BEGIN(ObjCARCContract,"objc-arc-contract","ObjC ARC contraction", false, false) INITIALIZE_PASS_END(ObjCARCContract
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)
void replaceAllUsesWith(Value *V)
void FindDependencies(DependenceKind Flavor, const Value *Arg, BasicBlock *StartBB, Instruction *StartInst, SmallPtrSet< Instruction *, 4 > &DependingInstructions, SmallPtrSet< const BasicBlock *, 4 > &Visited, ProvenanceAnalysis &PA)
static ConstantPointerNull * get(PointerType *T)
get() - Static factory methods - Return objects of the specified value
LLVM Basic Block Representation.
LLVM Constant Representation.
Pass * createObjCARCContractPass()
const DebugLoc & getDebugLoc() const
getDebugLoc - Return the debug location for this node as a DebugLoc.
static Type * getVoidTy(LLVMContext &C)
InstructionClass
A simple classification for instructions.
static bool IsNoopInstruction(const Instruction *I)
Value * getPointerOperand()
Location - A description of a memory location.
#define INITIALIZE_AG_DEPENDENCY(depName)
LLVMContext & getContext() const
All values hold a context through their type.
static unsigned getIncomingValueNumForOperand(unsigned i)
static CallInst * Create(Value *Func, ArrayRef< Value * > Args, const Twine &NameStr="", Instruction *InsertBefore=0)
SmallPtrSetIterator - This implements a const_iterator for SmallPtrSet.
static void EraseInstruction(Instruction *CI)
Erase the given instruction.
objc arc ObjC ARC contraction
static PointerType * getUnqual(Type *ElementType)
static bool IsNullOrUndef(const Value *V)
bool CanUse(const Instruction *Inst, const Value *Ptr, ProvenanceAnalysis &PA, InstructionClass Class)
raw_ostream & dbgs()
dbgs - Return a circular-buffered debug stream.
Value * getArgOperand(unsigned i) const
objc_autoreleaseReturnValue
BasicBlock * getSinglePredecessor()
Return this block if it has a single predecessor block. Otherwise return a null pointer.
void setCalledFunction(Value *Fn)
setCalledFunction - Set the function called.
NamedMDNode * getNamedMetadata(const Twine &Name) const
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
const Value * Ptr
Ptr - The address of the start of the location.
objc_retainAutoreleasedReturnValue
static InlineAsm * get(FunctionType *Ty, StringRef AsmString, StringRef Constraints, bool hasSideEffects, bool isAlignStack=false, AsmDialect asmDialect=AD_ATT)
objc_retainAutoreleaseReturnValue
LLVM Value Representation.
static bool IsRetain(InstructionClass Class)
Test if the given class is objc_retain or equivalent.
This is similar to BasicAliasAnalysis, and it uses many of the same techniques, except it uses specia...
inst_iterator inst_end(Function *F)
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.