[llvm] 4b802fe - [AMDGPU] Use sparse direct lookup table for VOPD eligibility (#206534)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Jun 30 01:23:44 PDT 2026
Author: Igor Wodiany
Date: 2026-06-30T09:23:40+01:00
New Revision: 4b802fed943f420377c80fac82257000c1a11a9e
URL: https://github.com/llvm/llvm-project/commit/4b802fed943f420377c80fac82257000c1a11a9e
DIFF: https://github.com/llvm/llvm-project/commit/4b802fed943f420377c80fac82257000c1a11a9e.diff
LOG: [AMDGPU] Use sparse direct lookup table for VOPD eligibility (#206534)
This replaces a manually generated table with a new TableGen feature
that enables sparse direct lookup. Additional changes are made to put
both X and Y eligibility into a single table.
Assisted-by: Claude Code
Added:
Modified:
llvm/lib/Target/AMDGPU/SIInstrInfo.td
llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
llvm/lib/Target/AMDGPU/VOPDInstructions.td
Removed:
################################################################################
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.td b/llvm/lib/Target/AMDGPU/SIInstrInfo.td
index 8c30e53e9b4e4..7be067c085b5f 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.td
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.td
@@ -3576,22 +3576,15 @@ def lo16_to_vgpr32 : OutPatFrag<(ops node:$op),
def hi16_to_vgpr32 : OutPatFrag<(ops node:$op),
(REG_SEQUENCE VGPR_32, (i16 (IMPLICIT_DEF)), lo16, $op, hi16)>;
-// Instructions eligible to be the first (X) instruction in Dual Issue VALU
-// (VOPD) encoding. Consumed by buildVOPDXYLookup() to build a direct lookup
-// table; no helper is generated.
-def VOPDXTable : GenericTable {
- let FilterClass = "VOPDX";
+// Direct lookup table for VOPDXY eligibility, indexed by the packed
+// (VOPDOp << 5) | (Subtarget << 1) | VOPD3 key.
+def VOPDXYTable : GenericTable {
+ let FilterClass = "VOPDXY";
let CppTypeName = "VOPDXYInfo";
- let Fields = ["VOPDOp", "Subtarget", "VOPD3"];
-}
-
-// Instructions eligible to be the second (Y) instruction in Dual Issue VALU
-// (VOPD) encoding. Consumed by buildVOPDXYLookup() to build a direct lookup
-// table; no helper is generated.
-def VOPDYTable : GenericTable {
- let FilterClass = "VOPDY";
- let CppTypeName = "VOPDXYInfo";
- let Fields = ["VOPDOp", "Subtarget", "VOPD3"];
+ let Fields = ["VOPDXYKey", "IsX", "IsY"];
+ let PrimaryKey = ["VOPDXYKey"];
+ let PrimaryKeyName = "getVOPDXYInfo";
+ let DisallowSparseTable = false;
}
include "SIInstructions.td"
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
index 34779acd2b8d2..588ca588819cc 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
@@ -420,9 +420,9 @@ struct VOPTrue16Info {
};
struct VOPDXYInfo {
- uint16_t VOPDOp;
- uint16_t Subtarget;
- bool VOPD3;
+ uint16_t VOPDXYKey;
+ bool IsX;
+ bool IsY;
};
#define GET_FP4FP8DstByteSelTable_DECL
@@ -465,10 +465,8 @@ struct FP4FP8DstByteSelInfo {
#define GET_VOPDComponentTable_IMPL
#define GET_VOPDPairs_DECL
#define GET_VOPDPairs_IMPL
-#define GET_VOPDXTable_DECL
-#define GET_VOPDXTable_IMPL
-#define GET_VOPDYTable_DECL
-#define GET_VOPDYTable_IMPL
+#define GET_VOPDXYTable_DECL
+#define GET_VOPDXYTable_IMPL
#define GET_VOPTrue16Table_DECL
#define GET_VOPTrue16Table_IMPL
#define GET_True16D16Table_IMPL
@@ -693,28 +691,6 @@ unsigned getVOPDEncodingFamily(const MCSubtargetInfo &ST) {
llvm_unreachable("Subtarget generation does not support VOPD!");
}
-static constexpr unsigned getVOPDXYKey(unsigned VOPDOp, unsigned Subtarget,
- bool VOPD3) {
- return (VOPDOp << 5) | (Subtarget << 1) | (VOPD3 ? 1u : 0u);
-}
-
-// TODO: Ideally, the table should be emitted by the TableGen backend, however
-// this is currently not supported, so the direct lookup table is generated
-// manually here.
-constexpr unsigned VOPDXYKeyBits = 11;
-static constexpr std::array<CanBeVOPD, 1 << VOPDXYKeyBits> buildVOPDXYLookup() {
- std::array<CanBeVOPD, 1 << VOPDXYKeyBits> Table{};
- for (auto &E : Table)
- E = {false, false};
- for (const auto &E : VOPDXTable)
- Table[getVOPDXYKey(E.VOPDOp, E.Subtarget, E.VOPD3)].X = true;
- for (const auto &E : VOPDYTable)
- Table[getVOPDXYKey(E.VOPDOp, E.Subtarget, E.VOPD3)].Y = true;
- return Table;
-}
-
-constexpr auto VOPDXYLookup = buildVOPDXYLookup();
-
CanBeVOPD getCanBeVOPD(unsigned Opc, unsigned EncodingFamily, bool VOPD3) {
bool IsConvertibleToBitOp = VOPD3 ? getBitOp2(Opc) : 0;
Opc = IsConvertibleToBitOp ? (unsigned)AMDGPU::V_BITOP3_B32_e64 : Opc;
@@ -723,7 +699,12 @@ CanBeVOPD getCanBeVOPD(unsigned Opc, unsigned EncodingFamily, bool VOPD3) {
const VOPDComponentInfo *Info = getVOPDComponentHelper(Opc);
if (!Info)
return {false, false};
- return VOPDXYLookup[getVOPDXYKey(Info->VOPDOp, EncodingFamily, VOPD3)];
+ unsigned Key =
+ (Info->VOPDOp << 5) | (EncodingFamily << 1) | (VOPD3 ? 1u : 0u);
+ const VOPDXYInfo *XYInfo = getVOPDXYInfo(Key);
+ if (!XYInfo)
+ return {false, false};
+ return {XYInfo->IsX, XYInfo->IsY};
}
unsigned getVOPDOpcode(unsigned Opc, bool VOPD3) {
diff --git a/llvm/lib/Target/AMDGPU/VOPDInstructions.td b/llvm/lib/Target/AMDGPU/VOPDInstructions.td
index 6a905d432b5c2..1fadb8999b14b 100644
--- a/llvm/lib/Target/AMDGPU/VOPDInstructions.td
+++ b/llvm/lib/Target/AMDGPU/VOPDInstructions.td
@@ -103,6 +103,7 @@ class GFXGenD<GFXGen Gen, list<string> DXPseudos, list<string> DYPseudos,
list<string> VOPDXPseudos = DXPseudos;
list<string> VOPDYPseudos = DYPseudos;
Predicate SubtargetPredicate = subtargetPred;
+ bit IsVOPD3 = 0;
}
class VOPD_Base<dag outs, dag ins, string asm, VOP_Pseudo VDX, VOP_Pseudo VDY,
@@ -262,9 +263,13 @@ defvar VOPD3YPseudosGFX1250 = !listconcat(
!eq(!find(x, "FMAMK"), -1))),
VOPD3YPseudosExtra);
-def GFX1250GenD3 : GFXGenD<GFX1250Gen, VOPD3XPseudosGFX1250, VOPD3YPseudosGFX1250>;
+def GFX1250GenD3 : GFXGenD<GFX1250Gen, VOPD3XPseudosGFX1250, VOPD3YPseudosGFX1250> {
+ let IsVOPD3 = 1;
+}
-def GFX13GenD3 : GFXGenD<GFX13Gen, VOPD3XPseudosGFX13, VOPD3YPseudosGFX1250>;
+def GFX13GenD3 : GFXGenD<GFX13Gen, VOPD3XPseudosGFX13, VOPD3YPseudosGFX1250> {
+ let IsVOPD3 = 1;
+}
class getOpcMap<string OPName> {
defvar BaseName = !substr(OPName,2);
@@ -290,29 +295,26 @@ foreach Gen = [GFX1250GenD3, GFX13GenD3] in {
}
}
-class VOPDXY<bits<6> Op, int Sub, bit IsVOPD3> {
- bits<6> VOPDOp = Op;
- bits<4> Subtarget = Sub;
- bit VOPD3 = IsVOPD3;
+class VOPDXY<bits<6> Op, bits<4> Sub, bit IsVOPD3, bit X, bit Y> {
+ bits<11> VOPDXYKey = {Op, Sub, IsVOPD3};
+ bit IsX = X;
+ bit IsY = Y;
}
-class VOPDX<bits<6> Op, int Sub, bit IsVOPD3> : VOPDXY<Op, Sub, IsVOPD3>;
-class VOPDY<bits<6> Op, int Sub, bit IsVOPD3> : VOPDXY<Op, Sub, IsVOPD3>;
-
-foreach Gen = [GFX11GenD, GFX1170GenD, GFX12GenD, GFX1250GenD, GFX13GenD] in {
- foreach p = Gen.VOPDXPseudos in
- def "VOPDX_" # p # Gen.Suffix :
- VOPDX<!cast<VOPD_Component>(p).VOPDOp, Gen.Subtarget, 0>;
- foreach p = Gen.VOPDYPseudos in
- def "VOPDY_" # p # Gen.Suffix :
- VOPDY<!cast<VOPD_Component>(p).VOPDOp, Gen.Subtarget, 0>;
-}
-
-foreach Gen = [GFX1250GenD3, GFX13GenD3] in {
- foreach p = Gen.VOPDXPseudos in
- def "VOPDX_VOPD3_" # p # Gen.Suffix :
- VOPDX<!cast<VOPD_Component>(p).VOPDOp, Gen.Subtarget, 1>;
- foreach p = Gen.VOPDYPseudos in
- def "VOPDY_VOPD3_" # p # Gen.Suffix :
- VOPDY<!cast<VOPD_Component>(p).VOPDOp, Gen.Subtarget, 1>;
+foreach Gen = [GFX11GenD, GFX1170GenD, GFX12GenD, GFX1250GenD, GFX13GenD,
+ GFX1250GenD3, GFX13GenD3] in {
+ defvar Prefix = !if(Gen.IsVOPD3, "VOPDXY_VOPD3_", "VOPDXY_");
+ defvar XOnly = !listremove(Gen.VOPDXPseudos, Gen.VOPDYPseudos);
+ defvar YOnly = !listremove(Gen.VOPDYPseudos, Gen.VOPDXPseudos);
+ defvar XAndY = !listremove(Gen.VOPDXPseudos, XOnly);
+
+ foreach p = XOnly in
+ def Prefix # p # Gen.Suffix :
+ VOPDXY<!cast<VOPD_Component>(p).VOPDOp, Gen.Subtarget, Gen.IsVOPD3, 1, 0>;
+ foreach p = YOnly in
+ def Prefix # p # Gen.Suffix :
+ VOPDXY<!cast<VOPD_Component>(p).VOPDOp, Gen.Subtarget, Gen.IsVOPD3, 0, 1>;
+ foreach p = XAndY in
+ def Prefix # p # Gen.Suffix :
+ VOPDXY<!cast<VOPD_Component>(p).VOPDOp, Gen.Subtarget, Gen.IsVOPD3, 1, 1>;
}
More information about the llvm-commits
mailing list