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

>From 115502f896ef32fcccd8db1670b8682b46887963 Mon Sep 17 00:00:00 2001
From: Petar Avramovic <[email protected]>
Date: Mon, 20 Jul 2026 17:19:21 +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 | 66 +++++++++++++++++++++----
 1 file changed, 56 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp 
b/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
index 44e467b0ba721..4698b4e1be57e 100644
--- a/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
@@ -34,6 +34,35 @@ 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>.
+static bool isValidVOPDSrc(const SIInstrInfo &TII, int VOPDOpc,
+                           unsigned CompIdx, unsigned SrcIdx,
+                           Register PhysSrcReg) {
+  using namespace AMDGPU;
+  int OpIdx = -1;
+  const bool IsX = CompIdx == VOPD::X;
+  switch (SrcIdx) {
+  case 0:
+    OpIdx = getNamedOperandIdx(VOPDOpc, IsX ? OpName::src0X : OpName::src0Y);
+    break;
+  case 1:
+    OpIdx = getNamedOperandIdx(VOPDOpc, IsX ? OpName::vsrc1X : OpName::vsrc1Y);
+    break;
+  case 2:
+    OpIdx = getNamedOperandIdx(VOPDOpc, IsX ? OpName::vsrc2X : OpName::vsrc2Y);
+    if (OpIdx == -1)
+      OpIdx = getNamedOperandIdx(VOPDOpc, IsX ? OpName::src2X : OpName::src2Y);
+    break;
+  default:
+    llvm_unreachable("unexpected VOPD source index");
+  }
+
+  assert(OpIdx != -1);
+  return TII.getRegClass(TII.get(VOPDOpc), OpIdx)->contains(PhysSrcReg);
+}
+
 bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
                                    const MachineInstr &MIX,
                                    const MachineInstr &MIY, bool IsVOPD3,
@@ -63,6 +92,12 @@ 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);
+  assert(VOPDOpc != -1);
+
   auto InstInfo = AMDGPU::getVOPDInstInfo(MIX.getDesc(), MIY.getDesc());
 
   for (auto CompIdx : VOPD::COMPONENTS) {
@@ -70,9 +105,10 @@ bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
 
     const MachineOperand &Src0 = *TII.getNamedOperand(MI, 
AMDGPU::OpName::src0);
     if (Src0.isReg()) {
-      if (!TRI->isVectorRegister(MRI, Src0.getReg())) {
+      if (!isValidVOPDSrc(TII, VOPDOpc, CompIdx, 0, Src0.getReg()))
+        return false;
+      if (!TRI->isVectorRegister(MRI, Src0.getReg()))
         UniqueScalarRegs.insert(Src0.getReg());
-      }
     } else if (!TII.isInlineConstant(Src0)) {
       if (IsVOPD3)
         return false;
@@ -90,23 +126,33 @@ 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()))
+    if (const MachineOperand *Src1 =
+            TII.getNamedOperand(MI, AMDGPU::OpName::src1)) {
+      if (Src1->isReg()) {
+        if (!isValidVOPDSrc(TII, VOPDOpc, CompIdx, 1, Src1->getReg()))
           return false;
+        assert(TRI->isVectorRegister(MRI, Src1->getReg()));
+      } else if (IsVOPD3) {
+        return false;
       }
+    }
 
+    if (IsVOPD3) {
       if (const MachineOperand *Src2 =
               TII.getNamedOperand(MI, AMDGPU::OpName::src2)) {
         if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::bitop3)) {
           // BITOP3 can be converted to DUAL_BITOP2 when src2 is zero.
           if (!Src2->isImm() || Src2->getImm())
             return false;
-        } else if (MI.getOpcode() == AMDGPU::V_CNDMASK_B32_e64) {
-          UniqueScalarRegs.insert(Src2->getReg());
-        } else if (!Src2->isReg() || !TRI->isVGPR(MRI, Src2->getReg())) {
-          return false;
+        } else {
+          if (!Src2->isReg())
+            return false;
+          if (!isValidVOPDSrc(TII, VOPDOpc, CompIdx, 2, Src2->getReg()))
+            return false;
+          if (!TRI->isVectorRegister(MRI, Src2->getReg())) {
+            assert(MI.getOpcode() == AMDGPU::V_CNDMASK_B32_e64);
+            UniqueScalarRegs.insert(Src2->getReg());
+          }
         }
       }
       for (auto OpName : {AMDGPU::OpName::clamp, AMDGPU::OpName::omod,

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

Reply via email to