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