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:
parent
c9d70c3f7d
commit
05f0b5f315
@ -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();
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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)
|
||||||
|
@ -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.
|
||||||
|
Loading…
Reference in New Issue
Block a user