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