1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[ObjC][ARC] Add and use a function which finds and returns the single

dependency. NFC

Use findSingleDependency in place of FindDependencies and stop passing a
set of Instructions around. Modify FindDependencies to return a boolean
flag which indicates whether the dependencies it has found are all
valid.
This commit is contained in:
Akira Hatanaka 2020-11-13 10:40:40 -08:00
parent c9d70c3f7d
commit 05f0b5f315
4 changed files with 64 additions and 82 deletions

View File

@ -208,12 +208,10 @@ llvm::objcarc::Depends(DependenceKind Flavor, Instruction *Inst,
/// non-local dependencies on Arg. /// non-local dependencies on Arg.
/// ///
/// TODO: Cache results? /// TODO: Cache results?
void static bool findDependencies(DependenceKind Flavor, const Value *Arg,
llvm::objcarc::FindDependencies(DependenceKind Flavor, BasicBlock *StartBB, Instruction *StartInst,
const Value *Arg, SmallPtrSetImpl<Instruction *> &DependingInsts,
BasicBlock *StartBB, Instruction *StartInst, ProvenanceAnalysis &PA) {
SmallPtrSetImpl<Instruction *> &DependingInsts,
ProvenanceAnalysis &PA) {
BasicBlock::iterator StartPos = StartInst->getIterator(); BasicBlock::iterator StartPos = StartInst->getIterator();
SmallPtrSet<const BasicBlock *, 4> Visited; SmallPtrSet<const BasicBlock *, 4> Visited;
@ -229,15 +227,14 @@ llvm::objcarc::FindDependencies(DependenceKind Flavor,
if (LocalStartPos == StartBBBegin) { if (LocalStartPos == StartBBBegin) {
pred_iterator PI(LocalStartBB), PE(LocalStartBB, false); pred_iterator PI(LocalStartBB), PE(LocalStartBB, false);
if (PI == PE) if (PI == PE)
// If we've reached the function entry, produce a null dependence. // Return if we've reached the function entry.
DependingInsts.insert(nullptr); return false;
else // Add the predecessors to the worklist.
// Add the predecessors to the worklist. do {
do { BasicBlock *PredBB = *PI;
BasicBlock *PredBB = *PI; if (Visited.insert(PredBB).second)
if (Visited.insert(PredBB).second) Worklist.push_back(std::make_pair(PredBB, PredBB->end()));
Worklist.push_back(std::make_pair(PredBB, PredBB->end())); } while (++PI != PE);
} while (++PI != PE);
break; break;
} }
@ -256,9 +253,22 @@ llvm::objcarc::FindDependencies(DependenceKind Flavor,
if (BB == StartBB) if (BB == StartBB)
continue; continue;
for (const BasicBlock *Succ : successors(BB)) for (const BasicBlock *Succ : successors(BB))
if (Succ != StartBB && !Visited.count(Succ)) { if (Succ != StartBB && !Visited.count(Succ))
DependingInsts.insert(reinterpret_cast<Instruction *>(-1)); return false;
return;
}
} }
return true;
}
llvm::Instruction *llvm::objcarc::findSingleDependency(DependenceKind Flavor,
const Value *Arg,
BasicBlock *StartBB,
Instruction *StartInst,
ProvenanceAnalysis &PA) {
SmallPtrSet<Instruction *, 4> DependingInsts;
if (!findDependencies(Flavor, Arg, StartBB, StartInst, DependingInsts, PA) ||
DependingInsts.size() != 1)
return nullptr;
return *DependingInsts.begin();
} }

View File

@ -50,11 +50,12 @@ enum DependenceKind {
RetainRVDep ///< Blocks objc_retainAutoreleasedReturnValue. RetainRVDep ///< Blocks objc_retainAutoreleasedReturnValue.
}; };
void FindDependencies(DependenceKind Flavor, /// Find dependent instructions. If there is exactly one dependent instruction,
const Value *Arg, /// return it. Otherwise, return null.
BasicBlock *StartBB, Instruction *StartInst, llvm::Instruction *findSingleDependency(DependenceKind Flavor, const Value *Arg,
SmallPtrSetImpl<Instruction *> &DependingInstructions, BasicBlock *StartBB,
ProvenanceAnalysis &PA); Instruction *StartInst,
ProvenanceAnalysis &PA);
bool bool
Depends(DependenceKind Flavor, Instruction *Inst, const Value *Arg, Depends(DependenceKind Flavor, Instruction *Inst, const Value *Arg,

View File

@ -161,20 +161,11 @@ bool ObjCARCContract::contractAutorelease(Function &F, Instruction *Autorelease,
// Check that there are no instructions between the retain and the autorelease // Check that there are no instructions between the retain and the autorelease
// (such as an autorelease_pop) which may change the count. // (such as an autorelease_pop) which may change the count.
CallInst *Retain = nullptr; DependenceKind DK = Class == ARCInstKind::AutoreleaseRV
SmallPtrSet<Instruction *, 4> DependingInstructions; ? RetainAutoreleaseRVDep
: RetainAutoreleaseDep;
if (Class == ARCInstKind::AutoreleaseRV) auto *Retain = dyn_cast_or_null<CallInst>(
FindDependencies(RetainAutoreleaseRVDep, Arg, Autorelease->getParent(), findSingleDependency(DK, Arg, Autorelease->getParent(), Autorelease, PA));
Autorelease, DependingInstructions, PA);
else
FindDependencies(RetainAutoreleaseDep, Arg, Autorelease->getParent(),
Autorelease, DependingInstructions, PA);
if (DependingInstructions.size() != 1)
return false;
Retain = dyn_cast_or_null<CallInst>(*DependingInstructions.begin());
if (!Retain || GetBasicARCInstKind(Retain) != ARCInstKind::Retain || if (!Retain || GetBasicARCInstKind(Retain) != ARCInstKind::Retain ||
GetArgRCIdentityRoot(Retain) != Arg) GetArgRCIdentityRoot(Retain) != Arg)

View File

@ -1125,7 +1125,7 @@ void ObjCARCOpt::OptimizeIndividualCallImpl(
if (!HasNull) if (!HasNull)
continue; continue;
SmallPtrSet<Instruction *, 4> DependingInstructions; Instruction *DepInst = nullptr;
// Check that there is nothing that cares about the reference // Check that there is nothing that cares about the reference
// count between the call and the phi. // count between the call and the phi.
@ -1137,13 +1137,13 @@ void ObjCARCOpt::OptimizeIndividualCallImpl(
case ARCInstKind::Release: case ARCInstKind::Release:
// These can't be moved across things that care about the retain // These can't be moved across things that care about the retain
// count. // count.
FindDependencies(NeedsPositiveRetainCount, Arg, Inst->getParent(), Inst, DepInst = findSingleDependency(NeedsPositiveRetainCount, Arg,
DependingInstructions, PA); Inst->getParent(), Inst, PA);
break; break;
case ARCInstKind::Autorelease: case ARCInstKind::Autorelease:
// These can't be moved across autorelease pool scope boundaries. // These can't be moved across autorelease pool scope boundaries.
FindDependencies(AutoreleasePoolBoundary, Arg, Inst->getParent(), Inst, DepInst = findSingleDependency(AutoreleasePoolBoundary, Arg,
DependingInstructions, PA); Inst->getParent(), Inst, PA);
break; break;
case ARCInstKind::ClaimRV: case ARCInstKind::ClaimRV:
case ARCInstKind::RetainRV: case ARCInstKind::RetainRV:
@ -1157,9 +1157,7 @@ void ObjCARCOpt::OptimizeIndividualCallImpl(
llvm_unreachable("Invalid dependence flavor"); llvm_unreachable("Invalid dependence flavor");
} }
if (DependingInstructions.size() != 1) if (DepInst != PN)
continue;
if (*DependingInstructions.begin() != PN)
continue; continue;
Changed = true; Changed = true;
@ -2233,24 +2231,21 @@ bool ObjCARCOpt::OptimizeSequences(Function &F) {
/// Check if there is a dependent call earlier that does not have anything in /// Check if there is a dependent call earlier that does not have anything in
/// between the Retain and the call that can affect the reference count of their /// between the Retain and the call that can affect the reference count of their
/// shared pointer argument. Note that Retain need not be in BB. /// shared pointer argument. Note that Retain need not be in BB.
static bool static CallInst *HasSafePathToPredecessorCall(const Value *Arg,
HasSafePathToPredecessorCall(const Value *Arg, Instruction *Retain, Instruction *Retain,
SmallPtrSetImpl<Instruction *> &DepInsts, ProvenanceAnalysis &PA) {
ProvenanceAnalysis &PA) { auto *Call = dyn_cast_or_null<CallInst>(findSingleDependency(
FindDependencies(CanChangeRetainCount, Arg, Retain->getParent(), Retain, CanChangeRetainCount, Arg, Retain->getParent(), Retain, PA));
DepInsts, PA);
if (DepInsts.size() != 1)
return false;
auto *Call = dyn_cast_or_null<CallInst>(*DepInsts.begin());
// Check that the pointer is the return value of the call. // Check that the pointer is the return value of the call.
if (!Call || Arg != Call) if (!Call || Arg != Call)
return false; return nullptr;
// Check that the call is a regular call. // Check that the call is a regular call.
ARCInstKind Class = GetBasicARCInstKind(Call); ARCInstKind Class = GetBasicARCInstKind(Call);
return Class == ARCInstKind::CallOrUser || Class == ARCInstKind::Call; return Class == ARCInstKind::CallOrUser || Class == ARCInstKind::Call
? Call
: nullptr;
} }
/// Find a dependent retain that precedes the given autorelease for which there /// Find a dependent retain that precedes the given autorelease for which there
@ -2260,12 +2255,8 @@ static CallInst *
FindPredecessorRetainWithSafePath(const Value *Arg, BasicBlock *BB, FindPredecessorRetainWithSafePath(const Value *Arg, BasicBlock *BB,
Instruction *Autorelease, Instruction *Autorelease,
ProvenanceAnalysis &PA) { ProvenanceAnalysis &PA) {
SmallPtrSet<Instruction *, 4> DepInsts; auto *Retain = dyn_cast_or_null<CallInst>(
FindDependencies(CanChangeRetainCount, Arg, BB, Autorelease, DepInsts, PA); findSingleDependency(CanChangeRetainCount, Arg, BB, Autorelease, PA));
if (DepInsts.size() != 1)
return nullptr;
auto *Retain = dyn_cast_or_null<CallInst>(*DepInsts.begin());
// Check that we found a retain with the same argument. // Check that we found a retain with the same argument.
if (!Retain || !IsRetain(GetBasicARCInstKind(Retain)) || if (!Retain || !IsRetain(GetBasicARCInstKind(Retain)) ||
@ -2284,11 +2275,9 @@ FindPredecessorAutoreleaseWithSafePath(const Value *Arg, BasicBlock *BB,
ReturnInst *Ret, ReturnInst *Ret,
ProvenanceAnalysis &PA) { ProvenanceAnalysis &PA) {
SmallPtrSet<Instruction *, 4> DepInsts; SmallPtrSet<Instruction *, 4> DepInsts;
FindDependencies(NeedsPositiveRetainCount, Arg, BB, Ret, DepInsts, PA); auto *Autorelease = dyn_cast_or_null<CallInst>(
if (DepInsts.size() != 1) findSingleDependency(NeedsPositiveRetainCount, Arg, BB, Ret, PA));
return nullptr;
auto *Autorelease = dyn_cast_or_null<CallInst>(*DepInsts.begin());
if (!Autorelease) if (!Autorelease)
return nullptr; return nullptr;
ARCInstKind AutoreleaseClass = GetBasicARCInstKind(Autorelease); ARCInstKind AutoreleaseClass = GetBasicARCInstKind(Autorelease);
@ -2314,7 +2303,6 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {
LLVM_DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeReturns ==\n"); LLVM_DEBUG(dbgs() << "\n== ObjCARCOpt::OptimizeReturns ==\n");
SmallPtrSet<Instruction *, 4> DependingInstructions;
for (BasicBlock &BB: F) { for (BasicBlock &BB: F) {
ReturnInst *Ret = dyn_cast<ReturnInst>(&BB.back()); ReturnInst *Ret = dyn_cast<ReturnInst>(&BB.back());
if (!Ret) if (!Ret)
@ -2341,21 +2329,13 @@ void ObjCARCOpt::OptimizeReturns(Function &F) {
// Check that there is nothing that can affect the reference count // Check that there is nothing that can affect the reference count
// between the retain and the call. Note that Retain need not be in BB. // between the retain and the call. Note that Retain need not be in BB.
bool HasSafePathToCall = CallInst *Call = HasSafePathToPredecessorCall(Arg, Retain, PA);
HasSafePathToPredecessorCall(Arg, Retain, DependingInstructions, PA);
// Don't remove retainRV/autoreleaseRV pairs if the call isn't a tail call. // Don't remove retainRV/autoreleaseRV pairs if the call isn't a tail call.
if (HasSafePathToCall && if (!Call ||
GetBasicARCInstKind(Retain) == ARCInstKind::RetainRV && (!Call->isTailCall() &&
GetBasicARCInstKind(Autorelease) == ARCInstKind::AutoreleaseRV && GetBasicARCInstKind(Retain) == ARCInstKind::RetainRV &&
!cast<CallInst>(*DependingInstructions.begin())->isTailCall()) { GetBasicARCInstKind(Autorelease) == ARCInstKind::AutoreleaseRV))
DependingInstructions.clear();
continue;
}
DependingInstructions.clear();
if (!HasSafePathToCall)
continue; continue;
// If so, we can zap the retain and autorelease. // If so, we can zap the retain and autorelease.