1 //==- AMDGPUArgumentrUsageInfo.h - Function Arg Usage Info -------*- C++ -*-==// 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 #ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H 10 #define LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H 11 12 #include "llvm/ADT/DenseMap.h" 13 #include "llvm/CodeGen/Register.h" 14 #include "llvm/Pass.h" 15 #include "llvm/Support/LowLevelTypeImpl.h" 16 17 namespace llvm { 18 19 class Function; 20 class raw_ostream; 21 class TargetRegisterClass; 22 class TargetRegisterInfo; 23 24 struct ArgDescriptor { 25 private: 26 friend struct AMDGPUFunctionArgInfo; 27 friend class AMDGPUArgumentUsageInfo; 28 29 union { 30 Register Reg; 31 unsigned StackOffset; 32 }; 33 34 // Bitmask to locate argument within the register. 35 unsigned Mask; 36 37 bool IsStack : 1; 38 bool IsSet : 1; 39 40 public: 41 constexpr ArgDescriptor(unsigned Val = 0, unsigned Mask = ~0u, 42 bool IsStack = false, bool IsSet = false) 43 : Reg(Val), Mask(Mask), IsStack(IsStack), IsSet(IsSet) {} 44 45 static constexpr ArgDescriptor createRegister(Register Reg, 46 unsigned Mask = ~0u) { 47 return ArgDescriptor(Reg, Mask, false, true); 48 } 49 50 static constexpr ArgDescriptor createStack(unsigned Offset, 51 unsigned Mask = ~0u) { 52 return ArgDescriptor(Offset, Mask, true, true); 53 } 54 55 static constexpr ArgDescriptor createArg(const ArgDescriptor &Arg, 56 unsigned Mask) { 57 return ArgDescriptor(Arg.Reg, Mask, Arg.IsStack, Arg.IsSet); 58 } 59 60 bool isSet() const { 61 return IsSet; 62 } 63 64 explicit operator bool() const { 65 return isSet(); 66 } 67 68 bool isRegister() const { 69 return !IsStack; 70 } 71 72 Register getRegister() const { 73 assert(!IsStack); 74 return Reg; 75 } 76 77 unsigned getStackOffset() const { 78 assert(IsStack); 79 return StackOffset; 80 } 81 82 unsigned getMask() const { 83 return Mask; 84 } 85 86 bool isMasked() const { 87 return Mask != ~0u; 88 } 89 90 void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr) const; 91 }; 92 93 inline raw_ostream &operator<<(raw_ostream &OS, const ArgDescriptor &Arg) { 94 Arg.print(OS); 95 return OS; 96 } 97 98 struct AMDGPUFunctionArgInfo { 99 enum PreloadedValue { 100 // SGPRS: 101 PRIVATE_SEGMENT_BUFFER = 0, 102 DISPATCH_PTR = 1, 103 QUEUE_PTR = 2, 104 KERNARG_SEGMENT_PTR = 3, 105 DISPATCH_ID = 4, 106 FLAT_SCRATCH_INIT = 5, 107 WORKGROUP_ID_X = 10, 108 WORKGROUP_ID_Y = 11, 109 WORKGROUP_ID_Z = 12, 110 PRIVATE_SEGMENT_WAVE_BYTE_OFFSET = 14, 111 IMPLICIT_BUFFER_PTR = 15, 112 IMPLICIT_ARG_PTR = 16, 113 114 // VGPRS: 115 WORKITEM_ID_X = 17, 116 WORKITEM_ID_Y = 18, 117 WORKITEM_ID_Z = 19, 118 FIRST_VGPR_VALUE = WORKITEM_ID_X 119 }; 120 121 // Kernel input registers setup for the HSA ABI in allocation order. 122 123 // User SGPRs in kernels 124 // XXX - Can these require argument spills? 125 ArgDescriptor PrivateSegmentBuffer; 126 ArgDescriptor DispatchPtr; 127 ArgDescriptor QueuePtr; 128 ArgDescriptor KernargSegmentPtr; 129 ArgDescriptor DispatchID; 130 ArgDescriptor FlatScratchInit; 131 ArgDescriptor PrivateSegmentSize; 132 133 // System SGPRs in kernels. 134 ArgDescriptor WorkGroupIDX; 135 ArgDescriptor WorkGroupIDY; 136 ArgDescriptor WorkGroupIDZ; 137 ArgDescriptor WorkGroupInfo; 138 ArgDescriptor PrivateSegmentWaveByteOffset; 139 140 // Pointer with offset from kernargsegmentptr to where special ABI arguments 141 // are passed to callable functions. 142 ArgDescriptor ImplicitArgPtr; 143 144 // Input registers for non-HSA ABI 145 ArgDescriptor ImplicitBufferPtr; 146 147 // VGPRs inputs. These are always v0, v1 and v2 for entry functions. 148 ArgDescriptor WorkItemIDX; 149 ArgDescriptor WorkItemIDY; 150 ArgDescriptor WorkItemIDZ; 151 152 std::tuple<const ArgDescriptor *, const TargetRegisterClass *, LLT> 153 getPreloadedValue(PreloadedValue Value) const; 154 155 static constexpr AMDGPUFunctionArgInfo fixedABILayout(); 156 }; 157 158 class AMDGPUArgumentUsageInfo : public ImmutablePass { 159 private: 160 DenseMap<const Function *, AMDGPUFunctionArgInfo> ArgInfoMap; 161 162 public: 163 static char ID; 164 165 static const AMDGPUFunctionArgInfo ExternFunctionInfo; 166 static const AMDGPUFunctionArgInfo FixedABIFunctionInfo; 167 168 AMDGPUArgumentUsageInfo() : ImmutablePass(ID) { } 169 170 void getAnalysisUsage(AnalysisUsage &AU) const override { 171 AU.setPreservesAll(); 172 } 173 174 bool doInitialization(Module &M) override; 175 bool doFinalization(Module &M) override; 176 177 void print(raw_ostream &OS, const Module *M = nullptr) const override; 178 179 void setFuncArgInfo(const Function &F, const AMDGPUFunctionArgInfo &ArgInfo) { 180 ArgInfoMap[&F] = ArgInfo; 181 } 182 183 const AMDGPUFunctionArgInfo &lookupFuncArgInfo(const Function &F) const; 184 }; 185 186 } // end namespace llvm 187 188 #endif 189