blob: aa39c9a8bb080fd0f45b769dbe0d34664732d24c [file] [log] [blame]
Tim Renoufd737b552019-03-20 17:42:00 +00001//===-- 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
27using namespace llvm;
28using 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.
35void 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.
54bool 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.
66static 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.
88static 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.
109void 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.
115void 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.
121void 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.
127void 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.
132unsigned 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.
136void 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.
143void 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.
153void 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.
161void AMDGPUPALMetadata::setScratchSize(CallingConv::ID CC, unsigned Val) {
162 Registers[getScratchSizeKey(CC)] = Val;
163}
164
165// Convert the accumulated PAL metadata into an asm directive.
166void 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.
183void 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