49 #define DEBUG_TYPE "objc-arc-contract" 51 STATISTIC(NumPeeps,
"Number of calls peephole-optimized");
52 STATISTIC(NumStoreStrongs,
"Number objc_storeStrong calls formed");
64 class ObjCARCContract {
84 bool tryToPeepholeInstruction(
86 bool &TailOkForStoreStrong,
94 void tryToContractReleaseIntoStoreStrong(
104 ObjCARCContract OCARCC;
108 bool doInitialization(
Module &M)
override;
144 dbgs() <<
"Transforming objc_retain => " 145 "objc_retainAutoreleasedReturnValue since the operand is a " 146 "return value.\nOld: " 152 cast<CallInst>(Retain)->setCalledFunction(Decl);
168 auto *
Retain = dyn_cast_or_null<CallInst>(
188 Retain->setCalledFunction(Decl);
190 LLVM_DEBUG(
dbgs() <<
" New RetainAutorelease: " << *Retain <<
"\n");
201 bool SawRelease =
false;
209 E =
Load->getParent()->end();
213 if (
Store && SawRelease)
255 Store = dyn_cast<StoreInst>(Inst);
266 if (
Store->getPointerOperand()->stripPointerCasts() == LocPtr)
275 if (!
Store || !SawRelease)
314 if (!BlockColors.
empty()) {
316 assert(CV.
size() == 1 &&
"non-unique color for block!");
318 if (EHPad->isEHPad())
330 InsertBefore, BlockColors);
360 void ObjCARCContract::tryToContractReleaseIntoStoreStrong(
370 if (
Load->getParent() != BB)
397 llvm::dbgs() <<
" Contracting retain, release into objc_storeStrong.\n" 399 <<
" Store: " << *
Store <<
"\n" 400 <<
" Release: " << *Release <<
"\n" 401 <<
" Retain: " << *Retain <<
"\n" 402 <<
" Load: " << *
Load <<
"\n");
421 StoreStrongCalls.insert(StoreStrong);
426 if (&*Iter == Retain) ++Iter;
427 if (&*Iter ==
Store) ++Iter;
428 Store->eraseFromParent();
431 if (
Load->use_empty())
432 Load->eraseFromParent();
435 bool ObjCARCContract::tryToPeepholeInstruction(
437 bool &TailOkForStoreStrongs,
448 return contractAutorelease(
F, Inst, Class);
452 if (!optimizeRetainCall(
F, Inst))
469 if (BBI == InstParent->
begin()) {
472 goto decline_rv_optimization;
480 LLVM_DEBUG(
dbgs() <<
"Adding inline asm marker for the return value " 486 RVInstMarker->getString(),
491 decline_rv_optimization:
496 CallInst *CI = cast<CallInst>(Inst);
503 <<
" New = " << *Null <<
"\n");
513 tryToContractReleaseIntoStoreStrong(Inst, Iter, BlockColors);
519 if (isa<AllocaInst>(Inst))
520 TailOkForStoreStrongs =
false;
545 const char *MarkerKey =
"clang.arc.retainAutoreleasedReturnValueMarker";
546 RVInstMarker = dyn_cast_or_null<MDString>(
M.getModuleFlag(MarkerKey));
565 if (
F.hasPersonalityFn() &&
576 bool TailOkForStoreStrongs =
577 !
F.isVarArg() && !
F.callsFunctionThatReturnsTwice();
589 if (tryToPeepholeInstruction(
F, Inst,
I, TailOkForStoreStrongs,
599 auto ReplaceArgUses = [Inst,
this](
Value *
Arg) {
601 if (!isa<Instruction>(
Arg) && !isa<Argument>(
Arg))
617 if (!DT->isReachableFromEntry(U) || !DT->dominates(Inst, U))
626 BasicBlock *IncomingBB = PHI->getIncomingBlock(ValNo);
627 if (Replacement->
getType() != UseTy) {
633 InsertBB = DT->getNode(InsertBB)->getIDom()->getBlock();
636 assert(DT->dominates(Inst, &InsertBB->
back()) &&
637 "Invalid insertion point for bitcast");
645 for (
unsigned i = 0,
e = PHI->getNumIncomingValues(); i !=
e; ++i)
646 if (PHI->getIncomingBlock(i) == IncomingBB) {
652 PHI->setIncomingValue(i, Replacement);
655 if (Replacement->
getType() != UseTy)
656 Replacement =
new BitCastInst(Replacement, UseTy,
"",
657 cast<Instruction>(U.
getUser()));
663 Value *
Arg = cast<CallInst>(Inst)->getArgOperand(0);
672 Arg = BI->getOperand(0);
673 else if (isa<GEPOperator>(
Arg) &&
674 cast<GEPOperator>(
Arg)->hasAllZeroIndices())
675 Arg = cast<GEPOperator>(
Arg)->getPointerOperand();
676 else if (isa<GlobalAlias>(
Arg) &&
677 !cast<GlobalAlias>(
Arg)->isInterposable())
678 Arg = cast<GlobalAlias>(
Arg)->getAliasee();
685 for (
Value *PHI : PHIList)
697 if (
auto *BC = dyn_cast<BitCastInst>(U))
701 while (!BitCastUsers.
empty()) {
704 if (
auto *
B = dyn_cast<BitCastInst>(U))
713 if (TailOkForStoreStrongs)
714 for (
CallInst *CI : StoreStrongCalls)
716 StoreStrongCalls.clear();
727 "ObjC ARC contraction",
false,
false)
733 void ObjCARCContractLegacyPass::getAnalysisUsage(
AnalysisUsage &AU)
const {
736 AU.setPreservesCFG();
740 return new ObjCARCContractLegacyPass();
743 bool ObjCARCContractLegacyPass::doInitialization(
Module &M) {
744 return OCARCC.init(M);
748 auto *AA = &getAnalysis<AAResultsWrapperPass>().getAAResults();
749 auto *DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
750 return OCARCC.run(
F, AA, DT);
755 ObjCARCContract OCAC;
756 OCAC.init(*
F.getParent());
Pass interface - Implemented by all 'passes'.
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
reference emplace_back(ArgTypes &&... Args)
This file declares special dependency analysis routines used in Objective C ARC Optimizations.
llvm::Instruction * findSingleDependency(DependenceKind Flavor, const Value *Arg, BasicBlock *StartBB, Instruction *StartInst, ProvenanceAnalysis &PA)
Find dependent instructions.
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
This file contains a class ARCRuntimeEntryPoints for use in creating/managing references to entry poi...
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
This class represents lattice values for constants.
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 re...
LLVM_NODISCARD bool empty() const
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Blocks objc_retainAutorelease.
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
void push_back(const T &Elt)
This class represents a function call, abstracting a target machine's calling convention.
Value * GetArgRCIdentityRoot(Value *Inst)
Assuming the given instruction is one of the special calls such as objc_retain or objc_release,...
LLVMContext & getContext() const
All values hold a context through their type.
STATISTIC(NumFunctions, "Total number of functions")
Analysis pass which computes a DominatorTree.
An instruction for reading from memory.
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...
TinyPtrVector - This class is specialized for cases where there are normally 0 or 1 element in a vect...
PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM)
iterator begin()
Instruction iterator methods.
Value * getArgOperand(unsigned i) const
static unsigned getOperandNumForIncomingValue(unsigned i)
objc_autoreleaseReturnValue
INITIALIZE_PASS_BEGIN(ObjCARCContractLegacyPass, "objc-arc-contract", "ObjC ARC contraction", false, false) INITIALIZE_PASS_END(ObjCARCContractLegacyPass
inst_iterator inst_begin(Function *F)
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
A Use represents the edge between a Value definition and its users.
bool IsNullOrUndef(const Value *V)
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
objc_retainAutoreleasedReturnValue
Class to represent function types.
Type * getType() const
All values are typed, get the type of this value.
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)
This static method is the primary way of constructing a FunctionType.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
An instruction for storing to memory.
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
unsigned getOperandNo() const
Return the operand # of this use in its User.
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
bool ModuleHasARC(const Module &M)
Test if the given module looks interesting to run ARC optimization on.
use_iterator_impl< Use > use_iterator
iterator find(const_arg_type_t< KeyT > Val)
static bool runOnFunction(Function &F, bool PostInlining)
static MemoryLocation get(const LoadInst *LI)
Return a location with information about the memory reference by the given instruction.
initializer< Ty > init(const Ty &Val)
const Instruction * getFirstNonPHI() const
Returns a pointer to the first instruction in this block that is not a PHINode instruction.
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
A set of analyses that are preserved following a run of a transformation pass.
void initializeObjCARCContractLegacyPassPass(PassRegistry &)
static ConstantPointerNull * get(PointerType *T)
Static factory methods - Return objects of the specified value.
const BasicBlock * getSinglePredecessor() const
Return the predecessor of this block if it has a single predecessor block.
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.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
A manager for alias analyses.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
const Instruction & back() const
FunctionPass class - This class is used to implement most global optimizations.
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
self_iterator getIterator()
static Instruction * findRetainForStoreStrongContraction(Value *New, StoreInst *Store, Instruction *Release, ProvenanceAnalysis &PA)
const Value * stripPointerCasts() const
Strip off pointer casts, all-zero GEPs and address space casts.
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
static unsigned getIncomingValueNumForOperand(unsigned i)
static wasm::ValType getType(const TargetRegisterClass *RC)
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
ARCInstKind GetBasicARCInstKind(const Value *V)
Determine which objc runtime call instruction class V belongs to.
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.
DependenceKind
Defines different dependence kinds among various ARC constructs.
Representation for a specific memory location.
User * getUser() const
Returns the User that contains this Use.
static void EraseInstruction(Instruction *CI)
Erase the given instruction.
objc arc ObjC ARC contraction
Iterator for intrusive lists based on ilist_node.
SmallPtrSet - This class implements a set which is optimized for holding SmallSize or less elements.
static PointerType * getUnqual(Type *ElementType)
This constructs a pointer to an object of the specified type in the generic address space (address sp...
void setTailCall(bool IsTc=true)
This file declares a special form of Alias Analysis called Provenance Analysis''.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
ARCInstKind
Equivalence classes of instructions in the ARC Model.
objc_unsafeClaimAutoreleasedReturnValue
LLVM_NODISCARD T pop_back_val()
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
iterator_range< user_iterator > users()
Represents analyses that only rely on functions' control flow.
objc_storeStrong (derived)
bool IsRetain(ARCInstKind Class)
Test if the given class is objc_retain or equivalent.
LLVM_NODISCARD bool isModSet(const ModRefInfo MRI)
static StoreInst * findSafeStoreForStoreStrongContraction(LoadInst *Load, Instruction *Release, ProvenanceAnalysis &PA, AAResults *AA)
void preserveSet()
Mark an analysis set as preserved.
Blocks objc_retainAutoreleaseReturnValue.
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.
objc_retainAutoreleaseReturnValue
LLVM_NODISCARD bool empty() const
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
This is similar to BasicAliasAnalysis, and it uses many of the same techniques, except it uses specia...
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...
inst_iterator inst_end(Function *F)
A container for analyses that lazily runs them and caches their results.
Legacy analysis pass which computes a DominatorTree.
A wrapper pass to provide the legacy pass manager access to a suitably prepared AAResults object.
This header defines various interfaces for pass management in LLVM.
ModRefInfo getModRefInfo(const CallBase *Call, const MemoryLocation &Loc)
getModRefInfo (for call sites) - Return information about whether a particular call site modifies or ...
DenseMap< BasicBlock *, ColorVector > colorEHFunclets(Function &F)
If an EH funclet personality is in use (see isFuncletEHPersonality), this will recompute which blocks...
static IntegerType * getInt8Ty(LLVMContext &C)
static CallInst * createCallInst(FunctionType *FTy, Value *Func, ArrayRef< Value * > Args, const Twine &NameStr, Instruction *InsertBefore, const DenseMap< BasicBlock *, ColorVector > &BlockColors)
Create a call instruction with the correct funclet token.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
void getEquivalentPHIs(PHINodeTy &PN, VectorTy &PHIList)
Return the list of PHI nodes that are equivalent to PN.
bool IsNoopInstruction(const Instruction *I)
const BasicBlock * getParent() const
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)