mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 19:52:54 +01:00
Add support for folding spills into preceding defs when doing pre-alloc splitting.
llvm-svn: 60433
This commit is contained in:
parent
c9123e12e3
commit
afbd11e227
@ -40,6 +40,7 @@ static cl::opt<int> PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden);
|
||||
|
||||
STATISTIC(NumSplits, "Number of intervals split");
|
||||
STATISTIC(NumRemats, "Number of intervals split by rematerialization");
|
||||
STATISTIC(NumFolds, "Number of intervals split with spill folding");
|
||||
|
||||
namespace {
|
||||
class VISIBILITY_HIDDEN PreAllocSplitting : public MachineFunctionPass {
|
||||
@ -159,6 +160,12 @@ namespace {
|
||||
MachineBasicBlock::iterator RestorePt,
|
||||
unsigned RestoreIdx,
|
||||
SmallPtrSet<MachineInstr*, 4>& RefsInMBB);
|
||||
MachineInstr* FoldSpill(unsigned vreg, const TargetRegisterClass* RC,
|
||||
MachineInstr* DefMI,
|
||||
MachineInstr* Barrier,
|
||||
MachineBasicBlock* MBB,
|
||||
int& SS,
|
||||
SmallPtrSet<MachineInstr*, 4>& RefsInMBB);
|
||||
};
|
||||
} // end anonymous namespace
|
||||
|
||||
@ -714,7 +721,61 @@ bool PreAllocSplitting::Rematerialize(unsigned vreg, VNInfo* ValNo,
|
||||
++NumSplits;
|
||||
++NumRemats;
|
||||
return true;
|
||||
}
|
||||
|
||||
MachineInstr* PreAllocSplitting::FoldSpill(unsigned vreg,
|
||||
const TargetRegisterClass* RC,
|
||||
MachineInstr* DefMI,
|
||||
MachineInstr* Barrier,
|
||||
MachineBasicBlock* MBB,
|
||||
int& SS,
|
||||
SmallPtrSet<MachineInstr*, 4>& RefsInMBB) {
|
||||
MachineBasicBlock::iterator Pt = MBB->begin();
|
||||
|
||||
// Go top down if RefsInMBB is empty.
|
||||
if (RefsInMBB.empty())
|
||||
return 0;
|
||||
|
||||
MachineBasicBlock::iterator FoldPt = Barrier;
|
||||
while (&*FoldPt != DefMI && FoldPt != MBB->begin() &&
|
||||
!RefsInMBB.count(FoldPt))
|
||||
--FoldPt;
|
||||
|
||||
int OpIdx = FoldPt->findRegisterDefOperandIdx(vreg, false);
|
||||
if (OpIdx == -1)
|
||||
return 0;
|
||||
|
||||
SmallVector<unsigned, 1> Ops;
|
||||
Ops.push_back(OpIdx);
|
||||
|
||||
if (!TII->canFoldMemoryOperand(FoldPt, Ops))
|
||||
return 0;
|
||||
|
||||
DenseMap<unsigned, int>::iterator I = IntervalSSMap.find(vreg);
|
||||
if (I != IntervalSSMap.end()) {
|
||||
SS = I->second;
|
||||
} else {
|
||||
SS = MFI->CreateStackObject(RC->getSize(), RC->getAlignment());
|
||||
|
||||
}
|
||||
|
||||
MachineInstr* FMI = TII->foldMemoryOperand(*MBB->getParent(),
|
||||
FoldPt, Ops, SS);
|
||||
|
||||
if (FMI) {
|
||||
LIs->ReplaceMachineInstrInMaps(FoldPt, FMI);
|
||||
FMI = MBB->insert(MBB->erase(FoldPt), FMI);
|
||||
++NumFolds;
|
||||
|
||||
IntervalSSMap[vreg] = SS;
|
||||
CurrSLI = &LSs->getOrCreateInterval(SS);
|
||||
if (CurrSLI->hasAtLeastOneValue())
|
||||
CurrSValNo = CurrSLI->getValNumInfo(0);
|
||||
else
|
||||
CurrSValNo = CurrSLI->getNextValue(~0U, 0, LSs->getVNInfoAllocator());
|
||||
}
|
||||
|
||||
return FMI;
|
||||
}
|
||||
|
||||
/// SplitRegLiveInterval - Split (spill and restore) the given live interval
|
||||
@ -770,26 +831,38 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
|
||||
int SS = -1;
|
||||
if (ValNo->def == ~0U) {
|
||||
// If it's defined by a phi, we must split just before the barrier.
|
||||
if ((SpillMI = FoldSpill(LI->reg, RC, 0, Barrier,
|
||||
BarrierMBB, SS, RefsInMBB))) {
|
||||
SpillIndex = LIs->getInstructionIndex(SpillMI);
|
||||
} else {
|
||||
MachineBasicBlock::iterator SpillPt =
|
||||
findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB, SpillIndex);
|
||||
if (SpillPt == BarrierMBB->begin())
|
||||
return false; // No gap to insert spill.
|
||||
// Add spill.
|
||||
|
||||
SS = CreateSpillStackSlot(CurrLI->reg, RC);
|
||||
TII->storeRegToStackSlot(*BarrierMBB, SpillPt, CurrLI->reg, true, SS, RC);
|
||||
SpillMI = prior(SpillPt);
|
||||
LIs->InsertMachineInstrInMaps(SpillMI, SpillIndex);
|
||||
}
|
||||
} else if (!IsAvailableInStack(DefMBB, CurrLI->reg, ValNo->def,
|
||||
RestoreIndex, SpillIndex, SS)) {
|
||||
// If it's already split, just restore the value. There is no need to spill
|
||||
// the def again.
|
||||
if (!DefMI)
|
||||
return false; // Def is dead. Do nothing.
|
||||
|
||||
if ((SpillMI = FoldSpill(LI->reg, RC, DefMI, Barrier,
|
||||
BarrierMBB, SS, RefsInMBB))) {
|
||||
SpillIndex = LIs->getInstructionIndex(SpillMI);
|
||||
} else {
|
||||
// Check if it's possible to insert a spill after the def MI.
|
||||
MachineBasicBlock::iterator SpillPt;
|
||||
if (DefMBB == BarrierMBB) {
|
||||
// Add spill after the def and the last use before the barrier.
|
||||
SpillPt = findSpillPoint(BarrierMBB, Barrier, DefMI, RefsInMBB, SpillIndex);
|
||||
SpillPt = findSpillPoint(BarrierMBB, Barrier, DefMI,
|
||||
RefsInMBB, SpillIndex);
|
||||
if (SpillPt == DefMBB->begin())
|
||||
return false; // No gap to insert spill.
|
||||
} else {
|
||||
@ -805,6 +878,7 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
|
||||
SpillMI = prior(SpillPt);
|
||||
LIs->InsertMachineInstrInMaps(SpillMI, SpillIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// Remember def instruction index to spill index mapping.
|
||||
if (DefMI && SpillMI)
|
||||
|
Loading…
Reference in New Issue
Block a user