using namespace llvm;
static cl::opt<int> PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden);
+static cl::opt<int> DeadSplitLimit("dead-split-limit", cl::init(-1), cl::Hidden);
STATISTIC(NumSplits, "Number of intervals split");
STATISTIC(NumRemats, "Number of intervals split by rematerialization");
MachineFunction *CurrMF;
const TargetMachine *TM;
const TargetInstrInfo *TII;
+ const TargetRegisterInfo* TRI;
MachineFrameInfo *MFI;
MachineRegisterInfo *MRI;
LiveIntervals *LIs;
void RenumberValno(VNInfo* VN);
void ReconstructLiveInterval(LiveInterval* LI);
bool removeDeadSpills(SmallPtrSet<LiveInterval*, 8>& split);
- unsigned getNumberOfSpills(SmallPtrSet<MachineInstr*, 4>& MIs,
- unsigned Reg, int FrameIndex);
- VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator use,
- MachineBasicBlock* MBB,
- LiveInterval* LI,
+ unsigned getNumberOfNonSpills(SmallPtrSet<MachineInstr*, 4>& MIs,
+ unsigned Reg, int FrameIndex, bool& TwoAddr);
+ VNInfo* PerformPHIConstruction(MachineBasicBlock::iterator Use,
+ MachineBasicBlock* MBB, LiveInterval* LI,
SmallPtrSet<MachineInstr*, 4>& Visited,
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs,
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses,
DenseMap<MachineInstr*, VNInfo*>& NewVNs,
DenseMap<MachineBasicBlock*, VNInfo*>& LiveOut,
DenseMap<MachineBasicBlock*, VNInfo*>& Phis,
- bool toplevel, bool intrablock);
+ bool IsTopLevel, bool IsIntraBlock);
+ VNInfo* PerformPHIConstructionFallBack(MachineBasicBlock::iterator Use,
+ MachineBasicBlock* MBB, LiveInterval* LI,
+ SmallPtrSet<MachineInstr*, 4>& Visited,
+ DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs,
+ DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses,
+ DenseMap<MachineInstr*, VNInfo*>& NewVNs,
+ DenseMap<MachineBasicBlock*, VNInfo*>& LiveOut,
+ DenseMap<MachineBasicBlock*, VNInfo*>& Phis,
+ bool IsTopLevel, bool IsIntraBlock);
};
} // end anonymous namespace
Pt = MII;
SpillIndex = Gap;
break;
- }
+
+ // We can't insert the spill between the barrier (a call), and its
+ // corresponding call frame setup.
+ } else if (prior(MII)->getOpcode() == TRI->getCallFrameSetupOpcode() &&
+ MII == MachineBasicBlock::iterator(MI))
+ break;
} while (MII != EndPt);
} else {
MachineBasicBlock::iterator MII = MI;
MachineBasicBlock::iterator EndPt = DefMI
? MachineBasicBlock::iterator(DefMI) : MBB->begin();
+
+ // We can't insert the spill between the barrier (a call), and its
+ // corresponding call frame setup.
+ if (prior(MII)->getOpcode() == TRI->getCallFrameSetupOpcode()) --MII;
while (MII != EndPt && !RefsInMBB.count(MII)) {
unsigned Index = LIs->getInstructionIndex(MII);
if (LIs->hasGapBeforeInstr(Index)) {
Pt = MII;
RestoreIndex = Gap;
break;
- }
+
+ // We can't insert a restore between the barrier (a call) and its
+ // corresponding call frame teardown.
+ } else if (MII->getOpcode() == TRI->getCallFrameDestroyOpcode() &&
+ prior(MII) == MachineBasicBlock::iterator(MI))
+ break;
--MII;
} while (MII != EndPt);
} else {
MachineBasicBlock::iterator MII = MI;
MII = ++MII;
+ // We can't insert a restore between the barrier (a call) and its
+ // corresponding call frame teardown.
+ if (MII->getOpcode() == TRI->getCallFrameDestroyOpcode())
+ ++MII;
+
// FIXME: Limit the number of instructions to examine to reduce
// compile time?
- while (MII != MBB->end()) {
+ while (MII != MBB->getFirstTerminator()) {
unsigned Index = LIs->getInstructionIndex(MII);
if (Index > LastIdx)
break;
/// PerformPHIConstruction - From properly set up use and def lists, use a PHI
/// construction algorithm to compute the ranges and valnos for an interval.
-VNInfo* PreAllocSplitting::PerformPHIConstruction(
- MachineBasicBlock::iterator use,
- MachineBasicBlock* MBB,
- LiveInterval* LI,
+VNInfo*
+PreAllocSplitting::PerformPHIConstruction(MachineBasicBlock::iterator UseI,
+ MachineBasicBlock* MBB, LiveInterval* LI,
SmallPtrSet<MachineInstr*, 4>& Visited,
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs,
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses,
DenseMap<MachineInstr*, VNInfo*>& NewVNs,
DenseMap<MachineBasicBlock*, VNInfo*>& LiveOut,
DenseMap<MachineBasicBlock*, VNInfo*>& Phis,
- bool toplevel, bool intrablock) {
+ bool IsTopLevel, bool IsIntraBlock) {
// Return memoized result if it's available.
- if (toplevel && Visited.count(use) && NewVNs.count(use))
- return NewVNs[use];
- else if (!toplevel && intrablock && NewVNs.count(use))
- return NewVNs[use];
- else if (!intrablock && LiveOut.count(MBB))
+ if (IsTopLevel && Visited.count(UseI) && NewVNs.count(UseI))
+ return NewVNs[UseI];
+ else if (!IsTopLevel && IsIntraBlock && NewVNs.count(UseI))
+ return NewVNs[UseI];
+ else if (!IsIntraBlock && LiveOut.count(MBB))
return LiveOut[MBB];
- typedef DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> > RegMap;
-
// Check if our block contains any uses or defs.
bool ContainsDefs = Defs.count(MBB);
bool ContainsUses = Uses.count(MBB);
- VNInfo* ret = 0;
+ VNInfo* RetVNI = 0;
// Enumerate the cases of use/def contaning blocks.
if (!ContainsDefs && !ContainsUses) {
- Fallback:
- // NOTE: Because this is the fallback case from other cases, we do NOT
- // assume that we are not intrablock here.
- if (Phis.count(MBB)) return Phis[MBB];
-
- unsigned StartIndex = LIs->getMBBStartIdx(MBB);
-
- if (MBB->pred_size() == 1) {
- Phis[MBB] = ret = PerformPHIConstruction((*MBB->pred_begin())->end(),
- *(MBB->pred_begin()), LI, Visited,
- Defs, Uses, NewVNs, LiveOut, Phis,
- false, false);
- unsigned EndIndex = 0;
- if (intrablock) {
- EndIndex = LIs->getInstructionIndex(use);
- EndIndex = LiveIntervals::getUseIndex(EndIndex);
- } else
- EndIndex = LIs->getMBBEndIdx(MBB);
-
- LI->addRange(LiveRange(StartIndex, EndIndex+1, ret));
- if (intrablock)
- LI->addKill(ret, EndIndex);
- } else {
- Phis[MBB] = ret = LI->getNextValue(~0U, /*FIXME*/ 0,
- LIs->getVNInfoAllocator());
- if (!intrablock) LiveOut[MBB] = ret;
-
- // If there are no uses or defs between our starting point and the
- // beginning of the block, then recursive perform phi construction
- // on our predecessors.
- DenseMap<MachineBasicBlock*, VNInfo*> IncomingVNs;
- for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
- PE = MBB->pred_end(); PI != PE; ++PI) {
- VNInfo* Incoming = PerformPHIConstruction((*PI)->end(), *PI, LI,
- Visited, Defs, Uses, NewVNs,
- LiveOut, Phis, false, false);
- if (Incoming != 0)
- IncomingVNs[*PI] = Incoming;
- }
-
- // Otherwise, merge the incoming VNInfos with a phi join. Create a new
- // VNInfo to represent the joined value.
- for (DenseMap<MachineBasicBlock*, VNInfo*>::iterator I =
- IncomingVNs.begin(), E = IncomingVNs.end(); I != E; ++I) {
- I->second->hasPHIKill = true;
- unsigned KillIndex = LIs->getMBBEndIdx(I->first);
- LI->addKill(I->second, KillIndex);
- }
-
- unsigned EndIndex = 0;
- if (intrablock) {
- EndIndex = LIs->getInstructionIndex(use);
- EndIndex = LiveIntervals::getUseIndex(EndIndex);
- } else
- EndIndex = LIs->getMBBEndIdx(MBB);
- LI->addRange(LiveRange(StartIndex, EndIndex+1, ret));
- if (intrablock)
- LI->addKill(ret, EndIndex);
- }
+ return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, Uses,
+ NewVNs, LiveOut, Phis,
+ IsTopLevel, IsIntraBlock);
} else if (ContainsDefs && !ContainsUses) {
SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[MBB];
// instruction we care about, go to the fallback case. Note that that
// should never happen: this cannot be intrablock, so use should
// always be an end() iterator.
- assert(use == MBB->end() && "No use marked in intrablock");
+ assert(UseI == MBB->end() && "No use marked in intrablock");
- MachineBasicBlock::iterator walker = use;
- --walker;
- while (walker != MBB->begin())
- if (BlockDefs.count(walker)) {
+ MachineBasicBlock::iterator Walker = UseI;
+ --Walker;
+ while (Walker != MBB->begin()) {
+ if (BlockDefs.count(Walker))
break;
- } else
- --walker;
+ --Walker;
+ }
// Once we've found it, extend its VNInfo to our instruction.
- unsigned DefIndex = LIs->getInstructionIndex(walker);
+ unsigned DefIndex = LIs->getInstructionIndex(Walker);
DefIndex = LiveIntervals::getDefIndex(DefIndex);
unsigned EndIndex = LIs->getMBBEndIdx(MBB);
- ret = NewVNs[walker];
- LI->addRange(LiveRange(DefIndex, EndIndex+1, ret));
+ RetVNI = NewVNs[Walker];
+ LI->addRange(LiveRange(DefIndex, EndIndex+1, RetVNI));
} else if (!ContainsDefs && ContainsUses) {
SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[MBB];
// Search for the use in this block that precedes the instruction we care
- // about, going to the fallback case if we don't find it.
+ // about, going to the fallback case if we don't find it.
+ if (UseI == MBB->begin())
+ return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs,
+ Uses, NewVNs, LiveOut, Phis,
+ IsTopLevel, IsIntraBlock);
- if (use == MBB->begin())
- goto Fallback;
-
- MachineBasicBlock::iterator walker = use;
- --walker;
+ MachineBasicBlock::iterator Walker = UseI;
+ --Walker;
bool found = false;
- while (walker != MBB->begin())
- if (BlockUses.count(walker)) {
+ while (Walker != MBB->begin()) {
+ if (BlockUses.count(Walker)) {
found = true;
break;
- } else
- --walker;
+ }
+ --Walker;
+ }
// Must check begin() too.
if (!found) {
- if (BlockUses.count(walker))
+ if (BlockUses.count(Walker))
found = true;
else
- goto Fallback;
+ return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs,
+ Uses, NewVNs, LiveOut, Phis,
+ IsTopLevel, IsIntraBlock);
}
- unsigned UseIndex = LIs->getInstructionIndex(walker);
+ unsigned UseIndex = LIs->getInstructionIndex(Walker);
UseIndex = LiveIntervals::getUseIndex(UseIndex);
unsigned EndIndex = 0;
- if (intrablock) {
- EndIndex = LIs->getInstructionIndex(use);
+ if (IsIntraBlock) {
+ EndIndex = LIs->getInstructionIndex(UseI);
EndIndex = LiveIntervals::getUseIndex(EndIndex);
} else
EndIndex = LIs->getMBBEndIdx(MBB);
// Now, recursively phi construct the VNInfo for the use we found,
// and then extend it to include the instruction we care about
- ret = PerformPHIConstruction(walker, MBB, LI, Visited, Defs, Uses,
- NewVNs, LiveOut, Phis, false, true);
+ RetVNI = PerformPHIConstruction(Walker, MBB, LI, Visited, Defs, Uses,
+ NewVNs, LiveOut, Phis, false, true);
- LI->addRange(LiveRange(UseIndex, EndIndex+1, ret));
+ LI->addRange(LiveRange(UseIndex, EndIndex+1, RetVNI));
// FIXME: Need to set kills properly for inter-block stuff.
- if (LI->isKill(ret, UseIndex)) LI->removeKill(ret, UseIndex);
- if (intrablock)
- LI->addKill(ret, EndIndex);
- } else if (ContainsDefs && ContainsUses){
+ if (LI->isKill(RetVNI, UseIndex)) LI->removeKill(RetVNI, UseIndex);
+ if (IsIntraBlock)
+ LI->addKill(RetVNI, EndIndex);
+ } else if (ContainsDefs && ContainsUses) {
SmallPtrSet<MachineInstr*, 2>& BlockDefs = Defs[MBB];
SmallPtrSet<MachineInstr*, 2>& BlockUses = Uses[MBB];
// special note that checking for defs must take precedence over checking
// for uses, because of two-address instructions.
- if (use == MBB->begin())
- goto Fallback;
+ if (UseI == MBB->begin())
+ return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs, Uses,
+ NewVNs, LiveOut, Phis,
+ IsTopLevel, IsIntraBlock);
- MachineBasicBlock::iterator walker = use;
- --walker;
+ MachineBasicBlock::iterator Walker = UseI;
+ --Walker;
bool foundDef = false;
bool foundUse = false;
- while (walker != MBB->begin())
- if (BlockDefs.count(walker)) {
+ while (Walker != MBB->begin()) {
+ if (BlockDefs.count(Walker)) {
foundDef = true;
break;
- } else if (BlockUses.count(walker)) {
+ } else if (BlockUses.count(Walker)) {
foundUse = true;
break;
- } else
- --walker;
+ }
+ --Walker;
+ }
// Must check begin() too.
if (!foundDef && !foundUse) {
- if (BlockDefs.count(walker))
+ if (BlockDefs.count(Walker))
foundDef = true;
- else if (BlockUses.count(walker))
+ else if (BlockUses.count(Walker))
foundUse = true;
else
- goto Fallback;
+ return PerformPHIConstructionFallBack(UseI, MBB, LI, Visited, Defs,
+ Uses, NewVNs, LiveOut, Phis,
+ IsTopLevel, IsIntraBlock);
}
- unsigned StartIndex = LIs->getInstructionIndex(walker);
+ unsigned StartIndex = LIs->getInstructionIndex(Walker);
StartIndex = foundDef ? LiveIntervals::getDefIndex(StartIndex) :
LiveIntervals::getUseIndex(StartIndex);
unsigned EndIndex = 0;
- if (intrablock) {
- EndIndex = LIs->getInstructionIndex(use);
+ if (IsIntraBlock) {
+ EndIndex = LIs->getInstructionIndex(UseI);
EndIndex = LiveIntervals::getUseIndex(EndIndex);
} else
EndIndex = LIs->getMBBEndIdx(MBB);
if (foundDef)
- ret = NewVNs[walker];
+ RetVNI = NewVNs[Walker];
else
- ret = PerformPHIConstruction(walker, MBB, LI, Visited, Defs, Uses,
- NewVNs, LiveOut, Phis, false, true);
+ RetVNI = PerformPHIConstruction(Walker, MBB, LI, Visited, Defs, Uses,
+ NewVNs, LiveOut, Phis, false, true);
- LI->addRange(LiveRange(StartIndex, EndIndex+1, ret));
+ LI->addRange(LiveRange(StartIndex, EndIndex+1, RetVNI));
- if (foundUse && LI->isKill(ret, StartIndex))
- LI->removeKill(ret, StartIndex);
- if (intrablock) {
- LI->addKill(ret, EndIndex);
+ if (foundUse && LI->isKill(RetVNI, StartIndex))
+ LI->removeKill(RetVNI, StartIndex);
+ if (IsIntraBlock) {
+ LI->addKill(RetVNI, EndIndex);
}
}
// Memoize results so we don't have to recompute them.
- if (!intrablock) LiveOut[MBB] = ret;
+ if (!IsIntraBlock) LiveOut[MBB] = RetVNI;
else {
- if (!NewVNs.count(use))
- NewVNs[use] = ret;
- Visited.insert(use);
+ if (!NewVNs.count(UseI))
+ NewVNs[UseI] = RetVNI;
+ Visited.insert(UseI);
}
- return ret;
+ return RetVNI;
+}
+
+/// PerformPHIConstructionFallBack - PerformPHIConstruction fall back path.
+///
+VNInfo*
+PreAllocSplitting::PerformPHIConstructionFallBack(MachineBasicBlock::iterator UseI,
+ MachineBasicBlock* MBB, LiveInterval* LI,
+ SmallPtrSet<MachineInstr*, 4>& Visited,
+ DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Defs,
+ DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 2> >& Uses,
+ DenseMap<MachineInstr*, VNInfo*>& NewVNs,
+ DenseMap<MachineBasicBlock*, VNInfo*>& LiveOut,
+ DenseMap<MachineBasicBlock*, VNInfo*>& Phis,
+ bool IsTopLevel, bool IsIntraBlock) {
+ // NOTE: Because this is the fallback case from other cases, we do NOT
+ // assume that we are not intrablock here.
+ if (Phis.count(MBB)) return Phis[MBB];
+
+ unsigned StartIndex = LIs->getMBBStartIdx(MBB);
+ VNInfo *RetVNI = Phis[MBB] = LI->getNextValue(~0U, /*FIXME*/ 0,
+ LIs->getVNInfoAllocator());
+ if (!IsIntraBlock) LiveOut[MBB] = RetVNI;
+
+ // If there are no uses or defs between our starting point and the
+ // beginning of the block, then recursive perform phi construction
+ // on our predecessors.
+ DenseMap<MachineBasicBlock*, VNInfo*> IncomingVNs;
+ for (MachineBasicBlock::pred_iterator PI = MBB->pred_begin(),
+ PE = MBB->pred_end(); PI != PE; ++PI) {
+ VNInfo* Incoming = PerformPHIConstruction((*PI)->end(), *PI, LI,
+ Visited, Defs, Uses, NewVNs,
+ LiveOut, Phis, false, false);
+ if (Incoming != 0)
+ IncomingVNs[*PI] = Incoming;
+ }
+
+ if (MBB->pred_size() == 1 && !RetVNI->hasPHIKill) {
+ VNInfo* OldVN = RetVNI;
+ VNInfo* NewVN = IncomingVNs.begin()->second;
+ VNInfo* MergedVN = LI->MergeValueNumberInto(OldVN, NewVN);
+ if (MergedVN == OldVN) std::swap(OldVN, NewVN);
+
+ for (DenseMap<MachineBasicBlock*, VNInfo*>::iterator LOI = LiveOut.begin(),
+ LOE = LiveOut.end(); LOI != LOE; ++LOI)
+ if (LOI->second == OldVN)
+ LOI->second = MergedVN;
+ for (DenseMap<MachineInstr*, VNInfo*>::iterator NVI = NewVNs.begin(),
+ NVE = NewVNs.end(); NVI != NVE; ++NVI)
+ if (NVI->second == OldVN)
+ NVI->second = MergedVN;
+ for (DenseMap<MachineBasicBlock*, VNInfo*>::iterator PI = Phis.begin(),
+ PE = Phis.end(); PI != PE; ++PI)
+ if (PI->second == OldVN)
+ PI->second = MergedVN;
+ RetVNI = MergedVN;
+ } else {
+ // Otherwise, merge the incoming VNInfos with a phi join. Create a new
+ // VNInfo to represent the joined value.
+ for (DenseMap<MachineBasicBlock*, VNInfo*>::iterator I =
+ IncomingVNs.begin(), E = IncomingVNs.end(); I != E; ++I) {
+ I->second->hasPHIKill = true;
+ unsigned KillIndex = LIs->getMBBEndIdx(I->first);
+ if (!LiveInterval::isKill(I->second, KillIndex))
+ LI->addKill(I->second, KillIndex);
+ }
+ }
+
+ unsigned EndIndex = 0;
+ if (IsIntraBlock) {
+ EndIndex = LIs->getInstructionIndex(UseI);
+ EndIndex = LiveIntervals::getUseIndex(EndIndex);
+ } else
+ EndIndex = LIs->getMBBEndIdx(MBB);
+ LI->addRange(LiveRange(StartIndex, EndIndex+1, RetVNI));
+ if (IsIntraBlock)
+ LI->addKill(RetVNI, EndIndex);
+
+ // Memoize results so we don't have to recompute them.
+ if (!IsIntraBlock)
+ LiveOut[MBB] = RetVNI;
+ else {
+ if (!NewVNs.count(UseI))
+ NewVNs[UseI] = RetVNI;
+ Visited.insert(UseI);
+ }
+
+ return RetVNI;
}
/// ReconstructLiveInterval - Recompute a live interval from scratch.
MO.setReg(NewVReg);
}
+ // The renumbered vreg shares a stack slot with the old register.
+ if (IntervalSSMap.count(CurrLI->reg))
+ IntervalSSMap[NewVReg] = IntervalSSMap[CurrLI->reg];
+
NumRenumbers++;
}
return Change;
}
-unsigned PreAllocSplitting::getNumberOfSpills(
+unsigned PreAllocSplitting::getNumberOfNonSpills(
SmallPtrSet<MachineInstr*, 4>& MIs,
- unsigned Reg, int FrameIndex) {
- unsigned Spills = 0;
+ unsigned Reg, int FrameIndex,
+ bool& FeedsTwoAddr) {
+ unsigned NonSpills = 0;
for (SmallPtrSet<MachineInstr*, 4>::iterator UI = MIs.begin(), UE = MIs.end();
- UI != UI; ++UI) {
+ UI != UE; ++UI) {
int StoreFrameIndex;
unsigned StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex);
- if (StoreVReg == Reg && StoreFrameIndex == FrameIndex)
- Spills++;
+ if (StoreVReg != Reg || StoreFrameIndex != FrameIndex)
+ NonSpills++;
+
+ int DefIdx = (*UI)->findRegisterDefOperandIdx(Reg);
+ if (DefIdx != -1 && (*UI)->isRegReDefinedByTwoAddr(DefIdx))
+ FeedsTwoAddr = true;
}
- return Spills;
+ return NonSpills;
}
/// removeDeadSpills - After doing splitting, filter through all intervals we've
bool PreAllocSplitting::removeDeadSpills(SmallPtrSet<LiveInterval*, 8>& split) {
bool changed = false;
+ // Walk over all of the live intervals that were touched by the splitter,
+ // and see if we can do any DCE and/or folding.
for (SmallPtrSet<LiveInterval*, 8>::iterator LI = split.begin(),
LE = split.end(); LI != LE; ++LI) {
DenseMap<VNInfo*, SmallPtrSet<MachineInstr*, 4> > VNUseCount;
+ // First, collect all the uses of the vreg, and sort them by their
+ // reaching definition (VNInfo).
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin((*LI)->reg),
UE = MRI->use_end(); UI != UE; ++UI) {
unsigned index = LIs->getInstructionIndex(&*UI);
VNUseCount[LR->valno].insert(&*UI);
}
+ // Now, take the definitions (VNInfo's) one at a time and try to DCE
+ // and/or fold them away.
for (LiveInterval::vni_iterator VI = (*LI)->vni_begin(),
VE = (*LI)->vni_end(); VI != VE; ++VI) {
+
+ if (DeadSplitLimit != -1 && (int)NumDeadSpills == DeadSplitLimit)
+ return changed;
+
VNInfo* CurrVN = *VI;
+
+ // We don't currently try to handle definitions with PHI kills, because
+ // it would involve processing more than one VNInfo at once.
if (CurrVN->hasPHIKill) continue;
+ // We also don't try to handle the results of PHI joins, since there's
+ // no defining instruction to analyze.
unsigned DefIdx = CurrVN->def;
if (DefIdx == ~0U || DefIdx == ~1U) continue;
+ // We're only interested in eliminating cruft introduced by the splitter,
+ // is of the form load-use or load-use-store. First, check that the
+ // definition is a load, and remember what stack slot we loaded it from.
MachineInstr* DefMI = LIs->getInstructionFromIndex(DefIdx);
int FrameIndex;
if (!TII->isLoadFromStackSlot(DefMI, FrameIndex)) continue;
+ // If the definition has no uses at all, just DCE it.
if (VNUseCount[CurrVN].size() == 0) {
LIs->RemoveMachineInstrFromMaps(DefMI);
(*LI)->removeValNo(CurrVN);
DefMI->eraseFromParent();
+ VNUseCount.erase(CurrVN);
NumDeadSpills++;
changed = true;
continue;
}
- unsigned SpillCount = getNumberOfSpills(VNUseCount[CurrVN],
- (*LI)->reg, FrameIndex);
- if (SpillCount != VNUseCount[CurrVN].size()) continue;
+ // Second, get the number of non-store uses of the definition, as well as
+ // a flag indicating whether it feeds into a later two-address definition.
+ bool FeedsTwoAddr = false;
+ unsigned NonSpillCount = getNumberOfNonSpills(VNUseCount[CurrVN],
+ (*LI)->reg, FrameIndex,
+ FeedsTwoAddr);
+
+ // If there's one non-store use and it doesn't feed a two-addr, then
+ // this is a load-use-store case that we can try to fold.
+ if (NonSpillCount == 1 && !FeedsTwoAddr) {
+ // Start by finding the non-store use MachineInstr.
+ SmallPtrSet<MachineInstr*, 4>::iterator UI = VNUseCount[CurrVN].begin();
+ int StoreFrameIndex;
+ unsigned StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex);
+ while (UI != VNUseCount[CurrVN].end() &&
+ (StoreVReg == (*LI)->reg && StoreFrameIndex == FrameIndex)) {
+ ++UI;
+ if (UI != VNUseCount[CurrVN].end())
+ StoreVReg = TII->isStoreToStackSlot(*UI, StoreFrameIndex);
+ }
+ if (UI == VNUseCount[CurrVN].end()) continue;
+
+ MachineInstr* use = *UI;
+
+ // Attempt to fold it away!
+ int OpIdx = use->findRegisterUseOperandIdx((*LI)->reg, false);
+ if (OpIdx == -1) continue;
+ SmallVector<unsigned, 1> Ops;
+ Ops.push_back(OpIdx);
+ if (!TII->canFoldMemoryOperand(use, Ops)) continue;
+
+ MachineInstr* NewMI =
+ TII->foldMemoryOperand(*use->getParent()->getParent(),
+ use, Ops, FrameIndex);
+
+ if (!NewMI) continue;
+
+ // Update relevant analyses.
+ LIs->RemoveMachineInstrFromMaps(DefMI);
+ LIs->ReplaceMachineInstrInMaps(use, NewMI);
+ (*LI)->removeValNo(CurrVN);
+
+ DefMI->eraseFromParent();
+ MachineBasicBlock* MBB = use->getParent();
+ NewMI = MBB->insert(MBB->erase(use), NewMI);
+ VNUseCount[CurrVN].erase(use);
+ // Remove deleted instructions. Note that we need to remove them from
+ // the VNInfo->use map as well, just to be safe.
+ for (SmallPtrSet<MachineInstr*, 4>::iterator II =
+ VNUseCount[CurrVN].begin(), IE = VNUseCount[CurrVN].end();
+ II != IE; ++II) {
+ for (DenseMap<VNInfo*, SmallPtrSet<MachineInstr*, 4> >::iterator
+ VNI = VNUseCount.begin(), VNE = VNUseCount.end(); VNI != VNE;
+ ++VNI)
+ if (VNI->first != CurrVN)
+ VNI->second.erase(*II);
+ LIs->RemoveMachineInstrFromMaps(*II);
+ (*II)->eraseFromParent();
+ }
+
+ VNUseCount.erase(CurrVN);
+
+ for (DenseMap<VNInfo*, SmallPtrSet<MachineInstr*, 4> >::iterator
+ VI = VNUseCount.begin(), VE = VNUseCount.end(); VI != VE; ++VI)
+ if (VI->second.erase(use))
+ VI->second.insert(NewMI);
+
+ NumDeadSpills++;
+ changed = true;
+ continue;
+ }
+
+ // If there's more than one non-store instruction, we can't profitably
+ // fold it, so bail.
+ if (NonSpillCount) continue;
+
+ // Otherwise, this is a load-store case, so DCE them.
for (SmallPtrSet<MachineInstr*, 4>::iterator UI =
VNUseCount[CurrVN].begin(), UE = VNUseCount[CurrVN].end();
UI != UI; ++UI) {
(*UI)->eraseFromParent();
}
+ VNUseCount.erase(CurrVN);
+
LIs->RemoveMachineInstrFromMaps(DefMI);
(*LI)->removeValNo(CurrVN);
DefMI->eraseFromParent();
bool PreAllocSplitting::runOnMachineFunction(MachineFunction &MF) {
CurrMF = &MF;
TM = &MF.getTarget();
+ TRI = TM->getRegisterInfo();
TII = TM->getInstrInfo();
MFI = MF.getFrameInfo();
MRI = &MF.getRegInfo();