xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/AMDGPU/AMDGPUArgumentUsageInfo.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
10b57cec5SDimitry Andric //==- AMDGPUArgumentrUsageInfo.h - Function Arg Usage Info -------*- C++ -*-==//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H
100b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_AMDGPUARGUMENTUSAGEINFO_H
110b57cec5SDimitry Andric 
125f757f3fSDimitry Andric #include "llvm/ADT/DenseMap.h"
130b57cec5SDimitry Andric #include "llvm/CodeGen/Register.h"
140b57cec5SDimitry Andric #include "llvm/Pass.h"
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric namespace llvm {
170b57cec5SDimitry Andric 
180b57cec5SDimitry Andric class Function;
19e8d8bef9SDimitry Andric class LLT;
200b57cec5SDimitry Andric class raw_ostream;
210b57cec5SDimitry Andric class TargetRegisterClass;
220b57cec5SDimitry Andric class TargetRegisterInfo;
230b57cec5SDimitry Andric 
240b57cec5SDimitry Andric struct ArgDescriptor {
250b57cec5SDimitry Andric private:
260b57cec5SDimitry Andric   friend struct AMDGPUFunctionArgInfo;
270b57cec5SDimitry Andric   friend class AMDGPUArgumentUsageInfo;
280b57cec5SDimitry Andric 
290b57cec5SDimitry Andric   union {
30e8d8bef9SDimitry Andric     MCRegister Reg;
310b57cec5SDimitry Andric     unsigned StackOffset;
320b57cec5SDimitry Andric   };
330b57cec5SDimitry Andric 
340b57cec5SDimitry Andric   // Bitmask to locate argument within the register.
350b57cec5SDimitry Andric   unsigned Mask;
360b57cec5SDimitry Andric 
370b57cec5SDimitry Andric   bool IsStack : 1;
380b57cec5SDimitry Andric   bool IsSet : 1;
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric public:
415f757f3fSDimitry Andric   ArgDescriptor(unsigned Val = 0, unsigned Mask = ~0u, bool IsStack = false,
425f757f3fSDimitry Andric                 bool IsSet = false)
430b57cec5SDimitry Andric       : Reg(Val), Mask(Mask), IsStack(IsStack), IsSet(IsSet) {}
440b57cec5SDimitry Andric 
455f757f3fSDimitry Andric   static ArgDescriptor createRegister(Register Reg, unsigned Mask = ~0u) {
460b57cec5SDimitry Andric     return ArgDescriptor(Reg, Mask, false, true);
470b57cec5SDimitry Andric   }
480b57cec5SDimitry Andric 
495f757f3fSDimitry Andric   static ArgDescriptor createStack(unsigned Offset, unsigned Mask = ~0u) {
508bcb0991SDimitry Andric     return ArgDescriptor(Offset, Mask, true, true);
510b57cec5SDimitry Andric   }
520b57cec5SDimitry Andric 
535f757f3fSDimitry Andric   static ArgDescriptor createArg(const ArgDescriptor &Arg, unsigned Mask) {
540b57cec5SDimitry Andric     return ArgDescriptor(Arg.Reg, Mask, Arg.IsStack, Arg.IsSet);
550b57cec5SDimitry Andric   }
560b57cec5SDimitry Andric 
570b57cec5SDimitry Andric   bool isSet() const {
580b57cec5SDimitry Andric     return IsSet;
590b57cec5SDimitry Andric   }
600b57cec5SDimitry Andric 
610b57cec5SDimitry Andric   explicit operator bool() const {
620b57cec5SDimitry Andric     return isSet();
630b57cec5SDimitry Andric   }
640b57cec5SDimitry Andric 
650b57cec5SDimitry Andric   bool isRegister() const {
660b57cec5SDimitry Andric     return !IsStack;
670b57cec5SDimitry Andric   }
680b57cec5SDimitry Andric 
69e8d8bef9SDimitry Andric   MCRegister getRegister() const {
700b57cec5SDimitry Andric     assert(!IsStack);
710b57cec5SDimitry Andric     return Reg;
720b57cec5SDimitry Andric   }
730b57cec5SDimitry Andric 
740b57cec5SDimitry Andric   unsigned getStackOffset() const {
750b57cec5SDimitry Andric     assert(IsStack);
760b57cec5SDimitry Andric     return StackOffset;
770b57cec5SDimitry Andric   }
780b57cec5SDimitry Andric 
790b57cec5SDimitry Andric   unsigned getMask() const {
800b57cec5SDimitry Andric     return Mask;
810b57cec5SDimitry Andric   }
820b57cec5SDimitry Andric 
830b57cec5SDimitry Andric   bool isMasked() const {
840b57cec5SDimitry Andric     return Mask != ~0u;
850b57cec5SDimitry Andric   }
860b57cec5SDimitry Andric 
870b57cec5SDimitry Andric   void print(raw_ostream &OS, const TargetRegisterInfo *TRI = nullptr) const;
880b57cec5SDimitry Andric };
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric inline raw_ostream &operator<<(raw_ostream &OS, const ArgDescriptor &Arg) {
910b57cec5SDimitry Andric   Arg.print(OS);
920b57cec5SDimitry Andric   return OS;
930b57cec5SDimitry Andric }
940b57cec5SDimitry Andric 
955f757f3fSDimitry Andric struct KernArgPreloadDescriptor : public ArgDescriptor {
965f757f3fSDimitry Andric   KernArgPreloadDescriptor() {}
975f757f3fSDimitry Andric   SmallVector<MCRegister> Regs;
985f757f3fSDimitry Andric };
995f757f3fSDimitry Andric 
1000b57cec5SDimitry Andric struct AMDGPUFunctionArgInfo {
1015f757f3fSDimitry Andric   // clang-format off
1020b57cec5SDimitry Andric   enum PreloadedValue {
1030b57cec5SDimitry Andric     // SGPRS:
1040b57cec5SDimitry Andric     PRIVATE_SEGMENT_BUFFER = 0,
1050b57cec5SDimitry Andric     DISPATCH_PTR        =  1,
1060b57cec5SDimitry Andric     QUEUE_PTR           =  2,
1070b57cec5SDimitry Andric     KERNARG_SEGMENT_PTR =  3,
1080b57cec5SDimitry Andric     DISPATCH_ID         =  4,
1090b57cec5SDimitry Andric     FLAT_SCRATCH_INIT   =  5,
110fcaf7f86SDimitry Andric     LDS_KERNEL_ID       =  6, // LLVM internal, not part of the ABI
1110b57cec5SDimitry Andric     WORKGROUP_ID_X      = 10,
1120b57cec5SDimitry Andric     WORKGROUP_ID_Y      = 11,
1130b57cec5SDimitry Andric     WORKGROUP_ID_Z      = 12,
1140b57cec5SDimitry Andric     PRIVATE_SEGMENT_WAVE_BYTE_OFFSET = 14,
1150b57cec5SDimitry Andric     IMPLICIT_BUFFER_PTR = 15,
1160b57cec5SDimitry Andric     IMPLICIT_ARG_PTR = 16,
117*0fca6ea1SDimitry Andric     PRIVATE_SEGMENT_SIZE = 17,
1180b57cec5SDimitry Andric 
1190b57cec5SDimitry Andric     // VGPRS:
120*0fca6ea1SDimitry Andric     WORKITEM_ID_X       = 18,
121*0fca6ea1SDimitry Andric     WORKITEM_ID_Y       = 19,
122*0fca6ea1SDimitry Andric     WORKITEM_ID_Z       = 20,
1230b57cec5SDimitry Andric     FIRST_VGPR_VALUE    = WORKITEM_ID_X
1240b57cec5SDimitry Andric   };
1255f757f3fSDimitry Andric   // clang-format on
1260b57cec5SDimitry Andric 
1270b57cec5SDimitry Andric   // Kernel input registers setup for the HSA ABI in allocation order.
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   // User SGPRs in kernels
1300b57cec5SDimitry Andric   // XXX - Can these require argument spills?
1310b57cec5SDimitry Andric   ArgDescriptor PrivateSegmentBuffer;
1320b57cec5SDimitry Andric   ArgDescriptor DispatchPtr;
1330b57cec5SDimitry Andric   ArgDescriptor QueuePtr;
1340b57cec5SDimitry Andric   ArgDescriptor KernargSegmentPtr;
1350b57cec5SDimitry Andric   ArgDescriptor DispatchID;
1360b57cec5SDimitry Andric   ArgDescriptor FlatScratchInit;
1370b57cec5SDimitry Andric   ArgDescriptor PrivateSegmentSize;
138fcaf7f86SDimitry Andric   ArgDescriptor LDSKernelId;
1390b57cec5SDimitry Andric 
1400b57cec5SDimitry Andric   // System SGPRs in kernels.
1410b57cec5SDimitry Andric   ArgDescriptor WorkGroupIDX;
1420b57cec5SDimitry Andric   ArgDescriptor WorkGroupIDY;
1430b57cec5SDimitry Andric   ArgDescriptor WorkGroupIDZ;
1440b57cec5SDimitry Andric   ArgDescriptor WorkGroupInfo;
1450b57cec5SDimitry Andric   ArgDescriptor PrivateSegmentWaveByteOffset;
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   // Pointer with offset from kernargsegmentptr to where special ABI arguments
1480b57cec5SDimitry Andric   // are passed to callable functions.
1490b57cec5SDimitry Andric   ArgDescriptor ImplicitArgPtr;
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric   // Input registers for non-HSA ABI
1525ffd83dbSDimitry Andric   ArgDescriptor ImplicitBufferPtr;
1530b57cec5SDimitry Andric 
154fe6060f1SDimitry Andric   // VGPRs inputs. For entry functions these are either v0, v1 and v2 or packed
155fe6060f1SDimitry Andric   // into v0, 10 bits per dimension if packed-tid is set.
1560b57cec5SDimitry Andric   ArgDescriptor WorkItemIDX;
1570b57cec5SDimitry Andric   ArgDescriptor WorkItemIDY;
1580b57cec5SDimitry Andric   ArgDescriptor WorkItemIDZ;
1590b57cec5SDimitry Andric 
1605f757f3fSDimitry Andric   // Map the index of preloaded kernel arguments to its descriptor.
1615f757f3fSDimitry Andric   SmallDenseMap<int, KernArgPreloadDescriptor> PreloadKernArgs{};
1625f757f3fSDimitry Andric 
1635ffd83dbSDimitry Andric   std::tuple<const ArgDescriptor *, const TargetRegisterClass *, LLT>
1640b57cec5SDimitry Andric   getPreloadedValue(PreloadedValue Value) const;
1655ffd83dbSDimitry Andric 
1665f757f3fSDimitry Andric   static AMDGPUFunctionArgInfo fixedABILayout();
1670b57cec5SDimitry Andric };
1680b57cec5SDimitry Andric 
1690b57cec5SDimitry Andric class AMDGPUArgumentUsageInfo : public ImmutablePass {
1700b57cec5SDimitry Andric private:
1710b57cec5SDimitry Andric   DenseMap<const Function *, AMDGPUFunctionArgInfo> ArgInfoMap;
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric public:
1740b57cec5SDimitry Andric   static char ID;
1750b57cec5SDimitry Andric 
1765ffd83dbSDimitry Andric   static const AMDGPUFunctionArgInfo ExternFunctionInfo;
1775ffd83dbSDimitry Andric   static const AMDGPUFunctionArgInfo FixedABIFunctionInfo;
1785ffd83dbSDimitry Andric 
1790b57cec5SDimitry Andric   AMDGPUArgumentUsageInfo() : ImmutablePass(ID) { }
1800b57cec5SDimitry Andric 
1810b57cec5SDimitry Andric   void getAnalysisUsage(AnalysisUsage &AU) const override {
1820b57cec5SDimitry Andric     AU.setPreservesAll();
1830b57cec5SDimitry Andric   }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   bool doInitialization(Module &M) override;
1860b57cec5SDimitry Andric   bool doFinalization(Module &M) override;
1870b57cec5SDimitry Andric 
1880b57cec5SDimitry Andric   void print(raw_ostream &OS, const Module *M = nullptr) const override;
1890b57cec5SDimitry Andric 
1900b57cec5SDimitry Andric   void setFuncArgInfo(const Function &F, const AMDGPUFunctionArgInfo &ArgInfo) {
1910b57cec5SDimitry Andric     ArgInfoMap[&F] = ArgInfo;
1920b57cec5SDimitry Andric   }
1930b57cec5SDimitry Andric 
1945ffd83dbSDimitry Andric   const AMDGPUFunctionArgInfo &lookupFuncArgInfo(const Function &F) const;
1950b57cec5SDimitry Andric };
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric } // end namespace llvm
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric #endif
200