summaryrefslogtreecommitdiff
path: root/lib/CodeGen/InlineSpiller.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/CodeGen/InlineSpiller.cpp')
-rw-r--r--lib/CodeGen/InlineSpiller.cpp139
1 files changed, 84 insertions, 55 deletions
diff --git a/lib/CodeGen/InlineSpiller.cpp b/lib/CodeGen/InlineSpiller.cpp
index 8910652c40..d5f300f9aa 100644
--- a/lib/CodeGen/InlineSpiller.cpp
+++ b/lib/CodeGen/InlineSpiller.cpp
@@ -179,10 +179,8 @@ private:
bool coalesceStackAccess(MachineInstr *MI, unsigned Reg);
bool foldMemoryOperand(ArrayRef<std::pair<MachineInstr*, unsigned> >,
MachineInstr *LoadMI = 0);
- void insertReload(LiveInterval &NewLI, SlotIndex,
- MachineBasicBlock::iterator MI);
- void insertSpill(LiveInterval &NewLI, const LiveInterval &OldLI,
- SlotIndex, MachineBasicBlock::iterator MI);
+ void insertReload(unsigned VReg, SlotIndex, MachineBasicBlock::iterator MI);
+ void insertSpill(unsigned VReg, bool isKill, MachineBasicBlock::iterator MI);
void spillAroundUses(unsigned Reg);
void spillAll();
@@ -885,12 +883,12 @@ bool InlineSpiller::reMaterializeFor(LiveInterval &VirtReg,
}
// Alocate a new register for the remat.
- LiveInterval &NewLI = Edit->createFrom(Original);
- NewLI.markNotSpillable();
+ unsigned NewVReg = Edit->createFrom(Original);
// Finally we can rematerialize OrigMI before MI.
- SlotIndex DefIdx = Edit->rematerializeAt(*MI->getParent(), MI, NewLI.reg, RM,
+ SlotIndex DefIdx = Edit->rematerializeAt(*MI->getParent(), MI, NewVReg, RM,
TRI);
+ (void)DefIdx;
DEBUG(dbgs() << "\tremat: " << DefIdx << '\t'
<< *LIS.getInstructionFromIndex(DefIdx));
@@ -898,15 +896,12 @@ bool InlineSpiller::reMaterializeFor(LiveInterval &VirtReg,
for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
MachineOperand &MO = MI->getOperand(Ops[i].second);
if (MO.isReg() && MO.isUse() && MO.getReg() == VirtReg.reg) {
- MO.setReg(NewLI.reg);
+ MO.setReg(NewVReg);
MO.setIsKill();
}
}
- DEBUG(dbgs() << "\t " << UseIdx << '\t' << *MI);
+ DEBUG(dbgs() << "\t " << UseIdx << '\t' << *MI << '\n');
- VNInfo *DefVNI = NewLI.getNextValue(DefIdx, LIS.getVNInfoAllocator());
- NewLI.addRange(LiveRange(DefIdx, UseIdx.getRegSlot(), DefVNI));
- DEBUG(dbgs() << "\tinterval: " << NewLI << '\n');
++NumRemats;
return true;
}
@@ -1009,6 +1004,40 @@ bool InlineSpiller::coalesceStackAccess(MachineInstr *MI, unsigned Reg) {
return true;
}
+#if !defined(NDEBUG)
+// Dump the range of instructions from B to E with their slot indexes.
+static void dumpMachineInstrRangeWithSlotIndex(MachineBasicBlock::iterator B,
+ MachineBasicBlock::iterator E,
+ LiveIntervals const &LIS,
+ const char *const header,
+ unsigned VReg =0) {
+ char NextLine = '\n';
+ char SlotIndent = '\t';
+
+ if (llvm::next(B) == E) {
+ NextLine = ' ';
+ SlotIndent = ' ';
+ }
+
+ dbgs() << '\t' << header << ": " << NextLine;
+
+ for (MachineBasicBlock::iterator I = B; I != E; ++I) {
+ SlotIndex Idx = LIS.getInstructionIndex(I).getRegSlot();
+
+ // If a register was passed in and this instruction has it as a
+ // destination that is marked as an early clobber, print the
+ // early-clobber slot index.
+ if (VReg) {
+ MachineOperand *MO = I->findRegisterDefOperand(VReg);
+ if (MO && MO->isEarlyClobber())
+ Idx = Idx.getRegSlot(true);
+ }
+
+ dbgs() << SlotIndent << Idx << '\t' << *I;
+ }
+}
+#endif
+
/// foldMemoryOperand - Try folding stack slot references in Ops into their
/// instructions.
///
@@ -1049,6 +1078,8 @@ foldMemoryOperand(ArrayRef<std::pair<MachineInstr*, unsigned> > Ops,
FoldOps.push_back(Idx);
}
+ MachineInstrSpan MIS(MI);
+
MachineInstr *FoldMI =
LoadMI ? TII.foldMemoryOperand(MI, FoldOps, LoadMI)
: TII.foldMemoryOperand(MI, FoldOps, StackSlot);
@@ -1082,9 +1113,17 @@ foldMemoryOperand(ArrayRef<std::pair<MachineInstr*, unsigned> > Ops,
}
}
}
+
LIS.ReplaceMachineInstrInMaps(MI, FoldMI);
MI->eraseFromParent();
+ // Insert any new instructions other than FoldMI into the LIS maps.
+ assert(!MIS.empty() && "Unexpected empty span of instructions!");
+ for (MachineBasicBlock::iterator MII = MIS.begin(), End = MIS.end();
+ MII != End; ++MII)
+ if (&*MII != FoldMI)
+ LIS.InsertMachineInstrInMaps(&*MII);
+
// TII.foldMemoryOperand may have left some implicit operands on the
// instruction. Strip them.
if (ImpReg)
@@ -1096,8 +1135,9 @@ foldMemoryOperand(ArrayRef<std::pair<MachineInstr*, unsigned> > Ops,
FoldMI->RemoveOperand(i - 1);
}
- DEBUG(dbgs() << "\tfolded: " << LIS.getInstructionIndex(FoldMI) << '\t'
- << *FoldMI);
+ DEBUG(dumpMachineInstrRangeWithSlotIndex(MIS.begin(), MIS.end(), LIS,
+ "folded"));
+
if (!WasCopy)
++NumFolded;
else if (Ops.front().second == 0)
@@ -1107,36 +1147,35 @@ foldMemoryOperand(ArrayRef<std::pair<MachineInstr*, unsigned> > Ops,
return true;
}
-/// insertReload - Insert a reload of NewLI.reg before MI.
-void InlineSpiller::insertReload(LiveInterval &NewLI,
+void InlineSpiller::insertReload(unsigned NewVReg,
SlotIndex Idx,
MachineBasicBlock::iterator MI) {
MachineBasicBlock &MBB = *MI->getParent();
- TII.loadRegFromStackSlot(MBB, MI, NewLI.reg, StackSlot,
- MRI.getRegClass(NewLI.reg), &TRI);
- --MI; // Point to load instruction.
- SlotIndex LoadIdx = LIS.InsertMachineInstrInMaps(MI).getRegSlot();
- // Some (out-of-tree) targets have EC reload instructions.
- if (MachineOperand *MO = MI->findRegisterDefOperand(NewLI.reg))
- if (MO->isEarlyClobber())
- LoadIdx = LoadIdx.getRegSlot(true);
- DEBUG(dbgs() << "\treload: " << LoadIdx << '\t' << *MI);
- VNInfo *LoadVNI = NewLI.getNextValue(LoadIdx, LIS.getVNInfoAllocator());
- NewLI.addRange(LiveRange(LoadIdx, Idx, LoadVNI));
+
+ MachineInstrSpan MIS(MI);
+ TII.loadRegFromStackSlot(MBB, MI, NewVReg, StackSlot,
+ MRI.getRegClass(NewVReg), &TRI);
+
+ LIS.InsertMachineInstrRangeInMaps(MIS.begin(), MI);
+
+ DEBUG(dumpMachineInstrRangeWithSlotIndex(MIS.begin(), MI, LIS, "reload",
+ NewVReg));
++NumReloads;
}
-/// insertSpill - Insert a spill of NewLI.reg after MI.
-void InlineSpiller::insertSpill(LiveInterval &NewLI, const LiveInterval &OldLI,
- SlotIndex Idx, MachineBasicBlock::iterator MI) {
+/// insertSpill - Insert a spill of NewVReg after MI.
+void InlineSpiller::insertSpill(unsigned NewVReg, bool isKill,
+ MachineBasicBlock::iterator MI) {
MachineBasicBlock &MBB = *MI->getParent();
- TII.storeRegToStackSlot(MBB, ++MI, NewLI.reg, true, StackSlot,
- MRI.getRegClass(NewLI.reg), &TRI);
- --MI; // Point to store instruction.
- SlotIndex StoreIdx = LIS.InsertMachineInstrInMaps(MI).getRegSlot();
- DEBUG(dbgs() << "\tspilled: " << StoreIdx << '\t' << *MI);
- VNInfo *StoreVNI = NewLI.getNextValue(Idx, LIS.getVNInfoAllocator());
- NewLI.addRange(LiveRange(Idx, StoreIdx, StoreVNI));
+
+ MachineInstrSpan MIS(MI);
+ TII.storeRegToStackSlot(MBB, llvm::next(MI), NewVReg, isKill, StackSlot,
+ MRI.getRegClass(NewVReg), &TRI);
+
+ LIS.InsertMachineInstrRangeInMaps(llvm::next(MI), MIS.end());
+
+ DEBUG(dumpMachineInstrRangeWithSlotIndex(llvm::next(MI), MIS.end(), LIS,
+ "spill"));
++NumSpills;
}
@@ -1212,19 +1251,18 @@ void InlineSpiller::spillAroundUses(unsigned Reg) {
if (foldMemoryOperand(Ops))
continue;
- // Allocate interval around instruction.
+ // Create a new virtual register for spill/fill.
// FIXME: Infer regclass from instruction alone.
- LiveInterval &NewLI = Edit->createFrom(Reg);
- NewLI.markNotSpillable();
+ unsigned NewVReg = Edit->createFrom(Reg);
if (RI.Reads)
- insertReload(NewLI, Idx, MI);
+ insertReload(NewVReg, Idx, MI);
// Rewrite instruction operands.
bool hasLiveDef = false;
for (unsigned i = 0, e = Ops.size(); i != e; ++i) {
MachineOperand &MO = Ops[i].first->getOperand(Ops[i].second);
- MO.setReg(NewLI.reg);
+ MO.setReg(NewVReg);
if (MO.isUse()) {
if (!Ops[i].first->isRegTiedToDefOperand(Ops[i].second))
MO.setIsKill();
@@ -1233,21 +1271,12 @@ void InlineSpiller::spillAroundUses(unsigned Reg) {
hasLiveDef = true;
}
}
- DEBUG(dbgs() << "\trewrite: " << Idx << '\t' << *MI);
+ DEBUG(dbgs() << "\trewrite: " << Idx << '\t' << *MI << '\n');
// FIXME: Use a second vreg if instruction has no tied ops.
- if (RI.Writes) {
+ if (RI.Writes)
if (hasLiveDef)
- insertSpill(NewLI, OldLI, Idx, MI);
- else {
- // This instruction defines a dead value. We don't need to spill it,
- // but do create a live range for the dead value.
- VNInfo *VNI = NewLI.getNextValue(Idx, LIS.getVNInfoAllocator());
- NewLI.addRange(LiveRange(Idx, Idx.getDeadSlot(), VNI));
- }
- }
-
- DEBUG(dbgs() << "\tinterval: " << NewLI << '\n');
+ insertSpill(NewVReg, true, MI);
}
}
@@ -1309,7 +1338,7 @@ void InlineSpiller::spill(LiveRangeEdit &edit) {
DEBUG(dbgs() << "Inline spilling "
<< MRI.getRegClass(edit.getReg())->getName()
<< ':' << PrintReg(edit.getReg()) << ' ' << edit.getParent()
- << "\nFrom original " << LIS.getInterval(Original) << '\n');
+ << "\nFrom original " << PrintReg(Original) << '\n');
assert(edit.getParent().isSpillable() &&
"Attempting to spill already spilled value.");
assert(DeadDefs.empty() && "Previous spill didn't remove dead defs");