1 //===-- AMDGPUPALMetadata.cpp - Accumulate and print AMDGPU PAL metadata  -===//
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 /// \file
10 ///
11 /// This class has methods called by AMDGPUAsmPrinter to accumulate and print
12 /// the PAL metadata.
13 //
14 //===----------------------------------------------------------------------===//
15 //
16 
17 #include "AMDGPUPALMetadata.h"
18 #include "AMDGPU.h"
19 #include "AMDGPUAsmPrinter.h"
20 #include "MCTargetDesc/AMDGPUTargetStreamer.h"
21 #include "SIDefines.h"
22 #include "llvm/BinaryFormat/ELF.h"
23 #include "llvm/IR/CallingConv.h"
24 #include "llvm/Support/AMDGPUMetadata.h"
25 #include "llvm/Support/EndianStream.h"
26 
27 using namespace llvm;
28 using namespace llvm::AMDGPU;
29 
30 // Read the amdgpu.pal.metadata supplied by the
31 // frontend into our Registers, ready for per-function modification.  It
32 // is a NamedMD containing an MDTuple containing a number of MDNodes each of
33 // which is an integer value, and each two integer values forms a key=value
34 // pair that we store as Registers[key]=value in the map.
35 void AMDGPUPALMetadata::readFromIR(Module &M) {
36   auto NamedMD = M.getNamedMetadata("amdgpu.pal.metadata");
37   if (!NamedMD || !NamedMD->getNumOperands())
38     return;
39   auto Tuple = dyn_cast<MDTuple>(NamedMD->getOperand(0));
40   if (!Tuple)
41     return;
42   for (unsigned I = 0, E = Tuple->getNumOperands() & -2; I != E; I += 2) {
43     auto Key = mdconst::dyn_extract<ConstantInt>(Tuple->getOperand(I));
44     auto Val = mdconst::dyn_extract<ConstantInt>(Tuple->getOperand(I + 1));
45     if (!Key || !Val)
46       continue;
47     Registers[Key->getZExtValue()] = Val->getZExtValue();
48   }
49 }
50 
51 // Set PAL metadata from a binary blob from the applicable .note record.
52 // Returns false if bad format.  Blob must remain valid for the lifetime of the
53 // Metadata.
54 bool AMDGPUPALMetadata::setFromBlob(unsigned Type, StringRef Blob) {
55   assert(Type == ELF::NT_AMD_AMDGPU_PAL_METADATA);
56   auto Data = reinterpret_cast<const uint32_t *>(Blob.data());
57   for (unsigned I = 0; I != Blob.size() / sizeof(uint32_t) / 2; ++I)
58     setRegister(Data[I * 2], Data[I * 2 + 1]);
59   return true;
60 }
61 
62 // Given the calling convention, calculate the register number for rsrc1. In
63 // principle the register number could change in future hardware, but we know
64 // it is the same for gfx6-9 (except that LS and ES don't exist on gfx9), so
65 // we can use fixed values.
66 static unsigned getRsrc1Reg(CallingConv::ID CC) {
67   switch (CC) {
68   default:
69     return PALMD::R_2E12_COMPUTE_PGM_RSRC1;
70   case CallingConv::AMDGPU_LS:
71     return PALMD::R_2D4A_SPI_SHADER_PGM_RSRC1_LS;
72   case CallingConv::AMDGPU_HS:
73     return PALMD::R_2D0A_SPI_SHADER_PGM_RSRC1_HS;
74   case CallingConv::AMDGPU_ES:
75     return PALMD::R_2CCA_SPI_SHADER_PGM_RSRC1_ES;
76   case CallingConv::AMDGPU_GS:
77     return PALMD::R_2C8A_SPI_SHADER_PGM_RSRC1_GS;
78   case CallingConv::AMDGPU_VS:
79     return PALMD::R_2C4A_SPI_SHADER_PGM_RSRC1_VS;
80   case CallingConv::AMDGPU_PS:
81     return PALMD::R_2C0A_SPI_SHADER_PGM_RSRC1_PS;
82   }
83 }
84 
85 // Calculate the PAL metadata key for *S_SCRATCH_SIZE. It can be used
86 // with a constant offset to access any non-register shader-specific PAL
87 // metadata key.
88 static unsigned getScratchSizeKey(CallingConv::ID CC) {
89   switch (CC) {
90   case CallingConv::AMDGPU_PS:
91     return PALMD::Key::PS_SCRATCH_SIZE;
92   case CallingConv::AMDGPU_VS:
93     return PALMD::Key::VS_SCRATCH_SIZE;
94   case CallingConv::AMDGPU_GS:
95     return PALMD::Key::GS_SCRATCH_SIZE;
96   case CallingConv::AMDGPU_ES:
97     return PALMD::Key::ES_SCRATCH_SIZE;
98   case CallingConv::AMDGPU_HS:
99     return PALMD::Key::HS_SCRATCH_SIZE;
100   case CallingConv::AMDGPU_LS:
101     return PALMD::Key::LS_SCRATCH_SIZE;
102   default:
103     return PALMD::Key::CS_SCRATCH_SIZE;
104   }
105 }
106 
107 // Set the rsrc1 register in the metadata for a particular shader stage.
108 // In fact this ORs the value into any previous setting of the register.
109 void AMDGPUPALMetadata::setRsrc1(CallingConv::ID CC, unsigned Val) {
110   setRegister(getRsrc1Reg(CC), Val);
111 }
112 
113 // Set the rsrc2 register in the metadata for a particular shader stage.
114 // In fact this ORs the value into any previous setting of the register.
115 void AMDGPUPALMetadata::setRsrc2(CallingConv::ID CC, unsigned Val) {
116   setRegister(getRsrc1Reg(CC) + 1, Val);
117 }
118 
119 // Set the SPI_PS_INPUT_ENA register in the metadata.
120 // In fact this ORs the value into any previous setting of the register.
121 void AMDGPUPALMetadata::setSpiPsInputEna(unsigned Val) {
122   setRegister(PALMD::R_A1B3_SPI_PS_INPUT_ENA, Val);
123 }
124 
125 // Set the SPI_PS_INPUT_ADDR register in the metadata.
126 // In fact this ORs the value into any previous setting of the register.
127 void AMDGPUPALMetadata::setSpiPsInputAddr(unsigned Val) {
128   setRegister(PALMD::R_A1B4_SPI_PS_INPUT_ADDR, Val);
129 }
130 
131 // Get a register from the metadata, or 0 if not currently set.
132 unsigned AMDGPUPALMetadata::getRegister(unsigned Reg) { return Registers[Reg]; }
133 
134 // Set a register in the metadata.
135 // In fact this ORs the value into any previous setting of the register.
136 void AMDGPUPALMetadata::setRegister(unsigned Reg, unsigned Val) {
137   Registers[Reg] |= Val;
138 }
139 
140 // Set the number of used vgprs in the metadata. This is an optional advisory
141 // record for logging etc; wave dispatch actually uses the rsrc1 register for
142 // the shader stage to determine the number of vgprs to allocate.
143 void AMDGPUPALMetadata::setNumUsedVgprs(CallingConv::ID CC, unsigned Val) {
144   unsigned NumUsedVgprsKey = getScratchSizeKey(CC) +
145                              PALMD::Key::VS_NUM_USED_VGPRS -
146                              PALMD::Key::VS_SCRATCH_SIZE;
147   Registers[NumUsedVgprsKey] = Val;
148 }
149 
150 // Set the number of used sgprs in the metadata. This is an optional advisory
151 // record for logging etc; wave dispatch actually uses the rsrc1 register for
152 // the shader stage to determine the number of sgprs to allocate.
153 void AMDGPUPALMetadata::setNumUsedSgprs(CallingConv::ID CC, unsigned Val) {
154   unsigned NumUsedSgprsKey = getScratchSizeKey(CC) +
155                              PALMD::Key::VS_NUM_USED_SGPRS -
156                              PALMD::Key::VS_SCRATCH_SIZE;
157   Registers[NumUsedSgprsKey] = Val;
158 }
159 
160 // Set the scratch size in the metadata.
161 void AMDGPUPALMetadata::setScratchSize(CallingConv::ID CC, unsigned Val) {
162   Registers[getScratchSizeKey(CC)] = Val;
163 }
164 
165 // Convert the accumulated PAL metadata into an asm directive.
166 void AMDGPUPALMetadata::toString(std::string &String) {
167   String.clear();
168   if (Registers.empty())
169     return;
170   raw_string_ostream Stream(String);
171   Stream << '\t' << AMDGPU::PALMD::AssemblerDirective << ' ';
172   for (auto I = Registers.begin(), E = Registers.end(); I != E; ++I) {
173     if (I != Registers.begin())
174       Stream << ',';
175     Stream << "0x" << Twine::utohexstr(I->first) << ",0x"
176            << Twine::utohexstr(I->second);
177   }
178   Stream << '\n';
179 }
180 
181 // Convert the accumulated PAL metadata into a binary blob for writing as
182 // a .note record of the specified AMD type.
183 void AMDGPUPALMetadata::toBlob(unsigned Type, std::string &Blob) {
184   Blob.clear();
185   if (Type != ELF::NT_AMD_AMDGPU_PAL_METADATA)
186     return;
187   if (Registers.empty())
188     return;
189   raw_string_ostream OS(Blob);
190   support::endian::Writer EW(OS, support::endianness::little);
191   for (auto I : Registers) {
192     EW.write(uint32_t(I.first));
193     EW.write(uint32_t(I.second));
194   }
195 }
196 
197