|
11 | 11 |
|
12 | 12 | #include "MCTargetDesc/AMDGPUMCTargetDesc.h"
|
13 | 13 | #include "llvm/ADT/DenseMap.h"
|
| 14 | +#include "llvm/Analysis/ValueTracking.h" |
14 | 15 | #include "llvm/CodeGen/Register.h"
|
| 16 | +#include "llvm/IR/LLVMContext.h" |
| 17 | +#include "llvm/IR/Type.h" |
15 | 18 | #include "llvm/Pass.h"
|
16 | 19 |
|
17 | 20 | namespace llvm {
|
@@ -95,11 +98,78 @@ inline raw_ostream &operator<<(raw_ostream &OS, const ArgDescriptor &Arg) {
|
95 | 98 | return OS;
|
96 | 99 | }
|
97 | 100 |
|
98 |
| -struct KernArgPreloadDescriptor : public ArgDescriptor { |
99 |
| - KernArgPreloadDescriptor() {} |
100 |
| - SmallVector<MCRegister> Regs; |
| 101 | +namespace KernArgPreload { |
| 102 | + |
| 103 | +enum HiddenArg { |
| 104 | + HIDDEN_BLOCK_COUNT_X, |
| 105 | + HIDDEN_BLOCK_COUNT_Y, |
| 106 | + HIDDEN_BLOCK_COUNT_Z, |
| 107 | + HIDDEN_GROUP_SIZE_X, |
| 108 | + HIDDEN_GROUP_SIZE_Y, |
| 109 | + HIDDEN_GROUP_SIZE_Z, |
| 110 | + HIDDEN_REMAINDER_X, |
| 111 | + HIDDEN_REMAINDER_Y, |
| 112 | + HIDDEN_REMAINDER_Z, |
| 113 | + END_HIDDEN_ARGS |
101 | 114 | };
|
102 | 115 |
|
| 116 | +// Stores information about a specific hidden argument. |
| 117 | +struct HiddenArgInfo { |
| 118 | + // Offset in bytes from the location in the kernearg segment pointed to by |
| 119 | + // the implicitarg pointer. |
| 120 | + uint8_t Offset; |
| 121 | + // The size of the hidden argument in bytes. |
| 122 | + uint8_t Size; |
| 123 | + // The name of the hidden argument in the kernel signature. |
| 124 | + const char *Name; |
| 125 | +}; |
| 126 | + |
| 127 | +struct HiddenArgUtils { |
| 128 | + static constexpr HiddenArgInfo HiddenArgs[END_HIDDEN_ARGS] = { |
| 129 | + {0, 4, "_hidden_block_count_x"}, {4, 4, "_hidden_block_count_y"}, |
| 130 | + {8, 4, "_hidden_block_count_z"}, {12, 2, "_hidden_group_size_x"}, |
| 131 | + {14, 2, "_hidden_group_size_y"}, {16, 2, "_hidden_group_size_z"}, |
| 132 | + {18, 2, "_hidden_remainder_x"}, {20, 2, "_hidden_remainder_y"}, |
| 133 | + {22, 2, "_hidden_remainder_z"}}; |
| 134 | + |
| 135 | + static HiddenArg getHiddenArgFromOffset(unsigned Offset) { |
| 136 | + for (unsigned I = 0; I < END_HIDDEN_ARGS; ++I) |
| 137 | + if (HiddenArgs[I].Offset == Offset) |
| 138 | + return static_cast<HiddenArg>(I); |
| 139 | + |
| 140 | + return END_HIDDEN_ARGS; |
| 141 | + } |
| 142 | + |
| 143 | + static Type *getHiddenArgType(LLVMContext &Ctx, HiddenArg HA) { |
| 144 | + if (HA < END_HIDDEN_ARGS) |
| 145 | + return static_cast<Type *>(Type::getIntNTy(Ctx, HiddenArgs[HA].Size * 8)); |
| 146 | + |
| 147 | + llvm_unreachable("Unexpected hidden argument."); |
| 148 | + } |
| 149 | + |
| 150 | + static const char *getHiddenArgName(HiddenArg HA) { |
| 151 | + if (HA < END_HIDDEN_ARGS) { |
| 152 | + return HiddenArgs[HA].Name; |
| 153 | + } |
| 154 | + llvm_unreachable("Unexpected hidden argument."); |
| 155 | + } |
| 156 | +}; |
| 157 | + |
| 158 | +struct KernArgPreloadDescriptor { |
| 159 | + // Id of the original argument in the IR kernel function argument list. |
| 160 | + unsigned OrigArgIdx = 0; |
| 161 | + |
| 162 | + // If this IR argument was split into multiple parts, this is the index of the |
| 163 | + // part in the original argument. |
| 164 | + unsigned PartIdx = 0; |
| 165 | + |
| 166 | + // The registers that the argument is preloaded into. The argument may be |
| 167 | + // split accross multilpe registers. |
| 168 | + SmallVector<MCRegister, 2> Regs; |
| 169 | +}; |
| 170 | + |
| 171 | +} // namespace KernArgPreload |
| 172 | + |
103 | 173 | struct AMDGPUFunctionArgInfo {
|
104 | 174 | // clang-format off
|
105 | 175 | enum PreloadedValue {
|
@@ -161,14 +231,27 @@ struct AMDGPUFunctionArgInfo {
|
161 | 231 | ArgDescriptor WorkItemIDZ;
|
162 | 232 |
|
163 | 233 | // Map the index of preloaded kernel arguments to its descriptor.
|
164 |
| - SmallDenseMap<int, KernArgPreloadDescriptor> PreloadKernArgs{}; |
| 234 | + SmallDenseMap<int, KernArgPreload::KernArgPreloadDescriptor> |
| 235 | + PreloadKernArgs{}; |
| 236 | + // Map hidden argument to the index of it's descriptor. |
| 237 | + SmallDenseMap<KernArgPreload::HiddenArg, int> PreloadHiddenArgsIndexMap{}; |
165 | 238 | // The first user SGPR allocated for kernarg preloading.
|
166 | 239 | Register FirstKernArgPreloadReg;
|
167 | 240 |
|
168 | 241 | std::tuple<const ArgDescriptor *, const TargetRegisterClass *, LLT>
|
169 | 242 | getPreloadedValue(PreloadedValue Value) const;
|
170 | 243 |
|
171 | 244 | static AMDGPUFunctionArgInfo fixedABILayout();
|
| 245 | + |
| 246 | + // Returns preload argument descriptors for an IR argument index. Isel may |
| 247 | + // split IR arguments into multiple parts, the return vector holds all parts |
| 248 | + // associated with an IR argument in the kernel signature. |
| 249 | + SmallVector<const KernArgPreload::KernArgPreloadDescriptor *, 4> |
| 250 | + getPreloadDescriptorsForArgIdx(unsigned ArgIdx) const; |
| 251 | + |
| 252 | + // Returns the hidden arguments `KernArgPreloadDescriptor` if it is preloaded. |
| 253 | + std::optional<const KernArgPreload::KernArgPreloadDescriptor *> |
| 254 | + getHiddenArgPreloadDescriptor(KernArgPreload::HiddenArg HA) const; |
172 | 255 | };
|
173 | 256 |
|
174 | 257 | class AMDGPUArgumentUsageInfo : public ImmutablePass {
|
|
0 commit comments