mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-09 11:25:55 +00:00
Add support for rematerialization in pre-alloc-splitting.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@59587 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -39,6 +39,7 @@ using namespace llvm;
|
|||||||
static cl::opt<int> PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden);
|
static cl::opt<int> PreSplitLimit("pre-split-limit", cl::init(-1), cl::Hidden);
|
||||||
|
|
||||||
STATISTIC(NumSplits, "Number of intervals split");
|
STATISTIC(NumSplits, "Number of intervals split");
|
||||||
|
STATISTIC(NumRemats, "Number of intervals split by rematerialization");
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
class VISIBILITY_HIDDEN PreAllocSplitting : public MachineFunctionPass {
|
class VISIBILITY_HIDDEN PreAllocSplitting : public MachineFunctionPass {
|
||||||
@@ -153,6 +154,11 @@ namespace {
|
|||||||
|
|
||||||
bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB,
|
bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB,
|
||||||
MachineBasicBlock* BarrierMBB);
|
MachineBasicBlock* BarrierMBB);
|
||||||
|
bool Rematerialize(unsigned vreg, VNInfo* ValNo,
|
||||||
|
MachineInstr* DefMI,
|
||||||
|
MachineBasicBlock::iterator RestorePt,
|
||||||
|
unsigned RestoreIdx,
|
||||||
|
SmallPtrSet<MachineInstr*, 4>& RefsInMBB);
|
||||||
};
|
};
|
||||||
} // end anonymous namespace
|
} // end anonymous namespace
|
||||||
|
|
||||||
@@ -627,6 +633,90 @@ PreAllocSplitting::ShrinkWrapLiveInterval(VNInfo *ValNo, MachineBasicBlock *MBB,
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool PreAllocSplitting::Rematerialize(unsigned vreg, VNInfo* ValNo,
|
||||||
|
MachineInstr* DefMI,
|
||||||
|
MachineBasicBlock::iterator RestorePt,
|
||||||
|
unsigned RestoreIdx,
|
||||||
|
SmallPtrSet<MachineInstr*, 4>& RefsInMBB) {
|
||||||
|
MachineBasicBlock& MBB = *RestorePt->getParent();
|
||||||
|
|
||||||
|
MachineBasicBlock::iterator KillPt = BarrierMBB->end();
|
||||||
|
unsigned KillIdx = 0;
|
||||||
|
if (ValNo->def == ~0U || DefMI->getParent() == BarrierMBB)
|
||||||
|
KillPt = findSpillPoint(BarrierMBB, Barrier, NULL, RefsInMBB, KillIdx);
|
||||||
|
else
|
||||||
|
KillPt = findNextEmptySlot(DefMI->getParent(), DefMI, KillIdx);
|
||||||
|
|
||||||
|
if (KillPt == DefMI->getParent()->end())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TII->reMaterialize(MBB, RestorePt, vreg, DefMI);
|
||||||
|
LIs->InsertMachineInstrInMaps(prior(RestorePt), RestoreIdx);
|
||||||
|
|
||||||
|
if (KillPt->getParent() == BarrierMBB) {
|
||||||
|
UpdateRegisterInterval(ValNo, LIs->getUseIndex(KillIdx)+1,
|
||||||
|
LIs->getDefIndex(RestoreIdx));
|
||||||
|
|
||||||
|
++NumSplits;
|
||||||
|
++NumRemats;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Shrink wrap the live interval by walking up the CFG and find the
|
||||||
|
// new kills.
|
||||||
|
// Now let's find all the uses of the val#.
|
||||||
|
DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> > Uses;
|
||||||
|
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> > UseMIs;
|
||||||
|
SmallPtrSet<MachineBasicBlock*, 4> Seen;
|
||||||
|
SmallVector<MachineBasicBlock*, 4> UseMBBs;
|
||||||
|
for (MachineRegisterInfo::use_iterator UI = MRI->use_begin(CurrLI->reg),
|
||||||
|
UE = MRI->use_end(); UI != UE; ++UI) {
|
||||||
|
MachineOperand &UseMO = UI.getOperand();
|
||||||
|
MachineInstr *UseMI = UseMO.getParent();
|
||||||
|
unsigned UseIdx = LIs->getInstructionIndex(UseMI);
|
||||||
|
LiveInterval::iterator ULR = CurrLI->FindLiveRangeContaining(UseIdx);
|
||||||
|
if (ULR->valno != ValNo)
|
||||||
|
continue;
|
||||||
|
MachineBasicBlock *UseMBB = UseMI->getParent();
|
||||||
|
// Remember which other mbb's use this val#.
|
||||||
|
if (Seen.insert(UseMBB) && UseMBB != BarrierMBB)
|
||||||
|
UseMBBs.push_back(UseMBB);
|
||||||
|
DenseMap<MachineBasicBlock*, SmallVector<MachineOperand*, 4> >::iterator
|
||||||
|
UMII = Uses.find(UseMBB);
|
||||||
|
if (UMII != Uses.end()) {
|
||||||
|
DenseMap<MachineBasicBlock*, SmallPtrSet<MachineInstr*, 4> >::iterator
|
||||||
|
UMII2 = UseMIs.find(UseMBB);
|
||||||
|
UMII->second.push_back(&UseMO);
|
||||||
|
UMII2->second.insert(UseMI);
|
||||||
|
} else {
|
||||||
|
SmallVector<MachineOperand*, 4> Ops;
|
||||||
|
Ops.push_back(&UseMO);
|
||||||
|
Uses.insert(std::make_pair(UseMBB, Ops));
|
||||||
|
SmallPtrSet<MachineInstr*, 4> MIs;
|
||||||
|
MIs.insert(UseMI);
|
||||||
|
UseMIs.insert(std::make_pair(UseMBB, MIs));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk up the predecessor chains.
|
||||||
|
SmallPtrSet<MachineBasicBlock*, 8> Visited;
|
||||||
|
ShrinkWrapLiveInterval(ValNo, BarrierMBB, NULL, DefMI->getParent(), Visited,
|
||||||
|
Uses, UseMIs, UseMBBs);
|
||||||
|
|
||||||
|
// FIXME: If ValNo->hasPHIKill is false, then renumber the val# by
|
||||||
|
// the restore.
|
||||||
|
|
||||||
|
// Remove live range from barrier to the restore. FIXME: Find a better
|
||||||
|
// point to re-start the live interval.
|
||||||
|
UpdateRegisterInterval(ValNo, LIs->getUseIndex(BarrierIdx)+1,
|
||||||
|
LIs->getDefIndex(RestoreIdx));
|
||||||
|
|
||||||
|
++NumSplits;
|
||||||
|
++NumRemats;
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/// SplitRegLiveInterval - Split (spill and restore) the given live interval
|
/// SplitRegLiveInterval - Split (spill and restore) the given live interval
|
||||||
/// so it would not cross the barrier that's being processed. Shrink wrap
|
/// so it would not cross the barrier that's being processed. Shrink wrap
|
||||||
/// (minimize) the live interval to the last uses.
|
/// (minimize) the live interval to the last uses.
|
||||||
@@ -644,11 +734,8 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
|
|||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: For now, if definition is rematerializable, do not split.
|
|
||||||
MachineInstr *DefMI = (ValNo->def != ~0U)
|
MachineInstr *DefMI = (ValNo->def != ~0U)
|
||||||
? LIs->getInstructionFromIndex(ValNo->def) : NULL;
|
? LIs->getInstructionFromIndex(ValNo->def) : NULL;
|
||||||
if (DefMI && LIs->isReMaterializable(*LI, ValNo, DefMI))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// If this would create a new join point, do not split.
|
// If this would create a new join point, do not split.
|
||||||
if (DefMI && createsNewJoin(LR, DefMI->getParent(), Barrier->getParent()))
|
if (DefMI && createsNewJoin(LR, DefMI->getParent(), Barrier->getParent()))
|
||||||
@@ -670,6 +757,11 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
|
|||||||
if (RestorePt == BarrierMBB->end())
|
if (RestorePt == BarrierMBB->end())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
if (DefMI && LIs->isReMaterializable(*LI, ValNo, DefMI))
|
||||||
|
if (Rematerialize(LI->reg, ValNo, DefMI, RestorePt,
|
||||||
|
RestoreIndex, RefsInMBB))
|
||||||
|
return true;
|
||||||
|
|
||||||
// Add a spill either before the barrier or after the definition.
|
// Add a spill either before the barrier or after the definition.
|
||||||
MachineBasicBlock *DefMBB = DefMI ? DefMI->getParent() : NULL;
|
MachineBasicBlock *DefMBB = DefMI ? DefMI->getParent() : NULL;
|
||||||
const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg);
|
const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg);
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -pre-alloc-split -stats |& \
|
; RUN: llvm-as < %s | llc -march=x86 -mattr=+sse2 -pre-alloc-split -stats |& \
|
||||||
; RUN: not grep {pre-alloc-split}
|
; RUN: grep {pre-alloc-split} | count 2
|
||||||
|
|
||||||
define i32 @t() {
|
define i32 @t() {
|
||||||
entry:
|
entry:
|
||||||
|
Reference in New Issue
Block a user