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" 1881ad6265SDimitry Andric #include "AMDGPUTargetMachine.h" 190b57cec5SDimitry Andric #include "MCTargetDesc/AMDGPUMCTargetDesc.h" 200b57cec5SDimitry Andric #include "SIInstrInfo.h" 21*06c3fb27SDimitry Andric #include "SIModeRegisterDefaults.h" 2281ad6265SDimitry Andric #include "llvm/ADT/SetVector.h" 230b57cec5SDimitry Andric #include "llvm/CodeGen/MIRYamlMapping.h" 240b57cec5SDimitry Andric #include "llvm/CodeGen/PseudoSourceValue.h" 25e8d8bef9SDimitry Andric #include "llvm/Support/raw_ostream.h" 26bdd1243dSDimitry Andric #include <optional> 270b57cec5SDimitry Andric 280b57cec5SDimitry Andric namespace llvm { 290b57cec5SDimitry Andric 300b57cec5SDimitry Andric class MachineFrameInfo; 310b57cec5SDimitry Andric class MachineFunction; 32e8d8bef9SDimitry Andric class SIMachineFunctionInfo; 33e8d8bef9SDimitry Andric class SIRegisterInfo; 34349cc55cSDimitry Andric class TargetRegisterClass; 350b57cec5SDimitry Andric 360b57cec5SDimitry Andric class AMDGPUPseudoSourceValue : public PseudoSourceValue { 370b57cec5SDimitry Andric public: 380b57cec5SDimitry Andric enum AMDGPUPSVKind : unsigned { 39bdd1243dSDimitry Andric PSVImage = PseudoSourceValue::TargetCustom, 400b57cec5SDimitry Andric GWSResource 410b57cec5SDimitry Andric }; 420b57cec5SDimitry Andric 430b57cec5SDimitry Andric protected: 4481ad6265SDimitry Andric AMDGPUPseudoSourceValue(unsigned Kind, const AMDGPUTargetMachine &TM) 4581ad6265SDimitry Andric : PseudoSourceValue(Kind, TM) {} 460b57cec5SDimitry Andric 470b57cec5SDimitry Andric public: 480b57cec5SDimitry Andric bool isConstant(const MachineFrameInfo *) const override { 490b57cec5SDimitry Andric // This should probably be true for most images, but we will start by being 500b57cec5SDimitry Andric // conservative. 510b57cec5SDimitry Andric return false; 520b57cec5SDimitry Andric } 530b57cec5SDimitry Andric 540b57cec5SDimitry Andric bool isAliased(const MachineFrameInfo *) const override { 550b57cec5SDimitry Andric return true; 560b57cec5SDimitry Andric } 570b57cec5SDimitry Andric 580b57cec5SDimitry Andric bool mayAlias(const MachineFrameInfo *) const override { 590b57cec5SDimitry Andric return true; 600b57cec5SDimitry Andric } 610b57cec5SDimitry Andric }; 620b57cec5SDimitry Andric 630b57cec5SDimitry Andric class AMDGPUGWSResourcePseudoSourceValue final : public AMDGPUPseudoSourceValue { 640b57cec5SDimitry Andric public: 6581ad6265SDimitry Andric explicit AMDGPUGWSResourcePseudoSourceValue(const AMDGPUTargetMachine &TM) 6681ad6265SDimitry Andric : AMDGPUPseudoSourceValue(GWSResource, TM) {} 670b57cec5SDimitry Andric 680b57cec5SDimitry Andric static bool classof(const PseudoSourceValue *V) { 690b57cec5SDimitry Andric return V->kind() == GWSResource; 700b57cec5SDimitry Andric } 710b57cec5SDimitry Andric 720b57cec5SDimitry Andric // These are inaccessible memory from IR. 730b57cec5SDimitry Andric bool isAliased(const MachineFrameInfo *) const override { 740b57cec5SDimitry Andric return false; 750b57cec5SDimitry Andric } 760b57cec5SDimitry Andric 770b57cec5SDimitry Andric // These are inaccessible memory from IR. 780b57cec5SDimitry Andric bool mayAlias(const MachineFrameInfo *) const override { 790b57cec5SDimitry Andric return false; 800b57cec5SDimitry Andric } 810b57cec5SDimitry Andric 820b57cec5SDimitry Andric void printCustom(raw_ostream &OS) const override { 830b57cec5SDimitry Andric OS << "GWSResource"; 840b57cec5SDimitry Andric } 850b57cec5SDimitry Andric }; 860b57cec5SDimitry Andric 870b57cec5SDimitry Andric namespace yaml { 880b57cec5SDimitry Andric 890b57cec5SDimitry Andric struct SIArgument { 900b57cec5SDimitry Andric bool IsRegister; 910b57cec5SDimitry Andric union { 920b57cec5SDimitry Andric StringValue RegisterName; 930b57cec5SDimitry Andric unsigned StackOffset; 940b57cec5SDimitry Andric }; 95bdd1243dSDimitry Andric std::optional<unsigned> Mask; 960b57cec5SDimitry Andric 970b57cec5SDimitry Andric // Default constructor, which creates a stack argument. 980b57cec5SDimitry Andric SIArgument() : IsRegister(false), StackOffset(0) {} 990b57cec5SDimitry Andric SIArgument(const SIArgument &Other) { 1000b57cec5SDimitry Andric IsRegister = Other.IsRegister; 1010b57cec5SDimitry Andric if (IsRegister) { 1020b57cec5SDimitry Andric ::new ((void *)std::addressof(RegisterName)) 1030b57cec5SDimitry Andric StringValue(Other.RegisterName); 1040b57cec5SDimitry Andric } else 1050b57cec5SDimitry Andric StackOffset = Other.StackOffset; 1060b57cec5SDimitry Andric Mask = Other.Mask; 1070b57cec5SDimitry Andric } 1080b57cec5SDimitry Andric SIArgument &operator=(const SIArgument &Other) { 1090b57cec5SDimitry Andric IsRegister = Other.IsRegister; 1100b57cec5SDimitry Andric if (IsRegister) { 1110b57cec5SDimitry Andric ::new ((void *)std::addressof(RegisterName)) 1120b57cec5SDimitry Andric StringValue(Other.RegisterName); 1130b57cec5SDimitry Andric } else 1140b57cec5SDimitry Andric StackOffset = Other.StackOffset; 1150b57cec5SDimitry Andric Mask = Other.Mask; 1160b57cec5SDimitry Andric return *this; 1170b57cec5SDimitry Andric } 1180b57cec5SDimitry Andric ~SIArgument() { 1190b57cec5SDimitry Andric if (IsRegister) 1200b57cec5SDimitry Andric RegisterName.~StringValue(); 1210b57cec5SDimitry Andric } 1220b57cec5SDimitry Andric 1230b57cec5SDimitry Andric // Helper to create a register or stack argument. 1240b57cec5SDimitry Andric static inline SIArgument createArgument(bool IsReg) { 1250b57cec5SDimitry Andric if (IsReg) 1260b57cec5SDimitry Andric return SIArgument(IsReg); 1270b57cec5SDimitry Andric return SIArgument(); 1280b57cec5SDimitry Andric } 1290b57cec5SDimitry Andric 1300b57cec5SDimitry Andric private: 1310b57cec5SDimitry Andric // Construct a register argument. 1320b57cec5SDimitry Andric SIArgument(bool) : IsRegister(true), RegisterName() {} 1330b57cec5SDimitry Andric }; 1340b57cec5SDimitry Andric 1350b57cec5SDimitry Andric template <> struct MappingTraits<SIArgument> { 1360b57cec5SDimitry Andric static void mapping(IO &YamlIO, SIArgument &A) { 1370b57cec5SDimitry Andric if (YamlIO.outputting()) { 1380b57cec5SDimitry Andric if (A.IsRegister) 1390b57cec5SDimitry Andric YamlIO.mapRequired("reg", A.RegisterName); 1400b57cec5SDimitry Andric else 1410b57cec5SDimitry Andric YamlIO.mapRequired("offset", A.StackOffset); 1420b57cec5SDimitry Andric } else { 1430b57cec5SDimitry Andric auto Keys = YamlIO.keys(); 1440b57cec5SDimitry Andric if (is_contained(Keys, "reg")) { 1450b57cec5SDimitry Andric A = SIArgument::createArgument(true); 1460b57cec5SDimitry Andric YamlIO.mapRequired("reg", A.RegisterName); 1470b57cec5SDimitry Andric } else if (is_contained(Keys, "offset")) 1480b57cec5SDimitry Andric YamlIO.mapRequired("offset", A.StackOffset); 1490b57cec5SDimitry Andric else 1500b57cec5SDimitry Andric YamlIO.setError("missing required key 'reg' or 'offset'"); 1510b57cec5SDimitry Andric } 1520b57cec5SDimitry Andric YamlIO.mapOptional("mask", A.Mask); 1530b57cec5SDimitry Andric } 1540b57cec5SDimitry Andric static const bool flow = true; 1550b57cec5SDimitry Andric }; 1560b57cec5SDimitry Andric 1570b57cec5SDimitry Andric struct SIArgumentInfo { 158bdd1243dSDimitry Andric std::optional<SIArgument> PrivateSegmentBuffer; 159bdd1243dSDimitry Andric std::optional<SIArgument> DispatchPtr; 160bdd1243dSDimitry Andric std::optional<SIArgument> QueuePtr; 161bdd1243dSDimitry Andric std::optional<SIArgument> KernargSegmentPtr; 162bdd1243dSDimitry Andric std::optional<SIArgument> DispatchID; 163bdd1243dSDimitry Andric std::optional<SIArgument> FlatScratchInit; 164bdd1243dSDimitry Andric std::optional<SIArgument> PrivateSegmentSize; 1650b57cec5SDimitry Andric 166bdd1243dSDimitry Andric std::optional<SIArgument> WorkGroupIDX; 167bdd1243dSDimitry Andric std::optional<SIArgument> WorkGroupIDY; 168bdd1243dSDimitry Andric std::optional<SIArgument> WorkGroupIDZ; 169bdd1243dSDimitry Andric std::optional<SIArgument> WorkGroupInfo; 170bdd1243dSDimitry Andric std::optional<SIArgument> LDSKernelId; 171bdd1243dSDimitry Andric std::optional<SIArgument> PrivateSegmentWaveByteOffset; 1720b57cec5SDimitry Andric 173bdd1243dSDimitry Andric std::optional<SIArgument> ImplicitArgPtr; 174bdd1243dSDimitry Andric std::optional<SIArgument> ImplicitBufferPtr; 1750b57cec5SDimitry Andric 176bdd1243dSDimitry Andric std::optional<SIArgument> WorkItemIDX; 177bdd1243dSDimitry Andric std::optional<SIArgument> WorkItemIDY; 178bdd1243dSDimitry Andric std::optional<SIArgument> WorkItemIDZ; 1790b57cec5SDimitry Andric }; 1800b57cec5SDimitry Andric 1810b57cec5SDimitry Andric template <> struct MappingTraits<SIArgumentInfo> { 1820b57cec5SDimitry Andric static void mapping(IO &YamlIO, SIArgumentInfo &AI) { 1830b57cec5SDimitry Andric YamlIO.mapOptional("privateSegmentBuffer", AI.PrivateSegmentBuffer); 1840b57cec5SDimitry Andric YamlIO.mapOptional("dispatchPtr", AI.DispatchPtr); 1850b57cec5SDimitry Andric YamlIO.mapOptional("queuePtr", AI.QueuePtr); 1860b57cec5SDimitry Andric YamlIO.mapOptional("kernargSegmentPtr", AI.KernargSegmentPtr); 1870b57cec5SDimitry Andric YamlIO.mapOptional("dispatchID", AI.DispatchID); 1880b57cec5SDimitry Andric YamlIO.mapOptional("flatScratchInit", AI.FlatScratchInit); 1890b57cec5SDimitry Andric YamlIO.mapOptional("privateSegmentSize", AI.PrivateSegmentSize); 1900b57cec5SDimitry Andric 1910b57cec5SDimitry Andric YamlIO.mapOptional("workGroupIDX", AI.WorkGroupIDX); 1920b57cec5SDimitry Andric YamlIO.mapOptional("workGroupIDY", AI.WorkGroupIDY); 1930b57cec5SDimitry Andric YamlIO.mapOptional("workGroupIDZ", AI.WorkGroupIDZ); 1940b57cec5SDimitry Andric YamlIO.mapOptional("workGroupInfo", AI.WorkGroupInfo); 195fcaf7f86SDimitry Andric YamlIO.mapOptional("LDSKernelId", AI.LDSKernelId); 1960b57cec5SDimitry Andric YamlIO.mapOptional("privateSegmentWaveByteOffset", 1970b57cec5SDimitry Andric AI.PrivateSegmentWaveByteOffset); 1980b57cec5SDimitry Andric 1990b57cec5SDimitry Andric YamlIO.mapOptional("implicitArgPtr", AI.ImplicitArgPtr); 2000b57cec5SDimitry Andric YamlIO.mapOptional("implicitBufferPtr", AI.ImplicitBufferPtr); 2010b57cec5SDimitry Andric 2020b57cec5SDimitry Andric YamlIO.mapOptional("workItemIDX", AI.WorkItemIDX); 2030b57cec5SDimitry Andric YamlIO.mapOptional("workItemIDY", AI.WorkItemIDY); 2040b57cec5SDimitry Andric YamlIO.mapOptional("workItemIDZ", AI.WorkItemIDZ); 2050b57cec5SDimitry Andric } 2060b57cec5SDimitry Andric }; 2070b57cec5SDimitry Andric 2080b57cec5SDimitry Andric // Default to default mode for default calling convention. 2090b57cec5SDimitry Andric struct SIMode { 2100b57cec5SDimitry Andric bool IEEE = true; 2110b57cec5SDimitry Andric bool DX10Clamp = true; 2125ffd83dbSDimitry Andric bool FP32InputDenormals = true; 2135ffd83dbSDimitry Andric bool FP32OutputDenormals = true; 2145ffd83dbSDimitry Andric bool FP64FP16InputDenormals = true; 2155ffd83dbSDimitry Andric bool FP64FP16OutputDenormals = true; 2160b57cec5SDimitry Andric 2170b57cec5SDimitry Andric SIMode() = default; 2180b57cec5SDimitry Andric 219*06c3fb27SDimitry Andric SIMode(const SIModeRegisterDefaults &Mode) { 2200b57cec5SDimitry Andric IEEE = Mode.IEEE; 2210b57cec5SDimitry Andric DX10Clamp = Mode.DX10Clamp; 222bdd1243dSDimitry Andric FP32InputDenormals = Mode.FP32Denormals.Input != DenormalMode::PreserveSign; 223bdd1243dSDimitry Andric FP32OutputDenormals = 224bdd1243dSDimitry Andric Mode.FP32Denormals.Output != DenormalMode::PreserveSign; 225bdd1243dSDimitry Andric FP64FP16InputDenormals = 226bdd1243dSDimitry Andric Mode.FP64FP16Denormals.Input != DenormalMode::PreserveSign; 227bdd1243dSDimitry Andric FP64FP16OutputDenormals = 228bdd1243dSDimitry Andric Mode.FP64FP16Denormals.Output != DenormalMode::PreserveSign; 2290b57cec5SDimitry Andric } 2300b57cec5SDimitry Andric 2310b57cec5SDimitry Andric bool operator ==(const SIMode Other) const { 232480093f4SDimitry Andric return IEEE == Other.IEEE && 233480093f4SDimitry Andric DX10Clamp == Other.DX10Clamp && 2345ffd83dbSDimitry Andric FP32InputDenormals == Other.FP32InputDenormals && 2355ffd83dbSDimitry Andric FP32OutputDenormals == Other.FP32OutputDenormals && 2365ffd83dbSDimitry Andric FP64FP16InputDenormals == Other.FP64FP16InputDenormals && 2375ffd83dbSDimitry Andric FP64FP16OutputDenormals == Other.FP64FP16OutputDenormals; 2380b57cec5SDimitry Andric } 2390b57cec5SDimitry Andric }; 2400b57cec5SDimitry Andric 2410b57cec5SDimitry Andric template <> struct MappingTraits<SIMode> { 2420b57cec5SDimitry Andric static void mapping(IO &YamlIO, SIMode &Mode) { 2430b57cec5SDimitry Andric YamlIO.mapOptional("ieee", Mode.IEEE, true); 2440b57cec5SDimitry Andric YamlIO.mapOptional("dx10-clamp", Mode.DX10Clamp, true); 2455ffd83dbSDimitry Andric YamlIO.mapOptional("fp32-input-denormals", Mode.FP32InputDenormals, true); 2465ffd83dbSDimitry Andric YamlIO.mapOptional("fp32-output-denormals", Mode.FP32OutputDenormals, true); 2475ffd83dbSDimitry Andric YamlIO.mapOptional("fp64-fp16-input-denormals", Mode.FP64FP16InputDenormals, true); 2485ffd83dbSDimitry Andric YamlIO.mapOptional("fp64-fp16-output-denormals", Mode.FP64FP16OutputDenormals, true); 2490b57cec5SDimitry Andric } 2500b57cec5SDimitry Andric }; 2510b57cec5SDimitry Andric 2520b57cec5SDimitry Andric struct SIMachineFunctionInfo final : public yaml::MachineFunctionInfo { 2530b57cec5SDimitry Andric uint64_t ExplicitKernArgSize = 0; 25481ad6265SDimitry Andric Align MaxKernArgAlign; 25581ad6265SDimitry Andric uint32_t LDSSize = 0; 25681ad6265SDimitry Andric uint32_t GDSSize = 0; 257e8d8bef9SDimitry Andric Align DynLDSAlign; 2580b57cec5SDimitry Andric bool IsEntryFunction = false; 2590b57cec5SDimitry Andric bool NoSignedZerosFPMath = false; 2600b57cec5SDimitry Andric bool MemoryBound = false; 2610b57cec5SDimitry Andric bool WaveLimiter = false; 262e8d8bef9SDimitry Andric bool HasSpilledSGPRs = false; 263e8d8bef9SDimitry Andric bool HasSpilledVGPRs = false; 2648bcb0991SDimitry Andric uint32_t HighBitsOf32BitAddress = 0; 2650b57cec5SDimitry Andric 266e8d8bef9SDimitry Andric // TODO: 10 may be a better default since it's the maximum. 267e8d8bef9SDimitry Andric unsigned Occupancy = 0; 268e8d8bef9SDimitry Andric 26981ad6265SDimitry Andric SmallVector<StringValue> WWMReservedRegs; 27081ad6265SDimitry Andric 2710b57cec5SDimitry Andric StringValue ScratchRSrcReg = "$private_rsrc_reg"; 2720b57cec5SDimitry Andric StringValue FrameOffsetReg = "$fp_reg"; 2730b57cec5SDimitry Andric StringValue StackPtrOffsetReg = "$sp_reg"; 2740b57cec5SDimitry Andric 27581ad6265SDimitry Andric unsigned BytesInStackArgArea = 0; 27681ad6265SDimitry Andric bool ReturnsVoid = true; 27781ad6265SDimitry Andric 278bdd1243dSDimitry Andric std::optional<SIArgumentInfo> ArgInfo; 279*06c3fb27SDimitry Andric 280*06c3fb27SDimitry Andric unsigned PSInputAddr = 0; 281*06c3fb27SDimitry Andric unsigned PSInputEnable = 0; 282*06c3fb27SDimitry Andric 2830b57cec5SDimitry Andric SIMode Mode; 284bdd1243dSDimitry Andric std::optional<FrameIndex> ScavengeFI; 28581ad6265SDimitry Andric StringValue VGPRForAGPRCopy; 286*06c3fb27SDimitry Andric StringValue SGPRForEXECCopy; 287*06c3fb27SDimitry Andric StringValue LongBranchReservedReg; 2880b57cec5SDimitry Andric 2890b57cec5SDimitry Andric SIMachineFunctionInfo() = default; 2900b57cec5SDimitry Andric SIMachineFunctionInfo(const llvm::SIMachineFunctionInfo &, 291fe6060f1SDimitry Andric const TargetRegisterInfo &TRI, 292fe6060f1SDimitry Andric const llvm::MachineFunction &MF); 2930b57cec5SDimitry Andric 2940b57cec5SDimitry Andric void mappingImpl(yaml::IO &YamlIO) override; 2950b57cec5SDimitry Andric ~SIMachineFunctionInfo() = default; 2960b57cec5SDimitry Andric }; 2970b57cec5SDimitry Andric 2980b57cec5SDimitry Andric template <> struct MappingTraits<SIMachineFunctionInfo> { 2990b57cec5SDimitry Andric static void mapping(IO &YamlIO, SIMachineFunctionInfo &MFI) { 3000b57cec5SDimitry Andric YamlIO.mapOptional("explicitKernArgSize", MFI.ExplicitKernArgSize, 3010b57cec5SDimitry Andric UINT64_C(0)); 30281ad6265SDimitry Andric YamlIO.mapOptional("maxKernArgAlign", MFI.MaxKernArgAlign); 3030b57cec5SDimitry Andric YamlIO.mapOptional("ldsSize", MFI.LDSSize, 0u); 30481ad6265SDimitry Andric YamlIO.mapOptional("gdsSize", MFI.GDSSize, 0u); 305e8d8bef9SDimitry Andric YamlIO.mapOptional("dynLDSAlign", MFI.DynLDSAlign, Align()); 3060b57cec5SDimitry Andric YamlIO.mapOptional("isEntryFunction", MFI.IsEntryFunction, false); 3070b57cec5SDimitry Andric YamlIO.mapOptional("noSignedZerosFPMath", MFI.NoSignedZerosFPMath, false); 3080b57cec5SDimitry Andric YamlIO.mapOptional("memoryBound", MFI.MemoryBound, false); 3090b57cec5SDimitry Andric YamlIO.mapOptional("waveLimiter", MFI.WaveLimiter, false); 310e8d8bef9SDimitry Andric YamlIO.mapOptional("hasSpilledSGPRs", MFI.HasSpilledSGPRs, false); 311e8d8bef9SDimitry Andric YamlIO.mapOptional("hasSpilledVGPRs", MFI.HasSpilledVGPRs, false); 3120b57cec5SDimitry Andric YamlIO.mapOptional("scratchRSrcReg", MFI.ScratchRSrcReg, 3130b57cec5SDimitry Andric StringValue("$private_rsrc_reg")); 3140b57cec5SDimitry Andric YamlIO.mapOptional("frameOffsetReg", MFI.FrameOffsetReg, 3150b57cec5SDimitry Andric StringValue("$fp_reg")); 3160b57cec5SDimitry Andric YamlIO.mapOptional("stackPtrOffsetReg", MFI.StackPtrOffsetReg, 3170b57cec5SDimitry Andric StringValue("$sp_reg")); 31881ad6265SDimitry Andric YamlIO.mapOptional("bytesInStackArgArea", MFI.BytesInStackArgArea, 0u); 31981ad6265SDimitry Andric YamlIO.mapOptional("returnsVoid", MFI.ReturnsVoid, true); 3200b57cec5SDimitry Andric YamlIO.mapOptional("argumentInfo", MFI.ArgInfo); 321*06c3fb27SDimitry Andric YamlIO.mapOptional("psInputAddr", MFI.PSInputAddr, 0u); 322*06c3fb27SDimitry Andric YamlIO.mapOptional("psInputEnable", MFI.PSInputEnable, 0u); 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); 32781ad6265SDimitry Andric YamlIO.mapOptional("wwmReservedRegs", MFI.WWMReservedRegs); 328fe6060f1SDimitry Andric YamlIO.mapOptional("scavengeFI", MFI.ScavengeFI); 32981ad6265SDimitry Andric YamlIO.mapOptional("vgprForAGPRCopy", MFI.VGPRForAGPRCopy, 33081ad6265SDimitry Andric StringValue()); // Don't print out when it's empty. 331*06c3fb27SDimitry Andric YamlIO.mapOptional("sgprForEXECCopy", MFI.SGPRForEXECCopy, 332*06c3fb27SDimitry Andric StringValue()); // Don't print out when it's empty. 333*06c3fb27SDimitry Andric YamlIO.mapOptional("longBranchReservedReg", MFI.LongBranchReservedReg, 334*06c3fb27SDimitry Andric StringValue()); 3350b57cec5SDimitry Andric } 3360b57cec5SDimitry Andric }; 3370b57cec5SDimitry Andric 3380b57cec5SDimitry Andric } // end namespace yaml 3390b57cec5SDimitry Andric 340bdd1243dSDimitry Andric // A CSR SGPR value can be preserved inside a callee using one of the following 341bdd1243dSDimitry Andric // methods. 342bdd1243dSDimitry Andric // 1. Copy to an unused scratch SGPR. 343bdd1243dSDimitry Andric // 2. Spill to a VGPR lane. 344bdd1243dSDimitry Andric // 3. Spill to memory via. a scratch VGPR. 345bdd1243dSDimitry Andric // class PrologEpilogSGPRSaveRestoreInfo represents the save/restore method used 346bdd1243dSDimitry Andric // for an SGPR at function prolog/epilog. 347bdd1243dSDimitry Andric enum class SGPRSaveKind : uint8_t { 348bdd1243dSDimitry Andric COPY_TO_SCRATCH_SGPR, 349bdd1243dSDimitry Andric SPILL_TO_VGPR_LANE, 350bdd1243dSDimitry Andric SPILL_TO_MEM 351bdd1243dSDimitry Andric }; 352bdd1243dSDimitry Andric 353bdd1243dSDimitry Andric class PrologEpilogSGPRSaveRestoreInfo { 354bdd1243dSDimitry Andric SGPRSaveKind Kind; 355bdd1243dSDimitry Andric union { 356bdd1243dSDimitry Andric int Index; 357bdd1243dSDimitry Andric Register Reg; 358bdd1243dSDimitry Andric }; 359bdd1243dSDimitry Andric 360bdd1243dSDimitry Andric public: 361bdd1243dSDimitry Andric PrologEpilogSGPRSaveRestoreInfo(SGPRSaveKind K, int I) : Kind(K), Index(I) {} 362bdd1243dSDimitry Andric PrologEpilogSGPRSaveRestoreInfo(SGPRSaveKind K, Register R) 363bdd1243dSDimitry Andric : Kind(K), Reg(R) {} 364bdd1243dSDimitry Andric Register getReg() const { return Reg; } 365bdd1243dSDimitry Andric int getIndex() const { return Index; } 366bdd1243dSDimitry Andric SGPRSaveKind getKind() const { return Kind; } 367bdd1243dSDimitry Andric }; 368bdd1243dSDimitry Andric 3690b57cec5SDimitry Andric /// This class keeps track of the SPI_SP_INPUT_ADDR config register, which 3700b57cec5SDimitry Andric /// tells the hardware which interpolation parameters to load. 371*06c3fb27SDimitry Andric class SIMachineFunctionInfo final : public AMDGPUMachineFunction, 372*06c3fb27SDimitry Andric private MachineRegisterInfo::Delegate { 3730b57cec5SDimitry Andric friend class GCNTargetMachine; 3740b57cec5SDimitry Andric 375bdd1243dSDimitry Andric // State of MODE register, assumed FP mode. 376*06c3fb27SDimitry Andric SIModeRegisterDefaults Mode; 377bdd1243dSDimitry Andric 3780b57cec5SDimitry Andric // Registers that may be reserved for spilling purposes. These may be the same 3790b57cec5SDimitry Andric // as the input registers. 3805ffd83dbSDimitry Andric Register ScratchRSrcReg = AMDGPU::PRIVATE_RSRC_REG; 3810b57cec5SDimitry Andric 382bdd1243dSDimitry Andric // This is the unswizzled offset from the current dispatch's scratch wave 3835ffd83dbSDimitry Andric // base to the beginning of the current function's frame. 3845ffd83dbSDimitry Andric Register FrameOffsetReg = AMDGPU::FP_REG; 3850b57cec5SDimitry Andric 3865ffd83dbSDimitry Andric // This is an ABI register used in the non-entry calling convention to 3875ffd83dbSDimitry Andric // communicate the unswizzled offset from the current dispatch's scratch wave 3885ffd83dbSDimitry Andric // base to the beginning of the new function's frame. 3895ffd83dbSDimitry Andric Register StackPtrOffsetReg = AMDGPU::SP_REG; 3900b57cec5SDimitry Andric 391*06c3fb27SDimitry Andric // Registers that may be reserved when RA doesn't allocate enough 392*06c3fb27SDimitry Andric // registers to plan for the case where an indirect branch ends up 393*06c3fb27SDimitry Andric // being needed during branch relaxation. 394*06c3fb27SDimitry Andric Register LongBranchReservedReg; 395*06c3fb27SDimitry Andric 3960b57cec5SDimitry Andric AMDGPUFunctionArgInfo ArgInfo; 3970b57cec5SDimitry Andric 3980b57cec5SDimitry Andric // Graphics info. 3990b57cec5SDimitry Andric unsigned PSInputAddr = 0; 4000b57cec5SDimitry Andric unsigned PSInputEnable = 0; 4010b57cec5SDimitry Andric 4020b57cec5SDimitry Andric /// Number of bytes of arguments this function has on the stack. If the callee 4030b57cec5SDimitry Andric /// is expected to restore the argument stack this should be a multiple of 16, 4040b57cec5SDimitry Andric /// all usable during a tail call. 4050b57cec5SDimitry Andric /// 4060b57cec5SDimitry Andric /// The alternative would forbid tail call optimisation in some cases: if we 4070b57cec5SDimitry Andric /// want to transfer control from a function with 8-bytes of stack-argument 4080b57cec5SDimitry Andric /// space to a function with 16-bytes then misalignment of this value would 4090b57cec5SDimitry Andric /// make a stack adjustment necessary, which could not be undone by the 4100b57cec5SDimitry Andric /// callee. 4110b57cec5SDimitry Andric unsigned BytesInStackArgArea = 0; 4120b57cec5SDimitry Andric 4130b57cec5SDimitry Andric bool ReturnsVoid = true; 4140b57cec5SDimitry Andric 4150b57cec5SDimitry Andric // A pair of default/requested minimum/maximum flat work group sizes. 4160b57cec5SDimitry Andric // Minimum - first, maximum - second. 4170b57cec5SDimitry Andric std::pair<unsigned, unsigned> FlatWorkGroupSizes = {0, 0}; 4180b57cec5SDimitry Andric 4190b57cec5SDimitry Andric // A pair of default/requested minimum/maximum number of waves per execution 4200b57cec5SDimitry Andric // unit. Minimum - first, maximum - second. 4210b57cec5SDimitry Andric std::pair<unsigned, unsigned> WavesPerEU = {0, 0}; 4220b57cec5SDimitry Andric 42381ad6265SDimitry Andric const AMDGPUGWSResourcePseudoSourceValue GWSResourcePSV; 4240b57cec5SDimitry Andric 4250b57cec5SDimitry Andric private: 4260b57cec5SDimitry Andric unsigned NumUserSGPRs = 0; 4270b57cec5SDimitry Andric unsigned NumSystemSGPRs = 0; 4280b57cec5SDimitry Andric 4290b57cec5SDimitry Andric bool HasSpilledSGPRs = false; 4300b57cec5SDimitry Andric bool HasSpilledVGPRs = false; 4310b57cec5SDimitry Andric bool HasNonSpillStackObjects = false; 4320b57cec5SDimitry Andric bool IsStackRealigned = false; 4330b57cec5SDimitry Andric 4340b57cec5SDimitry Andric unsigned NumSpilledSGPRs = 0; 4350b57cec5SDimitry Andric unsigned NumSpilledVGPRs = 0; 4360b57cec5SDimitry Andric 4370b57cec5SDimitry Andric // Feature bits required for inputs passed in user SGPRs. 4380b57cec5SDimitry Andric bool PrivateSegmentBuffer : 1; 4390b57cec5SDimitry Andric bool DispatchPtr : 1; 4400b57cec5SDimitry Andric bool QueuePtr : 1; 4410b57cec5SDimitry Andric bool KernargSegmentPtr : 1; 4420b57cec5SDimitry Andric bool DispatchID : 1; 4430b57cec5SDimitry Andric bool FlatScratchInit : 1; 4440b57cec5SDimitry Andric 4450b57cec5SDimitry Andric // Feature bits required for inputs passed in system SGPRs. 4460b57cec5SDimitry Andric bool WorkGroupIDX : 1; // Always initialized. 4470b57cec5SDimitry Andric bool WorkGroupIDY : 1; 4480b57cec5SDimitry Andric bool WorkGroupIDZ : 1; 4490b57cec5SDimitry Andric bool WorkGroupInfo : 1; 450fcaf7f86SDimitry Andric bool LDSKernelId : 1; 4510b57cec5SDimitry Andric bool PrivateSegmentWaveByteOffset : 1; 4520b57cec5SDimitry Andric 4530b57cec5SDimitry Andric bool WorkItemIDX : 1; // Always initialized. 4540b57cec5SDimitry Andric bool WorkItemIDY : 1; 4550b57cec5SDimitry Andric bool WorkItemIDZ : 1; 4560b57cec5SDimitry Andric 4570b57cec5SDimitry Andric // Private memory buffer 4580b57cec5SDimitry Andric // Compute directly in sgpr[0:1] 4590b57cec5SDimitry Andric // Other shaders indirect 64-bits at sgpr[0:1] 4600b57cec5SDimitry Andric bool ImplicitBufferPtr : 1; 4610b57cec5SDimitry Andric 4620b57cec5SDimitry Andric // Pointer to where the ABI inserts special kernel arguments separate from the 4630b57cec5SDimitry Andric // user arguments. This is an offset from the KernargSegmentPtr. 4640b57cec5SDimitry Andric bool ImplicitArgPtr : 1; 4650b57cec5SDimitry Andric 46681ad6265SDimitry Andric bool MayNeedAGPRs : 1; 46781ad6265SDimitry Andric 4680b57cec5SDimitry Andric // The hard-wired high half of the address of the global information table 4690b57cec5SDimitry Andric // for AMDPAL OS type. 0xffffffff represents no hard-wired high half, since 4700b57cec5SDimitry Andric // current hardware only allows a 16 bit value. 4710b57cec5SDimitry Andric unsigned GITPtrHigh; 4720b57cec5SDimitry Andric 4730b57cec5SDimitry Andric unsigned HighBitsOf32BitAddress; 4740b57cec5SDimitry Andric 475*06c3fb27SDimitry Andric // Flags associated with the virtual registers. 476*06c3fb27SDimitry Andric IndexedMap<uint8_t, VirtReg2IndexFunctor> VRegFlags; 477*06c3fb27SDimitry Andric 4780b57cec5SDimitry Andric // Current recorded maximum possible occupancy. 4790b57cec5SDimitry Andric unsigned Occupancy; 4800b57cec5SDimitry Andric 481bdd1243dSDimitry Andric mutable std::optional<bool> UsesAGPRs; 482349cc55cSDimitry Andric 4830b57cec5SDimitry Andric MCPhysReg getNextUserSGPR() const; 4840b57cec5SDimitry Andric 4850b57cec5SDimitry Andric MCPhysReg getNextSystemSGPR() const; 4860b57cec5SDimitry Andric 487*06c3fb27SDimitry Andric // MachineRegisterInfo callback functions to notify events. 488*06c3fb27SDimitry Andric void MRI_NoteNewVirtualRegister(Register Reg) override; 489*06c3fb27SDimitry Andric void MRI_NoteCloneVirtualRegister(Register NewReg, Register SrcReg) override; 490*06c3fb27SDimitry Andric 4910b57cec5SDimitry Andric public: 4920b57cec5SDimitry Andric struct VGPRSpillToAGPR { 4930b57cec5SDimitry Andric SmallVector<MCPhysReg, 32> Lanes; 4940b57cec5SDimitry Andric bool FullyAllocated = false; 4950eae32dcSDimitry Andric bool IsDead = false; 4960b57cec5SDimitry Andric }; 4970b57cec5SDimitry Andric 4980b57cec5SDimitry Andric private: 499*06c3fb27SDimitry Andric // To track virtual VGPR + lane index for each subregister of the SGPR spilled 500*06c3fb27SDimitry Andric // to frameindex key during SILowerSGPRSpills pass. 501bdd1243dSDimitry Andric DenseMap<int, std::vector<SIRegisterInfo::SpilledReg>> 502*06c3fb27SDimitry Andric SGPRSpillsToVirtualVGPRLanes; 503*06c3fb27SDimitry Andric // To track physical VGPR + lane index for CSR SGPR spills and special SGPRs 504*06c3fb27SDimitry Andric // like Frame Pointer identified during PrologEpilogInserter. 505*06c3fb27SDimitry Andric DenseMap<int, std::vector<SIRegisterInfo::SpilledReg>> 506*06c3fb27SDimitry Andric SGPRSpillsToPhysicalVGPRLanes; 507*06c3fb27SDimitry Andric unsigned NumVirtualVGPRSpillLanes = 0; 508*06c3fb27SDimitry Andric unsigned NumPhysicalVGPRSpillLanes = 0; 509bdd1243dSDimitry Andric SmallVector<Register, 2> SpillVGPRs; 510bdd1243dSDimitry Andric using WWMSpillsMap = MapVector<Register, int>; 511bdd1243dSDimitry Andric // To track the registers used in instructions that can potentially modify the 512bdd1243dSDimitry Andric // inactive lanes. The WWM instructions and the writelane instructions for 513bdd1243dSDimitry Andric // spilling SGPRs to VGPRs fall under such category of operations. The VGPRs 514bdd1243dSDimitry Andric // modified by them should be spilled/restored at function prolog/epilog to 515bdd1243dSDimitry Andric // avoid any undesired outcome. Each entry in this map holds a pair of values, 516bdd1243dSDimitry Andric // the VGPR and its stack slot index. 517bdd1243dSDimitry Andric WWMSpillsMap WWMSpills; 518bdd1243dSDimitry Andric 519bdd1243dSDimitry Andric using ReservedRegSet = SmallSetVector<Register, 8>; 520bdd1243dSDimitry Andric // To track the VGPRs reserved for WWM instructions. They get stack slots 521bdd1243dSDimitry Andric // later during PrologEpilogInserter and get added into the superset WWMSpills 522bdd1243dSDimitry Andric // for actual spilling. A separate set makes the register reserved part and 523bdd1243dSDimitry Andric // the serialization easier. 524bdd1243dSDimitry Andric ReservedRegSet WWMReservedRegs; 525bdd1243dSDimitry Andric 526bdd1243dSDimitry Andric using PrologEpilogSGPRSpillsMap = 527bdd1243dSDimitry Andric DenseMap<Register, PrologEpilogSGPRSaveRestoreInfo>; 528bdd1243dSDimitry Andric // To track the SGPR spill method used for a CSR SGPR register during 529bdd1243dSDimitry Andric // frame lowering. Even though the SGPR spills are handled during 530bdd1243dSDimitry Andric // SILowerSGPRSpills pass, some special handling needed later during the 531bdd1243dSDimitry Andric // PrologEpilogInserter. 532bdd1243dSDimitry Andric PrologEpilogSGPRSpillsMap PrologEpilogSGPRSpills; 5330b57cec5SDimitry Andric 534*06c3fb27SDimitry Andric // To save/restore EXEC MASK around WWM spills and copies. 535*06c3fb27SDimitry Andric Register SGPRForEXECCopy; 536*06c3fb27SDimitry Andric 5370b57cec5SDimitry Andric DenseMap<int, VGPRSpillToAGPR> VGPRToAGPRSpills; 5380b57cec5SDimitry Andric 5390b57cec5SDimitry Andric // AGPRs used for VGPR spills. 5400b57cec5SDimitry Andric SmallVector<MCPhysReg, 32> SpillAGPR; 5410b57cec5SDimitry Andric 5420b57cec5SDimitry Andric // VGPRs used for AGPR spills. 5430b57cec5SDimitry Andric SmallVector<MCPhysReg, 32> SpillVGPR; 5440b57cec5SDimitry Andric 545fe6060f1SDimitry Andric // Emergency stack slot. Sometimes, we create this before finalizing the stack 546fe6060f1SDimitry Andric // frame, so save it here and add it to the RegScavenger later. 547bdd1243dSDimitry Andric std::optional<int> ScavengeFI; 548fe6060f1SDimitry Andric 54981ad6265SDimitry Andric private: 55081ad6265SDimitry Andric Register VGPRForAGPRCopy; 55181ad6265SDimitry Andric 552*06c3fb27SDimitry Andric bool allocateVirtualVGPRForSGPRSpills(MachineFunction &MF, int FI, 553bdd1243dSDimitry Andric unsigned LaneIndex); 554*06c3fb27SDimitry Andric bool allocatePhysicalVGPRForSGPRSpills(MachineFunction &MF, int FI, 555bdd1243dSDimitry Andric unsigned LaneIndex); 556bdd1243dSDimitry Andric 55781ad6265SDimitry Andric public: 55881ad6265SDimitry Andric Register getVGPRForAGPRCopy() const { 55981ad6265SDimitry Andric return VGPRForAGPRCopy; 56081ad6265SDimitry Andric } 56181ad6265SDimitry Andric 56281ad6265SDimitry Andric void setVGPRForAGPRCopy(Register NewVGPRForAGPRCopy) { 56381ad6265SDimitry Andric VGPRForAGPRCopy = NewVGPRForAGPRCopy; 56481ad6265SDimitry Andric } 56581ad6265SDimitry Andric 566bdd1243dSDimitry Andric bool isCalleeSavedReg(const MCPhysReg *CSRegs, MCPhysReg Reg) const; 5675ffd83dbSDimitry Andric 5680b57cec5SDimitry Andric public: 56981ad6265SDimitry Andric SIMachineFunctionInfo(const SIMachineFunctionInfo &MFI) = default; 570bdd1243dSDimitry Andric SIMachineFunctionInfo(const Function &F, const GCNSubtarget *STI); 57181ad6265SDimitry Andric 57281ad6265SDimitry Andric MachineFunctionInfo * 57381ad6265SDimitry Andric clone(BumpPtrAllocator &Allocator, MachineFunction &DestMF, 57481ad6265SDimitry Andric const DenseMap<MachineBasicBlock *, MachineBasicBlock *> &Src2DstMBB) 57581ad6265SDimitry Andric const override; 5760b57cec5SDimitry Andric 577fe6060f1SDimitry Andric bool initializeBaseYamlFields(const yaml::SIMachineFunctionInfo &YamlMFI, 578fe6060f1SDimitry Andric const MachineFunction &MF, 579fe6060f1SDimitry Andric PerFunctionMIParsingState &PFS, 580fe6060f1SDimitry Andric SMDiagnostic &Error, SMRange &SourceRange); 581fe6060f1SDimitry Andric 582bdd1243dSDimitry Andric void reserveWWMRegister(Register Reg) { WWMReservedRegs.insert(Reg); } 583bdd1243dSDimitry Andric 584*06c3fb27SDimitry Andric SIModeRegisterDefaults getMode() const { return Mode; } 5850b57cec5SDimitry Andric 58681ad6265SDimitry Andric ArrayRef<SIRegisterInfo::SpilledReg> 587*06c3fb27SDimitry Andric getSGPRSpillToVirtualVGPRLanes(int FrameIndex) const { 588*06c3fb27SDimitry Andric auto I = SGPRSpillsToVirtualVGPRLanes.find(FrameIndex); 589*06c3fb27SDimitry Andric return (I == SGPRSpillsToVirtualVGPRLanes.end()) 59081ad6265SDimitry Andric ? ArrayRef<SIRegisterInfo::SpilledReg>() 591bdd1243dSDimitry Andric : ArrayRef(I->second); 5920b57cec5SDimitry Andric } 5930b57cec5SDimitry Andric 594bdd1243dSDimitry Andric ArrayRef<Register> getSGPRSpillVGPRs() const { return SpillVGPRs; } 595bdd1243dSDimitry Andric const WWMSpillsMap &getWWMSpills() const { return WWMSpills; } 596bdd1243dSDimitry Andric const ReservedRegSet &getWWMReservedRegs() const { return WWMReservedRegs; } 597bdd1243dSDimitry Andric 598bdd1243dSDimitry Andric const PrologEpilogSGPRSpillsMap &getPrologEpilogSGPRSpills() const { 599bdd1243dSDimitry Andric return PrologEpilogSGPRSpills; 600bdd1243dSDimitry Andric } 601bdd1243dSDimitry Andric 602bdd1243dSDimitry Andric void addToPrologEpilogSGPRSpills(Register Reg, 603bdd1243dSDimitry Andric PrologEpilogSGPRSaveRestoreInfo SI) { 604bdd1243dSDimitry Andric PrologEpilogSGPRSpills.insert(std::make_pair(Reg, SI)); 605bdd1243dSDimitry Andric } 606bdd1243dSDimitry Andric 607bdd1243dSDimitry Andric // Check if an entry created for \p Reg in PrologEpilogSGPRSpills. Return true 608bdd1243dSDimitry Andric // on success and false otherwise. 609bdd1243dSDimitry Andric bool hasPrologEpilogSGPRSpillEntry(Register Reg) const { 610*06c3fb27SDimitry Andric return PrologEpilogSGPRSpills.contains(Reg); 611bdd1243dSDimitry Andric } 612bdd1243dSDimitry Andric 613bdd1243dSDimitry Andric // Get the scratch SGPR if allocated to save/restore \p Reg. 614bdd1243dSDimitry Andric Register getScratchSGPRCopyDstReg(Register Reg) const { 615bdd1243dSDimitry Andric auto I = PrologEpilogSGPRSpills.find(Reg); 616bdd1243dSDimitry Andric if (I != PrologEpilogSGPRSpills.end() && 617bdd1243dSDimitry Andric I->second.getKind() == SGPRSaveKind::COPY_TO_SCRATCH_SGPR) 618bdd1243dSDimitry Andric return I->second.getReg(); 619bdd1243dSDimitry Andric 620bdd1243dSDimitry Andric return AMDGPU::NoRegister; 621bdd1243dSDimitry Andric } 622bdd1243dSDimitry Andric 623bdd1243dSDimitry Andric // Get all scratch SGPRs allocated to copy/restore the SGPR spills. 624bdd1243dSDimitry Andric void getAllScratchSGPRCopyDstRegs(SmallVectorImpl<Register> &Regs) const { 625bdd1243dSDimitry Andric for (const auto &SI : PrologEpilogSGPRSpills) { 626bdd1243dSDimitry Andric if (SI.second.getKind() == SGPRSaveKind::COPY_TO_SCRATCH_SGPR) 627bdd1243dSDimitry Andric Regs.push_back(SI.second.getReg()); 628bdd1243dSDimitry Andric } 629bdd1243dSDimitry Andric } 630bdd1243dSDimitry Andric 631bdd1243dSDimitry Andric // Check if \p FI is allocated for any SGPR spill to a VGPR lane during PEI. 632bdd1243dSDimitry Andric bool checkIndexInPrologEpilogSGPRSpills(int FI) const { 633bdd1243dSDimitry Andric return find_if(PrologEpilogSGPRSpills, 634bdd1243dSDimitry Andric [FI](const std::pair<Register, 635bdd1243dSDimitry Andric PrologEpilogSGPRSaveRestoreInfo> &SI) { 636bdd1243dSDimitry Andric return SI.second.getKind() == 637bdd1243dSDimitry Andric SGPRSaveKind::SPILL_TO_VGPR_LANE && 638bdd1243dSDimitry Andric SI.second.getIndex() == FI; 639bdd1243dSDimitry Andric }) != PrologEpilogSGPRSpills.end(); 640bdd1243dSDimitry Andric } 641bdd1243dSDimitry Andric 642bdd1243dSDimitry Andric const PrologEpilogSGPRSaveRestoreInfo & 643bdd1243dSDimitry Andric getPrologEpilogSGPRSaveRestoreInfo(Register Reg) const { 644bdd1243dSDimitry Andric auto I = PrologEpilogSGPRSpills.find(Reg); 645bdd1243dSDimitry Andric assert(I != PrologEpilogSGPRSpills.end()); 646bdd1243dSDimitry Andric 647bdd1243dSDimitry Andric return I->second; 648bdd1243dSDimitry Andric } 649bdd1243dSDimitry Andric 650bdd1243dSDimitry Andric ArrayRef<SIRegisterInfo::SpilledReg> 651*06c3fb27SDimitry Andric getSGPRSpillToPhysicalVGPRLanes(int FrameIndex) const { 652*06c3fb27SDimitry Andric auto I = SGPRSpillsToPhysicalVGPRLanes.find(FrameIndex); 653*06c3fb27SDimitry Andric return (I == SGPRSpillsToPhysicalVGPRLanes.end()) 654bdd1243dSDimitry Andric ? ArrayRef<SIRegisterInfo::SpilledReg>() 655bdd1243dSDimitry Andric : ArrayRef(I->second); 656bdd1243dSDimitry Andric } 657bdd1243dSDimitry Andric 658*06c3fb27SDimitry Andric void setFlag(Register Reg, uint8_t Flag) { 659*06c3fb27SDimitry Andric assert(Reg.isVirtual()); 660*06c3fb27SDimitry Andric if (VRegFlags.inBounds(Reg)) 661*06c3fb27SDimitry Andric VRegFlags[Reg] |= Flag; 662*06c3fb27SDimitry Andric } 663*06c3fb27SDimitry Andric 664*06c3fb27SDimitry Andric bool checkFlag(Register Reg, uint8_t Flag) const { 665*06c3fb27SDimitry Andric if (Reg.isPhysical()) 666*06c3fb27SDimitry Andric return false; 667*06c3fb27SDimitry Andric 668*06c3fb27SDimitry Andric return VRegFlags.inBounds(Reg) && VRegFlags[Reg] & Flag; 669*06c3fb27SDimitry Andric } 670*06c3fb27SDimitry Andric 671*06c3fb27SDimitry Andric bool hasVRegFlags() { return VRegFlags.size(); } 672*06c3fb27SDimitry Andric 673bdd1243dSDimitry Andric void allocateWWMSpill(MachineFunction &MF, Register VGPR, uint64_t Size = 4, 674bdd1243dSDimitry Andric Align Alignment = Align(4)); 675bdd1243dSDimitry Andric 676bdd1243dSDimitry Andric void splitWWMSpillRegisters( 677bdd1243dSDimitry Andric MachineFunction &MF, 678bdd1243dSDimitry Andric SmallVectorImpl<std::pair<Register, int>> &CalleeSavedRegs, 679bdd1243dSDimitry Andric SmallVectorImpl<std::pair<Register, int>> &ScratchRegs) const; 6800b57cec5SDimitry Andric 6810b57cec5SDimitry Andric ArrayRef<MCPhysReg> getAGPRSpillVGPRs() const { 6820b57cec5SDimitry Andric return SpillAGPR; 6830b57cec5SDimitry Andric } 6840b57cec5SDimitry Andric 685*06c3fb27SDimitry Andric Register getSGPRForEXECCopy() const { return SGPRForEXECCopy; } 686*06c3fb27SDimitry Andric 687*06c3fb27SDimitry Andric void setSGPRForEXECCopy(Register Reg) { SGPRForEXECCopy = Reg; } 688*06c3fb27SDimitry Andric 6890b57cec5SDimitry Andric ArrayRef<MCPhysReg> getVGPRSpillAGPRs() const { 6900b57cec5SDimitry Andric return SpillVGPR; 6910b57cec5SDimitry Andric } 6920b57cec5SDimitry Andric 6930b57cec5SDimitry Andric MCPhysReg getVGPRToAGPRSpill(int FrameIndex, unsigned Lane) const { 6940b57cec5SDimitry Andric auto I = VGPRToAGPRSpills.find(FrameIndex); 6950b57cec5SDimitry Andric return (I == VGPRToAGPRSpills.end()) ? (MCPhysReg)AMDGPU::NoRegister 6960b57cec5SDimitry Andric : I->second.Lanes[Lane]; 6970b57cec5SDimitry Andric } 6980b57cec5SDimitry Andric 6990eae32dcSDimitry Andric void setVGPRToAGPRSpillDead(int FrameIndex) { 7000eae32dcSDimitry Andric auto I = VGPRToAGPRSpills.find(FrameIndex); 7010eae32dcSDimitry Andric if (I != VGPRToAGPRSpills.end()) 7020eae32dcSDimitry Andric I->second.IsDead = true; 7030eae32dcSDimitry Andric } 7040eae32dcSDimitry Andric 705bdd1243dSDimitry Andric bool allocateSGPRSpillToVGPRLane(MachineFunction &MF, int FI, 706bdd1243dSDimitry Andric bool IsPrologEpilog = false); 7070b57cec5SDimitry Andric bool allocateVGPRSpillToAGPR(MachineFunction &MF, int FI, bool isAGPRtoVGPR); 70881ad6265SDimitry Andric 70981ad6265SDimitry Andric /// If \p ResetSGPRSpillStackIDs is true, reset the stack ID from sgpr-spill 71081ad6265SDimitry Andric /// to the default stack. 71181ad6265SDimitry Andric bool removeDeadFrameIndices(MachineFrameInfo &MFI, 71281ad6265SDimitry Andric bool ResetSGPRSpillStackIDs); 7130b57cec5SDimitry Andric 714fe6060f1SDimitry Andric int getScavengeFI(MachineFrameInfo &MFI, const SIRegisterInfo &TRI); 715bdd1243dSDimitry Andric std::optional<int> getOptionalScavengeFI() const { return ScavengeFI; } 716fe6060f1SDimitry Andric 7170b57cec5SDimitry Andric unsigned getBytesInStackArgArea() const { 7180b57cec5SDimitry Andric return BytesInStackArgArea; 7190b57cec5SDimitry Andric } 7200b57cec5SDimitry Andric 7210b57cec5SDimitry Andric void setBytesInStackArgArea(unsigned Bytes) { 7220b57cec5SDimitry Andric BytesInStackArgArea = Bytes; 7230b57cec5SDimitry Andric } 7240b57cec5SDimitry Andric 7250b57cec5SDimitry Andric // Add user SGPRs. 7265ffd83dbSDimitry Andric Register addPrivateSegmentBuffer(const SIRegisterInfo &TRI); 7275ffd83dbSDimitry Andric Register addDispatchPtr(const SIRegisterInfo &TRI); 7285ffd83dbSDimitry Andric Register addQueuePtr(const SIRegisterInfo &TRI); 7295ffd83dbSDimitry Andric Register addKernargSegmentPtr(const SIRegisterInfo &TRI); 7305ffd83dbSDimitry Andric Register addDispatchID(const SIRegisterInfo &TRI); 7315ffd83dbSDimitry Andric Register addFlatScratchInit(const SIRegisterInfo &TRI); 7325ffd83dbSDimitry Andric Register addImplicitBufferPtr(const SIRegisterInfo &TRI); 733fcaf7f86SDimitry Andric Register addLDSKernelId(); 7340b57cec5SDimitry Andric 73581ad6265SDimitry Andric /// Increment user SGPRs used for padding the argument list only. 73681ad6265SDimitry Andric Register addReservedUserSGPR() { 73781ad6265SDimitry Andric Register Next = getNextUserSGPR(); 73881ad6265SDimitry Andric ++NumUserSGPRs; 73981ad6265SDimitry Andric return Next; 74081ad6265SDimitry Andric } 74181ad6265SDimitry Andric 7420b57cec5SDimitry Andric // Add system SGPRs. 743*06c3fb27SDimitry Andric Register addWorkGroupIDX(bool HasArchitectedSGPRs) { 744*06c3fb27SDimitry Andric Register Reg = 745*06c3fb27SDimitry Andric HasArchitectedSGPRs ? (MCPhysReg)AMDGPU::TTMP9 : getNextSystemSGPR(); 746*06c3fb27SDimitry Andric ArgInfo.WorkGroupIDX = ArgDescriptor::createRegister(Reg); 747*06c3fb27SDimitry Andric if (!HasArchitectedSGPRs) 7480b57cec5SDimitry Andric NumSystemSGPRs += 1; 749*06c3fb27SDimitry Andric 7500b57cec5SDimitry Andric return ArgInfo.WorkGroupIDX.getRegister(); 7510b57cec5SDimitry Andric } 7520b57cec5SDimitry Andric 753*06c3fb27SDimitry Andric Register addWorkGroupIDY(bool HasArchitectedSGPRs) { 754*06c3fb27SDimitry Andric Register Reg = 755*06c3fb27SDimitry Andric HasArchitectedSGPRs ? (MCPhysReg)AMDGPU::TTMP7 : getNextSystemSGPR(); 756*06c3fb27SDimitry Andric unsigned Mask = HasArchitectedSGPRs && hasWorkGroupIDZ() ? 0xffff : ~0u; 757*06c3fb27SDimitry Andric ArgInfo.WorkGroupIDY = ArgDescriptor::createRegister(Reg, Mask); 758*06c3fb27SDimitry Andric if (!HasArchitectedSGPRs) 7590b57cec5SDimitry Andric NumSystemSGPRs += 1; 760*06c3fb27SDimitry Andric 7610b57cec5SDimitry Andric return ArgInfo.WorkGroupIDY.getRegister(); 7620b57cec5SDimitry Andric } 7630b57cec5SDimitry Andric 764*06c3fb27SDimitry Andric Register addWorkGroupIDZ(bool HasArchitectedSGPRs) { 765*06c3fb27SDimitry Andric Register Reg = 766*06c3fb27SDimitry Andric HasArchitectedSGPRs ? (MCPhysReg)AMDGPU::TTMP7 : getNextSystemSGPR(); 767*06c3fb27SDimitry Andric unsigned Mask = HasArchitectedSGPRs ? 0xffff << 16 : ~0u; 768*06c3fb27SDimitry Andric ArgInfo.WorkGroupIDZ = ArgDescriptor::createRegister(Reg, Mask); 769*06c3fb27SDimitry Andric if (!HasArchitectedSGPRs) 7700b57cec5SDimitry Andric NumSystemSGPRs += 1; 771*06c3fb27SDimitry Andric 7720b57cec5SDimitry Andric return ArgInfo.WorkGroupIDZ.getRegister(); 7730b57cec5SDimitry Andric } 7740b57cec5SDimitry Andric 7755ffd83dbSDimitry Andric Register addWorkGroupInfo() { 7760b57cec5SDimitry Andric ArgInfo.WorkGroupInfo = ArgDescriptor::createRegister(getNextSystemSGPR()); 7770b57cec5SDimitry Andric NumSystemSGPRs += 1; 7780b57cec5SDimitry Andric return ArgInfo.WorkGroupInfo.getRegister(); 7790b57cec5SDimitry Andric } 7800b57cec5SDimitry Andric 7810b57cec5SDimitry Andric // Add special VGPR inputs 7820b57cec5SDimitry Andric void setWorkItemIDX(ArgDescriptor Arg) { 7830b57cec5SDimitry Andric ArgInfo.WorkItemIDX = Arg; 7840b57cec5SDimitry Andric } 7850b57cec5SDimitry Andric 7860b57cec5SDimitry Andric void setWorkItemIDY(ArgDescriptor Arg) { 7870b57cec5SDimitry Andric ArgInfo.WorkItemIDY = Arg; 7880b57cec5SDimitry Andric } 7890b57cec5SDimitry Andric 7900b57cec5SDimitry Andric void setWorkItemIDZ(ArgDescriptor Arg) { 7910b57cec5SDimitry Andric ArgInfo.WorkItemIDZ = Arg; 7920b57cec5SDimitry Andric } 7930b57cec5SDimitry Andric 7945ffd83dbSDimitry Andric Register addPrivateSegmentWaveByteOffset() { 7950b57cec5SDimitry Andric ArgInfo.PrivateSegmentWaveByteOffset 7960b57cec5SDimitry Andric = ArgDescriptor::createRegister(getNextSystemSGPR()); 7970b57cec5SDimitry Andric NumSystemSGPRs += 1; 7980b57cec5SDimitry Andric return ArgInfo.PrivateSegmentWaveByteOffset.getRegister(); 7990b57cec5SDimitry Andric } 8000b57cec5SDimitry Andric 8015ffd83dbSDimitry Andric void setPrivateSegmentWaveByteOffset(Register Reg) { 8020b57cec5SDimitry Andric ArgInfo.PrivateSegmentWaveByteOffset = ArgDescriptor::createRegister(Reg); 8030b57cec5SDimitry Andric } 8040b57cec5SDimitry Andric 8050b57cec5SDimitry Andric bool hasPrivateSegmentBuffer() const { 8060b57cec5SDimitry Andric return PrivateSegmentBuffer; 8070b57cec5SDimitry Andric } 8080b57cec5SDimitry Andric 8090b57cec5SDimitry Andric bool hasDispatchPtr() const { 8100b57cec5SDimitry Andric return DispatchPtr; 8110b57cec5SDimitry Andric } 8120b57cec5SDimitry Andric 8130b57cec5SDimitry Andric bool hasQueuePtr() const { 8140b57cec5SDimitry Andric return QueuePtr; 8150b57cec5SDimitry Andric } 8160b57cec5SDimitry Andric 8170b57cec5SDimitry Andric bool hasKernargSegmentPtr() const { 8180b57cec5SDimitry Andric return KernargSegmentPtr; 8190b57cec5SDimitry Andric } 8200b57cec5SDimitry Andric 8210b57cec5SDimitry Andric bool hasDispatchID() const { 8220b57cec5SDimitry Andric return DispatchID; 8230b57cec5SDimitry Andric } 8240b57cec5SDimitry Andric 8250b57cec5SDimitry Andric bool hasFlatScratchInit() const { 8260b57cec5SDimitry Andric return FlatScratchInit; 8270b57cec5SDimitry Andric } 8280b57cec5SDimitry Andric 8290b57cec5SDimitry Andric bool hasWorkGroupIDX() const { 8300b57cec5SDimitry Andric return WorkGroupIDX; 8310b57cec5SDimitry Andric } 8320b57cec5SDimitry Andric 8330b57cec5SDimitry Andric bool hasWorkGroupIDY() const { 8340b57cec5SDimitry Andric return WorkGroupIDY; 8350b57cec5SDimitry Andric } 8360b57cec5SDimitry Andric 8370b57cec5SDimitry Andric bool hasWorkGroupIDZ() const { 8380b57cec5SDimitry Andric return WorkGroupIDZ; 8390b57cec5SDimitry Andric } 8400b57cec5SDimitry Andric 8410b57cec5SDimitry Andric bool hasWorkGroupInfo() const { 8420b57cec5SDimitry Andric return WorkGroupInfo; 8430b57cec5SDimitry Andric } 8440b57cec5SDimitry Andric 845fcaf7f86SDimitry Andric bool hasLDSKernelId() const { return LDSKernelId; } 846fcaf7f86SDimitry Andric 8470b57cec5SDimitry Andric bool hasPrivateSegmentWaveByteOffset() const { 8480b57cec5SDimitry Andric return PrivateSegmentWaveByteOffset; 8490b57cec5SDimitry Andric } 8500b57cec5SDimitry Andric 8510b57cec5SDimitry Andric bool hasWorkItemIDX() const { 8520b57cec5SDimitry Andric return WorkItemIDX; 8530b57cec5SDimitry Andric } 8540b57cec5SDimitry Andric 8550b57cec5SDimitry Andric bool hasWorkItemIDY() const { 8560b57cec5SDimitry Andric return WorkItemIDY; 8570b57cec5SDimitry Andric } 8580b57cec5SDimitry Andric 8590b57cec5SDimitry Andric bool hasWorkItemIDZ() const { 8600b57cec5SDimitry Andric return WorkItemIDZ; 8610b57cec5SDimitry Andric } 8620b57cec5SDimitry Andric 8630b57cec5SDimitry Andric bool hasImplicitArgPtr() const { 8640b57cec5SDimitry Andric return ImplicitArgPtr; 8650b57cec5SDimitry Andric } 8660b57cec5SDimitry Andric 8670b57cec5SDimitry Andric bool hasImplicitBufferPtr() const { 8680b57cec5SDimitry Andric return ImplicitBufferPtr; 8690b57cec5SDimitry Andric } 8700b57cec5SDimitry Andric 8710b57cec5SDimitry Andric AMDGPUFunctionArgInfo &getArgInfo() { 8720b57cec5SDimitry Andric return ArgInfo; 8730b57cec5SDimitry Andric } 8740b57cec5SDimitry Andric 8750b57cec5SDimitry Andric const AMDGPUFunctionArgInfo &getArgInfo() const { 8760b57cec5SDimitry Andric return ArgInfo; 8770b57cec5SDimitry Andric } 8780b57cec5SDimitry Andric 8795ffd83dbSDimitry Andric std::tuple<const ArgDescriptor *, const TargetRegisterClass *, LLT> 8800b57cec5SDimitry Andric getPreloadedValue(AMDGPUFunctionArgInfo::PreloadedValue Value) const { 8810b57cec5SDimitry Andric return ArgInfo.getPreloadedValue(Value); 8820b57cec5SDimitry Andric } 8830b57cec5SDimitry Andric 884e8d8bef9SDimitry Andric MCRegister getPreloadedReg(AMDGPUFunctionArgInfo::PreloadedValue Value) const { 8855ffd83dbSDimitry Andric auto Arg = std::get<0>(ArgInfo.getPreloadedValue(Value)); 886e8d8bef9SDimitry Andric return Arg ? Arg->getRegister() : MCRegister(); 8870b57cec5SDimitry Andric } 8880b57cec5SDimitry Andric 8890b57cec5SDimitry Andric unsigned getGITPtrHigh() const { 8900b57cec5SDimitry Andric return GITPtrHigh; 8910b57cec5SDimitry Andric } 8920b57cec5SDimitry Andric 8935ffd83dbSDimitry Andric Register getGITPtrLoReg(const MachineFunction &MF) const; 8945ffd83dbSDimitry Andric 8958bcb0991SDimitry Andric uint32_t get32BitAddressHighBits() const { 8960b57cec5SDimitry Andric return HighBitsOf32BitAddress; 8970b57cec5SDimitry Andric } 8980b57cec5SDimitry Andric 8990b57cec5SDimitry Andric unsigned getNumUserSGPRs() const { 9000b57cec5SDimitry Andric return NumUserSGPRs; 9010b57cec5SDimitry Andric } 9020b57cec5SDimitry Andric 9030b57cec5SDimitry Andric unsigned getNumPreloadedSGPRs() const { 9040b57cec5SDimitry Andric return NumUserSGPRs + NumSystemSGPRs; 9050b57cec5SDimitry Andric } 9060b57cec5SDimitry Andric 9075ffd83dbSDimitry Andric Register getPrivateSegmentWaveByteOffsetSystemSGPR() const { 9080b57cec5SDimitry Andric return ArgInfo.PrivateSegmentWaveByteOffset.getRegister(); 9090b57cec5SDimitry Andric } 9100b57cec5SDimitry Andric 9110b57cec5SDimitry Andric /// Returns the physical register reserved for use as the resource 9120b57cec5SDimitry Andric /// descriptor for scratch accesses. 9135ffd83dbSDimitry Andric Register getScratchRSrcReg() const { 9140b57cec5SDimitry Andric return ScratchRSrcReg; 9150b57cec5SDimitry Andric } 9160b57cec5SDimitry Andric 9175ffd83dbSDimitry Andric void setScratchRSrcReg(Register Reg) { 9180b57cec5SDimitry Andric assert(Reg != 0 && "Should never be unset"); 9190b57cec5SDimitry Andric ScratchRSrcReg = Reg; 9200b57cec5SDimitry Andric } 9210b57cec5SDimitry Andric 9225ffd83dbSDimitry Andric Register getFrameOffsetReg() const { 9230b57cec5SDimitry Andric return FrameOffsetReg; 9240b57cec5SDimitry Andric } 9250b57cec5SDimitry Andric 9265ffd83dbSDimitry Andric void setFrameOffsetReg(Register Reg) { 9270b57cec5SDimitry Andric assert(Reg != 0 && "Should never be unset"); 9280b57cec5SDimitry Andric FrameOffsetReg = Reg; 9290b57cec5SDimitry Andric } 9300b57cec5SDimitry Andric 9315ffd83dbSDimitry Andric void setStackPtrOffsetReg(Register Reg) { 9320b57cec5SDimitry Andric assert(Reg != 0 && "Should never be unset"); 9330b57cec5SDimitry Andric StackPtrOffsetReg = Reg; 9340b57cec5SDimitry Andric } 9350b57cec5SDimitry Andric 936*06c3fb27SDimitry Andric void setLongBranchReservedReg(Register Reg) { LongBranchReservedReg = Reg; } 937*06c3fb27SDimitry Andric 9380b57cec5SDimitry Andric // Note the unset value for this is AMDGPU::SP_REG rather than 9390b57cec5SDimitry Andric // NoRegister. This is mostly a workaround for MIR tests where state that 9400b57cec5SDimitry Andric // can't be directly computed from the function is not preserved in serialized 9410b57cec5SDimitry Andric // MIR. 9425ffd83dbSDimitry Andric Register getStackPtrOffsetReg() const { 9430b57cec5SDimitry Andric return StackPtrOffsetReg; 9440b57cec5SDimitry Andric } 9450b57cec5SDimitry Andric 946*06c3fb27SDimitry Andric Register getLongBranchReservedReg() const { return LongBranchReservedReg; } 947*06c3fb27SDimitry Andric 9485ffd83dbSDimitry Andric Register getQueuePtrUserSGPR() const { 9490b57cec5SDimitry Andric return ArgInfo.QueuePtr.getRegister(); 9500b57cec5SDimitry Andric } 9510b57cec5SDimitry Andric 9525ffd83dbSDimitry Andric Register getImplicitBufferPtrUserSGPR() const { 9530b57cec5SDimitry Andric return ArgInfo.ImplicitBufferPtr.getRegister(); 9540b57cec5SDimitry Andric } 9550b57cec5SDimitry Andric 9560b57cec5SDimitry Andric bool hasSpilledSGPRs() const { 9570b57cec5SDimitry Andric return HasSpilledSGPRs; 9580b57cec5SDimitry Andric } 9590b57cec5SDimitry Andric 9600b57cec5SDimitry Andric void setHasSpilledSGPRs(bool Spill = true) { 9610b57cec5SDimitry Andric HasSpilledSGPRs = Spill; 9620b57cec5SDimitry Andric } 9630b57cec5SDimitry Andric 9640b57cec5SDimitry Andric bool hasSpilledVGPRs() const { 9650b57cec5SDimitry Andric return HasSpilledVGPRs; 9660b57cec5SDimitry Andric } 9670b57cec5SDimitry Andric 9680b57cec5SDimitry Andric void setHasSpilledVGPRs(bool Spill = true) { 9690b57cec5SDimitry Andric HasSpilledVGPRs = Spill; 9700b57cec5SDimitry Andric } 9710b57cec5SDimitry Andric 9720b57cec5SDimitry Andric bool hasNonSpillStackObjects() const { 9730b57cec5SDimitry Andric return HasNonSpillStackObjects; 9740b57cec5SDimitry Andric } 9750b57cec5SDimitry Andric 9760b57cec5SDimitry Andric void setHasNonSpillStackObjects(bool StackObject = true) { 9770b57cec5SDimitry Andric HasNonSpillStackObjects = StackObject; 9780b57cec5SDimitry Andric } 9790b57cec5SDimitry Andric 9800b57cec5SDimitry Andric bool isStackRealigned() const { 9810b57cec5SDimitry Andric return IsStackRealigned; 9820b57cec5SDimitry Andric } 9830b57cec5SDimitry Andric 9840b57cec5SDimitry Andric void setIsStackRealigned(bool Realigned = true) { 9850b57cec5SDimitry Andric IsStackRealigned = Realigned; 9860b57cec5SDimitry Andric } 9870b57cec5SDimitry Andric 9880b57cec5SDimitry Andric unsigned getNumSpilledSGPRs() const { 9890b57cec5SDimitry Andric return NumSpilledSGPRs; 9900b57cec5SDimitry Andric } 9910b57cec5SDimitry Andric 9920b57cec5SDimitry Andric unsigned getNumSpilledVGPRs() const { 9930b57cec5SDimitry Andric return NumSpilledVGPRs; 9940b57cec5SDimitry Andric } 9950b57cec5SDimitry Andric 9960b57cec5SDimitry Andric void addToSpilledSGPRs(unsigned num) { 9970b57cec5SDimitry Andric NumSpilledSGPRs += num; 9980b57cec5SDimitry Andric } 9990b57cec5SDimitry Andric 10000b57cec5SDimitry Andric void addToSpilledVGPRs(unsigned num) { 10010b57cec5SDimitry Andric NumSpilledVGPRs += num; 10020b57cec5SDimitry Andric } 10030b57cec5SDimitry Andric 10040b57cec5SDimitry Andric unsigned getPSInputAddr() const { 10050b57cec5SDimitry Andric return PSInputAddr; 10060b57cec5SDimitry Andric } 10070b57cec5SDimitry Andric 10080b57cec5SDimitry Andric unsigned getPSInputEnable() const { 10090b57cec5SDimitry Andric return PSInputEnable; 10100b57cec5SDimitry Andric } 10110b57cec5SDimitry Andric 10120b57cec5SDimitry Andric bool isPSInputAllocated(unsigned Index) const { 10130b57cec5SDimitry Andric return PSInputAddr & (1 << Index); 10140b57cec5SDimitry Andric } 10150b57cec5SDimitry Andric 10160b57cec5SDimitry Andric void markPSInputAllocated(unsigned Index) { 10170b57cec5SDimitry Andric PSInputAddr |= 1 << Index; 10180b57cec5SDimitry Andric } 10190b57cec5SDimitry Andric 10200b57cec5SDimitry Andric void markPSInputEnabled(unsigned Index) { 10210b57cec5SDimitry Andric PSInputEnable |= 1 << Index; 10220b57cec5SDimitry Andric } 10230b57cec5SDimitry Andric 10240b57cec5SDimitry Andric bool returnsVoid() const { 10250b57cec5SDimitry Andric return ReturnsVoid; 10260b57cec5SDimitry Andric } 10270b57cec5SDimitry Andric 10280b57cec5SDimitry Andric void setIfReturnsVoid(bool Value) { 10290b57cec5SDimitry Andric ReturnsVoid = Value; 10300b57cec5SDimitry Andric } 10310b57cec5SDimitry Andric 10320b57cec5SDimitry Andric /// \returns A pair of default/requested minimum/maximum flat work group sizes 10330b57cec5SDimitry Andric /// for this function. 10340b57cec5SDimitry Andric std::pair<unsigned, unsigned> getFlatWorkGroupSizes() const { 10350b57cec5SDimitry Andric return FlatWorkGroupSizes; 10360b57cec5SDimitry Andric } 10370b57cec5SDimitry Andric 10380b57cec5SDimitry Andric /// \returns Default/requested minimum flat work group size for this function. 10390b57cec5SDimitry Andric unsigned getMinFlatWorkGroupSize() const { 10400b57cec5SDimitry Andric return FlatWorkGroupSizes.first; 10410b57cec5SDimitry Andric } 10420b57cec5SDimitry Andric 10430b57cec5SDimitry Andric /// \returns Default/requested maximum flat work group size for this function. 10440b57cec5SDimitry Andric unsigned getMaxFlatWorkGroupSize() const { 10450b57cec5SDimitry Andric return FlatWorkGroupSizes.second; 10460b57cec5SDimitry Andric } 10470b57cec5SDimitry Andric 10480b57cec5SDimitry Andric /// \returns A pair of default/requested minimum/maximum number of waves per 10490b57cec5SDimitry Andric /// execution unit. 10500b57cec5SDimitry Andric std::pair<unsigned, unsigned> getWavesPerEU() const { 10510b57cec5SDimitry Andric return WavesPerEU; 10520b57cec5SDimitry Andric } 10530b57cec5SDimitry Andric 10540b57cec5SDimitry Andric /// \returns Default/requested minimum number of waves per execution unit. 10550b57cec5SDimitry Andric unsigned getMinWavesPerEU() const { 10560b57cec5SDimitry Andric return WavesPerEU.first; 10570b57cec5SDimitry Andric } 10580b57cec5SDimitry Andric 10590b57cec5SDimitry Andric /// \returns Default/requested maximum number of waves per execution unit. 10600b57cec5SDimitry Andric unsigned getMaxWavesPerEU() const { 10610b57cec5SDimitry Andric return WavesPerEU.second; 10620b57cec5SDimitry Andric } 10630b57cec5SDimitry Andric 10640b57cec5SDimitry Andric /// \returns SGPR used for \p Dim's work group ID. 10655ffd83dbSDimitry Andric Register getWorkGroupIDSGPR(unsigned Dim) const { 10660b57cec5SDimitry Andric switch (Dim) { 10670b57cec5SDimitry Andric case 0: 10680b57cec5SDimitry Andric assert(hasWorkGroupIDX()); 10690b57cec5SDimitry Andric return ArgInfo.WorkGroupIDX.getRegister(); 10700b57cec5SDimitry Andric case 1: 10710b57cec5SDimitry Andric assert(hasWorkGroupIDY()); 10720b57cec5SDimitry Andric return ArgInfo.WorkGroupIDY.getRegister(); 10730b57cec5SDimitry Andric case 2: 10740b57cec5SDimitry Andric assert(hasWorkGroupIDZ()); 10750b57cec5SDimitry Andric return ArgInfo.WorkGroupIDZ.getRegister(); 10760b57cec5SDimitry Andric } 10770b57cec5SDimitry Andric llvm_unreachable("unexpected dimension"); 10780b57cec5SDimitry Andric } 10790b57cec5SDimitry Andric 108081ad6265SDimitry Andric const AMDGPUGWSResourcePseudoSourceValue * 108181ad6265SDimitry Andric getGWSPSV(const AMDGPUTargetMachine &TM) { 108281ad6265SDimitry Andric return &GWSResourcePSV; 10830b57cec5SDimitry Andric } 10840b57cec5SDimitry Andric 10850b57cec5SDimitry Andric unsigned getOccupancy() const { 10860b57cec5SDimitry Andric return Occupancy; 10870b57cec5SDimitry Andric } 10880b57cec5SDimitry Andric 10890b57cec5SDimitry Andric unsigned getMinAllowedOccupancy() const { 10900b57cec5SDimitry Andric if (!isMemoryBound() && !needsWaveLimiter()) 10910b57cec5SDimitry Andric return Occupancy; 10920b57cec5SDimitry Andric return (Occupancy < 4) ? Occupancy : 4; 10930b57cec5SDimitry Andric } 10940b57cec5SDimitry Andric 10950b57cec5SDimitry Andric void limitOccupancy(const MachineFunction &MF); 10960b57cec5SDimitry Andric 10970b57cec5SDimitry Andric void limitOccupancy(unsigned Limit) { 10980b57cec5SDimitry Andric if (Occupancy > Limit) 10990b57cec5SDimitry Andric Occupancy = Limit; 11000b57cec5SDimitry Andric } 11010b57cec5SDimitry Andric 11020b57cec5SDimitry Andric void increaseOccupancy(const MachineFunction &MF, unsigned Limit) { 11030b57cec5SDimitry Andric if (Occupancy < Limit) 11040b57cec5SDimitry Andric Occupancy = Limit; 11050b57cec5SDimitry Andric limitOccupancy(MF); 11060b57cec5SDimitry Andric } 1107349cc55cSDimitry Andric 110881ad6265SDimitry Andric bool mayNeedAGPRs() const { 110981ad6265SDimitry Andric return MayNeedAGPRs; 111081ad6265SDimitry Andric } 111181ad6265SDimitry Andric 111281ad6265SDimitry Andric // \returns true if a function has a use of AGPRs via inline asm or 111381ad6265SDimitry Andric // has a call which may use it. 1114bdd1243dSDimitry Andric bool mayUseAGPRs(const Function &F) const; 111581ad6265SDimitry Andric 1116349cc55cSDimitry Andric // \returns true if a function needs or may need AGPRs. 1117349cc55cSDimitry Andric bool usesAGPRs(const MachineFunction &MF) const; 11180b57cec5SDimitry Andric }; 11190b57cec5SDimitry Andric 11200b57cec5SDimitry Andric } // end namespace llvm 11210b57cec5SDimitry Andric 11220b57cec5SDimitry Andric #endif // LLVM_LIB_TARGET_AMDGPU_SIMACHINEFUNCTIONINFO_H 1123