[llvm] [AMDGPU][NFC] Add SingleSGPRReadFromTuple feature and rename related functions (PR #211933)
Changpeng Fang via llvm-commits
llvm-commits at lists.llvm.org
Fri Jul 24 14:49:59 PDT 2026
https://github.com/changpeng created https://github.com/llvm/llvm-project/pull/211933
Refactors 64-bit and wider packed instruction handling by introducing the
SingleSGPRReadFromTuple subtarget feature and renaming related helper
functions. This replaces GFX12+-specific checks with a feature flag that more
accurately captures the hardware behavior where a single SGPR is read from a tuple.
Changes:
- Renames isPackedFP32or64BitInst to isWidePackedInst for clarity
- Renames isLegalGFX12PlusPackedMathFP32or64BitOperand to isLegalWidePackedInstOperand to reflect the generalized functionality
- Adds SingleSGPRReadFromTuple subtarget feature
- Enables the feature for ISA versions 12, 12.50, and 13
- Updates verification and legalization logic to use the feature flag instead of hardcoded GFX12+ checks
>From 4666017f0eb293a25b0d044eec173f91092f11a2 Mon Sep 17 00:00:00 2001
From: Changpeng Fang <changpeng.fang at amd.com>
Date: Fri, 24 Jul 2026 14:43:09 -0700
Subject: [PATCH] [AMDGPU][NFC] Add SingleSGPRReadFromTuple feature and rename
related functions
Refactors 64-bit and wider packed instruction handling by introducing
the SingleSGPRReadFromTuple subtarget feature and renaming related helper
functions. This replaces GFX12+-specific checks with a feature flag that
more accurately captures the hardware behavior where a single SGPR is read
from a tuple.
Changes:
- Renames isPackedFP32or64BitInst to isWidePackedInst for clarity
- Renames isLegalGFX12PlusPackedMathFP32or64BitOperand to
isLegalWidePackedInstOperand to reflect the generalized functionality
- Adds SingleSGPRReadFromTuple subtarget feature
- Enables the feature for ISA versions 12, 12.50, and 13
- Updates verification and legalization logic to use the feature flag
instead of hardcoded GFX12+ checks
---
llvm/lib/Target/AMDGPU/AMDGPU.td | 10 +++++-
llvm/lib/Target/AMDGPU/SIInstrInfo.cpp | 33 +++++++++----------
llvm/lib/Target/AMDGPU/SIInstrInfo.h | 2 +-
.../Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp | 3 +-
llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h | 2 +-
5 files changed, 28 insertions(+), 22 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index bdc9acaa2f6bb..6bee942866443 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -1160,6 +1160,11 @@ defm WMMACoexecutionHazards : AMDGPUSubtargetFeature<"wmma-coexecution-hazards",
/*GenPredicate=*/0
>;
+defm SingleSGPRReadFromTuple : AMDGPUSubtargetFeature<"single-sgpr-read-from-tuple",
+ "Read a single sgpr from a tuple for wide packed instructions",
+ /*GenPredicate=*/0
+>;
+
defm SALUFloatInsts : AMDGPUSubtargetFeature<"salu-float",
"Has SALU floating point instructions"
>;
@@ -2184,7 +2189,8 @@ def FeatureISAVersion12 : FeatureSet<
FeatureRealTrue16Insts,
FeatureMTBUFInsts,
FeatureFormattedMUBUFInsts,
- FeatureDataCacheLineSize128
+ FeatureDataCacheLineSize128,
+ FeatureSingleSGPRReadFromTuple
]>;
def FeatureISAVersion12_50_Common : FeatureSet<
@@ -2272,6 +2278,7 @@ def FeatureISAVersion12_50_Common : FeatureSet<
FeatureRealTrue16Insts,
FeatureVMovB64Inst,
FeatureVMulU64Inst,
+ FeatureSingleSGPRReadFromTuple
]>;
def FeatureISAVersion12_50 : FeatureSet<
@@ -2408,6 +2415,7 @@ def FeatureISAVersion13 : FeatureSet<
FeatureCvtPkNormVOP3Insts,
FeatureSmemPrefetchInsts,
FeatureAsyncLoadToLDSInsts,
+ FeatureSingleSGPRReadFromTuple
]>;
def FeatureISAVersion13_Generic: FeatureSet<
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
index 28914d598a72d..24884c3a4216b 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.cpp
@@ -5939,11 +5939,10 @@ bool SIInstrInfo::verifyInstruction(const MachineInstr &MI,
}
}
- // See SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
- // information.
- if (AMDGPU::isPackedFP32or64BitInst(Opcode) && AMDGPU::isGFX12Plus(ST)) {
+ // See SIInstrInfo::isLegalWidePackedInstOperand for more information.
+ if (ST.hasSingleSGPRReadFromTuple() && AMDGPU::isWidePackedInst(Opcode)) {
for (unsigned I = 0; I < 3; ++I) {
- if (!isLegalGFX12PlusPackedMathFP32or64BitOperand(MRI, MI, I))
+ if (!isLegalWidePackedInstOperand(MRI, MI, I))
return false;
}
}
@@ -6301,8 +6300,7 @@ void SIInstrInfo::legalizeOpWithMove(MachineInstr &MI, unsigned OpIdx) const {
DebugLoc DL = MBB->findDebugLoc(I);
if (Size == 128 && AMDGPU::isPacked64BitInst(MI.getOpcode()) &&
- isLegalGFX12PlusPackedMathFP32or64BitOperand(
- MRI, MI, VOP3OpIdxToSrcN(MI, OpIdx))) {
+ isLegalWidePackedInstOperand(MRI, MI, VOP3OpIdxToSrcN(MI, OpIdx))) {
// Special case for V_PK_*64 instructions: these do not have OPSEL but SGPR
// sources behave like OPSEL is set replicating low 64-bits into high. VGPR
// sources in turn read actual 4 registers. To move operand from an SGPR to
@@ -6404,12 +6402,11 @@ bool SIInstrInfo::isLegalRegOperand(const MachineInstr &MI, unsigned OpIdx,
const MCOperandInfo OpInfo = MI.getDesc().operands()[OpIdx];
unsigned Opc = MI.getOpcode();
- // See SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
- // information.
- if (AMDGPU::isPackedFP32or64BitInst(MI.getOpcode()) &&
- AMDGPU::isGFX12Plus(ST) && MO.isReg() && RI.isSGPRReg(MRI, MO.getReg()) &&
- !isLegalGFX12PlusPackedMathFP32or64BitOperand(
- MRI, MI, VOP3OpIdxToSrcN(MI, OpIdx), &MO))
+ // See SIInstrInfo::isLegalWidePackdInstOperand for more information.
+ if (ST.hasSingleSGPRReadFromTuple() && MO.isReg() &&
+ RI.isSGPRReg(MRI, MO.getReg()) &&
+ AMDGPU::isWidePackedInst(MI.getOpcode()) &&
+ !isLegalWidePackedInstOperand(MRI, MI, VOP3OpIdxToSrcN(MI, OpIdx), &MO))
return false;
if (!isLegalRegOperand(MRI, OpInfo, MO))
@@ -6475,7 +6472,7 @@ bool SIInstrInfo::isLegalVSrcOperand(const MachineRegisterInfo &MRI,
return true;
}
-bool SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand(
+bool SIInstrInfo::isLegalWidePackedInstOperand(
const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
const MachineOperand *MO) const {
constexpr unsigned NumOps = 3;
@@ -6896,12 +6893,12 @@ void SIInstrInfo::legalizeOperandsVOP3(MachineRegisterInfo &MRI,
!RI.isVGPR(MRI, MI.getOperand(VOP3Idx[2]).getReg()))
legalizeOpWithMove(MI, VOP3Idx[2]);
- // Fix the register class of packed FP32 instructions on gfx12+. See
- // SIInstrInfo::isLegalGFX12PlusPackedMathFP32or64BitOperand for more
- // information.
- if (AMDGPU::isPackedFP32or64BitInst(Opc) && AMDGPU::isGFX12Plus(ST)) {
+ // Fix the register class of 64-bit or wider packed instructions on target
+ // that reads a sigle sgpr from a tuple.
+ // Ser SIInstrInfo::isLegalWidePackedInstOperand for more information.
+ if (ST.hasSingleSGPRReadFromTuple() && AMDGPU::isWidePackedInst(Opc)) {
for (unsigned I = 0; I < 3; ++I) {
- if (!isLegalGFX12PlusPackedMathFP32or64BitOperand(MRI, MI, /*SrcN=*/I))
+ if (!isLegalWidePackedInstOperand(MRI, MI, /*SrcN=*/I))
legalizeOpWithMove(MI, VOP3Idx[I]);
}
}
diff --git a/llvm/lib/Target/AMDGPU/SIInstrInfo.h b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
index 8e15b7b45b609..02a0db6a9810f 100644
--- a/llvm/lib/Target/AMDGPU/SIInstrInfo.h
+++ b/llvm/lib/Target/AMDGPU/SIInstrInfo.h
@@ -1490,7 +1490,7 @@ class SIInstrInfo final : public AMDGPUGenInstrInfo {
/// \p SrcN can be 0, 1, or 2, representing src0, src1, and src2,
/// respectively. If \p MO is nullptr, the operand corresponding to SrcN will
/// be used.
- bool isLegalGFX12PlusPackedMathFP32or64BitOperand(
+ bool isLegalWidePackedInstOperand(
const MachineRegisterInfo &MRI, const MachineInstr &MI, unsigned SrcN,
const MachineOperand *MO = nullptr) const;
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
index 6c847107db593..16307a613aad0 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp
@@ -3766,7 +3766,8 @@ bool isPacked64BitInst(unsigned Opc) {
}
}
-bool isPackedFP32or64BitInst(unsigned Opc) {
+// Wide means operand size is equal to or larger than 64-bit
+bool isWidePackedInst(unsigned Opc) {
return isPackedFP32Inst(Opc) || isPacked64BitInst(Opc);
}
diff --git a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
index 9dcd1ed9d1441..d12e46e55cfda 100644
--- a/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
+++ b/llvm/lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h
@@ -1695,7 +1695,7 @@ LLVM_READONLY bool isPackedFP32Inst(unsigned Opc);
LLVM_READONLY bool isPacked64BitInst(unsigned Opc);
-LLVM_READONLY bool isPackedFP32or64BitInst(unsigned Opc);
+LLVM_READONLY bool isWidePackedInst(unsigned Opc);
LLVM_READONLY
bool isLegalSMRDEncodedUnsignedOffset(const MCSubtargetInfo &ST,
More information about the llvm-commits
mailing list