Index: lib/Target/AMDGPU/AMDGPUAsmPrinter.h =================================================================== --- lib/Target/AMDGPU/AMDGPUAsmPrinter.h +++ lib/Target/AMDGPU/AMDGPUAsmPrinter.h @@ -40,6 +40,8 @@ NumVGPR(0), NumSGPR(0), FlatUsed(false), + NumSGPRsForNumActiveWavesPerEU(0), + NumVGPRsForNumActiveWavesPerEU(0), ReservedVGPRFirst(0), ReservedVGPRCount(0), DebuggerWavefrontPrivateSegmentOffsetSGPR((uint16_t)-1), @@ -71,6 +73,13 @@ uint32_t LDSSize; bool FlatUsed; + // Number of SGPRs that meets number of active waves per execution unit + // request. + uint32_t NumSGPRsForNumActiveWavesPerEU; + // Number of VGPRs that meets number of active waves per execution unit + // request. + uint32_t NumVGPRsForNumActiveWavesPerEU; + // If ReservedVGPRCount is 0 then must be 0. Otherwise, this is the first // fixed VGPR number reserved. uint16_t ReservedVGPRFirst; Index: lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -202,6 +202,16 @@ OutStreamer->emitRawComment(" LDSByteSize: " + Twine(KernelInfo.LDSSize) + " bytes/workgroup (compile time only)", false); + OutStreamer->emitRawComment(" SGPRBlocks: " + + Twine(KernelInfo.SGPRBlocks), false); + OutStreamer->emitRawComment(" VGPRBlocks: " + + Twine(KernelInfo.VGPRBlocks), false); + + OutStreamer->emitRawComment(" NumSGPRsForNumActiveWavesPerEU: " + + Twine(KernelInfo.NumSGPRsForNumActiveWavesPerEU), false); + OutStreamer->emitRawComment(" NumVGPRsForNumActiveWavesPerEU: " + + Twine(KernelInfo.NumVGPRsForNumActiveWavesPerEU), false); + OutStreamer->emitRawComment(" ReservedVGPRFirst: " + Twine(KernelInfo.ReservedVGPRFirst), false); OutStreamer->emitRawComment(" ReservedVGPRCount: " + Twine(KernelInfo.ReservedVGPRCount), @@ -446,16 +456,11 @@ ExtraSGPRs = 6; } - MaxSGPR += ExtraSGPRs; - // Record first reserved register and reserved register count fields, and // update max register counts if "amdgpu-debugger-reserve-regs" attribute was - // specified. - if (STM.debuggerReserveRegs()) { - ProgInfo.ReservedVGPRFirst = MaxVGPR + 1; - ProgInfo.ReservedVGPRCount = MFI->getDebuggerReservedVGPRCount(); - MaxVGPR += MFI->getDebuggerReservedVGPRCount(); - } + // requested. + ProgInfo.ReservedVGPRFirst = STM.debuggerReserveRegs() ? MaxVGPR + 1 : 0; + ProgInfo.ReservedVGPRCount = RI->getDebuggerReservedNumVGPRs(STM); // Update DebuggerWavefrontPrivateSegmentOffsetSGPR and // DebuggerPrivateSegmentBufferSGPR fields if "amdgpu-debugger-emit-prologue" @@ -467,11 +472,24 @@ RI->getHWRegIndex(MFI->getScratchRSrcReg()); } + // Account for extra SGPRs and VGPRs reserved for debugger usage. + MaxSGPR += ExtraSGPRs; + MaxVGPR += RI->getDebuggerReservedNumVGPRs(STM); + // We found the maximum register index. They start at 0, so add one to get the // number of registers. ProgInfo.NumVGPR = MaxVGPR + 1; ProgInfo.NumSGPR = MaxSGPR + 1; + // Adjust number of registers used to meet default/requested minimum/maximum + // number of active waves per execution unit request. + ProgInfo.NumSGPRsForNumActiveWavesPerEU = std::max( + ProgInfo.NumSGPR, + RI->getMinNumSGPRs(STM, MFI->getMaxNumActiveWavesPerEU())); + ProgInfo.NumVGPRsForNumActiveWavesPerEU = std::max( + ProgInfo.NumVGPR, + RI->getMinNumVGPRs(MFI->getMaxNumActiveWavesPerEU())); + if (STM.hasSGPRInitBug()) { if (ProgInfo.NumSGPR > SISubtarget::FIXED_SGPR_COUNT_FOR_INIT_BUG) { LLVMContext &Ctx = MF.getFunction()->getContext(); @@ -482,6 +500,8 @@ } ProgInfo.NumSGPR = SISubtarget::FIXED_SGPR_COUNT_FOR_INIT_BUG; + ProgInfo.NumSGPRsForNumActiveWavesPerEU = + SISubtarget::FIXED_SGPR_COUNT_FOR_INIT_BUG; } if (MFI->NumUserSGPRs > STM.getMaxNumUserSGPRs()) { @@ -498,8 +518,15 @@ Ctx.diagnose(Diag); } - ProgInfo.VGPRBlocks = (ProgInfo.NumVGPR - 1) / 4; - ProgInfo.SGPRBlocks = (ProgInfo.NumSGPR - 1) / 8; + // SGPRBlocks is actual number of SGPR blocks minus 1. + ProgInfo.SGPRBlocks = alignTo(ProgInfo.NumSGPRsForNumActiveWavesPerEU, + RI->getSGPRAllocGranule()); + ProgInfo.SGPRBlocks = ProgInfo.SGPRBlocks / RI->getSGPRAllocGranule() - 1; + // VGPRBlocks is actual number of VGPR blocks minus 1. + ProgInfo.VGPRBlocks = alignTo(ProgInfo.NumVGPRsForNumActiveWavesPerEU, + RI->getVGPRAllocGranule()); + ProgInfo.VGPRBlocks = ProgInfo.VGPRBlocks / RI->getVGPRAllocGranule() - 1; + // Set the value to initialize FP_ROUND and FP_DENORM parts of the mode // register. ProgInfo.FloatMode = getFPMode(MF); @@ -525,8 +552,8 @@ LDSAlignShift = 9; } - unsigned LDSSpillSize = MFI->LDSWaveSpillSize * - MFI->getMaximumWorkGroupSize(MF); + unsigned LDSSpillSize = + MFI->LDSWaveSpillSize * MFI->getMaxFlatWorkGroupSize(); ProgInfo.LDSSize = MFI->getLDSSize() + LDSSpillSize; ProgInfo.LDSBlocks = Index: lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp +++ lib/Target/AMDGPU/AMDGPUPromoteAlloca.cpp @@ -184,13 +184,12 @@ // TODO: Have some sort of hint or other heuristics to guess occupancy based // on other factors.. - unsigned OccupancyHint - = AMDGPU::getIntegerAttribute(F, "amdgpu-max-waves-per-eu", 0); + unsigned OccupancyHint = ST.getNumActiveWavesPerEU(F).second; if (OccupancyHint == 0) OccupancyHint = 7; // Clamp to max value. - OccupancyHint = std::min(OccupancyHint, ST.getMaxWavesPerCU()); + OccupancyHint = std::min(OccupancyHint, ST.getMaxNumActiveWavesPerEU()); // Check the hint but ignore it if it's obviously wrong from the existing LDS // usage. @@ -650,9 +649,11 @@ if (AMDGPU::isShader(ContainingFunction.getCallingConv())) return; + const AMDGPUSubtarget &ST = + TM->getSubtarget(ContainingFunction); // FIXME: We should also try to get this value from the reqd_work_group_size // function attribute if it is available. - unsigned WorkGroupSize = AMDGPU::getMaximumWorkGroupSize(ContainingFunction); + unsigned WorkGroupSize = ST.getFlatWorkGroupSizes(ContainingFunction).second; const DataLayout &DL = Mod->getDataLayout(); Index: lib/Target/AMDGPU/AMDGPUSubtarget.h =================================================================== --- lib/Target/AMDGPU/AMDGPUSubtarget.h +++ lib/Target/AMDGPU/AMDGPUSubtarget.h @@ -263,14 +263,6 @@ return EnableXNACK; } - unsigned getMaxWavesPerCU() const { - if (getGeneration() >= AMDGPUSubtarget::SOUTHERN_ISLANDS) - return 10; - - // FIXME: Not sure what this is for other subtagets. - return 8; - } - /// \brief Returns the offset in bytes from the start of the input buffer /// of the first explicit kernel argument. unsigned getExplicitKernelArgOffset() const { @@ -289,6 +281,104 @@ bool enableSubRegLiveness() const override { return true; } + + /// Returns number of execution units per compute unit supported by the + /// subtarget. + unsigned getNumEUsPerCU() const { + return 4; + } + + /// Returns maximum number of work groups per compute unit supported by the + /// subtarget and limited by given flat work group size. + unsigned getMaxNumWorkGroupsPerCU(unsigned FlatWorkGroupSize) const { + if (getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS) + return 8; + return getNumWavesPerWorkGroup(FlatWorkGroupSize) == 1 ? 40 : 16; + } + + /// Returns maximum number of active waves per compute unit supported by the + /// subtarget without any kind of limitation. + unsigned getMaxNumActiveWavesPerCU() const { + return getMaxNumActiveWavesPerEU() * getNumEUsPerCU(); + } + + /// Returns maximum number of active waves per compute unit supported by the + /// subtarget and limited by given flat work group size. + unsigned getMaxNumActiveWavesPerCU(unsigned FlatWorkGroupSize) const { + unsigned NumWavesPerWorkGroup = + getNumWavesPerWorkGroup(FlatWorkGroupSize); + unsigned MaxNumWorkGroupsPerCU = + getMaxNumWorkGroupsPerCU(FlatWorkGroupSize); + unsigned MaxNumActiveWavesPerCU = + NumWavesPerWorkGroup * MaxNumWorkGroupsPerCU; + MaxNumActiveWavesPerCU = + std::min(MaxNumActiveWavesPerCU, getMaxNumActiveWavesPerCU()); + MaxNumActiveWavesPerCU = + alignDown(MaxNumActiveWavesPerCU, NumWavesPerWorkGroup); + MaxNumActiveWavesPerCU = MaxNumActiveWavesPerCU / NumWavesPerWorkGroup; + MaxNumActiveWavesPerCU = MaxNumActiveWavesPerCU * NumWavesPerWorkGroup; + return MaxNumActiveWavesPerCU; + } + + /// Returns minimum number of active waves per execution unit supported by the + /// subtarget. + unsigned getMinNumActiveWavesPerEU() const { + return 1; + } + + /// Returns maximum number of active waves per execution unit supported by the + /// subtarget without any kind of limitation. + unsigned getMaxNumActiveWavesPerEU() const { + // FIXME: Not sure what this is for subtargets below Southern Islands. + if (getGeneration() < AMDGPUSubtarget::SOUTHERN_ISLANDS) + return 8; + // FIXME: Need to take scratch memory into account. + return 10; + } + + /// Returns maximum number of active waves per execution unit supported by the + /// subtarget and limited by given flat work group size. + unsigned getMaxNumActiveWavesPerEU(unsigned FlatWorkGroupSize) const { + unsigned MaxNumActiveWavesPerCU = + getMaxNumActiveWavesPerCU(FlatWorkGroupSize); + unsigned MaxNumActiveWavesPerEU = + alignDown(MaxNumActiveWavesPerCU, getNumEUsPerCU()); + MaxNumActiveWavesPerEU = MaxNumActiveWavesPerEU / getNumEUsPerCU(); + return MaxNumActiveWavesPerEU; + } + + /// Returns minimum flat work group size supported by the subtarget. + unsigned getMinFlatWorkGroupSize() const { + return 1; + } + + /// Returns maximum flat work group size supported by the subtarget. + unsigned getMaxFlatWorkGroupSize() const { + return 2048; + } + + /// Returns number of waves per work group given the flat work group size. + unsigned getNumWavesPerWorkGroup(unsigned FlatWorkGroupSize) const { + return alignTo(FlatWorkGroupSize, getWavefrontSize()) / getWavefrontSize(); + } + + /// Returns subtarget's default pair of minimum/maximum flat work group sizes + /// for function \p F, or minimum/maximum flat work group sizes explicitly + /// requested using "amdgpu-flat-work-group-size" attribute attached to + /// function \p F. Returns subtarget's default values and emits error if + /// explicitly requested values cannot be converted to integer, or violate + /// subtarget's specifications. + std::pair getFlatWorkGroupSizes(const Function &F) const; + + /// Returns subtarget's default pair of minimum/maximum number of active waves + /// per execution unit for function \p F, or minimum/maximum number of active + /// waves per execution unit explicitly requested using + /// "amdgpu-num-active-waves-per-eu" attribute attached to function \p F. + /// Returns subtarget's default values and emits error if explicitly requested + /// values cannot be converted to integer, violate subtarget's specifications, + /// or are not compatible with minimum/maximum number of active waves limited + /// by flat work group size, register usage, and/or lds usage. + std::pair getNumActiveWavesPerEU(const Function &F) const; }; class R600Subtarget final : public AMDGPUSubtarget { Index: lib/Target/AMDGPU/AMDGPUSubtarget.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUSubtarget.cpp +++ lib/Target/AMDGPU/AMDGPUSubtarget.cpp @@ -178,6 +178,82 @@ return 1; } +std::pair AMDGPUSubtarget::getFlatWorkGroupSizes( + const Function &F) const { + + // Default minimum/maximum flat work group sizes. + std::pair Default = + AMDGPU::isCompute(F.getCallingConv()) ? + std::pair(128, 256) : + std::pair(1, getWavefrontSize()); + + // Requested minimum/maximum flat work group sizes. + std::pair Requested = + AMDGPU::getIntegerPairAttribute(F, "amdgpu-flat-work-group-size", Default); + + // Make sure requested minimum is less than requested maximum. + if (Requested.first > Requested.second) + return Default; + + // Make sure requested values do not violate subtarget's specifications. + if (Requested.first < getMinFlatWorkGroupSize()) + return Default; + if (Requested.second > getMaxFlatWorkGroupSize()) + return Default; + + return Requested; +} + +std::pair AMDGPUSubtarget::getNumActiveWavesPerEU( + const Function &F) const { + + // Default minimum/maximum number of active waves per execution unit. + std::pair Default = std::pair(1, 0); + + // Default/requested minimum/maximum flat work group sizes. + std::pair FlatWorkGroupSizes = getFlatWorkGroupSizes(F); + + // If minimum/maximum flat work group sizes were explicitly requested using + // "amdgpu-flat-work-group-size" attribute, then set default minimum/maximum + // number of active waves per execution unit to values implied by requested + // minimum/maximum flat work group sizes. + unsigned ImpliedByMinFlatWorkGroupSize = + getMaxNumActiveWavesPerEU(FlatWorkGroupSizes.first); + unsigned ImpliedByMaxFlatWorkGroupSize = + getMaxNumActiveWavesPerEU(FlatWorkGroupSizes.second); + unsigned MinImpliedByFlatWorkGroupSize = + std::min(ImpliedByMinFlatWorkGroupSize, ImpliedByMaxFlatWorkGroupSize); + unsigned MaxImpliedByFlatWorkGroupSize = + std::max(ImpliedByMinFlatWorkGroupSize, ImpliedByMaxFlatWorkGroupSize); + if (F.hasFnAttribute("amdgpu-flat-work-group-size")) { + Default.first = MinImpliedByFlatWorkGroupSize; + Default.second = MaxImpliedByFlatWorkGroupSize; + } + + // Requested minimum/maximum number of active waves per execution unit. + std::pair Requested = AMDGPU::getIntegerPairAttribute( + F, "amdgpu-num-active-waves-per-eu", Default, true); + + // Make sure requested minimum is less than requested maximum. + if (Requested.second && Requested.first > Requested.second) + return Default; + + // Make sure requested values do not violate subtarget's specifications. + if (Requested.first < getMinNumActiveWavesPerEU() || + Requested.first > getMaxNumActiveWavesPerEU()) + return Default; + if (Requested.second > getMaxNumActiveWavesPerEU()) + return Default; + + // Make sure requested values are compatible with values implied by requested + // minimum/maximum flat work group sizes. + if (Requested.first > MinImpliedByFlatWorkGroupSize || + Requested.second > MaxImpliedByFlatWorkGroupSize) + return Default; + + return Requested; +} + R600Subtarget::R600Subtarget(const Triple &TT, StringRef GPU, StringRef FS, const TargetMachine &TM) : AMDGPUSubtarget(TT, GPU, FS, TM), Index: lib/Target/AMDGPU/SIInstrInfo.cpp =================================================================== --- lib/Target/AMDGPU/SIInstrInfo.cpp +++ lib/Target/AMDGPU/SIInstrInfo.cpp @@ -729,7 +729,7 @@ const SISubtarget &ST = MF->getSubtarget(); const SIRegisterInfo *TRI = ST.getRegisterInfo(); DebugLoc DL = MBB.findDebugLoc(MI); - unsigned WorkGroupSize = MFI->getMaximumWorkGroupSize(*MF); + unsigned WorkGroupSize = MFI->getMaxFlatWorkGroupSize(); unsigned WavefrontSize = ST.getWavefrontSize(); unsigned TIDReg = MFI->getTIDReg(); Index: lib/Target/AMDGPU/SIMachineFunctionInfo.h =================================================================== --- lib/Target/AMDGPU/SIMachineFunctionInfo.h +++ lib/Target/AMDGPU/SIMachineFunctionInfo.h @@ -60,10 +60,14 @@ unsigned PSInputAddr; bool ReturnsVoid; - unsigned MaximumWorkGroupSize; + // A pair of default/requested minimum/maximum flat work group sizes. + // Minimum - first, maximum - second. + std::pair FlatWorkGroupSizes; + + // A pair of default/requested minimum/maximum number of active waves per + // execution unit. Minimum - first, maximum - second. + std::pair NumActiveWavesPerEU; - // Number of reserved VGPRs for debugger usage. - unsigned DebuggerReservedVGPRCount; // Stack object indices for work group IDs. std::array DebuggerWorkGroupIDStackObjectIndices; // Stack object indices for work item IDs. @@ -352,9 +356,38 @@ ReturnsVoid = Value; } - /// \returns Number of reserved VGPRs for debugger usage. - unsigned getDebuggerReservedVGPRCount() const { - return DebuggerReservedVGPRCount; + /// Returns a pair of default/requested minimum/maximum flat work group sizes + /// for this function. + std::pair getFlatWorkGroupSizes() const { + return FlatWorkGroupSizes; + } + + /// Returns default/requested minimum flat work group size for this function. + unsigned getMinFlatWorkGroupSize() const { + return FlatWorkGroupSizes.first; + } + + /// Returns default/requested maximum flat work group sizes for this function. + unsigned getMaxFlatWorkGroupSize() const { + return FlatWorkGroupSizes.second; + } + + /// Returns a pair of default/requested minimum/maximum number of active waves + /// per execution unit. + std::pair getNumActiveWavesPerEU() const { + return NumActiveWavesPerEU; + } + + /// Returns default/requested minimum number of active waves per execution + /// unit. + unsigned getMinNumActiveWavesPerEU() const { + return NumActiveWavesPerEU.first; + } + + /// Returns default/requested maximum number of active waves per execution + /// unit. + unsigned getMaxNumActiveWavesPerEU() const { + return NumActiveWavesPerEU.second; } /// \returns Stack object index for \p Dim's work group ID. @@ -412,8 +445,6 @@ } llvm_unreachable("unexpected dimension"); } - - unsigned getMaximumWorkGroupSize(const MachineFunction &MF) const; }; } // End namespace llvm Index: lib/Target/AMDGPU/SIMachineFunctionInfo.cpp =================================================================== --- lib/Target/AMDGPU/SIMachineFunctionInfo.cpp +++ lib/Target/AMDGPU/SIMachineFunctionInfo.cpp @@ -48,8 +48,8 @@ PrivateSegmentWaveByteOffsetSystemSGPR(AMDGPU::NoRegister), PSInputAddr(0), ReturnsVoid(true), - MaximumWorkGroupSize(0), - DebuggerReservedVGPRCount(0), + FlatWorkGroupSizes(0, 0), + NumActiveWavesPerEU(0, 0), DebuggerWorkGroupIDStackObjectIndices({{0, 0, 0}}), DebuggerWorkItemIDStackObjectIndices({{0, 0, 0}}), LDSWaveSpillSize(0), @@ -136,13 +136,8 @@ ST.isAmdHsaOS()) FlatScratchInit = true; - if (AMDGPU::isCompute(F->getCallingConv())) - MaximumWorkGroupSize = AMDGPU::getMaximumWorkGroupSize(*F); - else - MaximumWorkGroupSize = ST.getWavefrontSize(); - - if (ST.debuggerReserveRegs()) - DebuggerReservedVGPRCount = 4; + FlatWorkGroupSizes = ST.getFlatWorkGroupSizes(*F); + NumActiveWavesPerEU = ST.getNumActiveWavesPerEU(*F); } unsigned SIMachineFunctionInfo::addPrivateSegmentBuffer( @@ -229,8 +224,3 @@ Spill.VGPR = LaneVGPRs[LaneVGPRIdx]; return Spill; } - -unsigned SIMachineFunctionInfo::getMaximumWorkGroupSize( - const MachineFunction &MF) const { - return MaximumWorkGroupSize; -} Index: lib/Target/AMDGPU/SIRegisterInfo.h =================================================================== --- lib/Target/AMDGPU/SIRegisterInfo.h +++ lib/Target/AMDGPU/SIRegisterInfo.h @@ -176,14 +176,6 @@ unsigned getPreloadedValue(const MachineFunction &MF, enum PreloadedValue Value) const; - /// \brief Give the maximum number of VGPRs that can be used by \p WaveCount - /// concurrent waves. - unsigned getNumVGPRsAllowed(unsigned WaveCount) const; - - /// \brief Give the maximum number of SGPRs that can be used by \p WaveCount - /// concurrent waves. - unsigned getNumSGPRsAllowed(const SISubtarget &ST, unsigned WaveCount) const; - unsigned findUnusedRegister(const MachineRegisterInfo &MRI, const TargetRegisterClass *RC) const; @@ -192,6 +184,70 @@ bool isVGPR(const MachineRegisterInfo &MRI, unsigned Reg) const; + /// Returns SGPR allocation granularity supported by the subtarget. + unsigned getSGPRAllocGranule() const { + return 8; + } + + /// Returns total number of SGPRs supported by the subtarget. + unsigned getTotalNumSGPRs(const SISubtarget &ST) const; + + /// Returns addressable number of SGPRs supported by the subtarget. + unsigned getAddressableNumSGPRs(const SISubtarget &ST) const; + + /// Returns reserved number of SGPRs supported by the subtarget. + unsigned getReservedNumSGPRs(const SISubtarget &ST) const; + + /// Returns minimum number of SGPRs that meets given number of active waves + /// per execution unit requirement for given subtarget. + unsigned getMinNumSGPRs(const SISubtarget &ST, + unsigned NumActiveWavesPerEU) const; + + /// Returns maximum number of SGPRs that meets given number of active waves + /// per execution unit requirement for given subtarget. + unsigned getMaxNumSGPRs(const SISubtarget &ST, + unsigned NumActiveWavesPerEU) const; + + /// Returns maximum number of SGPRs that meets number of active waves per + /// execution unit requirement for function \p MF, or number of SGPRs + /// explicitly requested using "amdgpu-num-sgpr" attribute attached to + /// function \p MF. Returns value that meets number of active waves per + /// execution unit requirement and emits error if explicitly requested value + /// cannot be converted to integer, violates subtarget's specifications, or + /// does not meet number of active waver per execution unit requirement. + unsigned getMaxNumSGPRs(const MachineFunction &MF) const; + + /// Returns VGPR allocation granularity supported by the subtarget. + unsigned getVGPRAllocGranule() const { + return 4; + } + + /// Returns total number of VGPRs supported by the subtarget. + unsigned getTotalNumVGPRs() const { + return 256; + } + + /// Returns reserved number of VGPRs for debugger use supported by the + /// subtarget. + unsigned getDebuggerReservedNumVGPRs(const SISubtarget &ST) const; + + /// Returns minimum number of SGPRs that meets given number of active waves + /// per execution unit requirement. + unsigned getMinNumVGPRs(unsigned NumActiveWavesPerEU) const; + + /// Returns maximum number of VGPRs that meets given number of active waves + /// per execution unit requirement. + unsigned getMaxNumVGPRs(unsigned NumActiveWavesPerEU) const; + + /// Returns maximum number of VGPRs that meets number of active waves per + /// execution unit requirement for function \p MF, or number of VGPRs + /// explicitly requested using "amdgpu-num-vgpr" attribute attached to + /// function \p MF. Returns value that meets number of active waves per + /// execution unit requirement and emits error if explicitly requested value + /// cannot be converted to integer, violates subtarget's specifications, or + /// does not meet number of active waves per execution unit requirement. + unsigned getMaxNumVGPRs(const MachineFunction &MF) const; + private: void buildScratchLoadStore(MachineBasicBlock::iterator MI, unsigned LoadStoreOp, const MachineOperand *SrcDst, Index: lib/Target/AMDGPU/SIRegisterInfo.cpp =================================================================== --- lib/Target/AMDGPU/SIRegisterInfo.cpp +++ lib/Target/AMDGPU/SIRegisterInfo.cpp @@ -24,53 +24,6 @@ using namespace llvm; -static unsigned getMaxWaveCountPerSIMD(const MachineFunction &MF) { - const SIMachineFunctionInfo &MFI = *MF.getInfo(); - const SISubtarget &ST = MF.getSubtarget(); - unsigned SIMDPerCU = 4; - - unsigned MaxInvocationsPerWave = SIMDPerCU * ST.getWavefrontSize(); - return alignTo(MFI.getMaximumWorkGroupSize(MF), MaxInvocationsPerWave) / - MaxInvocationsPerWave; -} - -static unsigned getMaxWorkGroupSGPRCount(const MachineFunction &MF) { - const SISubtarget &ST = MF.getSubtarget(); - unsigned MaxWaveCountPerSIMD = getMaxWaveCountPerSIMD(MF); - - unsigned TotalSGPRCountPerSIMD, AddressableSGPRCount, SGPRUsageAlignment; - unsigned ReservedSGPRCount; - - if (ST.getGeneration() >= SISubtarget::VOLCANIC_ISLANDS) { - TotalSGPRCountPerSIMD = 800; - AddressableSGPRCount = 102; - SGPRUsageAlignment = 16; - ReservedSGPRCount = 6; // VCC, FLAT_SCRATCH, XNACK - } else { - TotalSGPRCountPerSIMD = 512; - AddressableSGPRCount = 104; - SGPRUsageAlignment = 8; - ReservedSGPRCount = 2; // VCC - } - - unsigned MaxSGPRCount = (TotalSGPRCountPerSIMD / MaxWaveCountPerSIMD); - MaxSGPRCount = alignDown(MaxSGPRCount, SGPRUsageAlignment); - - if (ST.hasSGPRInitBug()) - MaxSGPRCount = SISubtarget::FIXED_SGPR_COUNT_FOR_INIT_BUG; - - return std::min(MaxSGPRCount - ReservedSGPRCount, AddressableSGPRCount); -} - -static unsigned getMaxWorkGroupVGPRCount(const MachineFunction &MF) { - unsigned MaxWaveCountPerSIMD = getMaxWaveCountPerSIMD(MF); - unsigned TotalVGPRCountPerSIMD = 256; - unsigned VGPRUsageAlignment = 4; - - return alignDown(TotalVGPRCountPerSIMD / MaxWaveCountPerSIMD, - VGPRUsageAlignment); -} - static bool hasPressureSet(const int *PSets, unsigned PSetID) { for (unsigned i = 0; PSets[i] != -1; ++i) { if (PSets[i] == (int)PSetID) @@ -119,14 +72,14 @@ unsigned SIRegisterInfo::reservedPrivateSegmentBufferReg( const MachineFunction &MF) const { - unsigned BaseIdx = alignDown(getMaxWorkGroupSGPRCount(MF), 4) - 4; + unsigned BaseIdx = alignDown(getMaxNumSGPRs(MF), 4) - 4; unsigned BaseReg(AMDGPU::SGPR_32RegClass.getRegister(BaseIdx)); return getMatchingSuperReg(BaseReg, AMDGPU::sub0, &AMDGPU::SReg_128RegClass); } unsigned SIRegisterInfo::reservedPrivateSegmentWaveByteOffsetReg( const MachineFunction &MF) const { - unsigned RegCount = getMaxWorkGroupSGPRCount(MF); + unsigned RegCount = getMaxNumSGPRs(MF); unsigned Reg; // Try to place it in a hole after PrivateSegmentbufferReg. @@ -161,18 +114,16 @@ reserveRegisterTuples(Reserved, AMDGPU::TTMP8_TTMP9); reserveRegisterTuples(Reserved, AMDGPU::TTMP10_TTMP11); - unsigned MaxWorkGroupSGPRCount = getMaxWorkGroupSGPRCount(MF); - unsigned MaxWorkGroupVGPRCount = getMaxWorkGroupVGPRCount(MF); - - unsigned NumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs(); - unsigned NumVGPRs = AMDGPU::VGPR_32RegClass.getNumRegs(); - for (unsigned i = MaxWorkGroupSGPRCount; i < NumSGPRs; ++i) { + unsigned MaxNumSGPRs = getMaxNumSGPRs(MF); + unsigned TotalNumSGPRs = AMDGPU::SGPR_32RegClass.getNumRegs(); + for (unsigned i = MaxNumSGPRs; i < TotalNumSGPRs; ++i) { unsigned Reg = AMDGPU::SGPR_32RegClass.getRegister(i); reserveRegisterTuples(Reserved, Reg); } - - for (unsigned i = MaxWorkGroupVGPRCount; i < NumVGPRs; ++i) { + unsigned MaxNumVGPRs = getMaxNumVGPRs(MF); + unsigned TotalNumVGPRs = AMDGPU::VGPR_32RegClass.getNumRegs(); + for (unsigned i = MaxNumVGPRs; i < TotalNumVGPRs; ++i) { unsigned Reg = AMDGPU::VGPR_32RegClass.getRegister(i); reserveRegisterTuples(Reserved, Reg); } @@ -194,27 +145,13 @@ assert(!isSubRegister(ScratchRSrcReg, ScratchWaveOffsetReg)); } - // Reserve registers for debugger usage if "amdgpu-debugger-reserve-trap-regs" - // attribute was specified. - const SISubtarget &ST = MF.getSubtarget(); - if (ST.debuggerReserveRegs()) { - unsigned ReservedVGPRFirst = - MaxWorkGroupVGPRCount - MFI->getDebuggerReservedVGPRCount(); - for (unsigned i = ReservedVGPRFirst; i < MaxWorkGroupVGPRCount; ++i) { - unsigned Reg = AMDGPU::VGPR_32RegClass.getRegister(i); - reserveRegisterTuples(Reserved, Reg); - } - } - return Reserved; } unsigned SIRegisterInfo::getRegPressureSetLimit(const MachineFunction &MF, unsigned Idx) const { - const SISubtarget &STI = MF.getSubtarget(); - // FIXME: We should adjust the max number of waves based on LDS size. - unsigned SGPRLimit = getNumSGPRsAllowed(STI, STI.getMaxWavesPerCU()); - unsigned VGPRLimit = getNumVGPRsAllowed(STI.getMaxWavesPerCU()); + unsigned SGPRLimit = getMaxNumSGPRs(MF); + unsigned VGPRLimit = getMaxNumVGPRs(MF); unsigned VSLimit = SGPRLimit + VGPRLimit; @@ -966,50 +903,197 @@ return AMDGPU::NoRegister; } -unsigned SIRegisterInfo::getNumVGPRsAllowed(unsigned WaveCount) const { - switch(WaveCount) { - case 10: return 24; - case 9: return 28; - case 8: return 32; - case 7: return 36; - case 6: return 40; - case 5: return 48; - case 4: return 64; - case 3: return 84; - case 2: return 128; - default: return 256; +bool SIRegisterInfo::isVGPR(const MachineRegisterInfo &MRI, + unsigned Reg) const { + const TargetRegisterClass *RC; + if (TargetRegisterInfo::isVirtualRegister(Reg)) + RC = MRI.getRegClass(Reg); + else + RC = getPhysRegClass(Reg); + + return hasVGPRs(RC); +} + +unsigned SIRegisterInfo::getTotalNumSGPRs(const SISubtarget &ST) const { + if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) + return 800; + return 512; +} + +unsigned SIRegisterInfo::getAddressableNumSGPRs(const SISubtarget &ST) const { + if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) + return 102; + return 104; +} + +unsigned SIRegisterInfo::getReservedNumSGPRs(const SISubtarget &ST) const { + if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) + return 6; // VCC, FLAT_SCRATCH, XNACK. + return 2; // VCC. +} + +unsigned SIRegisterInfo::getMinNumSGPRs(const SISubtarget &ST, + unsigned NumActiveWavesPerEU) const { + if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) { + switch (NumActiveWavesPerEU) { + case 0: return 0; + case 10: return 0; + case 9: return 0; + case 8: return 81; + default: return 97; + } + } else { + switch (NumActiveWavesPerEU) { + case 0: return 0; + case 10: return 0; + case 9: return 49; + case 8: return 57; + case 7: return 65; + case 6: return 73; + case 5: return 81; + default: return 97; + } } } -unsigned SIRegisterInfo::getNumSGPRsAllowed(const SISubtarget &ST, - unsigned WaveCount) const { - if (ST.getGeneration() >= SISubtarget::VOLCANIC_ISLANDS) { - switch (WaveCount) { +unsigned SIRegisterInfo::getMaxNumSGPRs(const SISubtarget &ST, + unsigned NumActiveWavesPerEU) const { + if (ST.getGeneration() >= AMDGPUSubtarget::VOLCANIC_ISLANDS) { + switch (NumActiveWavesPerEU) { + case 0: return 80; case 10: return 80; case 9: return 80; case 8: return 96; - default: return 102; + default: return getAddressableNumSGPRs(ST); } } else { - switch(WaveCount) { + switch (NumActiveWavesPerEU) { + case 0: return 48; case 10: return 48; case 9: return 56; case 8: return 64; case 7: return 72; case 6: return 80; case 5: return 96; - default: return 103; + default: return getAddressableNumSGPRs(ST); } } } -bool SIRegisterInfo::isVGPR(const MachineRegisterInfo &MRI, - unsigned Reg) const { - const TargetRegisterClass *RC; - if (TargetRegisterInfo::isVirtualRegister(Reg)) - RC = MRI.getRegClass(Reg); - else - RC = getPhysRegClass(Reg); +unsigned SIRegisterInfo::getMaxNumSGPRs(const MachineFunction &MF) const { + const Function &F = *MF.getFunction(); - return hasVGPRs(RC); + const SISubtarget &ST = MF.getSubtarget(); + const SIMachineFunctionInfo &MFI = *MF.getInfo(); + + // Compute maximum number of SGPRs function can use using default/requested + // minimum number of active waves per execution unit. + std::pair NumActiveWavesPerEU = + MFI.getNumActiveWavesPerEU(); + unsigned MaxNumSGPRs = getMaxNumSGPRs(ST, NumActiveWavesPerEU.first); + + // Check if maximum number of SGPRs was explicitly requested using + // "amdgpu-num-sgpr" attribute. + if (F.hasFnAttribute("amdgpu-num-sgpr")) { + unsigned Requested = + AMDGPU::getIntegerAttribute(F, "amdgpu-num-sgpr", MaxNumSGPRs); + + // Make sure requested value does not violate subtarget's specifications. + if (Requested && Requested <= getReservedNumSGPRs(ST)) + Requested = 0; + + // Make sure requested value is compatible with values implied by + // default/requested minimum/maximum number of active waves per execution + // unit. + if (Requested && Requested > getMaxNumSGPRs(ST, NumActiveWavesPerEU.first)) + Requested = 0; + if (NumActiveWavesPerEU.second && + Requested && Requested < getMinNumSGPRs(ST, NumActiveWavesPerEU.second)) + Requested = 0; + + if (Requested) + MaxNumSGPRs = Requested; + } + + if (ST.hasSGPRInitBug()) + MaxNumSGPRs = SISubtarget::FIXED_SGPR_COUNT_FOR_INIT_BUG; + + return MaxNumSGPRs - getReservedNumSGPRs(ST); +} + +unsigned SIRegisterInfo::getDebuggerReservedNumVGPRs( + const SISubtarget &ST) const { + if (ST.debuggerReserveRegs()) + return 4; + return 0; +} + +unsigned SIRegisterInfo::getMinNumVGPRs(unsigned NumActiveWavesPerEU) const { + switch (NumActiveWavesPerEU) { + case 0: return 0; + case 10: return 0; + case 9: return 25; + case 8: return 29; + case 7: return 33; + case 6: return 37; + case 5: return 41; + case 4: return 49; + case 3: return 65; + case 2: return 85; + default: return 129; + } +} + +unsigned SIRegisterInfo::getMaxNumVGPRs(unsigned NumActiveWavesPerEU) const { + switch (NumActiveWavesPerEU) { + case 0: return 24; + case 10: return 24; + case 9: return 28; + case 8: return 32; + case 7: return 36; + case 6: return 40; + case 5: return 48; + case 4: return 64; + case 3: return 84; + case 2: return 128; + default: return getTotalNumVGPRs(); + } +} + +unsigned SIRegisterInfo::getMaxNumVGPRs(const MachineFunction &MF) const { + const Function &F = *MF.getFunction(); + + const SISubtarget &ST = MF.getSubtarget(); + const SIMachineFunctionInfo &MFI = *MF.getInfo(); + + // Compute maximum number of VGPRs function can use using default/requested + // minimum number of active waves per execution unit. + std::pair NumActiveWavesPerEU = + MFI.getNumActiveWavesPerEU(); + unsigned MaxNumVGPRs = getMaxNumVGPRs(NumActiveWavesPerEU.first); + + // Check if maximum number of VGPRs was explicitly requested using + // "amdgpu-num-vgpr" attribute. + if (F.hasFnAttribute("amdgpu-num-vgpr")) { + unsigned Requested = + AMDGPU::getIntegerAttribute(F, "amdgpu-num-vgpr", MaxNumVGPRs); + + // Make sure requested value does not violate subtarget's specifications. + if (Requested && Requested <= getDebuggerReservedNumVGPRs(ST)) + Requested = 0; + + // Make sure requested value is compatible with values implied by + // default/requested minimum/maximum number of active waves per execution + // unit. + if (Requested && Requested > getMaxNumVGPRs(NumActiveWavesPerEU.first)) + Requested = 0; + if (NumActiveWavesPerEU.second && + Requested && Requested < getMinNumVGPRs(NumActiveWavesPerEU.second)) + Requested = 0; + + if (Requested) + MaxNumVGPRs = Requested; + } + + return MaxNumVGPRs - getDebuggerReservedNumVGPRs(ST); } Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -45,9 +45,21 @@ bool isGlobalSegment(const GlobalValue *GV); bool isReadOnlySegment(const GlobalValue *GV); +/// Returns integer value requested using \p F's \p Name attribute. Returns \p +/// Default if attribute is not present. Returns \p Default and emits error if +/// requested value cannot be converted to integer. int getIntegerAttribute(const Function &F, StringRef Name, int Default); -unsigned getMaximumWorkGroupSize(const Function &F); +/// Returns a pair of integer values requested using \p F's \p Name attribute in +/// "first[,second]" format ("second" is optional unless \p OnlyFirstRequired is +/// false). Returns \p Default if attribute is not present. Returns \p Default +/// and emits error if one of the requested values cannot be converted to +/// integer, or \p OnlyFirstRequired is false and "second" value is not present. +std::pair getIntegerPairAttribute(const Function &F, + StringRef Name, + std::pair Default, + bool OnlyFirstRequired = false); + unsigned getInitialPSInputAddr(const Function &F); bool isShader(CallingConv::ID cc); Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -124,8 +124,29 @@ return Result; } -unsigned getMaximumWorkGroupSize(const Function &F) { - return getIntegerAttribute(F, "amdgpu-max-work-group-size", 256); +std::pair getIntegerPairAttribute(const Function &F, + StringRef Name, + std::pair Default, + bool OnlyFirstRequired) { + Attribute A = F.getFnAttribute(Name); + if (!A.isStringAttribute()) + return Default; + + LLVMContext &Ctx = F.getContext(); + std::pair Ints = Default; + std::pair Strs = A.getValueAsString().split(','); + if (Strs.first.trim().getAsInteger(0, Ints.first)) { + Ctx.emitError("can't parse first integer attribute " + Name); + return Default; + } + if (Strs.second.trim().getAsInteger(0, Ints.second)) { + if (!OnlyFirstRequired || Strs.second.trim().size()) { + Ctx.emitError("can't parse second integer attribute " + Name); + return Default; + } + } + + return Ints; } unsigned getInitialPSInputAddr(const Function &F) { Index: test/CodeGen/AMDGPU/amdgpu.private-memory.ll =================================================================== --- test/CodeGen/AMDGPU/amdgpu.private-memory.ll +++ test/CodeGen/AMDGPU/amdgpu.private-memory.ll @@ -545,7 +545,7 @@ ret void } -attributes #0 = { nounwind "amdgpu-max-waves-per-eu"="2" } +attributes #0 = { nounwind "amdgpu-num-active-waves-per-eu"="1,2" } ; HSAOPT: !0 = !{} ; HSAOPT: !1 = !{i32 0, i32 2048} Index: test/CodeGen/AMDGPU/array-ptr-calc-i32.ll =================================================================== --- test/CodeGen/AMDGPU/array-ptr-calc-i32.ll +++ test/CodeGen/AMDGPU/array-ptr-calc-i32.ll @@ -47,6 +47,6 @@ ret void } -attributes #0 = { nounwind "amdgpu-max-waves-per-eu"="1" } +attributes #0 = { nounwind "amdgpu-num-active-waves-per-eu"="1,1" } attributes #1 = { nounwind readnone } attributes #2 = { nounwind convergent } Index: test/CodeGen/AMDGPU/indirect-private-64.ll =================================================================== --- test/CodeGen/AMDGPU/indirect-private-64.ll +++ test/CodeGen/AMDGPU/indirect-private-64.ll @@ -121,4 +121,4 @@ } attributes #0 = { convergent nounwind } -attributes #1 = { nounwind "amdgpu-max-waves-per-eu"="2" "amdgpu-max-work-group-size"="64" } +attributes #1 = { nounwind "amdgpu-num-active-waves-per-eu"="2,2" "amdgpu-flat-work-group-size"="64,64" } Index: test/CodeGen/AMDGPU/large-work-group-promote-alloca.ll =================================================================== --- test/CodeGen/AMDGPU/large-work-group-promote-alloca.ll +++ test/CodeGen/AMDGPU/large-work-group-promote-alloca.ll @@ -254,11 +254,11 @@ ret void } -attributes #0 = { nounwind "amdgpu-max-work-group-size"="63" } -attributes #1 = { nounwind "amdgpu-max-waves-per-eu"="3" "amdgpu-max-work-group-size"="256" } -attributes #2 = { nounwind "amdgpu-max-waves-per-eu"="1" "amdgpu-max-work-group-size"="1600" } -attributes #3 = { nounwind "amdgpu-max-waves-per-eu"="0" } -attributes #4 = { nounwind "amdgpu-max-waves-per-eu"="-1" } -attributes #5 = { nounwind "amdgpu-max-waves-per-eu"="6" "amdgpu-max-work-group-size"="64" } -attributes #6 = { nounwind "amdgpu-max-waves-per-eu"="8" "amdgpu-max-work-group-size"="64" } -attributes #7 = { nounwind "amdgpu-max-waves-per-eu"="9" "amdgpu-max-work-group-size"="64" } +attributes #0 = { nounwind "amdgpu-flat-work-group-size"="63,63" } +attributes #1 = { nounwind "amdgpu-num-active-waves-per-eu"="1,3" "amdgpu-flat-work-group-size"="256,256" } +attributes #2 = { nounwind "amdgpu-num-active-waves-per-eu"="1,1" "amdgpu-flat-work-group-size"="1600,1600" } +attributes #3 = { nounwind "amdgpu-num-active-waves-per-eu"="1,10" } +attributes #4 = { nounwind "amdgpu-num-active-waves-per-eu"="1,10" } +attributes #5 = { nounwind "amdgpu-num-active-waves-per-eu"="1,6" "amdgpu-flat-work-group-size"="64,64" } +attributes #6 = { nounwind "amdgpu-num-active-waves-per-eu"="1,8" "amdgpu-flat-work-group-size"="64,64" } +attributes #7 = { nounwind "amdgpu-num-active-waves-per-eu"="1,9" "amdgpu-flat-work-group-size"="64,64" } Index: test/CodeGen/AMDGPU/large-work-group-registers.ll =================================================================== --- test/CodeGen/AMDGPU/large-work-group-registers.ll +++ test/CodeGen/AMDGPU/large-work-group-registers.ll @@ -1,6 +1,6 @@ ; RUN: llc -march=amdgcn -mcpu=tonga -post-RA-scheduler=0 < %s | FileCheck %s -; CHECK: NumVgprs: 64 +; CHECK: NumVgprs: 32 define void @main([9 x <16 x i8>] addrspace(2)* byval, [17 x <16 x i8>] addrspace(2)* byval, [17 x <8 x i32>] addrspace(2)* byval, [16 x <8 x i32>] addrspace(2)* byval, [16 x <4 x i32>] addrspace(2)* byval, <3 x i32> inreg, <3 x i32> inreg, <3 x i32>) #0 { main_body: %8 = getelementptr [16 x <4 x i32>], [16 x <4 x i32>] addrspace(2)* %4, i64 0, i64 8 @@ -33,7 +33,7 @@ declare void @llvm.amdgcn.buffer.store.format.v4f32(<4 x float>, <4 x i32>, i32, i32, i1, i1) #2 -attributes #0 = { "amdgpu-max-work-group-size"="1024" } +attributes #0 = { "amdgpu-flat-work-group-size"="1024,1024" } attributes #1 = { convergent nounwind } attributes #2 = { nounwind } Index: test/CodeGen/AMDGPU/private-memory-r600.ll =================================================================== --- test/CodeGen/AMDGPU/private-memory-r600.ll +++ test/CodeGen/AMDGPU/private-memory-r600.ll @@ -297,4 +297,4 @@ ; OPT: !0 = !{i32 0, i32 2048} -attributes #0 = { nounwind "amdgpu-max-waves-per-eu"="2" } +attributes #0 = { nounwind "amdgpu-num-active-waves-per-eu"="1,2" } Index: test/CodeGen/AMDGPU/promote-alloca-mem-intrinsics.ll =================================================================== --- test/CodeGen/AMDGPU/promote-alloca-mem-intrinsics.ll +++ test/CodeGen/AMDGPU/promote-alloca-mem-intrinsics.ll @@ -61,5 +61,5 @@ ret void } -attributes #0 = { nounwind "amdgpu-max-work-group-size"="64" "amdgpu-max-waves-per-eu"="3" } +attributes #0 = { nounwind "amdgpu-flat-work-group-size"="64,64" "amdgpu-num-active-waves-per-eu"="3,3" } attributes #1 = { nounwind readnone } Index: test/CodeGen/AMDGPU/promote-alloca-no-opts.ll =================================================================== --- test/CodeGen/AMDGPU/promote-alloca-no-opts.ll +++ test/CodeGen/AMDGPU/promote-alloca-no-opts.ll @@ -34,5 +34,5 @@ ret void } -attributes #0 = { nounwind "amdgpu-max-work-group-size"="64" } -attributes #1 = { nounwind optnone noinline "amdgpu-max-work-group-size"="64" } +attributes #0 = { nounwind "amdgpu-flat-work-group-size"="64,64" } +attributes #1 = { nounwind optnone noinline "amdgpu-flat-work-group-size"="64,64" } Index: test/CodeGen/AMDGPU/promote-alloca-padding-size-estimate.ll =================================================================== --- test/CodeGen/AMDGPU/promote-alloca-padding-size-estimate.ll +++ test/CodeGen/AMDGPU/promote-alloca-padding-size-estimate.ll @@ -127,4 +127,4 @@ ret void } -attributes #0 = { nounwind "amdgpu-max-work-group-size"="64" } +attributes #0 = { nounwind "amdgpu-flat-work-group-size"="64,64" "amdgpu-num-active-waves-per-eu"="1,7" } Index: test/CodeGen/AMDGPU/promote-alloca-to-lds-icmp.ll =================================================================== --- test/CodeGen/AMDGPU/promote-alloca-to-lds-icmp.ll +++ test/CodeGen/AMDGPU/promote-alloca-to-lds-icmp.ll @@ -61,4 +61,4 @@ declare i32* @get_unknown_pointer() #0 -attributes #0 = { nounwind "amdgpu-max-waves-per-eu"="1" } +attributes #0 = { nounwind "amdgpu-num-active-waves-per-eu"="1,1" } Index: test/CodeGen/AMDGPU/promote-alloca-to-lds-phi.ll =================================================================== --- test/CodeGen/AMDGPU/promote-alloca-to-lds-phi.ll +++ test/CodeGen/AMDGPU/promote-alloca-to-lds-phi.ll @@ -201,4 +201,4 @@ declare i32* @get_unknown_pointer() #0 -attributes #0 = { nounwind "amdgpu-max-waves-per-eu"="1" } +attributes #0 = { nounwind "amdgpu-num-active-waves-per-eu"="1,1" } Index: test/CodeGen/AMDGPU/promote-alloca-to-lds-select.ll =================================================================== --- test/CodeGen/AMDGPU/promote-alloca-to-lds-select.ll +++ test/CodeGen/AMDGPU/promote-alloca-to-lds-select.ll @@ -129,5 +129,5 @@ ret void } -attributes #0 = { norecurse nounwind "amdgpu-max-waves-per-eu"="1" } +attributes #0 = { norecurse nounwind "amdgpu-num-active-waves-per-eu"="1,1" } attributes #1 = { norecurse nounwind } \ No newline at end of file Index: test/CodeGen/AMDGPU/target-cpu.ll =================================================================== --- test/CodeGen/AMDGPU/target-cpu.ll +++ test/CodeGen/AMDGPU/target-cpu.ll @@ -108,5 +108,5 @@ attributes #2 = { nounwind "target-cpu"="tahiti" } attributes #3 = { nounwind "target-cpu"="bonaire" } attributes #4 = { nounwind "target-cpu"="fiji" } -attributes #5 = { nounwind "target-features"="+promote-alloca" "amdgpu-max-waves-per-eu"="3" } -attributes #6 = { nounwind "target-features"="-promote-alloca" "amdgpu-max-waves-per-eu"="3" } +attributes #5 = { nounwind "target-features"="+promote-alloca" "amdgpu-num-active-waves-per-eu"="1,3" } +attributes #6 = { nounwind "target-features"="-promote-alloca" "amdgpu-num-active-waves-per-eu"="1,3" }