[llvm] [AMDGPU] Reject DPP combine when old is narrower than dst (PR #217894)

Arseniy Obolenskiy via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 9 08:53:28 PDT 2026


https://github.com/aobolensk updated https://github.com/llvm/llvm-project/pull/217894

>From 2d93a27af34f641056a207a8bdb7a81784b75dd0 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Fri, 21 Aug 2026 14:09:14 +0200
Subject: [PATCH 1/2] [AMDGPU] Reject DPP combine when old is narrower than dst

Old is copied from the mov dst class, but the combined dst can be wider (e.g. V_CVT_F64_I32), making old illegal for it
---
 llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp       |  6 ++++++
 llvm/test/CodeGen/AMDGPU/dpp_combine_gfx11.mir | 18 ++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp b/llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp
index 9d22757b4514a..08585d62f54b7 100644
--- a/llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp
@@ -261,6 +261,12 @@ MachineInstr *GCNDPPCombine::createDPPInst(MachineInstr &OrigMI,
       DPPInst.addReg(CombOldVGPR.Reg, getUndefRegState(!Def),
                      CombOldVGPR.SubReg);
       ++NumOperands;
+
+      if (!TII->isOperandLegal(*DPPInst, OldIdx)) {
+        LLVM_DEBUG(dbgs() << "  failed: old operand is illegal\n");
+        Fail = true;
+        break;
+      }
     } else if (TII->isVOPC(DPPOp) || (TII->isVOP3(DPPOp) && OrigOpE32 != -1 &&
                                       TII->isVOPC(OrigOpE32))) {
       // VOPC DPP and VOPC promoted to VOP3 DPP do not have an old operand
diff --git a/llvm/test/CodeGen/AMDGPU/dpp_combine_gfx11.mir b/llvm/test/CodeGen/AMDGPU/dpp_combine_gfx11.mir
index b7c884c7995e7..63a807d345486 100644
--- a/llvm/test/CodeGen/AMDGPU/dpp_combine_gfx11.mir
+++ b/llvm/test/CodeGen/AMDGPU/dpp_combine_gfx11.mir
@@ -950,3 +950,21 @@ body:             |
     %10:vgpr_32 = V_MOV_B32_dpp %3, %0, 1, 15, 15, 1, implicit $exec
     %11:vgpr_32 = V_FMA_MIX_F32 12, %10, 12, %1, 12, %2, 0, 0, 0, implicit $mode, implicit $exec
 ...
+
+# GCN-LABEL: name: dpp_64bit_dst_32bit_old
+# GCN: %2:vgpr_32 = V_MOV_B32_dpp %1, %0, 85, 15, 15, 1, implicit $exec
+# GCN: %3:vreg_64 = V_CVT_F64_I32_e64 %2, 0, 0, implicit $mode, implicit $exec
+
+name: dpp_64bit_dst_32bit_old
+tracksRegLiveness: true
+body:             |
+  bb.0:
+    liveins: $vgpr0
+
+    %0:vgpr_32 = COPY $vgpr0
+    %1:vgpr_32 = IMPLICIT_DEF
+    ; should not be combined: old is 32-bit but V_CVT_F64_I32 dst is 64-bit
+    %2:vgpr_32 = V_MOV_B32_dpp %1, %0, 85, 15, 15, 1, implicit $exec
+    %3:vreg_64 = V_CVT_F64_I32_e64 %2, 0, 0, implicit $mode, implicit $exec
+    S_ENDPGM 0, implicit %3
+...

>From 2b4ed3b9616aa77fcf3ee7b2ebf54cde616c0487 Mon Sep 17 00:00:00 2001
From: Arseniy Obolenskiy <arseniy.obolenskiy at amd.com>
Date: Wed, 9 Sep 2026 16:31:32 +0200
Subject: [PATCH 2/2] Address comments

---
 llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp | 17 ++++++++++-------
 1 file changed, 10 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp b/llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp
index 08585d62f54b7..7c7ef9b231e0a 100644
--- a/llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNDPPCombine.cpp
@@ -216,6 +216,16 @@ MachineInstr *GCNDPPCombine::createDPPInst(MachineInstr &OrigMI,
     LLVM_DEBUG(dbgs() << "  failed: no DPP opcode\n");
     return nullptr;
   }
+
+  const int OldIdx = AMDGPU::getNamedOperandIdx(DPPOp, AMDGPU::OpName::old);
+  const int MovDstIdx =
+      AMDGPU::getNamedOperandIdx(MovMI.getOpcode(), AMDGPU::OpName::vdst);
+  if (OldIdx != -1 &&
+      TII->getOpSize(DPPOp, OldIdx) != TII->getOpSize(MovMI, MovDstIdx)) {
+    LLVM_DEBUG(dbgs() << "  failed: old operand size differs from dst\n");
+    return nullptr;
+  }
+
   int OrigOpE32 = AMDGPU::getVOPe32(OrigOp);
   // Prior checks cover Mask with VOPC condition, but not on purpose
   auto *RowMaskOpnd = TII->getNamedOperand(MovMI, AMDGPU::OpName::row_mask);
@@ -249,7 +259,6 @@ MachineInstr *GCNDPPCombine::createDPPInst(MachineInstr &OrigMI,
       // If we shrunk a 64bit vop3b to 32bits, just ignore the sdst
     }
 
-    const int OldIdx = AMDGPU::getNamedOperandIdx(DPPOp, AMDGPU::OpName::old);
     if (OldIdx != -1) {
       assert(OldIdx == NumOperands);
       assert(isOfRegClass(
@@ -261,12 +270,6 @@ MachineInstr *GCNDPPCombine::createDPPInst(MachineInstr &OrigMI,
       DPPInst.addReg(CombOldVGPR.Reg, getUndefRegState(!Def),
                      CombOldVGPR.SubReg);
       ++NumOperands;
-
-      if (!TII->isOperandLegal(*DPPInst, OldIdx)) {
-        LLVM_DEBUG(dbgs() << "  failed: old operand is illegal\n");
-        Fail = true;
-        break;
-      }
     } else if (TII->isVOPC(DPPOp) || (TII->isVOP3(DPPOp) && OrigOpE32 != -1 &&
                                       TII->isVOPC(OrigOpE32))) {
       // VOPC DPP and VOPC promoted to VOP3 DPP do not have an old operand



More information about the llvm-commits mailing list