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