[llvm] AMDGPU: Refactor checkVOPDRegConstraints (PR #196514)
Petar Avramovic via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 16 01:46:45 PDT 2026
https://github.com/petar-avramovic updated https://github.com/llvm/llvm-project/pull/196514
>From e83e07be75bd10877b5c05c8bd03c5e3eab50345 Mon Sep 17 00:00:00 2001
From: Petar Avramovic <Petar.Avramovic at amd.com>
Date: Fri, 8 May 2026 12:16:25 +0200
Subject: [PATCH] AMDGPU: Refactor checkVOPDRegConstraints
---
llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp | 69 ++++++++++---------------
1 file changed, 28 insertions(+), 41 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp b/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
index 93069e71dffe1..44e467b0ba721 100644
--- a/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
+++ b/llvm/lib/Target/AMDGPU/GCNVOPDUtils.cpp
@@ -63,14 +63,6 @@ bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
};
SmallSet<Register, 4> UniqueScalarRegs;
- auto getVRegIdx = [&](unsigned OpcodeIdx, unsigned OperandIdx) {
- const MachineInstr &MI = (OpcodeIdx == VOPD::X) ? MIX : MIY;
- const MachineOperand &Operand = MI.getOperand(OperandIdx);
- if (Operand.isReg() && TRI->isVectorRegister(MRI, Operand.getReg()))
- return Operand.getReg();
- return Register();
- };
-
auto InstInfo = AMDGPU::getVOPDInstInfo(MIX.getDesc(), MIY.getDesc());
for (auto CompIdx : VOPD::COMPONENTS) {
@@ -87,33 +79,36 @@ bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
addLiteral(Src0);
}
+ // V_FMAMK_F32 (src1) and V_FMAAK_F32 (src2) have a mandatory literal.
+ // VOPD3 instructions don't set MandatoryLiteralIdx.
if (InstInfo[CompIdx].hasMandatoryLiteral()) {
- if (IsVOPD3)
- return false;
-
auto CompOprIdx = InstInfo[CompIdx].getMandatoryLiteralCompOperandIndex();
addLiteral(MI.getOperand(CompOprIdx));
}
+
+ // VOPD only. Affects V_CNDMASK_B32_e32.
if (MI.getDesc().hasImplicitUseOfPhysReg(AMDGPU::VCC))
UniqueScalarRegs.insert(AMDGPU::VCC_LO);
if (IsVOPD3) {
- for (auto OpName : {AMDGPU::OpName::src1, AMDGPU::OpName::src2}) {
- const MachineOperand *Src = TII.getNamedOperand(MI, OpName);
- if (!Src)
- continue;
- if (OpName == AMDGPU::OpName::src2) {
- if (AMDGPU::hasNamedOperand(MI.getOpcode(), AMDGPU::OpName::bitop3))
- continue;
- if (MI.getOpcode() == AMDGPU::V_CNDMASK_B32_e64) {
- UniqueScalarRegs.insert(Src->getReg());
- continue;
- }
- }
- if (!Src->isReg() || !TRI->isVGPR(MRI, Src->getReg()))
+ if (const MachineOperand *Src1 =
+ TII.getNamedOperand(MI, AMDGPU::OpName::src1)) {
+ if (!Src1->isReg() || !TRI->isVGPR(MRI, Src1->getReg()))
return false;
}
+ 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;
+ }
+ }
for (auto OpName : {AMDGPU::OpName::clamp, AMDGPU::OpName::omod,
AMDGPU::OpName::op_sel}) {
if (TII.hasModifiersSet(MI, OpName))
@@ -137,33 +132,25 @@ bool llvm::checkVOPDRegConstraints(const SIInstrInfo &TII,
if ((UniqueLiterals.size() + UniqueScalarRegs.size()) > 2)
return false;
+ auto getVRegIdx = [&](unsigned OpcodeIdx, unsigned OperandIdx) {
+ const MachineInstr &MI = (OpcodeIdx == VOPD::X) ? MIX : MIY;
+ const MachineOperand &Operand = MI.getOperand(OperandIdx);
+ if (Operand.isReg() && TRI->isVectorRegister(MRI, Operand.getReg()))
+ return Operand.getReg();
+ return Register();
+ };
+
// On GFX1170+ if both OpX and OpY are V_MOV_B32 then OPY uses SRC2
// source-cache.
bool SkipSrc = (ST.hasGFX11_7Insts() || ST.hasGFX12Insts()) &&
MIX.getOpcode() == AMDGPU::V_MOV_B32_e32 &&
MIY.getOpcode() == AMDGPU::V_MOV_B32_e32;
+ // Check VGPR bank constraints for operand registers across both instructions.
if (InstInfo.hasInvalidOperand(getVRegIdx, *TRI, SkipSrc, AllowSameVGPR,
IsVOPD3))
return false;
- if (IsVOPD3) {
- // BITOP3 can be converted to DUAL_BITOP2 only if src2 is zero.
- // MIX check is only relevant to scheduling?
- if (AMDGPU::hasNamedOperand(MIX.getOpcode(), AMDGPU::OpName::bitop3)) {
- const MachineOperand &Src2 =
- *TII.getNamedOperand(MIX, AMDGPU::OpName::src2);
- if (!Src2.isImm() || Src2.getImm())
- return false;
- }
- if (AMDGPU::hasNamedOperand(MIY.getOpcode(), AMDGPU::OpName::bitop3)) {
- const MachineOperand &Src2 =
- *TII.getNamedOperand(MIY, AMDGPU::OpName::src2);
- if (!Src2.isImm() || Src2.getImm())
- return false;
- }
- }
-
LLVM_DEBUG(dbgs() << "VOPD Reg Constraints Passed\n\tX: " << MIX
<< "\n\tY: " << MIY << "\n");
return true;
More information about the llvm-commits
mailing list