10b57cec5SDimitry Andric //==- SIMachineFunctionInfo.h - SIMachineFunctionInfo interface --*- 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 /// \file 100b57cec5SDimitry Andric // 110b57cec5SDimitry Andric //===----------------------------------------------------------------------===// 120b57cec5SDimitry Andric 130b57cec5SDimitry Andric #ifndef LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 140b57cec5SDimitry Andric #define LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 150b57cec5SDimitry Andric 160b57cec5SDimitry Andric #include "AMDGPUArgumentUsageInfo.h" 170b57cec5SDimitry Andric #include "AMDGPUMachineFunction.h" 180b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 190b57cec5SDimitry Andric #include "SIInstrInfo.h" 20fe6060f1SDimitry Andric #include "llvm/ADT/MapVector.h" 210b57cec5SDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h" 220b57cec5SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h" 23e8d8bef9SDimitry Andric #include "llvm/Support/raw_ostream.h" 240b57cec5SDimitry Andric 250b57cec5SDimitry Andric namespace llvm { 260b57cec5SDimitry Andric 270b57cec5SDimitry Andric class MachineFrameInfo; 280b57cec5SDimitry Andric class MachineFunction; 29e8d8bef9SDimitry Andric class SIMachineFunctionInfo; 30e8d8bef9SDimitry Andric class SIRegisterInfo; 31349cc55cSDimitry Andric class TargetRegisterClass; 320b57cec5SDimitry Andric 330b57cec5SDimitry Andric class AMDGPUPseudoSourceValue : public PseudoSourceValue { 340b57cec5SDimitry Andric public: 350b57cec5SDimitry Andric enum AMDGPUPSVKind : unsigned { 360b57cec5SDimitry Andric PSVBuffer = PseudoSourceValue::TargetCustom, 370b57cec5SDimitry Andric PSVImage, 380b57cec5SDimitry Andric GWSResource 390b57cec5SDimitry Andric }; 400b57cec5SDimitry Andric 410b57cec5SDimitry Andric protected: 420b57cec5SDimitry Andric AMDGPUPseudoSourceValue(unsigned Kind, const TargetInstrInfo &TII) 430b57cec5SDimitry Andric : PseudoSourceValue(Kind, TII) {} 440b57cec5SDimitry Andric 450b57cec5SDimitry Andric public: 460b57cec5SDimitry Andric bool isConstant(const MachineFrameInfo *) const override { 470b57cec5SDimitry Andric // This should probably be true for most images, but we will start by being 480b57cec5SDimitry Andric // conservative. 490b57cec5SDimitry Andric return false; 500b57cec5SDimitry Andric } 510b57cec5SDimitry Andric 520b57cec5SDimitry Andric bool isAliased(const MachineFrameInfo *) const override { 530b57cec5SDimitry Andric return true; 540b57cec5SDimitry Andric } 550b57cec5SDimitry Andric 560b57cec5SDimitry Andric bool mayAlias(const MachineFrameInfo *) const override { 570b57cec5SDimitry Andric return true; 580b57cec5SDimitry Andric } 590b57cec5SDimitry Andric }; 600b57cec5SDimitry Andric 610b57cec5SDimitry Andric class AMDGPUBufferPseudoSourceValue final : public AMDGPUPseudoSourceValue { 620b57cec5SDimitry Andric public: 630b57cec5SDimitry Andric explicit AMDGPUBufferPseudoSourceValue(const TargetInstrInfo &TII) 640b57cec5SDimitry Andric : AMDGPUPseudoSourceValue(PSVBuffer, TII) {} 650b57cec5SDimitry Andric 660b57cec5SDimitry Andric static bool classof(const PseudoSourceValue *V) { 670b57cec5SDimitry Andric return V->kind() == PSVBuffer; 680b57cec5SDimitry Andric } 69e8d8bef9SDimitry Andric 70e8d8bef9SDimitry Andric void printCustom(raw_ostream &OS) const override { OS << "BufferResource"; } 710b57cec5SDimitry Andric }; 720b57cec5SDimitry Andric 730b57cec5SDimitry Andric class AMDGPUImagePseudoSourceValue final : public AMDGPUPseudoSourceValue { 740b57cec5SDimitry Andric public: 750b57cec5SDimitry Andric // TODO: Is the img rsrc useful? 760b57cec5SDimitry Andric explicit AMDGPUImagePseudoSourceValue(const TargetInstrInfo &TII) 770b57cec5SDimitry Andric : AMDGPUPseudoSourceValue(PSVImage, TII) {} 780b57cec5SDimitry Andric 790b57cec5SDimitry Andric static bool classof(const PseudoSourceValue *V) { 800b57cec5SDimitry Andric return V->kind() == PSVImage; 810b57cec5SDimitry Andric } 82e8d8bef9SDimitry Andric 83e8d8bef9SDimitry Andric void printCustom(raw_ostream &OS) const override { OS << "ImageResource"; } 840b57cec5SDimitry Andric }; 850b57cec5SDimitry Andric 860b57cec5SDimitry Andric class AMDGPUGWSResourcePseudoSourceValue final : public AMDGPUPseudoSourceValue { 870b57cec5SDimitry Andric public: 880b57cec5SDimitry Andric explicit AMDGPUGWSResourcePseudoSourceValue(const TargetInstrInfo &TII) 890b57cec5SDimitry Andric : AMDGPUPseudoSourceValue(GWSResource, TII) {} 900b57cec5SDimitry Andric 910b57cec5SDimitry Andric static bool classof(const PseudoSourceValue *V) { 920b57cec5SDimitry Andric return V->kind() == GWSResource; 930b57cec5SDimitry Andric } 940b57cec5SDimitry Andric 950b57cec5SDimitry Andric // These are inaccessible memory from IR. 960b57cec5SDimitry Andric bool isAliased(const MachineFrameInfo *) const override { 970b57cec5SDimitry Andric return false; 980b57cec5SDimitry Andric } 990b57cec5SDimitry Andric 1000b57cec5SDimitry Andric // These are inaccessible memory from IR. 1010b57cec5SDimitry Andric bool mayAlias(const MachineFrameInfo *) const override { 1020b57cec5SDimitry Andric return false; 1030b57cec5SDimitry Andric } 1040b57cec5SDimitry Andric 1050b57cec5SDimitry Andric void printCustom(raw_ostream &OS) const override { 1060b57cec5SDimitry Andric OS << "GWSResource"; 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric }; 1090b57cec5SDimitry Andric 1100b57cec5SDimitry Andric namespace yaml { 1110b57cec5SDimitry Andric 1120b57cec5SDimitry Andric struct SIArgument { 1130b57cec5SDimitry Andric bool IsRegister; 1140b57cec5SDimitry Andric union { 1150b57cec5SDimitry Andric StringValue RegisterName; 1160b57cec5SDimitry Andric unsigned StackOffset; 1170b57cec5SDimitry Andric }; 1180b57cec5SDimitry Andric Optional<unsigned> Mask; 1190b57cec5SDimitry Andric 1200b57cec5SDimitry Andric // Default constructor, which creates a stack argument. 1210b57cec5SDimitry Andric SIArgument() : IsRegister(false), StackOffset(0) {} 1220b57cec5SDimitry Andric SIArgument(const SIArgument &Other) { 1230b57cec5SDimitry Andric IsRegister = Other.IsRegister; 1240b57cec5SDimitry Andric if (IsRegister) { 1250b57cec5SDimitry Andric ::new ((void *)std::addressof(RegisterName)) 1260b57cec5SDimitry Andric StringValue(Other.RegisterName); 1270b57cec5SDimitry Andric } else 1280b57cec5SDimitry Andric StackOffset = Other.StackOffset; 1290b57cec5SDimitry Andric Mask = Other.Mask; 1300b57cec5SDimitry Andric } 1310b57cec5SDimitry Andric SIArgument &operator=(const SIArgument &Other) { 1320b57cec5SDimitry Andric IsRegister = Other.IsRegister; 1330b57cec5SDimitry Andric if (IsRegister) { 1340b57cec5SDimitry Andric ::new ((void *)std::addressof(RegisterName)) 1350b57cec5SDimitry Andric StringValue(Other.RegisterName); 1360b57cec5SDimitry Andric } else 1370b57cec5SDimitry Andric StackOffset = Other.StackOffset; 1380b57cec5SDimitry Andric Mask = Other.Mask; 1390b57cec5SDimitry Andric return *this; 1400b57cec5SDimitry Andric } 1410b57cec5SDimitry Andric ~SIArgument() { 1420b57cec5SDimitry Andric if (IsRegister) 1430b57cec5SDimitry Andric RegisterName.~StringValue(); 1440b57cec5SDimitry Andric } 1450b57cec5SDimitry Andric 1460b57cec5SDimitry Andric // Helper to create a register or stack argument. 1470b57cec5SDimitry Andric static inline SIArgument createArgument(bool IsReg) { 1480b57cec5SDimitry Andric if (IsReg) 1490b57cec5SDimitry Andric return SIArgument(IsReg); 1500b57cec5SDimitry Andric return SIArgument(); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric 1530b57cec5SDimitry Andric private: 1540b57cec5SDimitry Andric // Construct a register argument. 1550b57cec5SDimitry Andric SIArgument(bool) : IsRegister(true), RegisterName() {} 1560b57cec5SDimitry Andric }; 1570b57cec5SDimitry Andric 1580b57cec5SDimitry Andric template <> struct MappingTraits<SIArgument> { 1590b57cec5SDimitry Andric static void mapping(IO &YamlIO, SIArgument &A) { 1600b57cec5SDimitry Andric if (YamlIO.outputting()) { 1610b57cec5SDimitry Andric if (A.IsRegister) 1620b57cec5SDimitry Andric YamlIO.mapRequired("reg", A.RegisterName); 1630b57cec5SDimitry Andric else 1640b57cec5SDimitry Andric YamlIO.mapRequired("offset", A.StackOffset); 1650b57cec5SDimitry Andric } else { 1660b57cec5SDimitry Andric auto Keys = YamlIO.keys(); 1670b57cec5SDimitry Andric if (is_contained(Keys, "reg")) { 1680b57cec5SDimitry Andric A = SIArgument::createArgument(true); 1690b57cec5SDimitry Andric YamlIO.mapRequired("reg", A.RegisterName); 1700b57cec5SDimitry Andric } else if (is_contained(Keys, "offset")) 1710b57cec5SDimitry Andric YamlIO.mapRequired("offset", A.StackOffset); 1720b57cec5SDimitry Andric else 1730b57cec5SDimitry Andric YamlIO.setError("missing required key 'reg' or 'offset'"); 1740b57cec5SDimitry Andric } 1750b57cec5SDimitry Andric YamlIO.mapOptional("mask", A.Mask); 1760b57cec5SDimitry Andric } 1770b57cec5SDimitry Andric static const bool flow = true; 1780b57cec5SDimitry Andric }; 1790b57cec5SDimitry Andric 1800b57cec5SDimitry Andric struct SIArgumentInfo { 1810b57cec5SDimitry Andric Optional<SIArgument> PrivateSegmentBuffer; 1820b57cec5SDimitry Andric Optional<SIArgument> DispatchPtr; 1830b57cec5SDimitry Andric Optional<SIArgument> QueuePtr; 1840b57cec5SDimitry Andric Optional<SIArgument> KernargSegmentPtr; 1850b57cec5SDimitry Andric Optional<SIArgument> DispatchID; 1860b57cec5SDimitry Andric Optional<SIArgument> FlatScratchInit; 1870b57cec5SDimitry Andric Optional<SIArgument> PrivateSegmentSize; 1880b57cec5SDimitry Andric 1890b57cec5SDimitry Andric Optional<SIArgument> WorkGroupIDX; 1900b57cec5SDimitry Andric Optional<SIArgument> WorkGroupIDY; 1910b57cec5SDimitry Andric Optional<SIArgument> WorkGroupIDZ; 1920b57cec5SDimitry Andric Optional<SIArgument> WorkGroupInfo; 1930b57cec5SDimitry Andric Optional<SIArgument> PrivateSegmentWaveByteOffset; 1940b57cec5SDimitry Andric 1950b57cec5SDimitry Andric Optional<SIArgument> ImplicitArgPtr; 1960b57cec5SDimitry Andric Optional<SIArgument> ImplicitBufferPtr; 1970b57cec5SDimitry Andric 1980b57cec5SDimitry Andric Optional<SIArgument> WorkItemIDX; 1990b57cec5SDimitry Andric Optional<SIArgument> WorkItemIDY; 2000b57cec5SDimitry Andric Optional<SIArgument> WorkItemIDZ; 2010b57cec5SDimitry Andric }; 2020b57cec5SDimitry Andric 2030b57cec5SDimitry Andric template <> struct MappingTraits<SIArgumentInfo> { 2040b57cec5SDimitry Andric static void mapping(IO &YamlIO, SIArgumentInfo &AI) { 2050b57cec5SDimitry Andric YamlIO.mapOptional("privateSegmentBuffer", AI.PrivateSegmentBuffer); 2060b57cec5SDimitry Andric YamlIO.mapOptional("dispatchPtr", AI.DispatchPtr); 2070b57cec5SDimitry Andric YamlIO.mapOptional("queuePtr", AI.QueuePtr); 2080b57cec5SDimitry Andric YamlIO.mapOptional("kernargSegmentPtr", AI.KernargSegmentPtr); 2090b57cec5SDimitry Andric YamlIO.mapOptional("dispatchID", AI.DispatchID); 2100b57cec5SDimitry Andric YamlIO.mapOptional("flatScratchInit", AI.FlatScratchInit); 2110b57cec5SDimitry Andric YamlIO.mapOptional("privateSegmentSize", AI.PrivateSegmentSize); 2120b57cec5SDimitry Andric 2130b57cec5SDimitry Andric YamlIO.mapOptional("workGroupIDX", AI.WorkGroupIDX); 2140b57cec5SDimitry Andric YamlIO.mapOptional("workGroupIDY", AI.WorkGroupIDY); 2150b57cec5SDimitry Andric YamlIO.mapOptional("workGroupIDZ", AI.WorkGroupIDZ); 2160b57cec5SDimitry Andric YamlIO.mapOptional("workGroupInfo", AI.WorkGroupInfo); 2170b57cec5SDimitry Andric YamlIO.mapOptional("privateSegmentWaveByteOffset", 2180b57cec5SDimitry Andric AI.PrivateSegmentWaveByteOffset); 2190b57cec5SDimitry Andric 2200b57cec5SDimitry Andric YamlIO.mapOptional("implicitArgPtr", AI.ImplicitArgPtr); 2210b57cec5SDimitry Andric YamlIO.mapOptional("implicitBufferPtr", AI.ImplicitBufferPtr); 2220b57cec5SDimitry Andric 2230b57cec5SDimitry Andric YamlIO.mapOptional("workItemIDX", AI.WorkItemIDX); 2240b57cec5SDimitry Andric YamlIO.mapOptional("workItemIDY", AI.WorkItemIDY); 2250b57cec5SDimitry Andric YamlIO.mapOptional("workItemIDZ", AI.WorkItemIDZ); 2260b57cec5SDimitry Andric } 2270b57cec5SDimitry Andric }; 2280b57cec5SDimitry Andric 2290b57cec5SDimitry Andric // Default to default mode for default calling convention. 2300b57cec5SDimitry Andric struct SIMode { 2310b57cec5SDimitry Andric bool IEEE = true; 2320b57cec5SDimitry Andric bool DX10Clamp = true; 2335ffd83dbSDimitry Andric bool FP32InputDenormals = true; 2345ffd83dbSDimitry Andric bool FP32OutputDenormals = true; 2355ffd83dbSDimitry Andric bool FP64FP16InputDenormals = true; 2365ffd83dbSDimitry Andric bool FP64FP16OutputDenormals = true; 2370b57cec5SDimitry Andric 2380b57cec5SDimitry Andric SIMode() = default; 2390b57cec5SDimitry Andric 2400b57cec5SDimitry Andric SIMode(const AMDGPU::SIModeRegisterDefaults &Mode) { 2410b57cec5SDimitry Andric IEEE = Mode.IEEE; 2420b57cec5SDimitry Andric DX10Clamp = Mode.DX10Clamp; 2435ffd83dbSDimitry Andric FP32InputDenormals = Mode.FP32InputDenormals; 2445ffd83dbSDimitry Andric FP32OutputDenormals = Mode.FP32OutputDenormals; 2455ffd83dbSDimitry Andric FP64FP16InputDenormals = Mode.FP64FP16InputDenormals; 2465ffd83dbSDimitry Andric FP64FP16OutputDenormals = Mode.FP64FP16OutputDenormals; 2470b57cec5SDimitry Andric } 2480b57cec5SDimitry Andric 2490b57cec5SDimitry Andric bool operator ==(const SIMode Other) const { 250480093f4SDimitry Andric return IEEE == Other.IEEE && 251480093f4SDimitry Andric DX10Clamp == Other.DX10Clamp && 2525ffd83dbSDimitry Andric FP32InputDenormals == Other.FP32InputDenormals && 2535ffd83dbSDimitry Andric FP32OutputDenormals == Other.FP32OutputDenormals && 2545ffd83dbSDimitry Andric FP64FP16InputDenormals == Other.FP64FP16InputDenormals && 2555ffd83dbSDimitry Andric FP64FP16OutputDenormals == Other.FP64FP16OutputDenormals; 2560b57cec5SDimitry Andric } 2570b57cec5SDimitry Andric }; 2580b57cec5SDimitry Andric 2590b57cec5SDimitry Andric template <> struct MappingTraits<SIMode> { 2600b57cec5SDimitry Andric static void mapping(IO &YamlIO, SIMode &Mode) { 2610b57cec5SDimitry Andric YamlIO.mapOptional("ieee", Mode.IEEE, true); 2620b57cec5SDimitry Andric YamlIO.mapOptional("dx10-clamp", Mode.DX10Clamp, true); 2635ffd83dbSDimitry Andric YamlIO.mapOptional("fp32-input-denormals", Mode.FP32InputDenormals, true); 2645ffd83dbSDimitry Andric YamlIO.mapOptional("fp32-output-denormals", Mode.FP32OutputDenormals, true); 2655ffd83dbSDimitry Andric YamlIO.mapOptional("fp64-fp16-input-denormals", Mode.FP64FP16InputDenormals, true); 2665ffd83dbSDimitry Andric YamlIO.mapOptional("fp64-fp16-output-denormals", Mode.FP64FP16OutputDenormals, true); 2670b57cec5SDimitry Andric } 2680b57cec5SDimitry Andric }; 2690b57cec5SDimitry Andric 2700b57cec5SDimitry Andric struct SIMachineFunctionInfo final : public yaml::MachineFunctionInfo { 2710b57cec5SDimitry Andric uint64_t ExplicitKernArgSize = 0; 2720b57cec5SDimitry Andric unsigned MaxKernArgAlign = 0; 2730b57cec5SDimitry Andric unsigned LDSSize = 0; 274e8d8bef9SDimitry Andric Align DynLDSAlign; 2750b57cec5SDimitry Andric bool IsEntryFunction = false; 2760b57cec5SDimitry Andric bool NoSignedZerosFPMath = false; 2770b57cec5SDimitry Andric bool MemoryBound = false; 2780b57cec5SDimitry Andric bool WaveLimiter = false; 279e8d8bef9SDimitry Andric bool HasSpilledSGPRs = false; 280e8d8bef9SDimitry Andric bool HasSpilledVGPRs = false; 2818bcb0991SDimitry Andric uint32_t HighBitsOf32BitAddress = 0; 2820b57cec5SDimitry Andric 283e8d8bef9SDimitry Andric // TODO: 10 may be a better default since it's the maximum. 284e8d8bef9SDimitry Andric unsigned Occupancy = 0; 285e8d8bef9SDimitry Andric 2860b57cec5SDimitry Andric StringValue ScratchRSrcReg = "$private_rsrc_reg"; 2870b57cec5SDimitry Andric StringValue FrameOffsetReg = "$fp_reg"; 2880b57cec5SDimitry Andric StringValue StackPtrOffsetReg = "$sp_reg"; 2890b57cec5SDimitry Andric 2900b57cec5SDimitry Andric Optional<SIArgumentInfo> ArgInfo; 2910b57cec5SDimitry Andric SIMode Mode; 292fe6060f1SDimitry Andric Optional<FrameIndex> ScavengeFI; 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric SIMachineFunctionInfo() = default; 2950b57cec5SDimitry Andric SIMachineFunctionInfo(const llvm::SIMachineFunctionInfo &, 296fe6060f1SDimitry Andric const TargetRegisterInfo &TRI, 297fe6060f1SDimitry Andric const llvm::MachineFunction &MF); 2980b57cec5SDimitry Andric 2990b57cec5SDimitry Andric void mappingImpl(yaml::IO &YamlIO) override; 3000b57cec5SDimitry Andric ~SIMachineFunctionInfo() = default; 3010b57cec5SDimitry Andric }; 3020b57cec5SDimitry Andric 3030b57cec5SDimitry Andric template <> struct MappingTraits<SIMachineFunctionInfo> { 3040b57cec5SDimitry Andric static void mapping(IO &YamlIO, SIMachineFunctionInfo &MFI) { 3050b57cec5SDimitry Andric YamlIO.mapOptional("explicitKernArgSize", MFI.ExplicitKernArgSize, 3060b57cec5SDimitry Andric UINT64_C(0)); 3070b57cec5SDimitry Andric YamlIO.mapOptional("maxKernArgAlign", MFI.MaxKernArgAlign, 0u); 3080b57cec5SDimitry Andric YamlIO.mapOptional("ldsSize", MFI.LDSSize, 0u); 309e8d8bef9SDimitry Andric YamlIO.mapOptional("dynLDSAlign", MFI.DynLDSAlign, Align()); 3100b57cec5SDimitry Andric YamlIO.mapOptional("isEntryFunction", MFI.IsEntryFunction, false); 3110b57cec5SDimitry Andric YamlIO.mapOptional("noSignedZerosFPMath", MFI.NoSignedZerosFPMath, false); 3120b57cec5SDimitry Andric YamlIO.mapOptional("memoryBound", MFI.MemoryBound, false); 3130b57cec5SDimitry Andric YamlIO.mapOptional("waveLimiter", MFI.WaveLimiter, false); 314e8d8bef9SDimitry Andric YamlIO.mapOptional("hasSpilledSGPRs", MFI.HasSpilledSGPRs, false); 315e8d8bef9SDimitry Andric YamlIO.mapOptional("hasSpilledVGPRs", MFI.HasSpilledVGPRs, false); 3160b57cec5SDimitry Andric YamlIO.mapOptional("scratchRSrcReg", MFI.ScratchRSrcReg, 3170b57cec5SDimitry Andric StringValue("$private_rsrc_reg")); 3180b57cec5SDimitry Andric YamlIO.mapOptional("frameOffsetReg", MFI.FrameOffsetReg, 3190b57cec5SDimitry Andric StringValue("$fp_reg")); 3200b57cec5SDimitry Andric YamlIO.mapOptional("stackPtrOffsetReg", MFI.StackPtrOffsetReg, 3210b57cec5SDimitry Andric StringValue("$sp_reg")); 3220b57cec5SDimitry Andric YamlIO.mapOptional("argumentInfo", MFI.ArgInfo); 3230b57cec5SDimitry Andric YamlIO.mapOptional("mode", MFI.Mode, SIMode()); 3248bcb0991SDimitry Andric YamlIO.mapOptional("highBitsOf32BitAddress", 3258bcb0991SDimitry Andric MFI.HighBitsOf32BitAddress, 0u); 326e8d8bef9SDimitry Andric YamlIO.mapOptional("occupancy", MFI.Occupancy, 0); 327fe6060f1SDimitry Andric YamlIO.mapOptional("scavengeFI", MFI.ScavengeFI); 3280b57cec5SDimitry Andric } 3290b57cec5SDimitry Andric }; 3300b57cec5SDimitry Andric 3310b57cec5SDimitry Andric } // end namespace yaml 3320b57cec5SDimitry Andric 3330b57cec5SDimitry Andric /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which 3340b57cec5SDimitry Andric /// tells the hardware which interpolation parameters to load. 3350b57cec5SDimitry Andric class SIMachineFunctionInfo final : public AMDGPUMachineFunction { 3360b57cec5SDimitry Andric friend class GCNTargetMachine; 3370b57cec5SDimitry Andric 3385ffd83dbSDimitry Andric Register TIDReg = AMDGPU::NoRegister; 3390b57cec5SDimitry Andric 3400b57cec5SDimitry Andric // Registers that may be reserved for spilling purposes. These may be the same 3410b57cec5SDimitry Andric // as the input registers. 3425ffd83dbSDimitry Andric Register ScratchRSrcReg = AMDGPU::PRIVATE_RSRC_REG; 3430b57cec5SDimitry Andric 3445ffd83dbSDimitry Andric // This is the the unswizzled offset from the current dispatch's scratch wave 3455ffd83dbSDimitry Andric // base to the beginning of the current function's frame. 3465ffd83dbSDimitry Andric Register FrameOffsetReg = AMDGPU::FP_REG; 3470b57cec5SDimitry Andric 3485ffd83dbSDimitry Andric // This is an ABI register used in the non-entry calling convention to 3495ffd83dbSDimitry Andric // communicate the unswizzled offset from the current dispatch's scratch wave 3505ffd83dbSDimitry Andric // base to the beginning of the new function's frame. 3515ffd83dbSDimitry Andric Register StackPtrOffsetReg = AMDGPU::SP_REG; 3520b57cec5SDimitry Andric 3530b57cec5SDimitry Andric AMDGPUFunctionArgInfo ArgInfo; 3540b57cec5SDimitry Andric 3550b57cec5SDimitry Andric // Graphics info. 3560b57cec5SDimitry Andric unsigned PSInputAddr = 0; 3570b57cec5SDimitry Andric unsigned PSInputEnable = 0; 3580b57cec5SDimitry Andric 3590b57cec5SDimitry Andric /// Number of bytes of arguments this function has on the stack. If the callee 3600b57cec5SDimitry Andric /// is expected to restore the argument stack this should be a multiple of 16, 3610b57cec5SDimitry Andric /// all usable during a tail call. 3620b57cec5SDimitry Andric /// 3630b57cec5SDimitry Andric /// The alternative would forbid tail call optimisation in some cases: if we 3640b57cec5SDimitry Andric /// want to transfer control from a function with 8-bytes of stack-argument 3650b57cec5SDimitry Andric /// space to a function with 16-bytes then misalignment of this value would 3660b57cec5SDimitry Andric /// make a stack adjustment necessary, which could not be undone by the 3670b57cec5SDimitry Andric /// callee. 3680b57cec5SDimitry Andric unsigned BytesInStackArgArea = 0; 3690b57cec5SDimitry Andric 3700b57cec5SDimitry Andric bool ReturnsVoid = true; 3710b57cec5SDimitry Andric 3720b57cec5SDimitry Andric // A pair of default/requested minimum/maximum flat work group sizes. 3730b57cec5SDimitry Andric // Minimum - first, maximum - second. 3740b57cec5SDimitry Andric std::pair<unsigned, unsigned> FlatWorkGroupSizes = {0, 0}; 3750b57cec5SDimitry Andric 3760b57cec5SDimitry Andric // A pair of default/requested minimum/maximum number of waves per execution 3770b57cec5SDimitry Andric // unit. Minimum - first, maximum - second. 3780b57cec5SDimitry Andric std::pair<unsigned, unsigned> WavesPerEU = {0, 0}; 3790b57cec5SDimitry Andric 380e8d8bef9SDimitry Andric std::unique_ptr<const AMDGPUBufferPseudoSourceValue> BufferPSV; 381e8d8bef9SDimitry Andric std::unique_ptr<const AMDGPUImagePseudoSourceValue> ImagePSV; 3820b57cec5SDimitry Andric std::unique_ptr<const AMDGPUGWSResourcePseudoSourceValue> GWSResourcePSV; 3830b57cec5SDimitry Andric 3840b57cec5SDimitry Andric private: 3850b57cec5SDimitry Andric unsigned LDSWaveSpillSize = 0; 3860b57cec5SDimitry Andric unsigned NumUserSGPRs = 0; 3870b57cec5SDimitry Andric unsigned NumSystemSGPRs = 0; 3880b57cec5SDimitry Andric 3890b57cec5SDimitry Andric bool HasSpilledSGPRs = false; 3900b57cec5SDimitry Andric bool HasSpilledVGPRs = false; 3910b57cec5SDimitry Andric bool HasNonSpillStackObjects = false; 3920b57cec5SDimitry Andric bool IsStackRealigned = false; 3930b57cec5SDimitry Andric 3940b57cec5SDimitry Andric unsigned NumSpilledSGPRs = 0; 3950b57cec5SDimitry Andric unsigned NumSpilledVGPRs = 0; 3960b57cec5SDimitry Andric 3970b57cec5SDimitry Andric // Feature bits required for inputs passed in user SGPRs. 3980b57cec5SDimitry Andric bool PrivateSegmentBuffer : 1; 3990b57cec5SDimitry Andric bool DispatchPtr : 1; 4000b57cec5SDimitry Andric bool QueuePtr : 1; 4010b57cec5SDimitry Andric bool KernargSegmentPtr : 1; 4020b57cec5SDimitry Andric bool DispatchID : 1; 4030b57cec5SDimitry Andric bool FlatScratchInit : 1; 4040b57cec5SDimitry Andric 4050b57cec5SDimitry Andric // Feature bits required for inputs passed in system SGPRs. 4060b57cec5SDimitry Andric bool WorkGroupIDX : 1; // Always initialized. 4070b57cec5SDimitry Andric bool WorkGroupIDY : 1; 4080b57cec5SDimitry Andric bool WorkGroupIDZ : 1; 4090b57cec5SDimitry Andric bool WorkGroupInfo : 1; 4100b57cec5SDimitry Andric bool PrivateSegmentWaveByteOffset : 1; 4110b57cec5SDimitry Andric 4120b57cec5SDimitry Andric bool WorkItemIDX : 1; // Always initialized. 4130b57cec5SDimitry Andric bool WorkItemIDY : 1; 4140b57cec5SDimitry Andric bool WorkItemIDZ : 1; 4150b57cec5SDimitry Andric 4160b57cec5SDimitry Andric // Private memory buffer 4170b57cec5SDimitry Andric // Compute directly in sgpr[0:1] 4180b57cec5SDimitry Andric // Other shaders indirect 64-bits at sgpr[0:1] 4190b57cec5SDimitry Andric bool ImplicitBufferPtr : 1; 4200b57cec5SDimitry Andric 4210b57cec5SDimitry Andric // Pointer to where the ABI inserts special kernel arguments separate from the 4220b57cec5SDimitry Andric // user arguments. This is an offset from the KernargSegmentPtr. 4230b57cec5SDimitry Andric bool ImplicitArgPtr : 1; 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric // The hard-wired high half of the address of the global information table 4260b57cec5SDimitry Andric // for AMDPAL OS type. 0xffffffff represents no hard-wired high half, since 4270b57cec5SDimitry Andric // current hardware only allows a 16 bit value. 4280b57cec5SDimitry Andric unsigned GITPtrHigh; 4290b57cec5SDimitry Andric 4300b57cec5SDimitry Andric unsigned HighBitsOf32BitAddress; 4310b57cec5SDimitry Andric unsigned GDSSize; 4320b57cec5SDimitry Andric 4330b57cec5SDimitry Andric // Current recorded maximum possible occupancy. 4340b57cec5SDimitry Andric unsigned Occupancy; 4350b57cec5SDimitry Andric 436349cc55cSDimitry Andric mutable Optional<bool> UsesAGPRs; 437349cc55cSDimitry Andric 4380b57cec5SDimitry Andric MCPhysReg getNextUserSGPR() const; 4390b57cec5SDimitry Andric 4400b57cec5SDimitry Andric MCPhysReg getNextSystemSGPR() const; 4410b57cec5SDimitry Andric 4420b57cec5SDimitry Andric public: 4430b57cec5SDimitry Andric struct SpilledReg { 4445ffd83dbSDimitry Andric Register VGPR; 4450b57cec5SDimitry Andric int Lane = -1; 4460b57cec5SDimitry Andric 4470b57cec5SDimitry Andric SpilledReg() = default; 4485ffd83dbSDimitry Andric SpilledReg(Register R, int L) : VGPR (R), Lane (L) {} 4490b57cec5SDimitry Andric 4500b57cec5SDimitry Andric bool hasLane() { return Lane != -1;} 4510b57cec5SDimitry Andric bool hasReg() { return VGPR != 0;} 4520b57cec5SDimitry Andric }; 4530b57cec5SDimitry Andric 454fe6060f1SDimitry Andric struct SGPRSpillVGPR { 4550b57cec5SDimitry Andric // VGPR used for SGPR spills 4565ffd83dbSDimitry Andric Register VGPR; 4570b57cec5SDimitry Andric 458fe6060f1SDimitry Andric // If the VGPR is is used for SGPR spills in a non-entrypoint function, the 459fe6060f1SDimitry Andric // stack slot used to save/restore it in the prolog/epilog. 4600b57cec5SDimitry Andric Optional<int> FI; 4610b57cec5SDimitry Andric 462fe6060f1SDimitry Andric SGPRSpillVGPR(Register V, Optional<int> F) : VGPR(V), FI(F) {} 4630b57cec5SDimitry Andric }; 4640b57cec5SDimitry Andric 4650b57cec5SDimitry Andric struct VGPRSpillToAGPR { 4660b57cec5SDimitry Andric SmallVector<MCPhysReg, 32> Lanes; 4670b57cec5SDimitry Andric bool FullyAllocated = false; 468*0eae32dcSDimitry Andric bool IsDead = false; 4690b57cec5SDimitry Andric }; 4700b57cec5SDimitry Andric 471fe6060f1SDimitry Andric // Map WWM VGPR to a stack slot that is used to save/restore it in the 472fe6060f1SDimitry Andric // prolog/epilog. 473fe6060f1SDimitry Andric MapVector<Register, Optional<int>> WWMReservedRegs; 4740b57cec5SDimitry Andric 4750b57cec5SDimitry Andric private: 4760b57cec5SDimitry Andric // Track VGPR + wave index for each subregister of the SGPR spilled to 4770b57cec5SDimitry Andric // frameindex key. 4780b57cec5SDimitry Andric DenseMap<int, std::vector<SpilledReg>> SGPRToVGPRSpills; 4790b57cec5SDimitry Andric unsigned NumVGPRSpillLanes = 0; 480fe6060f1SDimitry Andric SmallVector<SGPRSpillVGPR, 2> SpillVGPRs; 4810b57cec5SDimitry Andric 4820b57cec5SDimitry Andric DenseMap<int, VGPRSpillToAGPR> VGPRToAGPRSpills; 4830b57cec5SDimitry Andric 4840b57cec5SDimitry Andric // AGPRs used for VGPR spills. 4850b57cec5SDimitry Andric SmallVector<MCPhysReg, 32> SpillAGPR; 4860b57cec5SDimitry Andric 4870b57cec5SDimitry Andric // VGPRs used for AGPR spills. 4880b57cec5SDimitry Andric SmallVector<MCPhysReg, 32> SpillVGPR; 4890b57cec5SDimitry Andric 490fe6060f1SDimitry Andric // Emergency stack slot. Sometimes, we create this before finalizing the stack 491fe6060f1SDimitry Andric // frame, so save it here and add it to the RegScavenger later. 492fe6060f1SDimitry Andric Optional<int> ScavengeFI; 493fe6060f1SDimitry Andric 4940b57cec5SDimitry Andric public: // FIXME 4950b57cec5SDimitry Andric /// If this is set, an SGPR used for save/restore of the register used for the 4960b57cec5SDimitry Andric /// frame pointer. 4975ffd83dbSDimitry Andric Register SGPRForFPSaveRestoreCopy; 4980b57cec5SDimitry Andric Optional<int> FramePointerSaveIndex; 4990b57cec5SDimitry Andric 5005ffd83dbSDimitry Andric /// If this is set, an SGPR used for save/restore of the register used for the 5015ffd83dbSDimitry Andric /// base pointer. 5025ffd83dbSDimitry Andric Register SGPRForBPSaveRestoreCopy; 5035ffd83dbSDimitry Andric Optional<int> BasePointerSaveIndex; 5045ffd83dbSDimitry Andric 5055ffd83dbSDimitry Andric Register VGPRReservedForSGPRSpill; 5065ffd83dbSDimitry Andric bool isCalleeSavedReg(const MCPhysReg *CSRegs, MCPhysReg Reg); 5075ffd83dbSDimitry Andric 5080b57cec5SDimitry Andric public: 5090b57cec5SDimitry Andric SIMachineFunctionInfo(const MachineFunction &MF); 5100b57cec5SDimitry Andric 511fe6060f1SDimitry Andric bool initializeBaseYamlFields(const yaml::SIMachineFunctionInfo &YamlMFI, 512fe6060f1SDimitry Andric const MachineFunction &MF, 513fe6060f1SDimitry Andric PerFunctionMIParsingState &PFS, 514fe6060f1SDimitry Andric SMDiagnostic &Error, SMRange &SourceRange); 515fe6060f1SDimitry Andric 516fe6060f1SDimitry Andric void reserveWWMRegister(Register Reg, Optional<int> FI) { 517fe6060f1SDimitry Andric WWMReservedRegs.insert(std::make_pair(Reg, FI)); 518fe6060f1SDimitry Andric } 5190b57cec5SDimitry Andric 5200b57cec5SDimitry Andric ArrayRef<SpilledReg> getSGPRToVGPRSpills(int FrameIndex) const { 5210b57cec5SDimitry Andric auto I = SGPRToVGPRSpills.find(FrameIndex); 5220b57cec5SDimitry Andric return (I == SGPRToVGPRSpills.end()) ? 5230b57cec5SDimitry Andric ArrayRef<SpilledReg>() : makeArrayRef(I->second); 5240b57cec5SDimitry Andric } 5250b57cec5SDimitry Andric 526fe6060f1SDimitry Andric ArrayRef<SGPRSpillVGPR> getSGPRSpillVGPRs() const { return SpillVGPRs; } 5270b57cec5SDimitry Andric 5285ffd83dbSDimitry Andric void setSGPRSpillVGPRs(Register NewVGPR, Optional<int> newFI, int Index) { 5295ffd83dbSDimitry Andric SpillVGPRs[Index].VGPR = NewVGPR; 5305ffd83dbSDimitry Andric SpillVGPRs[Index].FI = newFI; 5315ffd83dbSDimitry Andric VGPRReservedForSGPRSpill = NewVGPR; 5325ffd83dbSDimitry Andric } 5335ffd83dbSDimitry Andric 5345ffd83dbSDimitry Andric bool removeVGPRForSGPRSpill(Register ReservedVGPR, MachineFunction &MF); 5355ffd83dbSDimitry Andric 5360b57cec5SDimitry Andric ArrayRef<MCPhysReg> getAGPRSpillVGPRs() const { 5370b57cec5SDimitry Andric return SpillAGPR; 5380b57cec5SDimitry Andric } 5390b57cec5SDimitry Andric 5400b57cec5SDimitry Andric ArrayRef<MCPhysReg> getVGPRSpillAGPRs() const { 5410b57cec5SDimitry Andric return SpillVGPR; 5420b57cec5SDimitry Andric } 5430b57cec5SDimitry Andric 5440b57cec5SDimitry Andric MCPhysReg getVGPRToAGPRSpill(int FrameIndex, unsigned Lane) const { 5450b57cec5SDimitry Andric auto I = VGPRToAGPRSpills.find(FrameIndex); 5460b57cec5SDimitry Andric return (I == VGPRToAGPRSpills.end()) ? (MCPhysReg)AMDGPU::NoRegister 5470b57cec5SDimitry Andric : I->second.Lanes[Lane]; 5480b57cec5SDimitry Andric } 5490b57cec5SDimitry Andric 550*0eae32dcSDimitry Andric void setVGPRToAGPRSpillDead(int FrameIndex) { 551*0eae32dcSDimitry Andric auto I = VGPRToAGPRSpills.find(FrameIndex); 552*0eae32dcSDimitry Andric if (I != VGPRToAGPRSpills.end()) 553*0eae32dcSDimitry Andric I->second.IsDead = true; 554*0eae32dcSDimitry Andric } 555*0eae32dcSDimitry Andric 5560b57cec5SDimitry Andric bool haveFreeLanesForSGPRSpill(const MachineFunction &MF, 5570b57cec5SDimitry Andric unsigned NumLane) const; 5580b57cec5SDimitry Andric bool allocateSGPRSpillToVGPR(MachineFunction &MF, int FI); 5595ffd83dbSDimitry Andric bool reserveVGPRforSGPRSpills(MachineFunction &MF); 5600b57cec5SDimitry Andric bool allocateVGPRSpillToAGPR(MachineFunction &MF, int FI, bool isAGPRtoVGPR); 5610b57cec5SDimitry Andric void removeDeadFrameIndices(MachineFrameInfo &MFI); 5620b57cec5SDimitry Andric 563fe6060f1SDimitry Andric int getScavengeFI(MachineFrameInfo &MFI, const SIRegisterInfo &TRI); 564fe6060f1SDimitry Andric Optional<int> getOptionalScavengeFI() const { return ScavengeFI; } 565fe6060f1SDimitry Andric 5660b57cec5SDimitry Andric bool hasCalculatedTID() const { return TIDReg != 0; }; 5675ffd83dbSDimitry Andric Register getTIDReg() const { return TIDReg; }; 5685ffd83dbSDimitry Andric void setTIDReg(Register Reg) { TIDReg = Reg; } 5690b57cec5SDimitry Andric 5700b57cec5SDimitry Andric unsigned getBytesInStackArgArea() const { 5710b57cec5SDimitry Andric return BytesInStackArgArea; 5720b57cec5SDimitry Andric } 5730b57cec5SDimitry Andric 5740b57cec5SDimitry Andric void setBytesInStackArgArea(unsigned Bytes) { 5750b57cec5SDimitry Andric BytesInStackArgArea = Bytes; 5760b57cec5SDimitry Andric } 5770b57cec5SDimitry Andric 5780b57cec5SDimitry Andric // Add user SGPRs. 5795ffd83dbSDimitry Andric Register addPrivateSegmentBuffer(const SIRegisterInfo &TRI); 5805ffd83dbSDimitry Andric Register addDispatchPtr(const SIRegisterInfo &TRI); 5815ffd83dbSDimitry Andric Register addQueuePtr(const SIRegisterInfo &TRI); 5825ffd83dbSDimitry Andric Register addKernargSegmentPtr(const SIRegisterInfo &TRI); 5835ffd83dbSDimitry Andric Register addDispatchID(const SIRegisterInfo &TRI); 5845ffd83dbSDimitry Andric Register addFlatScratchInit(const SIRegisterInfo &TRI); 5855ffd83dbSDimitry Andric Register addImplicitBufferPtr(const SIRegisterInfo &TRI); 5860b57cec5SDimitry Andric 5870b57cec5SDimitry Andric // Add system SGPRs. 5885ffd83dbSDimitry Andric Register addWorkGroupIDX() { 5890b57cec5SDimitry Andric ArgInfo.WorkGroupIDX = ArgDescriptor::createRegister(getNextSystemSGPR()); 5900b57cec5SDimitry Andric NumSystemSGPRs += 1; 5910b57cec5SDimitry Andric return ArgInfo.WorkGroupIDX.getRegister(); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 5945ffd83dbSDimitry Andric Register addWorkGroupIDY() { 5950b57cec5SDimitry Andric ArgInfo.WorkGroupIDY = ArgDescriptor::createRegister(getNextSystemSGPR()); 5960b57cec5SDimitry Andric NumSystemSGPRs += 1; 5970b57cec5SDimitry Andric return ArgInfo.WorkGroupIDY.getRegister(); 5980b57cec5SDimitry Andric } 5990b57cec5SDimitry Andric 6005ffd83dbSDimitry Andric Register addWorkGroupIDZ() { 6010b57cec5SDimitry Andric ArgInfo.WorkGroupIDZ = ArgDescriptor::createRegister(getNextSystemSGPR()); 6020b57cec5SDimitry Andric NumSystemSGPRs += 1; 6030b57cec5SDimitry Andric return ArgInfo.WorkGroupIDZ.getRegister(); 6040b57cec5SDimitry Andric } 6050b57cec5SDimitry Andric 6065ffd83dbSDimitry Andric Register addWorkGroupInfo() { 6070b57cec5SDimitry Andric ArgInfo.WorkGroupInfo = ArgDescriptor::createRegister(getNextSystemSGPR()); 6080b57cec5SDimitry Andric NumSystemSGPRs += 1; 6090b57cec5SDimitry Andric return ArgInfo.WorkGroupInfo.getRegister(); 6100b57cec5SDimitry Andric } 6110b57cec5SDimitry Andric 6120b57cec5SDimitry Andric // Add special VGPR inputs 6130b57cec5SDimitry Andric void setWorkItemIDX(ArgDescriptor Arg) { 6140b57cec5SDimitry Andric ArgInfo.WorkItemIDX = Arg; 6150b57cec5SDimitry Andric } 6160b57cec5SDimitry Andric 6170b57cec5SDimitry Andric void setWorkItemIDY(ArgDescriptor Arg) { 6180b57cec5SDimitry Andric ArgInfo.WorkItemIDY = Arg; 6190b57cec5SDimitry Andric } 6200b57cec5SDimitry Andric 6210b57cec5SDimitry Andric void setWorkItemIDZ(ArgDescriptor Arg) { 6220b57cec5SDimitry Andric ArgInfo.WorkItemIDZ = Arg; 6230b57cec5SDimitry Andric } 6240b57cec5SDimitry Andric 6255ffd83dbSDimitry Andric Register addPrivateSegmentWaveByteOffset() { 6260b57cec5SDimitry Andric ArgInfo.PrivateSegmentWaveByteOffset 6270b57cec5SDimitry Andric = ArgDescriptor::createRegister(getNextSystemSGPR()); 6280b57cec5SDimitry Andric NumSystemSGPRs += 1; 6290b57cec5SDimitry Andric return ArgInfo.PrivateSegmentWaveByteOffset.getRegister(); 6300b57cec5SDimitry Andric } 6310b57cec5SDimitry Andric 6325ffd83dbSDimitry Andric void setPrivateSegmentWaveByteOffset(Register Reg) { 6330b57cec5SDimitry Andric ArgInfo.PrivateSegmentWaveByteOffset = ArgDescriptor::createRegister(Reg); 6340b57cec5SDimitry Andric } 6350b57cec5SDimitry Andric 6360b57cec5SDimitry Andric bool hasPrivateSegmentBuffer() const { 6370b57cec5SDimitry Andric return PrivateSegmentBuffer; 6380b57cec5SDimitry Andric } 6390b57cec5SDimitry Andric 6400b57cec5SDimitry Andric bool hasDispatchPtr() const { 6410b57cec5SDimitry Andric return DispatchPtr; 6420b57cec5SDimitry Andric } 6430b57cec5SDimitry Andric 6440b57cec5SDimitry Andric bool hasQueuePtr() const { 6450b57cec5SDimitry Andric return QueuePtr; 6460b57cec5SDimitry Andric } 6470b57cec5SDimitry Andric 6480b57cec5SDimitry Andric bool hasKernargSegmentPtr() const { 6490b57cec5SDimitry Andric return KernargSegmentPtr; 6500b57cec5SDimitry Andric } 6510b57cec5SDimitry Andric 6520b57cec5SDimitry Andric bool hasDispatchID() const { 6530b57cec5SDimitry Andric return DispatchID; 6540b57cec5SDimitry Andric } 6550b57cec5SDimitry Andric 6560b57cec5SDimitry Andric bool hasFlatScratchInit() const { 6570b57cec5SDimitry Andric return FlatScratchInit; 6580b57cec5SDimitry Andric } 6590b57cec5SDimitry Andric 6600b57cec5SDimitry Andric bool hasWorkGroupIDX() const { 6610b57cec5SDimitry Andric return WorkGroupIDX; 6620b57cec5SDimitry Andric } 6630b57cec5SDimitry Andric 6640b57cec5SDimitry Andric bool hasWorkGroupIDY() const { 6650b57cec5SDimitry Andric return WorkGroupIDY; 6660b57cec5SDimitry Andric } 6670b57cec5SDimitry Andric 6680b57cec5SDimitry Andric bool hasWorkGroupIDZ() const { 6690b57cec5SDimitry Andric return WorkGroupIDZ; 6700b57cec5SDimitry Andric } 6710b57cec5SDimitry Andric 6720b57cec5SDimitry Andric bool hasWorkGroupInfo() const { 6730b57cec5SDimitry Andric return WorkGroupInfo; 6740b57cec5SDimitry Andric } 6750b57cec5SDimitry Andric 6760b57cec5SDimitry Andric bool hasPrivateSegmentWaveByteOffset() const { 6770b57cec5SDimitry Andric return PrivateSegmentWaveByteOffset; 6780b57cec5SDimitry Andric } 6790b57cec5SDimitry Andric 6800b57cec5SDimitry Andric bool hasWorkItemIDX() const { 6810b57cec5SDimitry Andric return WorkItemIDX; 6820b57cec5SDimitry Andric } 6830b57cec5SDimitry Andric 6840b57cec5SDimitry Andric bool hasWorkItemIDY() const { 6850b57cec5SDimitry Andric return WorkItemIDY; 6860b57cec5SDimitry Andric } 6870b57cec5SDimitry Andric 6880b57cec5SDimitry Andric bool hasWorkItemIDZ() const { 6890b57cec5SDimitry Andric return WorkItemIDZ; 6900b57cec5SDimitry Andric } 6910b57cec5SDimitry Andric 6920b57cec5SDimitry Andric bool hasImplicitArgPtr() const { 6930b57cec5SDimitry Andric return ImplicitArgPtr; 6940b57cec5SDimitry Andric } 6950b57cec5SDimitry Andric 6960b57cec5SDimitry Andric bool hasImplicitBufferPtr() const { 6970b57cec5SDimitry Andric return ImplicitBufferPtr; 6980b57cec5SDimitry Andric } 6990b57cec5SDimitry Andric 7000b57cec5SDimitry Andric AMDGPUFunctionArgInfo &getArgInfo() { 7010b57cec5SDimitry Andric return ArgInfo; 7020b57cec5SDimitry Andric } 7030b57cec5SDimitry Andric 7040b57cec5SDimitry Andric const AMDGPUFunctionArgInfo &getArgInfo() const { 7050b57cec5SDimitry Andric return ArgInfo; 7060b57cec5SDimitry Andric } 7070b57cec5SDimitry Andric 7085ffd83dbSDimitry Andric std::tuple<const ArgDescriptor *, const TargetRegisterClass *, LLT> 7090b57cec5SDimitry Andric getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const { 7100b57cec5SDimitry Andric return ArgInfo.getPreloadedValue(Value); 7110b57cec5SDimitry Andric } 7120b57cec5SDimitry Andric 713e8d8bef9SDimitry Andric MCRegister getPreloadedReg(AMDGPUFunctionArgInfo::PreloadedValue Value) const { 7145ffd83dbSDimitry Andric auto Arg = std::get<0>(ArgInfo.getPreloadedValue(Value)); 715e8d8bef9SDimitry Andric return Arg ? Arg->getRegister() : MCRegister(); 7160b57cec5SDimitry Andric } 7170b57cec5SDimitry Andric 7180b57cec5SDimitry Andric unsigned getGITPtrHigh() const { 7190b57cec5SDimitry Andric return GITPtrHigh; 7200b57cec5SDimitry Andric } 7210b57cec5SDimitry Andric 7225ffd83dbSDimitry Andric Register getGITPtrLoReg(const MachineFunction &MF) const; 7235ffd83dbSDimitry Andric 7248bcb0991SDimitry Andric uint32_t get32BitAddressHighBits() const { 7250b57cec5SDimitry Andric return HighBitsOf32BitAddress; 7260b57cec5SDimitry Andric } 7270b57cec5SDimitry Andric 7280b57cec5SDimitry Andric unsigned getGDSSize() const { 7290b57cec5SDimitry Andric return GDSSize; 7300b57cec5SDimitry Andric } 7310b57cec5SDimitry Andric 7320b57cec5SDimitry Andric unsigned getNumUserSGPRs() const { 7330b57cec5SDimitry Andric return NumUserSGPRs; 7340b57cec5SDimitry Andric } 7350b57cec5SDimitry Andric 7360b57cec5SDimitry Andric unsigned getNumPreloadedSGPRs() const { 7370b57cec5SDimitry Andric return NumUserSGPRs + NumSystemSGPRs; 7380b57cec5SDimitry Andric } 7390b57cec5SDimitry Andric 7405ffd83dbSDimitry Andric Register getPrivateSegmentWaveByteOffsetSystemSGPR() const { 7410b57cec5SDimitry Andric return ArgInfo.PrivateSegmentWaveByteOffset.getRegister(); 7420b57cec5SDimitry Andric } 7430b57cec5SDimitry Andric 7440b57cec5SDimitry Andric /// Returns the physical register reserved for use as the resource 7450b57cec5SDimitry Andric /// descriptor for scratch accesses. 7465ffd83dbSDimitry Andric Register getScratchRSrcReg() const { 7470b57cec5SDimitry Andric return ScratchRSrcReg; 7480b57cec5SDimitry Andric } 7490b57cec5SDimitry Andric 7505ffd83dbSDimitry Andric void setScratchRSrcReg(Register Reg) { 7510b57cec5SDimitry Andric assert(Reg != 0 && "Should never be unset"); 7520b57cec5SDimitry Andric ScratchRSrcReg = Reg; 7530b57cec5SDimitry Andric } 7540b57cec5SDimitry Andric 7555ffd83dbSDimitry Andric Register getFrameOffsetReg() const { 7560b57cec5SDimitry Andric return FrameOffsetReg; 7570b57cec5SDimitry Andric } 7580b57cec5SDimitry Andric 7595ffd83dbSDimitry Andric void setFrameOffsetReg(Register Reg) { 7600b57cec5SDimitry Andric assert(Reg != 0 && "Should never be unset"); 7610b57cec5SDimitry Andric FrameOffsetReg = Reg; 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric 7645ffd83dbSDimitry Andric void setStackPtrOffsetReg(Register Reg) { 7650b57cec5SDimitry Andric assert(Reg != 0 && "Should never be unset"); 7660b57cec5SDimitry Andric StackPtrOffsetReg = Reg; 7670b57cec5SDimitry Andric } 7680b57cec5SDimitry Andric 7690b57cec5SDimitry Andric // Note the unset value for this is AMDGPU::SP_REG rather than 7700b57cec5SDimitry Andric // NoRegister. This is mostly a workaround for MIR tests where state that 7710b57cec5SDimitry Andric // can't be directly computed from the function is not preserved in serialized 7720b57cec5SDimitry Andric // MIR. 7735ffd83dbSDimitry Andric Register getStackPtrOffsetReg() const { 7740b57cec5SDimitry Andric return StackPtrOffsetReg; 7750b57cec5SDimitry Andric } 7760b57cec5SDimitry Andric 7775ffd83dbSDimitry Andric Register getQueuePtrUserSGPR() const { 7780b57cec5SDimitry Andric return ArgInfo.QueuePtr.getRegister(); 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric 7815ffd83dbSDimitry Andric Register getImplicitBufferPtrUserSGPR() const { 7820b57cec5SDimitry Andric return ArgInfo.ImplicitBufferPtr.getRegister(); 7830b57cec5SDimitry Andric } 7840b57cec5SDimitry Andric 7850b57cec5SDimitry Andric bool hasSpilledSGPRs() const { 7860b57cec5SDimitry Andric return HasSpilledSGPRs; 7870b57cec5SDimitry Andric } 7880b57cec5SDimitry Andric 7890b57cec5SDimitry Andric void setHasSpilledSGPRs(bool Spill = true) { 7900b57cec5SDimitry Andric HasSpilledSGPRs = Spill; 7910b57cec5SDimitry Andric } 7920b57cec5SDimitry Andric 7930b57cec5SDimitry Andric bool hasSpilledVGPRs() const { 7940b57cec5SDimitry Andric return HasSpilledVGPRs; 7950b57cec5SDimitry Andric } 7960b57cec5SDimitry Andric 7970b57cec5SDimitry Andric void setHasSpilledVGPRs(bool Spill = true) { 7980b57cec5SDimitry Andric HasSpilledVGPRs = Spill; 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric 8010b57cec5SDimitry Andric bool hasNonSpillStackObjects() const { 8020b57cec5SDimitry Andric return HasNonSpillStackObjects; 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric void setHasNonSpillStackObjects(bool StackObject = true) { 8060b57cec5SDimitry Andric HasNonSpillStackObjects = StackObject; 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric bool isStackRealigned() const { 8100b57cec5SDimitry Andric return IsStackRealigned; 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric void setIsStackRealigned(bool Realigned = true) { 8140b57cec5SDimitry Andric IsStackRealigned = Realigned; 8150b57cec5SDimitry Andric } 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric unsigned getNumSpilledSGPRs() const { 8180b57cec5SDimitry Andric return NumSpilledSGPRs; 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric unsigned getNumSpilledVGPRs() const { 8220b57cec5SDimitry Andric return NumSpilledVGPRs; 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric void addToSpilledSGPRs(unsigned num) { 8260b57cec5SDimitry Andric NumSpilledSGPRs += num; 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric void addToSpilledVGPRs(unsigned num) { 8300b57cec5SDimitry Andric NumSpilledVGPRs += num; 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric unsigned getPSInputAddr() const { 8340b57cec5SDimitry Andric return PSInputAddr; 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric unsigned getPSInputEnable() const { 8380b57cec5SDimitry Andric return PSInputEnable; 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric bool isPSInputAllocated(unsigned Index) const { 8420b57cec5SDimitry Andric return PSInputAddr & (1 << Index); 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 8450b57cec5SDimitry Andric void markPSInputAllocated(unsigned Index) { 8460b57cec5SDimitry Andric PSInputAddr |= 1 << Index; 8470b57cec5SDimitry Andric } 8480b57cec5SDimitry Andric 8490b57cec5SDimitry Andric void markPSInputEnabled(unsigned Index) { 8500b57cec5SDimitry Andric PSInputEnable |= 1 << Index; 8510b57cec5SDimitry Andric } 8520b57cec5SDimitry Andric 8530b57cec5SDimitry Andric bool returnsVoid() const { 8540b57cec5SDimitry Andric return ReturnsVoid; 8550b57cec5SDimitry Andric } 8560b57cec5SDimitry Andric 8570b57cec5SDimitry Andric void setIfReturnsVoid(bool Value) { 8580b57cec5SDimitry Andric ReturnsVoid = Value; 8590b57cec5SDimitry Andric } 8600b57cec5SDimitry Andric 8610b57cec5SDimitry Andric /// \returns A pair of default/requested minimum/maximum flat work group sizes 8620b57cec5SDimitry Andric /// for this function. 8630b57cec5SDimitry Andric std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const { 8640b57cec5SDimitry Andric return FlatWorkGroupSizes; 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric /// \returns Default/requested minimum flat work group size for this function. 8680b57cec5SDimitry Andric unsigned getMinFlatWorkGroupSize() const { 8690b57cec5SDimitry Andric return FlatWorkGroupSizes.first; 8700b57cec5SDimitry Andric } 8710b57cec5SDimitry Andric 8720b57cec5SDimitry Andric /// \returns Default/requested maximum flat work group size for this function. 8730b57cec5SDimitry Andric unsigned getMaxFlatWorkGroupSize() const { 8740b57cec5SDimitry Andric return FlatWorkGroupSizes.second; 8750b57cec5SDimitry Andric } 8760b57cec5SDimitry Andric 8770b57cec5SDimitry Andric /// \returns A pair of default/requested minimum/maximum number of waves per 8780b57cec5SDimitry Andric /// execution unit. 8790b57cec5SDimitry Andric std::pair<unsigned, unsigned> getWavesPerEU() const { 8800b57cec5SDimitry Andric return WavesPerEU; 8810b57cec5SDimitry Andric } 8820b57cec5SDimitry Andric 8830b57cec5SDimitry Andric /// \returns Default/requested minimum number of waves per execution unit. 8840b57cec5SDimitry Andric unsigned getMinWavesPerEU() const { 8850b57cec5SDimitry Andric return WavesPerEU.first; 8860b57cec5SDimitry Andric } 8870b57cec5SDimitry Andric 8880b57cec5SDimitry Andric /// \returns Default/requested maximum number of waves per execution unit. 8890b57cec5SDimitry Andric unsigned getMaxWavesPerEU() const { 8900b57cec5SDimitry Andric return WavesPerEU.second; 8910b57cec5SDimitry Andric } 8920b57cec5SDimitry Andric 8930b57cec5SDimitry Andric /// \returns SGPR used for \p Dim's work group ID. 8945ffd83dbSDimitry Andric Register getWorkGroupIDSGPR(unsigned Dim) const { 8950b57cec5SDimitry Andric switch (Dim) { 8960b57cec5SDimitry Andric case 0: 8970b57cec5SDimitry Andric assert(hasWorkGroupIDX()); 8980b57cec5SDimitry Andric return ArgInfo.WorkGroupIDX.getRegister(); 8990b57cec5SDimitry Andric case 1: 9000b57cec5SDimitry Andric assert(hasWorkGroupIDY()); 9010b57cec5SDimitry Andric return ArgInfo.WorkGroupIDY.getRegister(); 9020b57cec5SDimitry Andric case 2: 9030b57cec5SDimitry Andric assert(hasWorkGroupIDZ()); 9040b57cec5SDimitry Andric return ArgInfo.WorkGroupIDZ.getRegister(); 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric llvm_unreachable("unexpected dimension"); 9070b57cec5SDimitry Andric } 9080b57cec5SDimitry Andric 9090b57cec5SDimitry Andric unsigned getLDSWaveSpillSize() const { 9100b57cec5SDimitry Andric return LDSWaveSpillSize; 9110b57cec5SDimitry Andric } 9120b57cec5SDimitry Andric 913e8d8bef9SDimitry Andric const AMDGPUBufferPseudoSourceValue *getBufferPSV(const SIInstrInfo &TII) { 914e8d8bef9SDimitry Andric if (!BufferPSV) 915e8d8bef9SDimitry Andric BufferPSV = std::make_unique<AMDGPUBufferPseudoSourceValue>(TII); 916e8d8bef9SDimitry Andric 917e8d8bef9SDimitry Andric return BufferPSV.get(); 9180b57cec5SDimitry Andric } 9190b57cec5SDimitry Andric 920e8d8bef9SDimitry Andric const AMDGPUImagePseudoSourceValue *getImagePSV(const SIInstrInfo &TII) { 921e8d8bef9SDimitry Andric if (!ImagePSV) 922e8d8bef9SDimitry Andric ImagePSV = std::make_unique<AMDGPUImagePseudoSourceValue>(TII); 923e8d8bef9SDimitry Andric 924e8d8bef9SDimitry Andric return ImagePSV.get(); 9250b57cec5SDimitry Andric } 9260b57cec5SDimitry Andric 9270b57cec5SDimitry Andric const AMDGPUGWSResourcePseudoSourceValue *getGWSPSV(const SIInstrInfo &TII) { 9280b57cec5SDimitry Andric if (!GWSResourcePSV) { 9290b57cec5SDimitry Andric GWSResourcePSV = 9308bcb0991SDimitry Andric std::make_unique<AMDGPUGWSResourcePseudoSourceValue>(TII); 9310b57cec5SDimitry Andric } 9320b57cec5SDimitry Andric 9330b57cec5SDimitry Andric return GWSResourcePSV.get(); 9340b57cec5SDimitry Andric } 9350b57cec5SDimitry Andric 9360b57cec5SDimitry Andric unsigned getOccupancy() const { 9370b57cec5SDimitry Andric return Occupancy; 9380b57cec5SDimitry Andric } 9390b57cec5SDimitry Andric 9400b57cec5SDimitry Andric unsigned getMinAllowedOccupancy() const { 9410b57cec5SDimitry Andric if (!isMemoryBound() && !needsWaveLimiter()) 9420b57cec5SDimitry Andric return Occupancy; 9430b57cec5SDimitry Andric return (Occupancy < 4) ? Occupancy : 4; 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric 9460b57cec5SDimitry Andric void limitOccupancy(const MachineFunction &MF); 9470b57cec5SDimitry Andric 9480b57cec5SDimitry Andric void limitOccupancy(unsigned Limit) { 9490b57cec5SDimitry Andric if (Occupancy > Limit) 9500b57cec5SDimitry Andric Occupancy = Limit; 9510b57cec5SDimitry Andric } 9520b57cec5SDimitry Andric 9530b57cec5SDimitry Andric void increaseOccupancy(const MachineFunction &MF, unsigned Limit) { 9540b57cec5SDimitry Andric if (Occupancy < Limit) 9550b57cec5SDimitry Andric Occupancy = Limit; 9560b57cec5SDimitry Andric limitOccupancy(MF); 9570b57cec5SDimitry Andric } 958349cc55cSDimitry Andric 959349cc55cSDimitry Andric // \returns true if a function needs or may need AGPRs. 960349cc55cSDimitry Andric bool usesAGPRs(const MachineFunction &MF) const; 9610b57cec5SDimitry Andric }; 9620b57cec5SDimitry Andric 9630b57cec5SDimitry Andric } // end namespace llvm 9640b57cec5SDimitry Andric 9650b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 966