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