diff options
Diffstat (limited to 'llvm/lib/Transforms/ObjCARC')
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARC.h | 47 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp | 6 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp | 18 | ||||
-rw-r--r-- | llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp | 38 |
5 files changed, 60 insertions, 53 deletions
diff --git a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp index f6c236c31ef..9160493212a 100644 --- a/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp +++ b/llvm/lib/Transforms/ObjCARC/DependencyAnalysis.cpp @@ -171,7 +171,7 @@ llvm::objcarc::Depends(DependenceKind Flavor, Instruction *Inst, case IC_Retain: case IC_RetainRV: // Check for a retain of the same pointer for merging. - return GetObjCArg(Inst) == Arg; + return GetArgRCIdentityRoot(Inst) == Arg; default: // Nothing else matters for objc_retainAutorelease formation. return false; @@ -183,7 +183,7 @@ llvm::objcarc::Depends(DependenceKind Flavor, Instruction *Inst, case IC_Retain: case IC_RetainRV: // Check for a retain of the same pointer for merging. - return GetObjCArg(Inst) == Arg; + return GetArgRCIdentityRoot(Inst) == Arg; default: // Anything that can autorelease interrupts // retainAutoreleaseReturnValue formation. diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARC.h b/llvm/lib/Transforms/ObjCARC/ObjCARC.h index 7a7eae84a1e..66fcc98c2a1 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARC.h +++ b/llvm/lib/Transforms/ObjCARC/ObjCARC.h @@ -229,10 +229,22 @@ static inline const Value *GetUnderlyingObjCPtr(const Value *V) { return V; } -/// \brief This is a wrapper around Value::stripPointerCasts which also knows -/// how to look through objc_retain and objc_autorelease calls, which we know to -/// return their argument verbatim. -static inline const Value *StripPointerCastsAndObjCCalls(const Value *V) { +/// The RCIdentity root of a value \p V is a dominating value U for which +/// retaining or releasing U is equivalent to retaining or releasing V. In other +/// words, ARC operations on \p V are equivalent to ARC operations on \p U. +/// +/// We use this in the ARC optimizer to make it easier to match up ARC +/// operations by always mapping ARC operations to RCIdentityRoots instead of +/// pointers themselves. +/// +/// The two ways that we see RCIdentical values in ObjC are via: +/// +/// 1. PointerCasts +/// 2. Forwarding Calls that return their argument verbatim. +/// +/// Thus this function strips off pointer casts and forwarding calls. *NOTE* +/// This implies that two RCIdentical values must alias. +static inline const Value *GetRCIdentityRoot(const Value *V) { for (;;) { V = V->stripPointerCasts(); if (!IsForwarding(GetBasicInstructionClass(V))) @@ -242,24 +254,19 @@ static inline const Value *StripPointerCastsAndObjCCalls(const Value *V) { return V; } -/// \brief This is a wrapper around Value::stripPointerCasts which also knows -/// how to look through objc_retain and objc_autorelease calls, which we know to -/// return their argument verbatim. -static inline Value *StripPointerCastsAndObjCCalls(Value *V) { - for (;;) { - V = V->stripPointerCasts(); - if (!IsForwarding(GetBasicInstructionClass(V))) - break; - V = cast<CallInst>(V)->getArgOperand(0); - } - return V; +/// Helper which calls const Value *GetRCIdentityRoot(const Value *V) and just +/// casts away the const of the result. For documentation about what an +/// RCIdentityRoot (and by extension GetRCIdentityRoot is) look at that +/// function. +static inline Value *GetRCIdentityRoot(Value *V) { + return const_cast<Value *>(GetRCIdentityRoot((const Value *)V)); } /// \brief Assuming the given instruction is one of the special calls such as -/// objc_retain or objc_release, return the argument value, stripped of no-op -/// casts and forwarding calls. -static inline Value *GetObjCArg(Value *Inst) { - return StripPointerCastsAndObjCCalls(cast<CallInst>(Inst)->getArgOperand(0)); +/// objc_retain or objc_release, return the RCIdentity root of the argument of +/// the call. +static inline Value *GetArgRCIdentityRoot(Value *Inst) { + return GetRCIdentityRoot(cast<CallInst>(Inst)->getArgOperand(0)); } static inline bool IsNullOrUndef(const Value *V) { @@ -371,7 +378,7 @@ static inline bool IsObjCIdentifiedObject(const Value *V) { if (const LoadInst *LI = dyn_cast<LoadInst>(V)) { const Value *Pointer = - StripPointerCastsAndObjCCalls(LI->getPointerOperand()); + GetRCIdentityRoot(LI->getPointerOperand()); if (const GlobalVariable *GV = dyn_cast<GlobalVariable>(Pointer)) { // A constant pointer can't be pointing to an object on the heap. It may // be reference-counted, but it won't be deleted. diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp index c61b6b0e6dd..ad18ea28a32 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCAliasAnalysis.cpp @@ -59,8 +59,8 @@ ObjCARCAliasAnalysis::alias(const Location &LocA, const Location &LocB) { // First, strip off no-ops, including ObjC-specific no-ops, and try making a // precise alias query. - const Value *SA = StripPointerCastsAndObjCCalls(LocA.Ptr); - const Value *SB = StripPointerCastsAndObjCCalls(LocB.Ptr); + const Value *SA = GetRCIdentityRoot(LocA.Ptr); + const Value *SB = GetRCIdentityRoot(LocB.Ptr); AliasResult Result = AliasAnalysis::alias(Location(SA, LocA.Size, LocA.AATags), Location(SB, LocB.Size, LocB.AATags)); @@ -92,7 +92,7 @@ ObjCARCAliasAnalysis::pointsToConstantMemory(const Location &Loc, // First, strip off no-ops, including ObjC-specific no-ops, and try making // a precise alias query. - const Value *S = StripPointerCastsAndObjCCalls(Loc.Ptr); + const Value *S = GetRCIdentityRoot(Loc.Ptr); if (AliasAnalysis::pointsToConstantMemory(Location(S, Loc.Size, Loc.AATags), OrLocal)) return true; diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp index 86f23ec1027..19fcd001f8f 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCContract.cpp @@ -110,7 +110,7 @@ namespace { /// return value. We do this late so we do not disrupt the dataflow analysis in /// ObjCARCOpt. bool ObjCARCContract::optimizeRetainCall(Function &F, Instruction *Retain) { - ImmutableCallSite CS(GetObjCArg(Retain)); + ImmutableCallSite CS(GetArgRCIdentityRoot(Retain)); const Instruction *Call = CS.getInstruction(); if (!Call) return false; @@ -146,7 +146,7 @@ bool ObjCARCContract::contractAutorelease( Function &F, Instruction *Autorelease, InstructionClass Class, SmallPtrSetImpl<Instruction *> &DependingInstructions, SmallPtrSetImpl<const BasicBlock *> &Visited) { - const Value *Arg = GetObjCArg(Autorelease); + const Value *Arg = GetArgRCIdentityRoot(Autorelease); // Check that there are no instructions between the retain and the autorelease // (such as an autorelease_pop) which may change the count. @@ -171,7 +171,7 @@ bool ObjCARCContract::contractAutorelease( if (!Retain || GetBasicInstructionClass(Retain) != IC_Retain || - GetObjCArg(Retain) != Arg) + GetArgRCIdentityRoot(Retain) != Arg) return false; Changed = true; @@ -199,7 +199,7 @@ bool ObjCARCContract::contractAutorelease( void ObjCARCContract:: tryToContractReleaseIntoStoreStrong(Instruction *Release, inst_iterator &Iter) { - LoadInst *Load = dyn_cast<LoadInst>(GetObjCArg(Release)); + LoadInst *Load = dyn_cast<LoadInst>(GetArgRCIdentityRoot(Release)); if (!Load || !Load->isSimple()) return; // For now, require everything to be in one basic block. @@ -242,7 +242,7 @@ tryToContractReleaseIntoStoreStrong(Instruction *Release, inst_iterator &Iter) { } } - Value *New = StripPointerCastsAndObjCCalls(Store->getValueOperand()); + Value *New = GetRCIdentityRoot(Store->getValueOperand()); // Walk up to find the retain. I = Store; @@ -251,7 +251,7 @@ tryToContractReleaseIntoStoreStrong(Instruction *Release, inst_iterator &Iter) { --I; Instruction *Retain = I; if (GetBasicInstructionClass(Retain) != IC_Retain) return; - if (GetObjCArg(Retain) != New) return; + if (GetArgRCIdentityRoot(Retain) != New) return; Changed = true; ++NumStoreStrongs; @@ -338,7 +338,7 @@ bool ObjCARCContract::tryToPeepholeInstruction( --BBI; } while (IsNoopInstruction(BBI)); - if (&*BBI == GetObjCArg(Inst)) { + if (&*BBI == GetArgRCIdentityRoot(Inst)) { DEBUG(dbgs() << "Adding inline asm marker for " "retainAutoreleasedReturnValue optimization.\n"); Changed = true; @@ -436,7 +436,7 @@ bool ObjCARCContract::runOnFunction(Function &F) { // Otherwise, try to undo objc-arc-expand. - // Don't use GetObjCArg because we don't want to look through bitcasts + // Don't use GetArgRCIdentityRoot because we don't want to look through bitcasts // and such; to do the replacement, the argument must have type i8*. Value *Arg = cast<CallInst>(Inst)->getArgOperand(0); @@ -457,7 +457,7 @@ bool ObjCARCContract::runOnFunction(Function &F) { // reachability here because an unreachable call is considered to // trivially dominate itself, which would lead us to rewriting its // argument in terms of its return value, which would lead to - // infinite loops in GetObjCArg. + // infinite loops in GetArgRCIdentityRoot. if (DT->isReachableFromEntry(U) && DT->dominates(Inst, U)) { Changed = true; Instruction *Replacement = Inst; diff --git a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp index 76932e6b600..992cd46f5f0 100644 --- a/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp +++ b/llvm/lib/Transforms/ObjCARC/ObjCARCOpts.cpp @@ -144,7 +144,7 @@ namespace { /// \defgroup ARCUtilities Utility declarations/definitions specific to ARC. /// @{ -/// \brief This is similar to StripPointerCastsAndObjCCalls but it stops as soon +/// \brief This is similar to GetRCIdentityRoot but it stops as soon /// as it finds a value with multiple uses. static const Value *FindSingleUseIdentifiedObject(const Value *Arg) { if (Arg->hasOneUse()) { @@ -165,7 +165,7 @@ static const Value *FindSingleUseIdentifiedObject(const Value *Arg) { // trivial uses, we can still consider this to be a single-use value. if (IsObjCIdentifiedObject(Arg)) { for (const User *U : Arg->users()) - if (!U->use_empty() || StripPointerCastsAndObjCCalls(U) != Arg) + if (!U->use_empty() || GetRCIdentityRoot(U) != Arg) return nullptr; return Arg; @@ -1191,7 +1191,7 @@ void ObjCARCOpt::getAnalysisUsage(AnalysisUsage &AU) const { bool ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) { // Check for the argument being from an immediately preceding call or invoke. - const Value *Arg = GetObjCArg(RetainRV); + const Value *Arg = GetArgRCIdentityRoot(RetainRV); ImmutableCallSite CS(Arg); if (const Instruction *Call = CS.getInstruction()) { if (Call->getParent() == RetainRV->getParent()) { @@ -1217,7 +1217,7 @@ ObjCARCOpt::OptimizeRetainRVCall(Function &F, Instruction *RetainRV) { if (I != Begin) { do --I; while (I != Begin && IsNoopInstruction(I)); if (GetBasicInstructionClass(I) == IC_AutoreleaseRV && - GetObjCArg(I) == Arg) { + GetArgRCIdentityRoot(I) == Arg) { Changed = true; ++NumPeeps; @@ -1252,7 +1252,7 @@ void ObjCARCOpt::OptimizeAutoreleaseRVCall(Function &F, Instruction *AutoreleaseRV, InstructionClass &Class) { // Check for a return of the pointer value. - const Value *Ptr = GetObjCArg(AutoreleaseRV); + const Value *Ptr = GetArgRCIdentityRoot(AutoreleaseRV); SmallVector<const Value *, 2> Users; Users.push_back(Ptr); do { @@ -1426,7 +1426,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { continue; } - const Value *Arg = GetObjCArg(Inst); + const Value *Arg = GetArgRCIdentityRoot(Inst); // ARC calls with null are no-ops. Delete them. if (IsNullOrUndef(Arg)) { @@ -1463,7 +1463,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { bool HasCriticalEdges = false; for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { Value *Incoming = - StripPointerCastsAndObjCCalls(PN->getIncomingValue(i)); + GetRCIdentityRoot(PN->getIncomingValue(i)); if (IsNullOrUndef(Incoming)) HasNull = true; else if (cast<TerminatorInst>(PN->getIncomingBlock(i)->back()) @@ -1517,7 +1517,7 @@ void ObjCARCOpt::OptimizeIndividualCalls(Function &F) { Type *ParamTy = CInst->getArgOperand(0)->getType(); for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) { Value *Incoming = - StripPointerCastsAndObjCCalls(PN->getIncomingValue(i)); + GetRCIdentityRoot(PN->getIncomingValue(i)); if (!IsNullOrUndef(Incoming)) { CallInst *Clone = cast<CallInst>(CInst->clone()); Value *Op = PN->getIncomingValue(i); @@ -1718,7 +1718,7 @@ ObjCARCOpt::VisitInstructionBottomUp(Instruction *Inst, switch (Class) { case IC_Release: { - Arg = GetObjCArg(Inst); + Arg = GetArgRCIdentityRoot(Inst); PtrState &S = MyStates.getPtrBottomUpState(Arg); @@ -1752,7 +1752,7 @@ ObjCARCOpt::VisitInstructionBottomUp(Instruction *Inst, break; case IC_Retain: case IC_RetainRV: { - Arg = GetObjCArg(Inst); + Arg = GetArgRCIdentityRoot(Inst); PtrState &S = MyStates.getPtrBottomUpState(Arg); S.SetKnownPositiveRefCount(); @@ -1808,7 +1808,7 @@ ObjCARCOpt::VisitInstructionBottomUp(Instruction *Inst, if (StoreInst *SI = dyn_cast<StoreInst>(Inst)) { if (AreAnyUnderlyingObjectsAnAlloca(SI->getPointerOperand())) { BBState::ptr_iterator I = MyStates.findPtrBottomUpState( - StripPointerCastsAndObjCCalls(SI->getValueOperand())); + GetRCIdentityRoot(SI->getValueOperand())); if (I != MyStates.bottom_up_ptr_end()) MultiOwnersSet.insert(I->first); } @@ -1978,7 +1978,7 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst, break; case IC_Retain: case IC_RetainRV: { - Arg = GetObjCArg(Inst); + Arg = GetArgRCIdentityRoot(Inst); PtrState &S = MyStates.getPtrTopDownState(Arg); @@ -2008,7 +2008,7 @@ ObjCARCOpt::VisitInstructionTopDown(Instruction *Inst, break; } case IC_Release: { - Arg = GetObjCArg(Inst); + Arg = GetArgRCIdentityRoot(Inst); PtrState &S = MyStates.getPtrTopDownState(Arg); S.ClearKnownPositiveRefCount(); @@ -2372,7 +2372,7 @@ ObjCARCOpt::ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState> const RRInfo &NewRetainRRI = It->second; KnownSafeTD &= NewRetainRRI.KnownSafe; MultipleOwners = - MultipleOwners || MultiOwnersSet.count(GetObjCArg(NewRetain)); + MultipleOwners || MultiOwnersSet.count(GetArgRCIdentityRoot(NewRetain)); for (Instruction *NewRetainRelease : NewRetainRRI.Calls) { DenseMap<Value *, RRInfo>::const_iterator Jt = Releases.find(NewRetainRelease); @@ -2581,7 +2581,7 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState> DEBUG(dbgs() << "Visiting: " << *Retain << "\n"); - Value *Arg = GetObjCArg(Retain); + Value *Arg = GetArgRCIdentityRoot(Retain); // If the object being released is in static or stack storage, we know it's // not being managed by ObjC reference counting, so we can delete pairs @@ -2593,7 +2593,7 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState> if (const LoadInst *LI = dyn_cast<LoadInst>(Arg)) if (const GlobalVariable *GV = dyn_cast<GlobalVariable>( - StripPointerCastsAndObjCCalls(LI->getPointerOperand()))) + GetRCIdentityRoot(LI->getPointerOperand()))) if (GV->isConstant()) KnownSafe = true; @@ -2860,7 +2860,7 @@ FindPredecessorRetainWithSafePath(const Value *Arg, BasicBlock *BB, // Check that we found a retain with the same argument. if (!Retain || !IsRetain(GetBasicInstructionClass(Retain)) || - GetObjCArg(Retain) != Arg) { + GetArgRCIdentityRoot(Retain) != Arg) { return nullptr; } @@ -2888,7 +2888,7 @@ FindPredecessorAutoreleaseWithSafePath(const Value *Arg, BasicBlock *BB, InstructionClass AutoreleaseClass = GetBasicInstructionClass(Autorelease); if (!IsAutorelease(AutoreleaseClass)) return nullptr; - if (GetObjCArg(Autorelease) != Arg) + if (GetArgRCIdentityRoot(Autorelease) != Arg) return nullptr; return Autorelease; @@ -2919,7 +2919,7 @@ void ObjCARCOpt::OptimizeReturns(Function &F) { if (!Ret) continue; - const Value *Arg = StripPointerCastsAndObjCCalls(Ret->getOperand(0)); + const Value *Arg = GetRCIdentityRoot(Ret->getOperand(0)); // Look for an ``autorelease'' instruction that is a predecessor of Ret and // dependent on Arg such that there are no instructions dependent on Arg |