@@ -65,11 +65,35 @@ class Spill2Reg : public MachineFunctionPass {
6565 // / differs across accesses to the same stack slot.
6666 unsigned SpillBits = 0 ;
6767#ifndef NDEBUG
68- LLVM_DUMP_METHOD void dump () const ;
68+ LLVM_DUMP_METHOD virtual void dump () const ;
69+ virtual ~MIData () {}
70+ #endif
71+ };
72+
73+ struct MIDataWithLiveIn : public MIData {
74+ MIDataWithLiveIn (MachineInstr *MI, const MachineOperand *MO,
75+ unsigned SpillBits)
76+ : MIData(MI, MO, SpillBits) {}
77+ // / We set this to false to mark the vector register associated to this
78+ // / reload as definitely not live-in. This is useful in blocks with both
79+ // / spill and reload of the same stack slot, like in the example:
80+ // / \verbatim
81+ // / bb:
82+ // / spill %stack.0
83+ // / reload %stack.0
84+ // / \endverbatim
85+ // / This information is used during `updateLiveIns()`. We are collecting
86+ // / this information during `collectSpillsAndReloads()` because we are
87+ // / already walking through the code there. Otherwise we would need to
88+ // / walk throught the code again in `updateLiveIns()` just to check for
89+ // / other spills in the block, which would waste compilation time.
90+ bool IsLiveIn = true ;
91+ #ifndef NDEBUG
92+ LLVM_DUMP_METHOD virtual void dump () const override ;
6993#endif
7094 };
7195 SmallVector<MIData, 1 > Spills;
72- SmallVector<MIData , 1 > Reloads;
96+ SmallVector<MIDataWithLiveIn , 1 > Reloads;
7397
7498 // / \Returns the register class of the register being spilled.
7599 const TargetRegisterClass *
@@ -78,6 +102,7 @@ class Spill2Reg : public MachineFunctionPass {
78102 auto Reg0 = Spills.front ().MO ->getReg ();
79103 return TRI->getCandidateRegisterClassForSpill2Reg (TRI, Reg0);
80104 }
105+
81106#ifndef NDEBUG
82107 LLVM_DUMP_METHOD void dump () const ;
83108#endif
@@ -194,6 +219,15 @@ void Spill2Reg::collectSpillsAndReloads() {
194219 }
195220 unsigned SpillBits = TRI->getRegSizeInBits (MO->getReg (), *MRI);
196221 Entry.Spills .emplace_back (Spill, MO, SpillBits);
222+
223+ // If any of the reloads collected so far is in the same MBB then mark
224+ // it as non live-in. This is used in `updateLiveIns()` where we update
225+ // the liveins of MBBs to include the new vector register. Doing this
226+ // now avoids an MBB walk in `updateLiveIns()` which should save
227+ // compilation time.
228+ for (auto &MID : Entry.Reloads )
229+ if (MID.MI ->getParent () == &MBB)
230+ MID.IsLiveIn = false ;
197231 } else if (const MachineOperand *MO =
198232 TII->isLoadFromStackSlotMO (MI, StackSlot)) {
199233 MachineInstr *Reload = &MI;
@@ -264,6 +298,49 @@ static void DFS(MachineBasicBlock *MBB, DenseSet<MachineBasicBlock *> &Visited,
264298 for (MachineBasicBlock *PredMBB : MBB->predecessors ())
265299 DFS (PredMBB, Visited, Fn);
266300}
301+
302+ void Spill2Reg::updateLiveIns (StackSlotDataEntry &Entry, MCRegister VectorReg) {
303+ // Collect the parent MBBs of Spills for fast lookup.
304+ DenseSet<MachineBasicBlock *> SpillMBBs (Entry.Spills .size ());
305+ DenseSet<MachineInstr *> Spills (Entry.Spills .size ());
306+ for (const auto &Data : Entry.Spills ) {
307+ SpillMBBs.insert (Data.MI ->getParent ());
308+ Spills.insert (Data.MI );
309+ }
310+
311+ auto AddLiveInIfRequired = [VectorReg, &SpillMBBs](MachineBasicBlock *MBB) {
312+ // If there is a spill in this MBB then we don't need to add a live-in.
313+ // This works even if there is a reload above the spill, like this:
314+ // reload stack.0
315+ // spill stack.0
316+ // because the live-in due to the reload is handled at a separate walk.
317+ if (SpillMBBs.count (MBB))
318+ // Return true to stop the recursion.
319+ return true ;
320+ // If there are no spills in this block then the register is live-in.
321+ if (!MBB->isLiveIn (VectorReg))
322+ MBB->addLiveIn (VectorReg);
323+ // Return false to continue the recursion.
324+ return false ;
325+ };
326+
327+ // Update the MBB live-ins. These are used for the live regs calculation.
328+ DenseSet<MachineBasicBlock *> Visited;
329+ for (const auto &ReloadData : Entry.Reloads ) {
330+ MachineInstr *Reload = ReloadData.MI ;
331+ MachineBasicBlock *MBB = Reload->getParent ();
332+ // From a previous walk in MBB we know whether the reload is live-in, or
333+ // whether the value comes from an earlier spill in the same MBB.
334+ if (!ReloadData.IsLiveIn )
335+ continue ;
336+ if (!MBB->isLiveIn (VectorReg))
337+ MBB->addLiveIn (VectorReg);
338+
339+ for (MachineBasicBlock *PredMBB : Reload->getParent ()->predecessors ())
340+ DFS (PredMBB, Visited, AddLiveInIfRequired);
341+ }
342+ }
343+
267344// Replace stack-based spills/reloads with register-based ones.
268345void Spill2Reg::replaceStackWithReg (StackSlotDataEntry &Entry,
269346 Register VectorReg) {
@@ -407,6 +484,12 @@ void Spill2Reg::generateCode() {
407484 if (!PhysVectorRegOpt)
408485 continue ;
409486
487+ // Update the MBB live-ins. These are used for the live regs calculation.
488+ // Collect the parent MBBs of Spills for fast lookup.
489+ // NOTE: We do that before calling replaceStackWithReg() because it will
490+ // remove the spill/reload instructions from Entry.
491+ updateLiveIns (Entry, *PhysVectorRegOpt);
492+
410493 // Replace stack accesses with register accesses.
411494 replaceStackWithReg (Entry, *PhysVectorRegOpt);
412495
@@ -436,6 +519,10 @@ void Spill2Reg::StackSlotDataEntry::MIData::dump() const {
436519 dbgs () << " (" << *MO << " ) " << *MI;
437520}
438521
522+ void Spill2Reg::StackSlotDataEntry::MIDataWithLiveIn::dump () const {
523+ dbgs () << " (" << *MO << " ) " << *MI << " IsLiveIn: " << IsLiveIn;
524+ }
525+
439526void Spill2Reg::StackSlotDataEntry::dump () const {
440527 dbgs ().indent (DumpInd) << " Disable: " << Disable << " \n " ;
441528 dbgs ().indent (DumpInd) << " Spills:\n " ;
0 commit comments