aboutsummaryrefslogtreecommitdiffstats
path: root/lib/CodeGen/PreAllocSplitting.cpp
diff options
context:
space:
mode:
authorOwen Anderson <resistor@mac.com>2008-11-19 04:28:29 +0000
committerOwen Anderson <resistor@mac.com>2008-11-19 04:28:29 +0000
commitf10e9510577101a19f0c358971df885c13122a41 (patch)
tree9d6b6879ff5776b8ae0658f5988cd09d2908ac19 /lib/CodeGen/PreAllocSplitting.cpp
parent2366405a72805b5c56ad2cb5f4675b7205bc644b (diff)
downloadexternal_llvm-f10e9510577101a19f0c358971df885c13122a41.zip
external_llvm-f10e9510577101a19f0c358971df885c13122a41.tar.gz
external_llvm-f10e9510577101a19f0c358971df885c13122a41.tar.bz2
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
Diffstat (limited to 'lib/CodeGen/PreAllocSplitting.cpp')
-rw-r--r--lib/CodeGen/PreAllocSplitting.cpp98
1 files changed, 95 insertions, 3 deletions
diff --git a/lib/CodeGen/PreAllocSplitting.cpp b/lib/CodeGen/PreAllocSplitting.cpp
index 2e385c8..c207274 100644
--- a/lib/CodeGen/PreAllocSplitting.cpp
+++ b/lib/CodeGen/PreAllocSplitting.cpp
@@ -39,6 +39,7 @@ using namespace llvm;
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");
namespace {
class VISIBILITY_HIDDEN PreAllocSplitting : public MachineFunctionPass {
@@ -153,6 +154,11 @@ namespace {
bool createsNewJoin(LiveRange* LR, MachineBasicBlock* DefMBB,
MachineBasicBlock* BarrierMBB);
+ bool Rematerialize(unsigned vreg, VNInfo* ValNo,
+ MachineInstr* DefMI,
+ MachineBasicBlock::iterator RestorePt,
+ unsigned RestoreIdx,
+ SmallPtrSet<MachineInstr*, 4>& RefsInMBB);
};
} // end anonymous namespace
@@ -627,6 +633,90 @@ PreAllocSplitting::ShrinkWrapLiveInterval(VNInfo *ValNo, MachineBasicBlock *MBB,
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
/// so it would not cross the barrier that's being processed. Shrink wrap
/// (minimize) the live interval to the last uses.
@@ -644,11 +734,8 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
abort();
}
- // FIXME: For now, if definition is rematerializable, do not split.
MachineInstr *DefMI = (ValNo->def != ~0U)
? 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 (DefMI && createsNewJoin(LR, DefMI->getParent(), Barrier->getParent()))
@@ -670,6 +757,11 @@ bool PreAllocSplitting::SplitRegLiveInterval(LiveInterval *LI) {
if (RestorePt == BarrierMBB->end())
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.
MachineBasicBlock *DefMBB = DefMI ? DefMI->getParent() : NULL;
const TargetRegisterClass *RC = MRI->getRegClass(CurrLI->reg);