Go to the documentation of this file.
29 #define DEBUG_TYPE "amdgpu-nsa-reassign"
32 "Number of NSA instructions with non-sequential address found");
34 "Number of NSA instructions changed to sequential");
48 StringRef getPassName()
const override {
return "GCN NSA Reassign"; }
83 NSA_Status CheckNSA(
const MachineInstr &
MI,
bool Fast =
false)
const;
86 unsigned StartReg)
const;
88 bool canAssign(
unsigned StartReg,
unsigned NumRegs)
const;
104 char GCNNSAReassign::
ID = 0;
110 unsigned StartReg)
const {
111 unsigned NumRegs = Intervals.size();
113 for (
unsigned N = 0;
N < NumRegs; ++
N)
114 if (VRM->hasPhys(Intervals[
N]->reg()))
115 LRM->unassign(*Intervals[
N]);
117 for (
unsigned N = 0;
N < NumRegs; ++
N)
121 for (
unsigned N = 0;
N < NumRegs; ++
N)
127 bool GCNNSAReassign::canAssign(
unsigned StartReg,
unsigned NumRegs)
const {
128 for (
unsigned N = 0;
N < NumRegs; ++
N) {
129 unsigned Reg = StartReg +
N;
133 for (
unsigned I = 0; CSRegs[
I]; ++
I)
135 !LRM->isPhysRegUsed(CSRegs[
I]))
144 unsigned NumRegs = Intervals.size();
146 if (NumRegs > MaxNumVGPRs)
148 unsigned MaxReg = MaxNumVGPRs - NumRegs + AMDGPU::VGPR0;
150 for (
unsigned Reg = AMDGPU::VGPR0;
Reg <= MaxReg; ++
Reg) {
151 if (!canAssign(
Reg, NumRegs))
154 if (tryAssignRegisters(Intervals,
Reg))
161 GCNNSAReassign::NSA_Status
162 GCNNSAReassign::CheckNSA(
const MachineInstr &
MI,
bool Fast)
const {
165 return NSA_Status::NOT_NSA;
167 switch (
Info->MIMGEncoding) {
168 case AMDGPU::MIMGEncGfx10NSA:
169 case AMDGPU::MIMGEncGfx11NSA:
172 return NSA_Status::NOT_NSA;
178 unsigned VgprBase = 0;
180 for (
unsigned I = 0;
I <
Info->VAddrOperands; ++
I) {
183 if (
Reg.isPhysical() || !VRM->isAssignedReg(
Reg))
184 return NSA_Status::FIXED;
190 return NSA_Status::FIXED;
202 return NSA_Status::FIXED;
209 if (VRM->getPreSplitReg(
Reg))
210 return NSA_Status::FIXED;
214 if (
Def &&
Def->isCopy() &&
Def->getOperand(1).getReg() == PhysReg)
215 return NSA_Status::FIXED;
219 return NSA_Status::FIXED;
222 return NSA_Status::FIXED;
225 if (!LIS->hasInterval(
Reg))
226 return NSA_Status::FIXED;
231 else if (VgprBase +
I != PhysReg)
235 return NSA ? NSA_Status::NON_CONTIGUOUS : NSA_Status::CONTIGUOUS;
244 TRI =
ST->getRegisterInfo();
245 VRM = &getAnalysis<VirtRegMap>();
246 LRM = &getAnalysis<LiveRegMatrix>();
247 LIS = &getAnalysis<LiveIntervals>();
250 MaxNumVGPRs =
ST->getMaxNumVGPRs(MF);
254 using Candidate = std::pair<const MachineInstr*, bool>;
258 switch (CheckNSA(
MI)) {
261 case NSA_Status::CONTIGUOUS:
262 Candidates.push_back(std::make_pair(&
MI,
true));
264 case NSA_Status::NON_CONTIGUOUS:
265 Candidates.push_back(std::make_pair(&
MI,
false));
266 ++NumNSAInstructions;
272 bool Changed =
false;
273 for (
auto &
C : Candidates) {
278 if (CheckNSA(*
MI,
true) == NSA_Status::CONTIGUOUS) {
292 for (
unsigned I = 0;
I <
Info->VAddrOperands; ++
I) {
301 Intervals.push_back(LI);
302 OrigRegs.push_back(VRM->getPhys(
Reg));
307 MinInd = MaxInd = LIS->getInstructionIndex(*
MI);
314 if (Intervals.empty())
318 <<
"\tOriginal allocation:\t";
324 bool Success = scavengeRegs(Intervals);
327 if (VRM->hasPhys(Intervals.back()->reg()))
333 return LIS->getInstructionIndex(*C.first) < I;
335 for (
auto E = Candidates.end();
Success &&
I !=
E &&
336 LIS->getInstructionIndex(*
I->first) < MaxInd; ++
I) {
337 if (
I->second && CheckNSA(*
I->first,
true) < NSA_Status::CONTIGUOUS) {
345 for (
unsigned I = 0;
I <
Info->VAddrOperands; ++
I)
346 if (VRM->hasPhys(Intervals[
I]->reg()))
347 LRM->unassign(*Intervals[
I]);
349 for (
unsigned I = 0;
I <
Info->VAddrOperands; ++
I)
350 LRM->assign(*Intervals[
I], OrigRegs[
I]);
358 dbgs() <<
"\tNew allocation:\t\t ["
This is an optimization pass for GlobalISel generic memory operations.
MachineRegisterInfo - Keep track of information for virtual and physical registers,...
static MCRegister from(unsigned Val)
Check the provided unsigned value is a valid MCRegister.
auto lower_bound(R &&Range, T &&Value)
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
INITIALIZE_PASS_BEGIN(GCNNSAReassign, DEBUG_TYPE, "GCN NSA Reassign", false, false) INITIALIZE_PASS_END(GCNNSAReassign
Reg
All possible values of the reg field in the ModR/M byte.
MachineInstr * getUniqueVRegDef(Register Reg) const
getUniqueVRegDef - Return the unique machine instr that defines the specified virtual register or nul...
MachineFunctionPass - This class adapts the FunctionPass interface to allow convenient creation of pa...
Expected< ExpressionValue > max(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
LLVM_READONLY int16_t getNamedOperandIdx(uint16_t Opcode, uint16_t NamedIdx)
unsigned const TargetRegisterInfo * TRI
void getAnalysisUsage(AnalysisUsage &AU) const override
getAnalysisUsage - Subclasses that override getAnalysisUsage must call this.
SlotIndex beginIndex() const
beginIndex - Return the lowest numbered slot covered.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
MachineRegisterInfo & getRegInfo()
getRegInfo - Return information about the registers currently in use.
iterator_range< use_nodbg_iterator > use_nodbg_operands(Register Reg) const
static PassRegistry * getPassRegistry()
getPassRegistry - Access the global registry object, which is automatically initialized at applicatio...
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Ty * getInfo()
getInfo - Keep track of various per-function pieces of information for backends that would like to do...
(vector float) vec_cmpeq(*A, *B) C
const MachineOperand & getOperand(unsigned i) const
Represent the analysis usage information of a pass.
MachineOperand class - Representation of each machine instruction operand.
STATISTIC(NumFunctions, "Total number of functions")
bool isSubRegisterEq(MCRegister RegA, MCRegister RegB) const
Returns true if RegB is a sub-register of RegA or if RegB == RegA.
Analysis containing CSE Info
LiveInterval - This class represents the liveness of a register, or stack slot.
SlotIndex - An opaque wrapper around machine indexes.
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
const TargetRegisterClass * getRegClass(Register Reg) const
Return the register class of the specified virtual register.
const TargetSubtargetInfo & getSubtarget() const
getSubtarget - Return the subtarget for which this machine code is being compiled.
Representation of each machine instruction.
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
const MCPhysReg * getCalleeSavedRegs() const
Returns list of callee saved registers.
uint16_t MCPhysReg
An unsigned integer type large enough to represent all physical registers, but not necessarily virtua...
bool is_contained(R &&Range, const E &Element)
Wrapper function around std::find to detect if an element exists in a container.
bool isAllocatable(MCRegister PhysReg) const
isAllocatable - Returns true when PhysReg belongs to an allocatable register class and it hasn't been...
const LLVM_READONLY MIMGInfo * getMIMGInfo(unsigned Opc)
Register getReg() const
getReg - Returns the register number.
void initializeGCNNSAReassignPass(PassRegistry &)
unsigned getOccupancy() const
Expected< ExpressionValue > min(const ExpressionValue &Lhs, const ExpressionValue &Rhs)
StringRef - Represent a constant reference to a string, i.e.
const MachineBasicBlock * getParent() const
unsigned const MachineRegisterInfo * MRI
Wrapper class representing virtual and physical registers.
SlotIndex endIndex() const
endNumber - return the maximum point of the range of the whole, exclusive.
void setPreservesAll()
Set by analyses that do not transform their input at all.
unsigned getRegSizeInBits(const TargetRegisterClass &RC) const
Return the size in bits of a register from class RC.
This class keeps track of the SPI_SP_INPUT_ADDR config register, which tells the hardware which inter...
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
AnalysisUsage & addRequired()
Printable printReg(Register Reg, const TargetRegisterInfo *TRI=nullptr, unsigned SubIdx=0, const MachineRegisterInfo *MRI=nullptr)
Prints virtual and physical registers with or without a TRI instance.