https://github.com/petar-avramovic created 
https://github.com/llvm/llvm-project/pull/196515

Replace isVGPR checks with isValidVOPDSrc that validates physical source
registers against the actual combined VOPD/VOPD3 instruction's operand
register classes. Now we also validate operands for VOPD instructions.

>From 2c22fc19e60c076ad79aee78f8fee037d683d26d Mon Sep 17 00:00:00 2001
From: Petar Avramovic <[email protected]>
Date: Fri, 8 May 2026 12:56:09 +0200
Subject: [PATCH] AMDGPU: Validate VOPD/VOPD3 physical source registers against
 operand RC

Replace isVGPR checks with isValidVOPDSrc that validates physical source
registers against the actual combined VOPD/VOPD3 instruction's operand
register classes. Now we also validate operands for VOPD instructions.
---
 llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp | 51 +++++++++++++++++++++----
 1 file changed, 44 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp 
b/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
index 7c3ec382dc04b..fb26175769d94 100644
--- a/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
@@ -34,6 +34,32 @@ using namespace llvm;
 
 #define DEBUG_TYPE "gcn-vopd-utils"
 
+// Check if physical register from src<SrcIdx> operand of MI<CompIdx> matches
+// register class constraints in corresponding VOPDOpc operand with name
+// src/vsrc<SrcIdx><CompIdx>.
+bool isValidVOPDSrc(const SIInstrInfo &TII, int VOPDOpc, unsigned CompIdx,
+                    unsigned SrcIdx, Register PhysSrcReg) {
+  static const AMDGPU::OpName Src0X[] = {AMDGPU::OpName::src0X};
+  static const AMDGPU::OpName Src1X[] = {AMDGPU::OpName::vsrc1X};
+  static const AMDGPU::OpName Src2X[] = {AMDGPU::OpName::vsrc2X,
+                                         AMDGPU::OpName::src2X};
+  static const AMDGPU::OpName Src0Y[] = {AMDGPU::OpName::src0Y};
+  static const AMDGPU::OpName Src1Y[] = {AMDGPU::OpName::vsrc1Y};
+  static const AMDGPU::OpName Src2Y[] = {AMDGPU::OpName::vsrc2Y,
+                                         AMDGPU::OpName::src2Y};
+  static const ArrayRef<AMDGPU::OpName> SrcNames[2][3] = {
+      {Src0X, Src1X, Src2X}, {Src0Y, Src1Y, Src2Y}};
+
+  int Idx = -1;
+  for (AMDGPU::OpName Name : SrcNames[CompIdx][SrcIdx]) {
+    Idx = getNamedOperandIdx(VOPDOpc, Name);
+    if (Idx > 0)
+      break;
+  }
+
+  return TII.getRegClass(TII.get(VOPDOpc), Idx)->contains(PhysSrcReg);
+}
+
 bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
                                    const MachineInstr &MIX,
                                    const MachineInstr &MIY, bool IsVOPD3,
@@ -63,6 +89,11 @@ bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
   };
   SmallSet<Register, 4> UniqueScalarRegs;
 
+  unsigned EncodingFamily = AMDGPU::getVOPDEncodingFamily(ST);
+  unsigned XOpc = AMDGPU::getVOPDOpcode(MIX.getOpcode(), IsVOPD3);
+  unsigned YOpc = AMDGPU::getVOPDOpcode(MIY.getOpcode(), IsVOPD3);
+  int VOPDOpc = AMDGPU::getVOPDFull(XOpc, YOpc, EncodingFamily, IsVOPD3);
+
   auto InstInfo = AMDGPU::getVOPDInstInfo(MIX.getDesc(), MIY.getDesc());
 
   for (auto CompIdx : VOPD::COMPONENTS) {
@@ -73,6 +104,8 @@ bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
       if (!TRI->isVectorRegister(MRI, Src0.getReg())) {
         UniqueScalarRegs.insert(Src0.getReg());
       }
+      if (!isValidVOPDSrc(TII, VOPDOpc, CompIdx, 0, Src0.getReg()))
+        return false;
     } else if (!TII.isInlineConstant(Src0)) {
       if (IsVOPD3)
         return false;
@@ -90,13 +123,16 @@ bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
     if (MI.getDesc().hasImplicitUseOfPhysReg(AMDGPU::VCC))
       UniqueScalarRegs.insert(AMDGPU::VCC_LO);
 
-    if (IsVOPD3) {
-      if (const MachineOperand *Src1 =
-              TII.getNamedOperand(MI, AMDGPU::OpName::src1)) {
-        if (!Src1->isReg() || !TRI->isVGPR(MRI, Src1->getReg()))
-          return false;
-      }
+    if (const MachineOperand *Src1 =
+            TII.getNamedOperand(MI, AMDGPU::OpName::src1)) {
+      if (IsVOPD3 && !Src1->isReg())
+        return false;
+      if (Src1->isReg() &&
+          !isValidVOPDSrc(TII, VOPDOpc, CompIdx, 1, Src1->getReg()))
+        return false;
+    }
 
+    if (IsVOPD3) {
       if (const MachineOperand *Src2 =
               TII.getNamedOperand(MI, AMDGPU::OpName::src2)) {
         if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::bitop3)) {
@@ -105,7 +141,8 @@ bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
             return false;
         } else if (MI.getOpcode() == AMDGPU::V_CNDMASK_B32_e64) {
           UniqueScalarRegs.insert(Src2->getReg());
-        } else if (!Src2->isReg() || !TRI->isVGPR(MRI, Src2->getReg())) {
+        } else if (!Src2->isReg() ||
+                   !isValidVOPDSrc(TII, VOPDOpc, CompIdx, 2, Src2->getReg())) {
           return false;
         }
       }

_______________________________________________
llvm-branch-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits

Reply via email to