34#define DEBUG_TYPE "si-lower-sgpr-spills"
42struct LaneVGPRInsertPt {
53 "amdgpu-num-vgprs-for-wwm-alloc",
54 cl::desc(
"Max num VGPRs for whole-wave register allocation."),
57class SILowerSGPRSpills {
76 : LIS(LIS), Indexes(Indexes), MDT(MDT), MCI(MCI) {}
81 void updateLaneVGPRDomInstr(
86 bool RequiresFullWWMPool);
112char SILowerSGPRSpillsLegacy::ID = 0;
115 "SI lower SGPR spill instructions",
false,
false)
134 assert(
Success &&
"spillCalleeSavedRegisters should always succeed");
139 Indexes->repairIndexesInRange(&SaveBlock, SaveBlock.begin(),
I);
143 LIS->removeAllRegUnitsForPhysReg(CS.getReg());
158 I == RestoreBlock.
begin() ?
I : std::prev(
I);
189void SILowerSGPRSpills::calculateSaveRestoreBlocks(
MachineFunction &MF) {
199 "Multiple save points not yet supported!");
203 "Multiple restore points not yet supported!");
205 MachineBasicBlock *RestoreBlock = RestorePoint.first;
216 for (MachineBasicBlock &
MBB : MF) {
234bool SILowerSGPRSpills::spillCalleeSavedRegs(
235 MachineFunction &MF, SmallVectorImpl<int> &CalleeSavedFIs) {
239 const SIFrameLowering *TFI =
ST.getFrameLowering();
241 RegScavenger *
RS =
nullptr;
245 TFI->determineCalleeSavesSGPR(MF, SavedRegs, RS);
248 if (!
F.hasFnAttribute(Attribute::Naked)) {
253 std::vector<CalleeSavedInfo> CSI;
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;
260 for (
unsigned I = 0; CSRegs[
I]; ++
I) {
261 MCRegister
Reg = CSRegs[
I];
264 if (
Reg == RetAddrRegSub0 ||
Reg == RetAddrRegSub1) {
265 SpillRetAddrReg =
true;
271 TRI->getSpillAlign(*RC),
true,
272 nullptr,
TRI->getSpillStackID(*RC));
274 CSI.emplace_back(
Reg, JunkFI);
282 if (SpillRetAddrReg) {
286 true,
nullptr,
TRI->getSpillStackID(*RC));
287 CSI.push_back(CalleeSavedInfo(RetAddrReg, JunkFI));
292 for (MachineBasicBlock *SaveBlock : SaveBlocks)
296 assert(SaveBlocks.size() == 1 &&
"shrink wrapping not fully implemented");
299 for (MachineBasicBlock *RestoreBlock : RestoreBlocks)
308MachineBasicBlock *SILowerSGPRSpills::getCycleDomBB(CycleRef
C) {
313 return IDom->getBlock();
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)
326void SILowerSGPRSpills::updateLaneVGPRDomInstr(
328 DenseMap<Register, LaneVGPRInsertPt> &LaneVGPRDomInstr) {
335 SIMachineFunctionInfo *FuncInfo =
340 for (
auto &Spill : VGPRSpills) {
341 if (PrevLaneVGPR ==
Spill.VGPR)
344 PrevLaneVGPR =
Spill.VGPR;
346 if (
Spill.Lane == 0 &&
I == LaneVGPRDomInstr.
end()) {
347 LaneVGPRDomInstr[
Spill.VGPR] = insertPt(
MBB, InsertPt);
350 LaneVGPRInsertPt Prev =
I->second;
351 MachineBasicBlock *PrevInsertMBB = Prev.MBB;
353 MachineBasicBlock *DomMBB = PrevInsertMBB;
359 if (PrevInsertPt ==
MBB->
end() ||
360 MDT->
dominates(&*InsertPt, &*PrevInsertPt))
361 I->second = insertPt(
MBB, InsertPt);
371 I->second = insertPt(
MBB, InsertPt);
372 else if (DomMBB != PrevInsertMBB)
379SILowerSGPRSpills::determineRegsForWWMAllocation(MachineFunction &MF) {
381 if (!MaxNumVGPRsForWwmAllocation)
382 return WWMRegCandidates;
385 BitVector ReservedRegs =
TRI->getReservedRegs(MF);
387 unsigned MaxNumVGPRs =
ST.getMaxNumVectorRegs(MF.
getFunction()).first;
391 for (
unsigned Reg = AMDGPU::VGPR0 + MaxNumVGPRs - 1;
392 WWMRegCandidates.
size() < MaxNumVGPRsForWwmAllocation &&
393 Reg >= AMDGPU::VGPR0;
400 return WWMRegCandidates;
403void SILowerSGPRSpills::assignWWMRegs(MachineFunction &MF,
405 bool RequiresFullWWMPool) {
406 SIMachineFunctionInfo *FuncInfo = MF.
getInfo<SIMachineFunctionInfo>();
410 BitVector WwmRegMask(
TRI->getNumRegs());
412 unsigned DesiredPoolSize =
414 static_cast<unsigned>(MaxNumVGPRsForWwmAllocation));
415 unsigned SelectedPoolSize =
416 std::min<unsigned>(DesiredPoolSize, WWMRegCandidates.
size());
420 for (MCRegister
Reg : WWMRegCandidates.
take_front(SelectedPoolSize))
421 TRI->markSuperRegs(WwmRegMask,
Reg);
423 if (RequiresFullWWMPool && SelectedPoolSize != DesiredPoolSize) {
425 TRI->markSuperRegs(WwmRegMask, AMDGPU::VGPR0);
427 "cannot find enough VGPRs for wwm-regalloc");
430 BitVector PerLaneVGPRMask(WwmRegMask);
431 PerLaneVGPRMask.flip().clearBitsNotInMask(
TRI->getAllVGPRRegMask());
437bool SILowerSGPRSpillsLegacy::runOnMachineFunction(MachineFunction &MF) {
438 auto *LISWrapper = getAnalysisIfAvailable<LiveIntervalsWrapperPass>();
439 LiveIntervals *LIS = LISWrapper ? &LISWrapper->getLIS() :
nullptr;
440 auto *SIWrapper = getAnalysisIfAvailable<SlotIndexesWrapperPass>();
441 SlotIndexes *Indexes = SIWrapper ? &SIWrapper->getSI() :
nullptr;
442 MachineDominatorTree *MDT =
443 &getAnalysis<MachineDominatorTreeWrapperPass>().getDomTree();
444 MachineCycleInfo *MCI =
445 &getAnalysis<MachineCycleInfoWrapperPass>().getCycleInfo();
446 return SILowerSGPRSpills(LIS, Indexes, MDT, MCI).run(MF);
449bool SILowerSGPRSpills::run(MachineFunction &MF) {
451 TII =
ST.getInstrInfo();
458 calculateSaveRestoreBlocks(MF);
459 SmallVector<int> CalleeSavedFIs;
460 bool HasCSRs = spillCalleeSavedRegs(MF, CalleeSavedFIs);
464 SIMachineFunctionInfo *FuncInfo = MF.
getInfo<SIMachineFunctionInfo>();
468 RestoreBlocks.
clear();
472 bool MadeChange =
false;
473 bool SpilledToVirtVGPRLanes =
false;
477 const bool HasSGPRSpillToVGPR =
TRI->spillSGPRToVGPR() &&
479 if (HasSGPRSpillToVGPR) {
490 DenseMap<Register, LaneVGPRInsertPt> LaneVGPRDomInstr;
495 bool HasStrictWWMRegion =
false;
497 for (MachineBasicBlock &
MBB : MF) {
499 if (
MI.getOpcode() == AMDGPU::ENTER_STRICT_WWM ||
500 MI.getOpcode() == AMDGPU::ENTER_STRICT_WQM) {
501 HasStrictWWMRegion =
true;
505 if (!
TII->isSGPRSpill(
MI))
508 if (
MI.getOperand(0).isUndef()) {
511 MI.eraseFromParent();
515 int FI =
TII->getNamedOperand(
MI, AMDGPU::OpName::addr)->getIndex();
519 if (IsCalleeSaveSGPRSpill) {
532 bool Spilled =
TRI->eliminateSGPRToVGPRSpillFrameIndex(
533 MI, FI,
nullptr, Indexes, LIS,
true);
536 "failed to spill SGPR to physical VGPR lane when allocated");
547 const bool RequiresFullWWMPool =
549 if (!OrdinarySGPRSpills.
empty())
550 WWMRegCandidates = determineRegsForWWMAllocation(MF);
552 const bool ShouldLowerOrdinarySpillsToVGPRLanes =
553 RequiresFullWWMPool || !WWMRegCandidates.
empty();
554 if (!ShouldLowerOrdinarySpillsToVGPRLanes && !OrdinarySGPRSpills.
empty())
557 if (ShouldLowerOrdinarySpillsToVGPRLanes) {
558 for (MachineInstr *
MI : OrdinarySGPRSpills) {
559 int FI =
TII->getNamedOperand(*
MI, AMDGPU::OpName::addr)->getIndex();
561 MachineBasicBlock *
MBB =
MI->getParent();
562 MachineInstrSpan MIS(
MI,
MBB);
563 bool Spilled =
TRI->eliminateSGPRToVGPRSpillFrameIndex(
564 *
MI, FI,
nullptr, Indexes, LIS);
567 "failed to spill SGPR to virtual VGPR lane when allocated");
569 updateLaneVGPRDomInstr(FI,
MBB, MIS.
begin(), LaneVGPRDomInstr);
570 SpilledToVirtVGPRLanes =
true;
576 LaneVGPRInsertPt IP = LaneVGPRDomInstr[
Reg];
578 MachineBasicBlock *AdjMBB = getCycleDomBB(
C);
582 MachineBasicBlock &
Block = *IP.MBB;
599 assignWWMRegs(MF, WWMRegCandidates, RequiresFullWWMPool);
601 for (MachineBasicBlock &
MBB : MF)
614 if (SpilledToVirtVGPRLanes) {
619 Register UnusedLowSGPR =
TRI->findUnusedRegister(MRI, RC, MF);
620 if (UnusedLowSGPR &&
TRI->getHWRegIndex(UnusedLowSGPR) <
630 RestoreBlocks.
clear();
643 SILowerSGPRSpills(LIS, Indexes, MDT, &MCI).
run(MF);
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Provides AMDGPU specific target descriptions.
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.
const HexagonInstrInfo * TII
Register const TargetRegisterInfo * TRI
Promote Memory to Register
#define INITIALIZE_PASS_DEPENDENCY(depName)
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
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),...
ArrayRef< T > take_front(size_t N=1) const
Return a copy of *this with only the first N elements.
size_t size() const
Get the array size.
bool empty() const
Check if the array is empty.
bool test(unsigned Idx) const
Returns true if bit Idx is set.
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)
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.
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),...
static PreservedAnalyses all()
Construct a special preserved set that preserves all passes.
PreservedAnalyses run(MachineFunction &MF, MachineFunctionAnalysisManager &MFAM)
void setSGPRForEXECCopy(Register Reg)
void setFlag(Register Reg, uint8_t Flag)
ArrayRef< SIRegisterInfo::SpilledReg > getSGPRSpillToVirtualVGPRLanes(int FrameIndex) const
void setNoWWMPoolSGPRSpillFallback()
Register getSGPRForEXECCopy() 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 updatePerLaneVGPRMask(BitVector &RegMask)
bool hasSpilledSGPRs() const
ArrayRef< Register > getSGPRSpillVGPRs() const
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...
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)
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...
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.
MCRegisterClass TargetRegisterClass