LLVM 24.0.0git
SILowerSGPRSpills.cpp
Go to the documentation of this file.
1//===-- SILowerSGPRSPills.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Handle SGPR spills. This pass takes the place of PrologEpilogInserter for all
10// SGPR spills, so must insert CSR SGPR spills as well as expand them.
11//
12// This pass must never create new SGPR virtual registers.
13//
14// FIXME: Must stop RegScavenger spills in later passes.
15//
16//===----------------------------------------------------------------------===//
17
18#include "SILowerSGPRSpills.h"
19#include "AMDGPU.h"
20#include "GCNSubtarget.h"
24#include "SISpillUtils.h"
31
32using namespace llvm;
33
34#define DEBUG_TYPE "si-lower-sgpr-spills"
35
37
38namespace {
39
40/// Insertion point for IMPLICIT_DEF: iterator may be MBB::end() and can't be
41/// dereferenced so the parent block is stored explicitly.
42struct LaneVGPRInsertPt {
45};
46
47static LaneVGPRInsertPt insertPt(MachineBasicBlock *MBB,
49 return {MBB, It};
50}
51
52static cl::opt<unsigned> MaxNumVGPRsForWwmAllocation(
53 "amdgpu-num-vgprs-for-wwm-alloc",
54 cl::desc("Max num VGPRs for whole-wave register allocation."),
56
57class SILowerSGPRSpills {
58private:
59 const SIRegisterInfo *TRI = nullptr;
60 const SIInstrInfo *TII = nullptr;
61 LiveIntervals *LIS = nullptr;
62 SlotIndexes *Indexes = nullptr;
63 MachineDominatorTree *MDT = nullptr;
64 MachineCycleInfo *MCI = nullptr;
65
66 // Save and Restore blocks of the current function. Typically there is a
67 // single save block, unless Windows EH funclets are involved.
68 MBBVector SaveBlocks;
69 MBBVector RestoreBlocks;
70
71 MachineBasicBlock *getCycleDomBB(CycleRef C);
72
73public:
74 SILowerSGPRSpills(LiveIntervals *LIS, SlotIndexes *Indexes,
76 : LIS(LIS), Indexes(Indexes), MDT(MDT), MCI(MCI) {}
77 bool run(MachineFunction &MF);
78 void calculateSaveRestoreBlocks(MachineFunction &MF);
79 bool spillCalleeSavedRegs(MachineFunction &MF,
80 SmallVectorImpl<int> &CalleeSavedFIs);
81 void updateLaneVGPRDomInstr(
83 DenseMap<Register, LaneVGPRInsertPt> &LaneVGPRDomInstr);
84 SmallVector<MCRegister> determineRegsForWWMAllocation(MachineFunction &MF);
85 void assignWWMRegs(MachineFunction &MF, ArrayRef<MCRegister> WWMRegCandidates,
86 bool RequiresFullWWMPool);
87};
88
89class SILowerSGPRSpillsLegacy : public MachineFunctionPass {
90public:
91 static char ID;
92
93 SILowerSGPRSpillsLegacy() : MachineFunctionPass(ID) {}
94
95 bool runOnMachineFunction(MachineFunction &MF) override;
96
97 void getAnalysisUsage(AnalysisUsage &AU) const override {
100 AU.setPreservesAll();
102 }
103
104 MachineFunctionProperties getClearedProperties() const override {
105 // SILowerSGPRSpills introduces new Virtual VGPRs for spilling SGPRs.
106 return MachineFunctionProperties().setIsSSA().setNoVRegs();
107 }
108};
109
110} // end anonymous namespace
111
112char SILowerSGPRSpillsLegacy::ID = 0;
113
114INITIALIZE_PASS_BEGIN(SILowerSGPRSpillsLegacy, DEBUG_TYPE,
115 "SI lower SGPR spill instructions", false, false)
120INITIALIZE_PASS_END(SILowerSGPRSpillsLegacy, DEBUG_TYPE,
121 "SI lower SGPR spill instructions", false, false)
122
123char &llvm::SILowerSGPRSpillsLegacyID = SILowerSGPRSpillsLegacy::ID;
124
125/// Insert spill code for the callee-saved registers used in the function.
127 ArrayRef<CalleeSavedInfo> CSI, SlotIndexes *Indexes,
128 LiveIntervals *LIS) {
129 const TargetFrameLowering *TFI = ST.getFrameLowering();
130 const TargetRegisterInfo *TRI = ST.getRegisterInfo();
131 MachineBasicBlock::iterator I = SaveBlock.begin();
132 MachineInstrSpan MIS(I, &SaveBlock);
133 bool Success = TFI->spillCalleeSavedRegisters(SaveBlock, I, CSI, TRI);
134 assert(Success && "spillCalleeSavedRegisters should always succeed");
135 (void)Success;
136
137 // TFI doesn't update Indexes and LIS, so we have to do it separately.
138 if (Indexes)
139 Indexes->repairIndexesInRange(&SaveBlock, SaveBlock.begin(), I);
140
141 if (LIS)
142 for (const CalleeSavedInfo &CS : CSI)
143 LIS->removeAllRegUnitsForPhysReg(CS.getReg());
144}
145
146/// Insert restore code for the callee-saved registers used in the function.
147static void insertCSRRestores(MachineBasicBlock &RestoreBlock,
149 SlotIndexes *Indexes, LiveIntervals *LIS) {
150 MachineFunction &MF = *RestoreBlock.getParent();
154 // Restore all registers immediately before the return and any
155 // terminators that precede it.
157 const MachineBasicBlock::iterator BeforeRestoresI =
158 I == RestoreBlock.begin() ? I : std::prev(I);
159
160 // FIXME: Just emit the readlane/writelane directly
161 if (!TFI->restoreCalleeSavedRegisters(RestoreBlock, I, CSI, TRI)) {
162 for (const CalleeSavedInfo &CI : reverse(CSI)) {
163 // Insert in reverse order. loadRegFromStackSlot can insert
164 // multiple instructions.
165 TFI->restoreCalleeSavedRegister(RestoreBlock, I, CI, &TII, TRI);
166
167 if (Indexes) {
168 MachineInstr &Inst = *std::prev(I);
169 Indexes->insertMachineInstrInMaps(Inst);
170 }
171
172 if (LIS)
173 LIS->removeAllRegUnitsForPhysReg(CI.getReg());
174 }
175 } else {
176 // TFI doesn't update Indexes and LIS, so we have to do it separately.
177 if (Indexes)
178 Indexes->repairIndexesInRange(&RestoreBlock, BeforeRestoresI,
179 RestoreBlock.getFirstTerminator());
180
181 if (LIS)
182 for (const CalleeSavedInfo &CS : CSI)
183 LIS->removeAllRegUnitsForPhysReg(CS.getReg());
184 }
185}
186
187/// Compute the sets of entry and return blocks for saving and restoring
188/// callee-saved registers, and placing prolog and epilog code.
189void SILowerSGPRSpills::calculateSaveRestoreBlocks(MachineFunction &MF) {
190 const MachineFrameInfo &MFI = MF.getFrameInfo();
191
192 // Even when we do not change any CSR, we still want to insert the
193 // prologue and epilogue of the function.
194 // So set the save points for those.
195
196 // Use the points found by shrink-wrapping, if any.
197 if (!MFI.getSavePoints().empty()) {
198 assert(MFI.getSavePoints().size() == 1 &&
199 "Multiple save points not yet supported!");
200 const auto &SavePoint = *MFI.getSavePoints().begin();
201 SaveBlocks.push_back(SavePoint.first);
202 assert(MFI.getRestorePoints().size() == 1 &&
203 "Multiple restore points not yet supported!");
204 const auto &RestorePoint = *MFI.getRestorePoints().begin();
205 MachineBasicBlock *RestoreBlock = RestorePoint.first;
206 // If RestoreBlock does not have any successor and is not a return block
207 // then the end point is unreachable and we do not need to insert any
208 // epilogue.
209 if (!RestoreBlock->succ_empty() || RestoreBlock->isReturnBlock())
210 RestoreBlocks.push_back(RestoreBlock);
211 return;
212 }
213
214 // Save refs to entry and return blocks.
215 SaveBlocks.push_back(&MF.front());
216 for (MachineBasicBlock &MBB : MF) {
217 if (MBB.isEHFuncletEntry())
218 SaveBlocks.push_back(&MBB);
219 if (MBB.isReturnBlock())
220 RestoreBlocks.push_back(&MBB);
221 }
222}
223
224// TODO: To support shrink wrapping, this would need to copy
225// PrologEpilogInserter's updateLiveness.
227 MachineBasicBlock &EntryBB = MF.front();
228
229 for (const CalleeSavedInfo &CSIReg : CSI)
230 EntryBB.addLiveIn(CSIReg.getReg());
231 EntryBB.sortUniqueLiveIns();
232}
233
234bool SILowerSGPRSpills::spillCalleeSavedRegs(
235 MachineFunction &MF, SmallVectorImpl<int> &CalleeSavedFIs) {
236 MachineRegisterInfo &MRI = MF.getRegInfo();
237 const Function &F = MF.getFunction();
238 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
239 const SIFrameLowering *TFI = ST.getFrameLowering();
240 MachineFrameInfo &MFI = MF.getFrameInfo();
241 RegScavenger *RS = nullptr;
242
243 // Determine which of the registers in the callee save list should be saved.
244 BitVector SavedRegs;
245 TFI->determineCalleeSavesSGPR(MF, SavedRegs, RS);
246
247 // Add the code to save and restore the callee saved registers.
248 if (!F.hasFnAttribute(Attribute::Naked)) {
249 // FIXME: This is a lie. The CalleeSavedInfo is incomplete, but this is
250 // necessary for verifier liveness checks.
251 MFI.setCalleeSavedInfoValid(true);
252
253 std::vector<CalleeSavedInfo> CSI;
254 const MCPhysReg *CSRegs = MRI.getCalleeSavedRegs();
255 MCRegister RetAddrReg = TRI->getReturnAddressReg(MF);
256 MCRegister RetAddrRegSub0 = TRI->getSubReg(RetAddrReg, AMDGPU::sub0);
257 MCRegister RetAddrRegSub1 = TRI->getSubReg(RetAddrReg, AMDGPU::sub1);
258 bool SpillRetAddrReg = false;
259
260 for (unsigned I = 0; CSRegs[I]; ++I) {
261 MCRegister Reg = CSRegs[I];
262
263 if (SavedRegs.test(Reg)) {
264 if (Reg == RetAddrRegSub0 || Reg == RetAddrRegSub1) {
265 SpillRetAddrReg = true;
266 continue;
267 }
268
269 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(Reg);
270 int JunkFI = MFI.CreateStackObject(TRI->getSpillSize(*RC),
271 TRI->getSpillAlign(*RC), true,
272 nullptr, TRI->getSpillStackID(*RC));
273
274 CSI.emplace_back(Reg, JunkFI);
275 CalleeSavedFIs.push_back(JunkFI);
276 }
277 }
278
279 // Return address uses a register pair. Add the super register to the
280 // CSI list so that it's easier to identify the entire spill and CFI
281 // can be emitted appropriately.
282 if (SpillRetAddrReg) {
283 const TargetRegisterClass *RC = TRI->getMinimalPhysRegClass(RetAddrReg);
284 int JunkFI =
285 MFI.CreateStackObject(TRI->getSpillSize(*RC), TRI->getSpillAlign(*RC),
286 true, nullptr, TRI->getSpillStackID(*RC));
287 CSI.push_back(CalleeSavedInfo(RetAddrReg, JunkFI));
288 CalleeSavedFIs.push_back(JunkFI);
289 }
290
291 if (!CSI.empty()) {
292 for (MachineBasicBlock *SaveBlock : SaveBlocks)
293 insertCSRSaves(ST, *SaveBlock, CSI, Indexes, LIS);
294
295 // Add live ins to save blocks.
296 assert(SaveBlocks.size() == 1 && "shrink wrapping not fully implemented");
297 updateLiveness(MF, CSI);
298
299 for (MachineBasicBlock *RestoreBlock : RestoreBlocks)
300 insertCSRRestores(*RestoreBlock, CSI, Indexes, LIS);
301 return true;
302 }
303 }
304
305 return false;
306}
307
308MachineBasicBlock *SILowerSGPRSpills::getCycleDomBB(CycleRef C) {
309 // If the insertion point lands on a cycle entry, move it to a block that
310 // dominates all entries.
311 if (MCI->isReducible(C)) {
312 if (auto *IDom = MDT->getNode(MCI->getHeader(C))->getIDom())
313 return IDom->getBlock();
314 llvm_unreachable("Expected cycle to have an IDom.");
315 return nullptr;
316 }
317
319 assert(!Entries.empty() && "Expected cycle to have at least one entry.");
320 MachineBasicBlock *EntryBB = Entries[0];
321 for (unsigned I = 1; I < Entries.size(); ++I)
322 EntryBB = MDT->findNearestCommonDominator(EntryBB, Entries[I]);
323 return EntryBB;
324}
325
326void SILowerSGPRSpills::updateLaneVGPRDomInstr(
327 int FI, MachineBasicBlock *MBB, MachineBasicBlock::iterator InsertPt,
328 DenseMap<Register, LaneVGPRInsertPt> &LaneVGPRDomInstr) {
329 // For the Def of a virtual LaneVGPR to dominate all its uses, we should
330 // insert an IMPLICIT_DEF before the dominating spill. Switching to a
331 // depth first order doesn't really help since the machine function can be in
332 // the unstructured control flow post-SSA. For each virtual register, hence
333 // finding the common dominator to get either the dominating spill or a block
334 // dominating all spills.
335 SIMachineFunctionInfo *FuncInfo =
336 MBB->getParent()->getInfo<SIMachineFunctionInfo>();
338 FuncInfo->getSGPRSpillToVirtualVGPRLanes(FI);
339 Register PrevLaneVGPR;
340 for (auto &Spill : VGPRSpills) {
341 if (PrevLaneVGPR == Spill.VGPR)
342 continue;
343
344 PrevLaneVGPR = Spill.VGPR;
345 auto I = LaneVGPRDomInstr.find(Spill.VGPR);
346 if (Spill.Lane == 0 && I == LaneVGPRDomInstr.end()) {
347 LaneVGPRDomInstr[Spill.VGPR] = insertPt(MBB, InsertPt);
348 } else {
349 assert(I != LaneVGPRDomInstr.end());
350 LaneVGPRInsertPt Prev = I->second;
351 MachineBasicBlock *PrevInsertMBB = Prev.MBB;
352 MachineBasicBlock::iterator PrevInsertPt = Prev.It;
353 MachineBasicBlock *DomMBB = PrevInsertMBB;
354 if (DomMBB == MBB) {
355 // The insertion point earlier selected in a predecessor block whose
356 // spills are currently being lowered. The earlier InsertPt would be
357 // the one just before the block terminator and it should be changed
358 // if we insert any new spill in it.
359 if (PrevInsertPt == MBB->end() ||
360 MDT->dominates(&*InsertPt, &*PrevInsertPt))
361 I->second = insertPt(MBB, InsertPt);
362
363 continue;
364 }
365
366 // Find the common dominator block between PrevInsertPt and the
367 // current spill.
368 DomMBB = MDT->findNearestCommonDominator(DomMBB, MBB);
369
370 if (DomMBB == MBB)
371 I->second = insertPt(MBB, InsertPt);
372 else if (DomMBB != PrevInsertMBB)
373 I->second = insertPt(DomMBB, DomMBB->getFirstTerminator());
374 }
375 }
376}
377
379SILowerSGPRSpills::determineRegsForWWMAllocation(MachineFunction &MF) {
380 SmallVector<MCRegister> WWMRegCandidates;
381 if (!MaxNumVGPRsForWwmAllocation)
382 return WWMRegCandidates;
383
384 MachineRegisterInfo &MRI = MF.getRegInfo();
385 BitVector ReservedRegs = TRI->getReservedRegs(MF);
386 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
387 unsigned MaxNumVGPRs = ST.getMaxNumVectorRegs(MF.getFunction()).first;
388
389 // Try to use the highest available registers for now. Later after
390 // vgpr-regalloc, they can be shifted to the lowest range.
391 for (unsigned Reg = AMDGPU::VGPR0 + MaxNumVGPRs - 1;
392 WWMRegCandidates.size() < MaxNumVGPRsForWwmAllocation &&
393 Reg >= AMDGPU::VGPR0;
394 --Reg) {
395 if (!ReservedRegs.test(Reg) &&
396 !MRI.isPhysRegUsed(Reg, /*SkipRegMaskTest=*/true))
397 WWMRegCandidates.push_back(Reg);
398 }
399
400 return WWMRegCandidates;
401}
402
403void SILowerSGPRSpills::assignWWMRegs(MachineFunction &MF,
404 ArrayRef<MCRegister> WWMRegCandidates,
405 bool RequiresFullWWMPool) {
406 SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
407 if (FuncInfo->getSGPRSpillVGPRs().empty())
408 return;
409
410 BitVector WwmRegMask(TRI->getNumRegs());
411
412 unsigned DesiredPoolSize =
413 std::min(static_cast<unsigned>(FuncInfo->getSGPRSpillVGPRs().size()),
414 static_cast<unsigned>(MaxNumVGPRsForWwmAllocation));
415 unsigned SelectedPoolSize =
416 std::min<unsigned>(DesiredPoolSize, WWMRegCandidates.size());
417 // WWM register candidates are ordered high-to-low, so take the highest
418 // available registers when the desired pool is smaller than the candidate
419 // list.
420 for (MCRegister Reg : WWMRegCandidates.take_front(SelectedPoolSize))
421 TRI->markSuperRegs(WwmRegMask, Reg);
422
423 if (RequiresFullWWMPool && SelectedPoolSize != DesiredPoolSize) {
424 // Reserve an arbitrary register and report the error.
425 TRI->markSuperRegs(WwmRegMask, AMDGPU::VGPR0);
427 "cannot find enough VGPRs for wwm-regalloc");
428 }
429
430 BitVector NonWwmRegMask(WwmRegMask);
431 NonWwmRegMask.flip().clearBitsNotInMask(TRI->getAllVGPRRegMask());
432
433 // The complement set will be the registers for non-wwm (per-thread) vgpr
434 // allocation.
435 FuncInfo->updateNonWWMRegMask(NonWwmRegMask);
436}
437
438bool SILowerSGPRSpillsLegacy::runOnMachineFunction(MachineFunction &MF) {
439 auto *LISWrapper = getAnalysisIfAvailable<LiveIntervalsWrapperPass>();
440 LiveIntervals *LIS = LISWrapper ? &LISWrapper->getLIS() : nullptr;
441 auto *SIWrapper = getAnalysisIfAvailable<SlotIndexesWrapperPass>();
442 SlotIndexes *Indexes = SIWrapper ? &SIWrapper->getSI() : nullptr;
443 MachineDominatorTree *MDT =
444 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
445 MachineCycleInfo *MCI =
446 &getAnalysis<MachineCycleInfoWrapperPass>().getCycleInfo();
447 return SILowerSGPRSpills(LIS, Indexes, MDT, MCI).run(MF);
448}
449
450bool SILowerSGPRSpills::run(MachineFunction &MF) {
451 const GCNSubtarget &ST = MF.getSubtarget<GCNSubtarget>();
452 TII = ST.getInstrInfo();
453 TRI = &TII->getRegisterInfo();
454
455 assert(SaveBlocks.empty() && RestoreBlocks.empty());
456
457 // First, expose any CSR SGPR spills. This is mostly the same as what PEI
458 // does, but somewhat simpler.
459 calculateSaveRestoreBlocks(MF);
460 SmallVector<int> CalleeSavedFIs;
461 bool HasCSRs = spillCalleeSavedRegs(MF, CalleeSavedFIs);
462
463 MachineFrameInfo &MFI = MF.getFrameInfo();
464 MachineRegisterInfo &MRI = MF.getRegInfo();
465 SIMachineFunctionInfo *FuncInfo = MF.getInfo<SIMachineFunctionInfo>();
466
467 if (!MFI.hasStackObjects() && !HasCSRs) {
468 SaveBlocks.clear();
469 RestoreBlocks.clear();
470 return false;
471 }
472
473 bool MadeChange = false;
474 bool SpilledToVirtVGPRLanes = false;
475
476 // TODO: CSR VGPRs will never be spilled to AGPRs. These can probably be
477 // handled as SpilledToReg in regular PrologEpilogInserter.
478 const bool HasSGPRSpillToVGPR = TRI->spillSGPRToVGPR() &&
479 (HasCSRs || FuncInfo->hasSpilledSGPRs());
480 if (HasSGPRSpillToVGPR) {
481 // Process all SGPR spills before frame offsets are finalized. Ideally SGPRs
482 // are spilled to VGPRs, in which case we can eliminate the stack usage.
483 //
484 // This operates under the assumption that only other SGPR spills are users
485 // of the frame index.
486
487 // To track the spill frame indices handled in this pass.
488 BitVector SpillFIs(MFI.getObjectIndexEnd(), false);
489
490 // To track the IMPLICIT_DEF insertion point for the lane vgprs.
491 DenseMap<Register, LaneVGPRInsertPt> LaneVGPRDomInstr;
492
493 // Defer ordinary spills until physical CSR spills have reserved their
494 // lane VGPRs and the WWM allocation pool can be selected.
495 SmallVector<MachineInstr *> OrdinarySGPRSpills;
496 bool HasStrictWWMRegion = false;
497
498 for (MachineBasicBlock &MBB : MF) {
499 for (MachineInstr &MI : llvm::make_early_inc_range(MBB)) {
500 if (MI.getOpcode() == AMDGPU::ENTER_STRICT_WWM ||
501 MI.getOpcode() == AMDGPU::ENTER_STRICT_WQM) {
502 HasStrictWWMRegion = true;
503 continue;
504 }
505
506 if (!TII->isSGPRSpill(MI))
507 continue;
508
509 if (MI.getOperand(0).isUndef()) {
510 if (Indexes)
512 MI.eraseFromParent();
513 continue;
514 }
515
516 int FI = TII->getNamedOperand(MI, AMDGPU::OpName::addr)->getIndex();
518
519 bool IsCalleeSaveSGPRSpill = llvm::is_contained(CalleeSavedFIs, FI);
520 if (IsCalleeSaveSGPRSpill) {
521 // Spill callee-saved SGPRs into physical VGPR lanes.
522
523 // TODO: This is to ensure the CFIs are static for efficient frame
524 // unwinding in the debugger. Spilling them into virtual VGPR lanes
525 // involve regalloc to allocate the physical VGPRs and that might
526 // cause intermediate spill/split of such liveranges for successful
527 // allocation. This would result in broken CFI encoding unless the
528 // regalloc aware CFI generation to insert new CFIs along with the
529 // intermediate spills is implemented. There is no such support
530 // currently exist in the LLVM compiler.
531 if (FuncInfo->allocateSGPRSpillToVGPRLane(
532 MF, FI, /*SpillToPhysVGPRLane=*/true)) {
533 bool Spilled = TRI->eliminateSGPRToVGPRSpillFrameIndex(
534 MI, FI, nullptr, Indexes, LIS, true);
535 if (!Spilled)
537 "failed to spill SGPR to physical VGPR lane when allocated");
538 }
539 } else
540 OrdinarySGPRSpills.push_back(&MI);
541 }
542 }
543
544 // Select candidates once, before ordinary lane lowering creates virtual
545 // VGPRs and changes the number of registers desired for the WWM pool.
546 SmallVector<MCRegister> WWMRegCandidates;
547 // These non-spillable WWM users retain the old all-or-nothing pool policy.
548 const bool RequiresFullWWMPool =
549 HasStrictWWMRegion || isPreallocateSGPRSpillVGPRsEnabled(MF);
550 if (!OrdinarySGPRSpills.empty())
551 WWMRegCandidates = determineRegsForWWMAllocation(MF);
552
553 const bool ShouldLowerOrdinarySpillsToVGPRLanes =
554 RequiresFullWWMPool || !WWMRegCandidates.empty();
555 if (!ShouldLowerOrdinarySpillsToVGPRLanes && !OrdinarySGPRSpills.empty())
557
558 if (ShouldLowerOrdinarySpillsToVGPRLanes) {
559 for (MachineInstr *MI : OrdinarySGPRSpills) {
560 int FI = TII->getNamedOperand(*MI, AMDGPU::OpName::addr)->getIndex();
561 if (FuncInfo->allocateSGPRSpillToVGPRLane(MF, FI)) {
562 MachineBasicBlock *MBB = MI->getParent();
563 MachineInstrSpan MIS(MI, MBB);
564 bool Spilled = TRI->eliminateSGPRToVGPRSpillFrameIndex(
565 *MI, FI, nullptr, Indexes, LIS);
566 if (!Spilled)
568 "failed to spill SGPR to virtual VGPR lane when allocated");
569 SpillFIs.set(FI);
570 updateLaneVGPRDomInstr(FI, MBB, MIS.begin(), LaneVGPRDomInstr);
571 SpilledToVirtVGPRLanes = true;
572 }
573 }
574 }
575
576 for (auto Reg : FuncInfo->getSGPRSpillVGPRs()) {
577 LaneVGPRInsertPt IP = LaneVGPRDomInstr[Reg];
578 if (CycleRef C = MCI->getTopLevelParentCycle(IP.MBB)) {
579 MachineBasicBlock *AdjMBB = getCycleDomBB(C);
580 IP = insertPt(AdjMBB, AdjMBB->getFirstTerminator());
581 }
582 // Insert the IMPLICIT_DEF at the identified points.
583 MachineBasicBlock &Block = *IP.MBB;
584 DebugLoc DL = Block.findDebugLoc(IP.It);
585 auto MIB = BuildMI(Block, IP.It, DL, TII->get(AMDGPU::IMPLICIT_DEF), Reg);
586
587 // Add WWM flag to the virtual register.
589
590 // Set SGPR_SPILL asm printer flag
591 MIB->setAsmPrinterFlag(AMDGPU::SGPR_SPILL);
592 if (LIS) {
593 LIS->InsertMachineInstrInMaps(*MIB);
595 }
596 }
597
598 // Assign the WWM pool from the pre-selected candidates and compute the
599 // complement mask for per-thread VGPR allocation.
600 assignWWMRegs(MF, WWMRegCandidates, RequiresFullWWMPool);
601
602 for (MachineBasicBlock &MBB : MF)
603 clearDebugInfoForSpillFIs(MFI, MBB, SpillFIs);
604
605 // All those frame indices which are dead by now should be removed from the
606 // function frame. Otherwise, there is a side effect such as re-mapping of
607 // free frame index ids by the later pass(es) like "stack slot coloring"
608 // which in turn could mess-up with the book keeping of "frame index to VGPR
609 // lane".
610 FuncInfo->removeDeadFrameIndices(MFI, /*ResetSGPRSpillStackIDs*/ false);
611
612 MadeChange = true;
613 }
614
615 if (SpilledToVirtVGPRLanes) {
616 const TargetRegisterClass *RC = TRI->getWaveMaskRegClass();
617 // Shift back the reserved SGPR for EXEC copy into the lowest range.
618 // This SGPR is reserved to handle the whole-wave spill/copy operations
619 // that might get inserted during vgpr regalloc.
620 Register UnusedLowSGPR = TRI->findUnusedRegister(MRI, RC, MF);
621 if (UnusedLowSGPR && TRI->getHWRegIndex(UnusedLowSGPR) <
622 TRI->getHWRegIndex(FuncInfo->getSGPRForEXECCopy()))
623 FuncInfo->setSGPRForEXECCopy(UnusedLowSGPR);
624 } else {
625 // No SGPR spills to virtual VGPR lanes and hence there won't be any WWM
626 // spills/copies. Reset the SGPR reserved for EXEC copy.
627 FuncInfo->setSGPRForEXECCopy(AMDGPU::NoRegister);
628 }
629
630 SaveBlocks.clear();
631 RestoreBlocks.clear();
632
633 return MadeChange;
634}
635
636PreservedAnalyses
639 MFPropsModifier _(*this, MF);
640 auto *LIS = MFAM.getCachedResult<LiveIntervalsAnalysis>(MF);
641 auto *Indexes = MFAM.getCachedResult<SlotIndexesAnalysis>(MF);
644 SILowerSGPRSpills(LIS, Indexes, MDT, &MCI).run(MF);
645 return PreservedAnalyses::all();
646}
#define Success
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
aarch64 promote const
Provides AMDGPU specific target descriptions.
MachineBasicBlock & MBB
MachineBasicBlock MachineBasicBlock::iterator DebugLoc DL
static GCRegistry::Add< ShadowStackGC > C("shadow-stack", "Very portable GC for uncooperative code generators")
AMD GCN specific subclass of TargetSubtarget.
#define DEBUG_TYPE
const HexagonInstrInfo * TII
#define _
IRTranslator LLVM IR MI
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
Register Reg
Register const TargetRegisterInfo * TRI
Promote Memory to Register
Definition Mem2Reg.cpp:110
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition PassSupport.h:42
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition PassSupport.h:44
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition PassSupport.h:39
static void insertCSRRestores(MachineBasicBlock &RestoreBlock, std::vector< CalleeSavedInfo > &CSI)
Insert restore code for the callee-saved registers used in the function.
SmallVector< MachineBasicBlock *, 4 > MBBVector
static void insertCSRSaves(MachineBasicBlock &SaveBlock, ArrayRef< CalleeSavedInfo > CSI)
Insert spill code for the callee-saved registers used in the function.
static void updateLiveness(MachineFunction &MF)
Helper function to update the liveness information for the callee-saved registers.
This file declares the machine register scavenger class.
static void insertCSRRestores(MachineBasicBlock &RestoreBlock, MutableArrayRef< CalleeSavedInfo > CSI, SlotIndexes *Indexes, LiveIntervals *LIS)
Insert restore code for the callee-saved registers used in the function.
PassT::Result * getCachedResult(IRUnitT &IR) const
Get the cached result of an analysis pass for a given IR unit.
PassT::Result & getResult(IRUnitT &IR, ExtraArgTs... ExtraArgs)
Get the result of an analysis pass for a given IR unit.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
void setPreservesAll()
Set by analyses that do not transform their input at all.
Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
Definition ArrayRef.h:218
size_t size() const
Get the array size.
Definition ArrayRef.h:141
bool empty() const
Check if the array is empty.
Definition ArrayRef.h:136
bool test(unsigned Idx) const
Returns true if bit Idx is set.
Definition BitVector.h:482
The CalleeSavedInfo class tracks the information need to locate where a callee saved register is in t...
Opaque handle to a cycle within a GenericCycleInfo that wraps the cycle's preorder index.
iterator find(const_arg_type_t< KeyT > Val)
Definition DenseMap.h:223
iterator end()
Definition DenseMap.h:141
NodeT * findNearestCommonDominator(NodeT *A, NodeT *B) const
Find nearest common dominator basic block for basic block A and B.
DomTreeNodeBase< NodeT > * getNode(const NodeT *BB) const
getNode - return the (Post)DominatorTree node for the specified basic block.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function.
Definition Function.cpp:353
bool isReducible(CycleRef C) const
ArrayRef< BlockT * > getEntries(CycleRef C) const
CycleRef getTopLevelParentCycle(const BlockT *Block) const
BlockT * getHeader(CycleRef C) const
const HexagonRegisterInfo & getRegisterInfo() const
LLVM_ABI void emitError(const Instruction *I, const Twine &ErrorStr)
emitError - Emit an error message to the currently installed error handler with optional location inf...
void removeAllRegUnitsForPhysReg(MCRegister Reg)
Remove associated live ranges for the register units associated with Reg.
SlotIndex InsertMachineInstrInMaps(MachineInstr &MI)
LiveInterval & createAndComputeVirtRegInterval(Register Reg)
An RAII based helper class to modify MachineFunctionProperties when running pass.
bool isEHFuncletEntry() const
Returns true if this is the entry block of an EH funclet.
LLVM_ABI iterator getFirstTerminator()
Returns an iterator to the first terminator instruction of this basic block.
bool isReturnBlock() const
Convenience function that returns true if the block ends in a return instruction.
LLVM_ABI void sortUniqueLiveIns()
Sorts and uniques the LiveIns vector.
LLVM_ABI DebugLoc findDebugLoc(instr_iterator MBBI)
Find the next valid DebugLoc starting at MBBI, skipping any debug instructions.
void addLiveIn(MCRegister PhysReg, LaneBitmask LaneMask=LaneBitmask::getAll())
Adds the specified register as a live in.
const MachineFunction * getParent() const
Return the MachineFunction containing this basic block.
MachineInstrBundleIterator< MachineInstr > iterator
LLVM_ABI Result run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
Legacy analysis pass which computes a MachineCycleInfo.
Analysis pass which computes a MachineDominatorTree.
Analysis pass which computes a MachineDominatorTree.
DominatorTree Class - Concrete subclass of DominatorTreeBase that is used to compute a normal dominat...
bool dominates(const MachineInstr *A, const MachineInstr *B) const
LLVM_ABI int CreateStackObject(uint64_t Size, Align Alignment, bool isSpillSlot, const AllocaInst *Alloca=nullptr, uint8_t ID=0)
Create a new statically sized stack object, returning a nonnegative identifier to represent it.
void setCalleeSavedInfoValid(bool v)
int getObjectIndexEnd() const
Return one past the maximum frame object index.
bool hasStackObjects() const
Return true if there are any stack objects in this function.
uint8_t getStackID(int ObjectIdx) const
const SaveRestorePoints & getRestorePoints() const
const SaveRestorePoints & getSavePoints() const
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
Properties which a MachineFunction may have at a given point in time.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
MachineFrameInfo & getFrameInfo()
getFrameInfo - Return the frame info object for the current function.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
Function & getFunction()
Return the LLVM function that this machine code represents.
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
const MachineBasicBlock & front() const
MachineInstrSpan provides an interface to get an iteration range containing the instruction it was in...
Representation of each machine instruction.
LLVM_ABI const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
LLVM_ABI bool isPhysRegUsed(MCRegister PhysReg, bool SkipRegMaskTest=false) const
Return true if the specified register is modified or read in this function.
Represent a mutable reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:294
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
Definition Analysis.h:118
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void setFlag(Register Reg, uint8_t Flag)
ArrayRef< SIRegisterInfo::SpilledReg > getSGPRSpillToVirtualVGPRLanes(int FrameIndex) const
bool allocateSGPRSpillToVGPRLane(MachineFunction &MF, int FI, bool SpillToPhysVGPRLane=false, bool IsPrologEpilog=false)
bool removeDeadFrameIndices(MachineFrameInfo &MFI, bool ResetSGPRSpillStackIDs)
If ResetSGPRSpillStackIDs is true, reset the stack ID from sgpr-spill to the default stack.
void updateNonWWMRegMask(BitVector &RegMask)
ArrayRef< Register > getSGPRSpillVGPRs() const
SlotIndexes pass.
SlotIndex insertMachineInstrInMaps(MachineInstr &MI, bool Late=false)
Insert the given machine instruction into the mapping.
LLVM_ABI void removeMachineInstrFromMaps(MachineInstr &MI, bool AllowBundled=false)
Removes machine instruction (bundle) MI from the mapping.
LLVM_ABI void repairIndexesInRange(MachineBasicBlock *MBB, MachineBasicBlock::iterator Begin, MachineBasicBlock::iterator End)
Repair indexes after adding and removing instructions.
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
void push_back(const T &Elt)
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Information about stack frame layout on the target.
void restoreCalleeSavedRegister(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, const CalleeSavedInfo &CS, const TargetInstrInfo *TII, const TargetRegisterInfo *TRI) const
virtual bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, ArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const
spillCalleeSavedRegisters - Issues instruction(s) to spill all callee saved registers and returns tru...
virtual bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, MutableArrayRef< CalleeSavedInfo > CSI, const TargetRegisterInfo *TRI) const
restoreCalleeSavedRegisters - Issues instruction(s) to restore all callee saved registers and returns...
TargetInstrInfo - Interface to description of machine instruction set.
TargetRegisterInfo base class - We assume that the target defines a static array of TargetRegisterDes...
virtual const TargetFrameLowering * getFrameLowering() const
virtual const TargetInstrInfo * getInstrInfo() const
virtual const TargetRegisterInfo * getRegisterInfo() const =0
Return the target's register information.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
initializer< Ty > init(const Ty &Val)
This is an optimization pass for GlobalISel generic memory operations.
MachineInstrBuilder BuildMI(MachineFunction &MF, const MIMetadata &MIMD, const MCInstrDesc &MCID)
Builder interface. Specify how to create the initial instruction itself.
iterator_range< early_inc_iterator_impl< detail::IterOfRange< RangeT > > > make_early_inc_range(RangeT &&Range)
Make a range that does early increment to allow mutation of the underlying range without disrupting i...
Definition STLExtras.h:633
AnalysisManager< MachineFunction > MachineFunctionAnalysisManager
void clearDebugInfoForSpillFIs(MachineFrameInfo &MFI, MachineBasicBlock &MBB, const BitVector &SpillFIs)
Replace frame index operands with null registers in debug value instructions for the specified spill ...
auto reverse(ContainerTy &&C)
Definition STLExtras.h:407
class LLVM_GSL_OWNER SmallVector
Forward declaration of SmallVector so that calculateSmallVectorDefaultInlinedElements can reference s...
char & SILowerSGPRSpillsLegacyID
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
Definition MCRegister.h:21
ArrayRef(const T &OneElt) -> ArrayRef< T >
bool isPreallocateSGPRSpillVGPRsEnabled(const MachineFunction &MF)
bool is_contained(R &&Range, const E &Element)
Returns true if Element is found in Range.
Definition STLExtras.h:1947
MCRegisterClass TargetRegisterClass
Definition FastISel.h:58