//===-- SISchedule.td - SI Scheduling definitions -------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// // // MachineModel definitions for Southern Islands (SI) // //===----------------------------------------------------------------------===// def : PredicateProlog<[{ const SIInstrInfo *TII = static_cast(SchedModel->getInstrInfo()); (void)TII; }]>; def WriteBranch : SchedWrite; def WriteExport : SchedWrite; def WriteLDS : SchedWrite; def WriteSALU : SchedWrite; def WriteSMEM : SchedWrite; def WriteVMEM : SchedWrite; def WriteBarrier : SchedWrite; def MIVGPRRead : SchedRead; def MIMFMARead : SchedRead; // Normal 16 or 32 bit VALU instructions def Write32Bit : SchedWrite; // Conversion to or from F32 (but not converting F64 to or from F32) def WriteFloatCvt : SchedWrite; // F16 or F32 transcendental instructions (these are quarter rate) def WriteTrans32 : SchedWrite; // Other quarter rate VALU instructions def WriteQuarterRate32 : SchedWrite; def WriteFloatFMA : SchedWrite; // Slow quarter rate f64 instruction. def WriteDouble : SchedWrite; // half rate f64 instruction (same as v_add_f64) def WriteDoubleAdd : SchedWrite; // Conversion to or from f64 instruction def WriteDoubleCvt : SchedWrite; // F64 "transcendental" (actually only reciprocal and/or square root) // instructions def WriteTrans64 : SchedWrite; // Half rate 64-bit instructions. def Write64Bit : SchedWrite; // Integer multiplications. def WriteIntMul : SchedWrite; // mAI multipass instructions. def Write2PassMAI : SchedWrite; def Write4PassMAI : SchedWrite; def Write8PassMAI : SchedWrite; def Write16PassMAI : SchedWrite; def Write4PassDGEMM : SchedWrite; def Write8PassDGEMM : SchedWrite; // FIXME: Should there be a class for instructions which are VALU // instructions and have VALU rates, but write to the SALU (i.e. VOPC // instructions) class SISchedMachineModel : SchedMachineModel { let CompleteModel = 1; // MicroOpBufferSize = 1 means that instructions will always be added // the ready queue when they become available. This exposes them // to the register pressure analysis. let MicroOpBufferSize = 1; let IssueWidth = 1; let PostRAScheduler = 1; // FIXME:Approximate 2 * branch cost. Try to hack around bad // early-ifcvt heuristics. These need improvement to avoid the OOE // heuristics. int MispredictPenalty = 20; } def SIFullSpeedModel : SISchedMachineModel; def SIQuarterSpeedModel : SISchedMachineModel; def SIDPFullSpeedModel : SISchedMachineModel; def SIDPGFX940FullSpeedModel : SISchedMachineModel; def GFX10SpeedModel : SISchedMachineModel; def GFX11SpeedModel : SISchedMachineModel; // XXX: Are the resource counts correct? def HWBranch : ProcResource<1> { let BufferSize = 1; } def HWExport : ProcResource<1> { let BufferSize = 1; } def HWLGKM : ProcResource<1> { let BufferSize = 1; } def HWSALU : ProcResource<1> { let BufferSize = 1; } def HWVMEM : ProcResource<1> { let BufferSize = 1; } def HWVALU : ProcResource<1> { let BufferSize = 1; } def HWTransVALU : ProcResource<1> { // Transcendental VALU let BufferSize = 1; } def HWRC : ProcResource<1> { // Register destination cache let BufferSize = 1; } def HWXDL : ProcResource<1> { // MFMA CU let BufferSize = 0; } class HWWriteRes resources, int latency> : WriteRes { let Latency = latency; } class HWVALUWriteRes : HWWriteRes; def PredMIReadVGPR : SchedPredicate<[{TII->hasVGPRUses(*MI)}]>; def MIReadVGPR : SchedReadVariant<[ SchedVar, SchedVar]>; // The latency numbers are taken from AMD Accelerated Parallel Processing // guide. They may not be accurate. // The latency values are 1 / (operations / cycle) / 4. multiclass SICommonWriteRes { let RetireOOO = 1 in { // llvm-mca specific flag def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; // Can be between 2 and 64 def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; // XXX: Guessed ??? def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; let ResourceCycles = [2] in def : HWWriteRes; let ResourceCycles = [4] in def : HWWriteRes; let ResourceCycles = [8] in def : HWWriteRes; let ResourceCycles = [16] in def : HWWriteRes; } // End RetireOOO = 1 def : ReadAdvance; // Technically mfma reads can be from 0 to 4 cycles but that does not make // sense to model because its register setup is huge. In particular if we // properly model read advance as -2 for a vgpr read it will result in a // bad scheduling of acc writes before that mfma. To avoid it we would // need to consume 2 or 4 more vgprs to be initialized before the acc // write sequence. Just assume worst case here. def : ReadAdvance; } def PredIsVGPR32Copy : SchedPredicate<[{TII->isVGPRCopy(*MI) && TII->getOpSize(*MI, 0) <= 32}]>; def PredIsVGPR64Copy : SchedPredicate<[{TII->isVGPRCopy(*MI) && TII->getOpSize(*MI, 0) > 32}]>; def WriteCopy : SchedWriteVariant<[ SchedVar, SchedVar, SchedVar]>; let SchedModel = SIFullSpeedModel in { defm : SICommonWriteRes; let RetireOOO = 1 in { // llvm-mca specific flag def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; } // End RetireOOO = 1 def : InstRW<[WriteCopy], (instrs COPY)>; } // End SchedModel = SIFullSpeedModel let SchedModel = SIQuarterSpeedModel in { defm : SICommonWriteRes; let RetireOOO = 1 in { // llvm-mca specific flag def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; } // End RetireOOO = 1 def : InstRW<[WriteCopy], (instrs COPY)>; def : InstRW<[Write64Bit, MIReadVGPR], (instregex "^V_ACCVGPR_WRITE_B32_e64$")>; def : InstRW<[Write2PassMAI, MIMFMARead], (instregex "^V_MFMA_..._4X4X")>; def : InstRW<[Write8PassMAI, MIMFMARead], (instregex "^V_MFMA_..._16X16X")>; def : InstRW<[Write16PassMAI, MIMFMARead], (instregex "^V_MFMA_..._32X32X")>; } // End SchedModel = SIQuarterSpeedModel let SchedModel = SIDPFullSpeedModel in { defm : SICommonWriteRes; let RetireOOO = 1 in { // llvm-mca specific flag def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; } // End RetireOOO = 1 def : InstRW<[WriteCopy], (instrs COPY)>; def : InstRW<[Write64Bit], (instregex "^V_ACCVGPR_WRITE_B32_e64$")>; def : InstRW<[Write2PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_4X4X")>; def : InstRW<[Write8PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_16X16X")>; def : InstRW<[Write16PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_32X32X")>; def : InstRW<[Write4PassDGEMM, MIMFMARead], (instregex "^V_MFMA_.64_4X4X")>; def : InstRW<[Write8PassDGEMM, MIMFMARead], (instregex "^V_MFMA_.64_16X16X")>; } // End SchedModel = SIDPFullSpeedModel let SchedModel = SIDPGFX940FullSpeedModel in { defm : SICommonWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : HWVALUWriteRes; def : InstRW<[WriteCopy], (instrs COPY)>; def : InstRW<[Write64Bit], (instregex "^V_ACCVGPR_WRITE_B32_e64$")>; def : InstRW<[Write2PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_4X4X")>; def : InstRW<[Write4PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_16X16X8X")>; def : InstRW<[Write4PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_16X16X16")>; def : InstRW<[Write4PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_16X16X32")>; def : InstRW<[Write8PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_16X16X[14][FBI]")>; def : InstRW<[Write8PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_32X32X4XF")>; def : InstRW<[Write8PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_32X32X8")>; def : InstRW<[Write8PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_32X32X16")>; def : InstRW<[Write16PassMAI, MIMFMARead], (instregex "^V_MFMA_.32_32X32X[124][FBI]")>; def : InstRW<[Write4PassDGEMM, MIMFMARead], (instregex "^V_MFMA_.64_4X4X")>; def : InstRW<[Write8PassDGEMM, MIMFMARead], (instregex "^V_MFMA_.64_16X16X")>; def : InstRW<[Write4PassMAI, MIMFMARead], (instregex "^V_SMFMAC_.32_16X16X")>; def : InstRW<[Write8PassMAI, MIMFMARead], (instregex "^V_SMFMAC_.32_32X32X")>; } // End SchedModel = SIDPGFX940FullSpeedModel let SchedModel = GFX10SpeedModel in { // The latency values are 1 / (operations / cycle). // Add 1 stall cycle for VGPR read. let RetireOOO = 1 in { // llvm-mca specific flag def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; } // End RetireOOO = 1 def : InstRW<[WriteCopy], (instrs COPY)>; } // End SchedModel = GFX10SpeedModel let SchedModel = GFX11SpeedModel in { def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : HWWriteRes; def : InstRW<[WriteCopy], (instrs COPY)>; } // End SchedModel = GFX11SpeedModel