[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