mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 05:24:01 +00:00
[ObjCARC] Refactored out the inner most 2-loops from PerformCodePlacement into the method ConnectTDBUTraversals.
The method PerformCodePlacement was doing too much (i.e. 3x loops, lots of different checking). This refactoring separates the analysis section of the method into a separate function while leaving the actual code placement and analysis preparation in PerformCodePlacement. *NOTE* Really this part of ObjCARC should be refactored out of the main pass class into its own seperate class/struct. But, it is not time to make that change yet though (don't want to make such an invasive change without fixing all of the bugs first). git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@173201 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -1849,6 +1849,19 @@ namespace {
|
||||
SmallVectorImpl<Instruction *> &DeadInsts,
|
||||
Module *M);
|
||||
|
||||
bool ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState> &BBStates,
|
||||
MapVector<Value *, RRInfo> &Retains,
|
||||
DenseMap<Value *, RRInfo> &Releases,
|
||||
Module *M,
|
||||
SmallVector<Instruction *, 4> &NewRetains,
|
||||
SmallVector<Instruction *, 4> &NewReleases,
|
||||
SmallVector<Instruction *, 8> &DeadInsts,
|
||||
RRInfo &RetainsToMove,
|
||||
RRInfo &ReleasesToMove,
|
||||
Value *Arg,
|
||||
bool KnownSafe,
|
||||
bool &AnyPairsCompletelyEliminated);
|
||||
|
||||
bool PerformCodePlacement(DenseMap<const BasicBlock *, BBState> &BBStates,
|
||||
MapVector<Value *, RRInfo> &Retains,
|
||||
DenseMap<Value *, RRInfo> &Releases,
|
||||
@ -3398,48 +3411,20 @@ void ObjCARCOpt::MoveCalls(Value *Arg,
|
||||
}
|
||||
}
|
||||
|
||||
/// Identify pairings between the retains and releases, and delete and/or move
|
||||
/// them.
|
||||
bool
|
||||
ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
|
||||
ObjCARCOpt::ConnectTDBUTraversals(DenseMap<const BasicBlock *, BBState>
|
||||
&BBStates,
|
||||
MapVector<Value *, RRInfo> &Retains,
|
||||
DenseMap<Value *, RRInfo> &Releases,
|
||||
Module *M) {
|
||||
bool AnyPairsCompletelyEliminated = false;
|
||||
RRInfo RetainsToMove;
|
||||
RRInfo ReleasesToMove;
|
||||
SmallVector<Instruction *, 4> NewRetains;
|
||||
SmallVector<Instruction *, 4> NewReleases;
|
||||
SmallVector<Instruction *, 8> DeadInsts;
|
||||
|
||||
// Visit each retain.
|
||||
for (MapVector<Value *, RRInfo>::const_iterator I = Retains.begin(),
|
||||
E = Retains.end(); I != E; ++I) {
|
||||
Value *V = I->first;
|
||||
if (!V) continue; // blotted
|
||||
|
||||
Instruction *Retain = cast<Instruction>(V);
|
||||
|
||||
DEBUG(dbgs() << "ObjCARCOpt::PerformCodePlacement: Visiting: " << *Retain
|
||||
<< "\n");
|
||||
|
||||
Value *Arg = GetObjCArg(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
|
||||
// regardless of what possible decrements or uses lie between them.
|
||||
bool KnownSafe = isa<Constant>(Arg) || isa<AllocaInst>(Arg);
|
||||
|
||||
// A constant pointer can't be pointing to an object on the heap. It may
|
||||
// be reference-counted, but it won't be deleted.
|
||||
if (const LoadInst *LI = dyn_cast<LoadInst>(Arg))
|
||||
if (const GlobalVariable *GV =
|
||||
dyn_cast<GlobalVariable>(
|
||||
StripPointerCastsAndObjCCalls(LI->getPointerOperand())))
|
||||
if (GV->isConstant())
|
||||
KnownSafe = true;
|
||||
|
||||
Module *M,
|
||||
SmallVector<Instruction *, 4> &NewRetains,
|
||||
SmallVector<Instruction *, 4> &NewReleases,
|
||||
SmallVector<Instruction *, 8> &DeadInsts,
|
||||
RRInfo &RetainsToMove,
|
||||
RRInfo &ReleasesToMove,
|
||||
Value *Arg,
|
||||
bool KnownSafe,
|
||||
bool &AnyPairsCompletelyEliminated) {
|
||||
// If a pair happens in a region where it is known that the reference count
|
||||
// is already incremented, we can similarly ignore possible decrements.
|
||||
bool KnownSafeTD = true, KnownSafeBU = true;
|
||||
@ -3454,7 +3439,6 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
|
||||
unsigned NewCount = 0;
|
||||
bool FirstRelease = true;
|
||||
bool FirstRetain = true;
|
||||
NewRetains.push_back(Retain);
|
||||
for (;;) {
|
||||
for (SmallVectorImpl<Instruction *>::const_iterator
|
||||
NI = NewRetains.begin(), NE = NewRetains.end(); NI != NE; ++NI) {
|
||||
@ -3470,7 +3454,7 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
|
||||
DenseMap<Value *, RRInfo>::const_iterator Jt =
|
||||
Releases.find(NewRetainRelease);
|
||||
if (Jt == Releases.end())
|
||||
goto next_retain;
|
||||
return false;
|
||||
const RRInfo &NewRetainReleaseRRI = Jt->second;
|
||||
assert(NewRetainReleaseRRI.Calls.count(NewRetain));
|
||||
if (ReleasesToMove.Calls.insert(NewRetainRelease)) {
|
||||
@ -3526,7 +3510,7 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
|
||||
MapVector<Value *, RRInfo>::const_iterator Jt =
|
||||
Retains.find(NewReleaseRetain);
|
||||
if (Jt == Retains.end())
|
||||
goto next_retain;
|
||||
return false;
|
||||
const RRInfo &NewReleaseRetainRRI = Jt->second;
|
||||
assert(NewReleaseRetainRRI.Calls.count(NewRelease));
|
||||
if (RetainsToMove.Calls.insert(NewReleaseRetain)) {
|
||||
@ -3543,7 +3527,7 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
|
||||
NewReleaseRetainRRI.IsRetainBlock)
|
||||
// It's not possible to merge the sequences if one uses
|
||||
// objc_retain and the other uses objc_retainBlock.
|
||||
goto next_retain;
|
||||
return false;
|
||||
|
||||
// Collect the optimal insertion points.
|
||||
if (!KnownSafe)
|
||||
@ -3578,7 +3562,7 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
|
||||
// TODO: If the fully aggressive solution isn't valid, try to find a
|
||||
// less aggressive solution which is.
|
||||
if (NewDelta != 0)
|
||||
goto next_retain;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine whether the original call points are balanced in the retain and
|
||||
@ -3587,17 +3571,78 @@ ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
|
||||
// TODO: It's theoretically possible to do code motion in this case, as
|
||||
// long as the existing imbalances are maintained.
|
||||
if (OldDelta != 0)
|
||||
goto next_retain;
|
||||
return false;
|
||||
|
||||
// Ok, everything checks out and we're all set. Let's move some code!
|
||||
Changed = true;
|
||||
assert(OldCount != 0 && "Unreachable code?");
|
||||
AnyPairsCompletelyEliminated = NewCount == 0;
|
||||
NumRRs += OldCount - NewCount;
|
||||
|
||||
// Set to true if we completely removed any RR pairs.
|
||||
AnyPairsCompletelyEliminated |= NewCount == 0;
|
||||
|
||||
// We can move calls!
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Identify pairings between the retains and releases, and delete and/or move
|
||||
/// them.
|
||||
bool
|
||||
ObjCARCOpt::PerformCodePlacement(DenseMap<const BasicBlock *, BBState>
|
||||
&BBStates,
|
||||
MapVector<Value *, RRInfo> &Retains,
|
||||
DenseMap<Value *, RRInfo> &Releases,
|
||||
Module *M) {
|
||||
bool AnyPairsCompletelyEliminated = false;
|
||||
RRInfo RetainsToMove;
|
||||
RRInfo ReleasesToMove;
|
||||
SmallVector<Instruction *, 4> NewRetains;
|
||||
SmallVector<Instruction *, 4> NewReleases;
|
||||
SmallVector<Instruction *, 8> DeadInsts;
|
||||
|
||||
// Visit each retain.
|
||||
for (MapVector<Value *, RRInfo>::const_iterator I = Retains.begin(),
|
||||
E = Retains.end(); I != E; ++I) {
|
||||
Value *V = I->first;
|
||||
if (!V) continue; // blotted
|
||||
|
||||
Instruction *Retain = cast<Instruction>(V);
|
||||
|
||||
DEBUG(dbgs() << "ObjCARCOpt::PerformCodePlacement: Visiting: " << *Retain
|
||||
<< "\n");
|
||||
|
||||
Value *Arg = GetObjCArg(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
|
||||
// regardless of what possible decrements or uses lie between them.
|
||||
bool KnownSafe = isa<Constant>(Arg) || isa<AllocaInst>(Arg);
|
||||
|
||||
// A constant pointer can't be pointing to an object on the heap. It may
|
||||
// be reference-counted, but it won't be deleted.
|
||||
if (const LoadInst *LI = dyn_cast<LoadInst>(Arg))
|
||||
if (const GlobalVariable *GV =
|
||||
dyn_cast<GlobalVariable>(
|
||||
StripPointerCastsAndObjCCalls(LI->getPointerOperand())))
|
||||
if (GV->isConstant())
|
||||
KnownSafe = true;
|
||||
|
||||
// Connect the dots between the top-down-collected RetainsToMove and
|
||||
// bottom-up-collected ReleasesToMove to form sets of related calls.
|
||||
NewRetains.push_back(Retain);
|
||||
bool PerformMoveCalls =
|
||||
ConnectTDBUTraversals(BBStates, Retains, Releases, M, NewRetains,
|
||||
NewReleases, DeadInsts, RetainsToMove,
|
||||
ReleasesToMove, Arg, KnownSafe,
|
||||
AnyPairsCompletelyEliminated);
|
||||
|
||||
if (PerformMoveCalls) {
|
||||
// Ok, everything checks out and we're all set. Let's move/delete some
|
||||
// code!
|
||||
MoveCalls(Arg, RetainsToMove, ReleasesToMove,
|
||||
Retains, Releases, DeadInsts, M);
|
||||
}
|
||||
|
||||
next_retain:
|
||||
// Clean up state for next retain.
|
||||
NewReleases.clear();
|
||||
NewRetains.clear();
|
||||
RetainsToMove.clear();
|
||||
|
Reference in New Issue
Block a user