From 95e0ec75a37c85efc50fa7dd02a02c419f2229b5 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 31 Jul 2025 14:38:35 -0300 Subject: [PATCH 1/6] Refactor helper classes Signed-off-by: Mikhail R. Gadelha --- .../lib/Target/RISCV/RISCVSchedSpacemitX60.td | 153 ++++++++++-------- 1 file changed, 83 insertions(+), 70 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td index bf23812c992ba..66df0cdebba0c 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td @@ -13,78 +13,103 @@ // //===----------------------------------------------------------------------===// -class SMX60IsWorstCaseMX MxList> { - string LLMUL = LargestLMUL.r; - bit c = !eq(mx, LLMUL); +//===----------------------------------------------------------------------===// +// Helpers + +// Maps LMUL string to corresponding value from the Values array +// LMUL values map to array indices as follows: +// MF8 -> Values[0], MF4 -> Values[1], MF2 -> Values[2], M1 -> Values[3], +// M2 -> Values[4], M4 -> Values[5], M8 -> Values[6] +// The !ge size checks ensure we don't access beyond the array bounds, for cases +// where M8 is not set (e.g., widening operations) +// Returns 0 if LMUL is invalid or if the array is too short +class GetLMULValue Values, string LMUL> { + int c = !cond( + !and(!eq(LMUL, "MF8"), !ge(!size(Values), 1)) : Values[0], + !and(!eq(LMUL, "MF4"), !ge(!size(Values), 2)) : Values[1], + !and(!eq(LMUL, "MF2"), !ge(!size(Values), 3)) : Values[2], + !and(!eq(LMUL, "M1"), !ge(!size(Values), 4)) : Values[3], + !and(!eq(LMUL, "M2"), !ge(!size(Values), 5)) : Values[4], + !and(!eq(LMUL, "M4"), !ge(!size(Values), 6)) : Values[5], + !and(!eq(LMUL, "M8"), !ge(!size(Values), 7)) : Values[6], + true : 0 + ); } -class SMX60IsWorstCaseMXSEW MxList, bit isF = 0> { - string LLMUL = LargestLMUL.r; - int SSEW = SmallestSEW.r; - bit c = !and(!eq(mx, LLMUL), !eq(sew, SSEW)); -} +// Returns BaseValue for LMUL values before startMx, Value for startMx, +// then doubles Value for each subsequent LMUL until targetMx +// Example: ConstantUntilLMULThenDoubleBase<"M1", 4, 2, "M8"> returns: +// MF8->2, MF4->2, MF2->2, M1->4, M2->8, M4->16, M8->32 +// This is useful for modeling scheduling parameters that scale with LMUL. +class ConstantUntilLMULThenDoubleBase { + int startPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], startMx>.c; + int targetPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], targetMx>.c; -defvar SMX60VLEN = 256; -defvar SMX60DLEN = !div(SMX60VLEN, 2); + // Calculate the difference in positions + int posDiff = !sub(targetPos, startPos); -class Get1248Latency { + // Calculate Value * (2^posDiff) using shift left int c = !cond( - !eq(mx, "M2") : 2, - !eq(mx, "M4") : 4, - !eq(mx, "M8") : 8, - true: 1 + !lt(posDiff, 0) : BaseValue, + !eq(posDiff, 0) : Value, + true: !mul(Value, !shl(1, posDiff)) ); } -// Used for: logical opsz, shifts, sign ext, merge/move, FP sign/recip/convert, mask ops, slides -class Get4816Latency { - int c = !cond( - !eq(mx, "M4") : 8, - !eq(mx, "M8") : 16, - true: 4 - ); +// Same as previous but BaseValue == Value +class ConstantUntilLMULThenDouble { + int c = ConstantUntilLMULThenDoubleBase.c; +} + +// Returns MF8->1, MF4->1, MF2->2, M1->4, M2->8, M4->16, M8->32 +class ConstantUntilMF4ThenDouble { + int c = ConstantUntilLMULThenDouble<"MF4", 1, mx>.c; +} + +// Returns MF8->1, MF4->1, MF2->1, M1->2, M2->4, M4->8, M8->16 +class ConstantUntilMF2ThenDouble { + int c = ConstantUntilLMULThenDouble<"MF2", 1, mx>.c; +} + +// Returns MF8->1, MF4->1, MF2->1, M1->1, M2->2, M4->4, M8->8 +class ConstantUntilM1ThenDouble { + int c = ConstantUntilLMULThenDouble<"M1", 1, mx>.c; } +//===----------------------------------------------------------------------===// +// Latency helper classes + // Used for: arithmetic (add/sub/min/max), saturating/averaging, FP add/sub/min/max -class Get458Latency { - int c = !cond( - !eq(mx, "M4") : 5, - !eq(mx, "M8") : 8, - true: 4 - ); +class Get4458Latency { + int c = GetLMULValue<[/*MF8=*/4, /*MF4=*/4, /*MF2=*/4, /*M1=*/4, /*M2=*/4, /*M4=*/5, /*M8=*/8], mx>.c; } -// Widening scaling pattern (4,4,4,4,5,8,8): plateaus at higher LMULs -// Used for: widening operations +// Used for: widening operations (no M8) class Get4588Latency { - int c = !cond( - !eq(mx, "M2") : 5, - !eq(mx, "M4") : 8, - !eq(mx, "M8") : 8, // M8 not supported for most widening, fallback - true: 4 - ); + int c = GetLMULValue<[/*MF8=*/4, /*MF4=*/4, /*MF2=*/4, /*M1=*/4, /*M2=*/5, /*M4=*/8], mx>.c; } // Used for: mask-producing comparisons, carry ops with mask, FP comparisons class Get461018Latency { - int c = !cond( - !eq(mx, "M2") : 6, - !eq(mx, "M4") : 10, - !eq(mx, "M8") : 18, - true: 4 - ); + int c = GetLMULValue<[/*MF8=*/4, /*MF4=*/4, /*MF2=*/4, /*M1=*/4, /*M2=*/6, /*M4=*/10, /*M8=*/18], mx>.c; } -// Used for: e64 multiply pattern, complex ops -class Get781632Latency { - int c = !cond( - !eq(mx, "M2") : 8, - !eq(mx, "M4") : 16, - !eq(mx, "M8") : 32, - true: 7 - ); +//===----------------------------------------------------------------------===// + +class SMX60IsWorstCaseMX MxList> { + string LLMUL = LargestLMUL.r; + bit c = !eq(mx, LLMUL); } +class SMX60IsWorstCaseMXSEW MxList, bit isF = 0> { + string LLMUL = LargestLMUL.r; + int SSEW = SmallestSEW.r; + bit c = !and(!eq(mx, LLMUL), !eq(sew, SSEW)); +} + +defvar SMX60VLEN = 256; +defvar SMX60DLEN = !div(SMX60VLEN, 2); + def SpacemitX60Model : SchedMachineModel { let IssueWidth = 2; // dual-issue let MicroOpBufferSize = 0; // in-order @@ -383,12 +408,13 @@ foreach LMul = [1, 2, 4, 8] in { foreach mx = SchedMxList in { defvar IsWorstCase = SMX60IsWorstCaseMX.c; - let Latency = Get458Latency.c, ReleaseAtCycles = [4] in { + let Latency = Get4458Latency.c, ReleaseAtCycles = [4] in { defm "" : LMULWriteResMX<"WriteVIMinMaxV", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVIMinMaxX", [SMX60_VIEU], mx, IsWorstCase>; } - let Latency = Get4816Latency.c, ReleaseAtCycles = [4] in { + defvar VIALULat = ConstantUntilLMULThenDouble<"M2", 4, mx>.c; + let Latency = VIALULat, ReleaseAtCycles = [4] in { // Pattern of vadd, vsub, vrsub: 4/4/5/8 // Pattern of vand, vor, vxor: 4/4/8/16 // They are grouped together, so we used the worst case 4/4/8/16 @@ -425,7 +451,7 @@ foreach mx = SchedMxList in { // Pattern of vmacc, vmadd, vmul, vmulh, etc.: e8/e16 = 4/4/5/8, e32 = 5,5,5,8, // e64 = 7,8,16,32. We use the worst-case until we can split the SEW. // TODO: change WriteVIMulV, etc to be defined with LMULSEWSchedWrites - let Latency = Get781632Latency.c, ReleaseAtCycles = [7] in { + let Latency = ConstantUntilLMULThenDoubleBase<"M2", 8, 7, mx>.c, ReleaseAtCycles = [7] in { defm "" : LMULWriteResMX<"WriteVIMulV", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVIMulX", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVIMulAddV", [SMX60_VIEU], mx, IsWorstCase>; @@ -461,15 +487,8 @@ foreach mx = SchedMxList in { foreach sew = SchedSEWSet.val in { defvar IsWorstCase = SMX60IsWorstCaseMXSEW.c; - // Slightly reduced for fractional LMULs - defvar Multiplier = !cond( - !eq(mx, "MF8") : 12, - !eq(mx, "MF4") : 12, - !eq(mx, "MF2") : 12, - true: 24 - ); - - let Latency = !mul(Get1248Latency.c, Multiplier), ReleaseAtCycles = [12] in { + defvar VIDivLat = ConstantUntilLMULThenDouble<"MF2", 12, mx>.c; + let Latency = VIDivLat, ReleaseAtCycles = [12] in { defm "" : LMULSEWWriteResMXSEW<"WriteVIDivV", [SMX60_VIEU], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVIDivX", [SMX60_VIEU], mx, sew, IsWorstCase>; } @@ -480,14 +499,8 @@ foreach mx = SchedMxList in { foreach mx = SchedMxListW in { defvar IsWorstCase = SMX60IsWorstCaseMX.c; - // Slightly increased for integer LMULs - defvar Multiplier = !cond( - !eq(mx, "M2") : 2, - !eq(mx, "M4") : 2, - true: 1 - ); - - let Latency = !mul(Get4816Latency.c, Multiplier), ReleaseAtCycles = [4] in { + defvar VNarrowingLat = ConstantUntilLMULThenDouble<"M1", 4, mx>.c; + let Latency = VNarrowingLat, ReleaseAtCycles = [4] in { defm "" : LMULWriteResMX<"WriteVNShiftV", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVNShiftX", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVNShiftI", [SMX60_VIEU], mx, IsWorstCase>; From dc8aa46d02f8f368755cf67cdab95016b8f34074 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 31 Jul 2025 14:44:04 -0300 Subject: [PATCH 2/6] Fix naming Signed-off-by: Mikhail R. Gadelha --- .../lib/Target/RISCV/RISCVSchedSpacemitX60.td | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td index 66df0cdebba0c..4d2c519593e39 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td @@ -38,10 +38,10 @@ class GetLMULValue Values, string LMUL> { // Returns BaseValue for LMUL values before startMx, Value for startMx, // then doubles Value for each subsequent LMUL until targetMx -// Example: ConstantUntilLMULThenDoubleBase<"M1", 4, 2, "M8"> returns: +// Example: ConstOneUntilLMULThenDoubleBase<"M1", 4, 2, "M8"> returns: // MF8->2, MF4->2, MF2->2, M1->4, M2->8, M4->16, M8->32 // This is useful for modeling scheduling parameters that scale with LMUL. -class ConstantUntilLMULThenDoubleBase { +class ConstOneUntilLMULThenDoubleBase { int startPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], startMx>.c; int targetPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], targetMx>.c; @@ -57,23 +57,23 @@ class ConstantUntilLMULThenDoubleBase { - int c = ConstantUntilLMULThenDoubleBase.c; +class ConstOneUntilLMULThenDouble { + int c = ConstOneUntilLMULThenDoubleBase.c; } // Returns MF8->1, MF4->1, MF2->2, M1->4, M2->8, M4->16, M8->32 -class ConstantUntilMF4ThenDouble { - int c = ConstantUntilLMULThenDouble<"MF4", 1, mx>.c; +class ConstOneUntilMF4ThenDouble { + int c = ConstOneUntilLMULThenDouble<"MF4", 1, mx>.c; } // Returns MF8->1, MF4->1, MF2->1, M1->2, M2->4, M4->8, M8->16 -class ConstantUntilMF2ThenDouble { - int c = ConstantUntilLMULThenDouble<"MF2", 1, mx>.c; +class ConstOneUntilMF2ThenDouble { + int c = ConstOneUntilLMULThenDouble<"MF2", 1, mx>.c; } // Returns MF8->1, MF4->1, MF2->1, M1->1, M2->2, M4->4, M8->8 -class ConstantUntilM1ThenDouble { - int c = ConstantUntilLMULThenDouble<"M1", 1, mx>.c; +class ConstOneUntilM1ThenDouble { + int c = ConstOneUntilLMULThenDouble<"M1", 1, mx>.c; } //===----------------------------------------------------------------------===// @@ -413,7 +413,7 @@ foreach mx = SchedMxList in { defm "" : LMULWriteResMX<"WriteVIMinMaxX", [SMX60_VIEU], mx, IsWorstCase>; } - defvar VIALULat = ConstantUntilLMULThenDouble<"M2", 4, mx>.c; + defvar VIALULat = ConstOneUntilLMULThenDouble<"M2", 4, mx>.c; let Latency = VIALULat, ReleaseAtCycles = [4] in { // Pattern of vadd, vsub, vrsub: 4/4/5/8 // Pattern of vand, vor, vxor: 4/4/8/16 @@ -451,7 +451,7 @@ foreach mx = SchedMxList in { // Pattern of vmacc, vmadd, vmul, vmulh, etc.: e8/e16 = 4/4/5/8, e32 = 5,5,5,8, // e64 = 7,8,16,32. We use the worst-case until we can split the SEW. // TODO: change WriteVIMulV, etc to be defined with LMULSEWSchedWrites - let Latency = ConstantUntilLMULThenDoubleBase<"M2", 8, 7, mx>.c, ReleaseAtCycles = [7] in { + let Latency = ConstOneUntilLMULThenDoubleBase<"M2", 8, 7, mx>.c, ReleaseAtCycles = [7] in { defm "" : LMULWriteResMX<"WriteVIMulV", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVIMulX", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVIMulAddV", [SMX60_VIEU], mx, IsWorstCase>; @@ -487,7 +487,7 @@ foreach mx = SchedMxList in { foreach sew = SchedSEWSet.val in { defvar IsWorstCase = SMX60IsWorstCaseMXSEW.c; - defvar VIDivLat = ConstantUntilLMULThenDouble<"MF2", 12, mx>.c; + defvar VIDivLat = ConstOneUntilLMULThenDouble<"MF2", 12, mx>.c; let Latency = VIDivLat, ReleaseAtCycles = [12] in { defm "" : LMULSEWWriteResMXSEW<"WriteVIDivV", [SMX60_VIEU], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVIDivX", [SMX60_VIEU], mx, sew, IsWorstCase>; @@ -499,7 +499,7 @@ foreach mx = SchedMxList in { foreach mx = SchedMxListW in { defvar IsWorstCase = SMX60IsWorstCaseMX.c; - defvar VNarrowingLat = ConstantUntilLMULThenDouble<"M1", 4, mx>.c; + defvar VNarrowingLat = ConstOneUntilLMULThenDouble<"M1", 4, mx>.c; let Latency = VNarrowingLat, ReleaseAtCycles = [4] in { defm "" : LMULWriteResMX<"WriteVNShiftV", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVNShiftX", [SMX60_VIEU], mx, IsWorstCase>; From 7c52beb6bbc7977d9357a605256a485f0a515cb4 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 31 Jul 2025 14:53:51 -0300 Subject: [PATCH 3/6] Error out when we pass an invalid LMUL Signed-off-by: Mikhail R. Gadelha --- llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td index 4d2c519593e39..93188b28dac87 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td @@ -22,7 +22,7 @@ // M2 -> Values[4], M4 -> Values[5], M8 -> Values[6] // The !ge size checks ensure we don't access beyond the array bounds, for cases // where M8 is not set (e.g., widening operations) -// Returns 0 if LMUL is invalid or if the array is too short +// TableGen will error if an invalid LMUL is passed or if the array is too short class GetLMULValue Values, string LMUL> { int c = !cond( !and(!eq(LMUL, "MF8"), !ge(!size(Values), 1)) : Values[0], @@ -31,8 +31,7 @@ class GetLMULValue Values, string LMUL> { !and(!eq(LMUL, "M1"), !ge(!size(Values), 4)) : Values[3], !and(!eq(LMUL, "M2"), !ge(!size(Values), 5)) : Values[4], !and(!eq(LMUL, "M4"), !ge(!size(Values), 6)) : Values[5], - !and(!eq(LMUL, "M8"), !ge(!size(Values), 7)) : Values[6], - true : 0 + !and(!eq(LMUL, "M8"), !ge(!size(Values), 7)) : Values[6] ); } From dd6db0b1ea280a98923792ee0fefbef6d2634c2f Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 31 Jul 2025 15:06:10 -0300 Subject: [PATCH 4/6] Rename and added assert Signed-off-by: Mikhail R. Gadelha --- .../lib/Target/RISCV/RISCVSchedSpacemitX60.td | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td index 93188b28dac87..6b4259365130c 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td @@ -35,17 +35,18 @@ class GetLMULValue Values, string LMUL> { ); } -// Returns BaseValue for LMUL values before startMx, Value for startMx, -// then doubles Value for each subsequent LMUL until targetMx -// Example: ConstOneUntilLMULThenDoubleBase<"M1", 4, 2, "M8"> returns: +// Returns BaseValue for LMUL values before startLMUL, Value for startLMUL, +// then doubles Value for each subsequent LMUL +// Example: ConstValueUntilLMULThenDoubleBase<"M1", 2, 4, "M8"> returns: // MF8->2, MF4->2, MF2->2, M1->4, M2->8, M4->16, M8->32 // This is useful for modeling scheduling parameters that scale with LMUL. -class ConstOneUntilLMULThenDoubleBase { - int startPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], startMx>.c; - int targetPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], targetMx>.c; +class ConstValueUntilLMULThenDoubleBase { + assert !le(BaseValue, Value), "BaseValue must be le to Value"; + int startPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], startLMUL>.c; + int currentPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], currentLMUL>.c; // Calculate the difference in positions - int posDiff = !sub(targetPos, startPos); + int posDiff = !sub(currentPos, startPos); // Calculate Value * (2^posDiff) using shift left int c = !cond( @@ -55,24 +56,24 @@ class ConstOneUntilLMULThenDoubleBase { - int c = ConstOneUntilLMULThenDoubleBase.c; +// Same as the previous function but BaseValue == Value +class ConstValueUntilLMULThenDouble { + int c = ConstValueUntilLMULThenDoubleBase.c; } // Returns MF8->1, MF4->1, MF2->2, M1->4, M2->8, M4->16, M8->32 class ConstOneUntilMF4ThenDouble { - int c = ConstOneUntilLMULThenDouble<"MF4", 1, mx>.c; + int c = ConstValueUntilLMULThenDouble<"MF4", 1, mx>.c; } // Returns MF8->1, MF4->1, MF2->1, M1->2, M2->4, M4->8, M8->16 class ConstOneUntilMF2ThenDouble { - int c = ConstOneUntilLMULThenDouble<"MF2", 1, mx>.c; + int c = ConstValueUntilLMULThenDouble<"MF2", 1, mx>.c; } // Returns MF8->1, MF4->1, MF2->1, M1->1, M2->2, M4->4, M8->8 class ConstOneUntilM1ThenDouble { - int c = ConstOneUntilLMULThenDouble<"M1", 1, mx>.c; + int c = ConstValueUntilLMULThenDouble<"M1", 1, mx>.c; } //===----------------------------------------------------------------------===// @@ -412,7 +413,7 @@ foreach mx = SchedMxList in { defm "" : LMULWriteResMX<"WriteVIMinMaxX", [SMX60_VIEU], mx, IsWorstCase>; } - defvar VIALULat = ConstOneUntilLMULThenDouble<"M2", 4, mx>.c; + defvar VIALULat = ConstValueUntilLMULThenDouble<"M2", 4, mx>.c; let Latency = VIALULat, ReleaseAtCycles = [4] in { // Pattern of vadd, vsub, vrsub: 4/4/5/8 // Pattern of vand, vor, vxor: 4/4/8/16 @@ -450,7 +451,7 @@ foreach mx = SchedMxList in { // Pattern of vmacc, vmadd, vmul, vmulh, etc.: e8/e16 = 4/4/5/8, e32 = 5,5,5,8, // e64 = 7,8,16,32. We use the worst-case until we can split the SEW. // TODO: change WriteVIMulV, etc to be defined with LMULSEWSchedWrites - let Latency = ConstOneUntilLMULThenDoubleBase<"M2", 8, 7, mx>.c, ReleaseAtCycles = [7] in { + let Latency = ConstValueUntilLMULThenDoubleBase<"M2", 7, 8, mx>.c, ReleaseAtCycles = [7] in { defm "" : LMULWriteResMX<"WriteVIMulV", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVIMulX", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVIMulAddV", [SMX60_VIEU], mx, IsWorstCase>; @@ -486,7 +487,7 @@ foreach mx = SchedMxList in { foreach sew = SchedSEWSet.val in { defvar IsWorstCase = SMX60IsWorstCaseMXSEW.c; - defvar VIDivLat = ConstOneUntilLMULThenDouble<"MF2", 12, mx>.c; + defvar VIDivLat = ConstValueUntilLMULThenDouble<"MF2", 12, mx>.c; let Latency = VIDivLat, ReleaseAtCycles = [12] in { defm "" : LMULSEWWriteResMXSEW<"WriteVIDivV", [SMX60_VIEU], mx, sew, IsWorstCase>; defm "" : LMULSEWWriteResMXSEW<"WriteVIDivX", [SMX60_VIEU], mx, sew, IsWorstCase>; @@ -498,7 +499,7 @@ foreach mx = SchedMxList in { foreach mx = SchedMxListW in { defvar IsWorstCase = SMX60IsWorstCaseMX.c; - defvar VNarrowingLat = ConstOneUntilLMULThenDouble<"M1", 4, mx>.c; + defvar VNarrowingLat = ConstValueUntilLMULThenDouble<"M1", 4, mx>.c; let Latency = VNarrowingLat, ReleaseAtCycles = [4] in { defm "" : LMULWriteResMX<"WriteVNShiftV", [SMX60_VIEU], mx, IsWorstCase>; defm "" : LMULWriteResMX<"WriteVNShiftX", [SMX60_VIEU], mx, IsWorstCase>; From 58133f853b182fb2f3305530e6b57933e9aca294 Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Thu, 31 Jul 2025 18:04:42 -0300 Subject: [PATCH 5/6] Simplify GetLMULValue Signed-off-by: Mikhail R. Gadelha --- .../lib/Target/RISCV/RISCVSchedSpacemitX60.td | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td index 6b4259365130c..dbceb66ded337 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td @@ -20,19 +20,24 @@ // LMUL values map to array indices as follows: // MF8 -> Values[0], MF4 -> Values[1], MF2 -> Values[2], M1 -> Values[3], // M2 -> Values[4], M4 -> Values[5], M8 -> Values[6] -// The !ge size checks ensure we don't access beyond the array bounds, for cases -// where M8 is not set (e.g., widening operations) -// TableGen will error if an invalid LMUL is passed or if the array is too short +// Shorter lists are allowed, e.g., widening instructions don't work on M8 class GetLMULValue Values, string LMUL> { - int c = !cond( - !and(!eq(LMUL, "MF8"), !ge(!size(Values), 1)) : Values[0], - !and(!eq(LMUL, "MF4"), !ge(!size(Values), 2)) : Values[1], - !and(!eq(LMUL, "MF2"), !ge(!size(Values), 3)) : Values[2], - !and(!eq(LMUL, "M1"), !ge(!size(Values), 4)) : Values[3], - !and(!eq(LMUL, "M2"), !ge(!size(Values), 5)) : Values[4], - !and(!eq(LMUL, "M4"), !ge(!size(Values), 6)) : Values[5], - !and(!eq(LMUL, "M8"), !ge(!size(Values), 7)) : Values[6] + int Index = !cond( + !eq(LMUL, "MF8"): 0, + !eq(LMUL, "MF4"): 1, + !eq(LMUL, "MF2"): 2, + !eq(LMUL, "M1"): 3, + !eq(LMUL, "M2"): 4, + !eq(LMUL, "M4"): 5, + !eq(LMUL, "M8"): 6, ); + + assert !lt(Index, !size(Values)), + "Missing LMUL value for '" # LMUL # "'. " # + "Expected at least " # !add(Index, 1) # " elements, but got " # + !size(Values) # "."; + + int c = Values[Index]; } // Returns BaseValue for LMUL values before startLMUL, Value for startLMUL, From 11c62f394e2bfeaca87bffb7fa15f39832a981cd Mon Sep 17 00:00:00 2001 From: "Mikhail R. Gadelha" Date: Fri, 1 Aug 2025 10:57:04 -0300 Subject: [PATCH 6/6] use defvar Signed-off-by: Mikhail R. Gadelha --- llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td index dbceb66ded337..cffc5db10b8d7 100644 --- a/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td +++ b/llvm/lib/Target/RISCV/RISCVSchedSpacemitX60.td @@ -22,7 +22,7 @@ // M2 -> Values[4], M4 -> Values[5], M8 -> Values[6] // Shorter lists are allowed, e.g., widening instructions don't work on M8 class GetLMULValue Values, string LMUL> { - int Index = !cond( + defvar Index = !cond( !eq(LMUL, "MF8"): 0, !eq(LMUL, "MF4"): 1, !eq(LMUL, "MF2"): 2, @@ -47,11 +47,11 @@ class GetLMULValue Values, string LMUL> { // This is useful for modeling scheduling parameters that scale with LMUL. class ConstValueUntilLMULThenDoubleBase { assert !le(BaseValue, Value), "BaseValue must be le to Value"; - int startPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], startLMUL>.c; - int currentPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], currentLMUL>.c; + defvar startPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], startLMUL>.c; + defvar currentPos = GetLMULValue<[0, 1, 2, 3, 4, 5, 6], currentLMUL>.c; // Calculate the difference in positions - int posDiff = !sub(currentPos, startPos); + defvar posDiff = !sub(currentPos, startPos); // Calculate Value * (2^posDiff) using shift left int c = !cond(