[llvm] AMDGPU: Use mi_match for more manual selector patterns (PR #216726)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Mon Aug 17 10:10:34 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/216726
>From 25a2d757610ab2bbc39818dd2e4b401fe6ff1736 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 17 Aug 2026 15:07:15 +0200
Subject: [PATCH 1/2] AMDGPU: Use mi_match for more manual selector patterns
Use mi_match G_SHUFFLE_VECTOR/G_FRAME_INDEX/G_SUB checks. Add new
matchers to check the shufflevector and frame index cases, avoiding
raw getVRegDef uses.
Co-authored-by: Claude (Opus 4.8) <noreply at anthropic.com>
---
.../llvm/CodeGen/GlobalISel/MIPatternMatch.h | 44 +++++++++++++++++++
.../AMDGPU/AMDGPUInstructionSelector.cpp | 35 ++++++---------
2 files changed, 58 insertions(+), 21 deletions(-)
diff --git a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
index 91c6275e5ba8d..7c336403159e2 100644
--- a/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
+++ b/llvm/include/llvm/CodeGen/GlobalISel/MIPatternMatch.h
@@ -597,6 +597,50 @@ inline GInstrBind<GConcatVectors> m_GConcatVectors(GConcatVectors *&Inst) {
return Inst;
}
+/// Matches a G_SHUFFLE_VECTOR, binding its two source operands and its mask.
+template <typename Src1Ty, typename Src2Ty> struct ShuffleVectorMatch {
+ Src1Ty Src1;
+ Src2Ty Src2;
+ ArrayRef<int> &Mask;
+
+ ShuffleVectorMatch(const Src1Ty &Src1, const Src2Ty &Src2,
+ ArrayRef<int> &Mask)
+ : Src1(Src1), Src2(Src2), Mask(Mask) {}
+ bool match(const MachineRegisterInfo &MRI, Register Reg) {
+ MachineInstr *TmpMI;
+ if (!mi_match(Reg, MRI, m_MInstr(TmpMI)))
+ return false;
+ auto *Shuf = dyn_cast<GShuffleVector>(TmpMI);
+ if (!Shuf || !Src1.match(MRI, Shuf->getSrc1Reg()) ||
+ !Src2.match(MRI, Shuf->getSrc2Reg()))
+ return false;
+ Mask = Shuf->getMask();
+ return true;
+ }
+};
+
+template <typename Src1Ty, typename Src2Ty>
+inline ShuffleVectorMatch<Src1Ty, Src2Ty>
+m_GShuffleVector(const Src1Ty &Src1, const Src2Ty &Src2, ArrayRef<int> &Mask) {
+ return ShuffleVectorMatch<Src1Ty, Src2Ty>(Src1, Src2, Mask);
+}
+
+/// Matches a G_FRAME_INDEX, binding its frame index.
+struct GFrameIndexMatch {
+ int &FI;
+ bool match(const MachineRegisterInfo &MRI, Register Reg) {
+ MachineInstr *TmpMI;
+ if (mi_match(Reg, MRI, m_MInstr(TmpMI)) &&
+ TmpMI->getOpcode() == TargetOpcode::G_FRAME_INDEX) {
+ FI = TmpMI->getOperand(1).getIndex();
+ return true;
+ }
+ return false;
+ }
+};
+
+inline GFrameIndexMatch m_GFrameIndex(int &FI) { return {FI}; }
+
// Helper for matching G_FCONSTANT
inline bind_ty<const ConstantFP *> m_GFCst(const ConstantFP *&C) { return C; }
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index 0a5dbca02fea2..0c6bbf39508d4 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -2942,18 +2942,16 @@ static bool isExtractHiElt(MachineRegisterInfo &MRI, Register In,
}
}
- MachineInstr *Shuffle = MRI.getVRegDef(Trunc);
- if (Shuffle->getOpcode() != AMDGPU::G_SHUFFLE_VECTOR)
+ ArrayRef<int> Mask;
+ Register Src1;
+ if (!mi_match(Trunc, MRI, m_GShuffleVector(m_Reg(Src1), m_Reg(), Mask)))
return false;
- assert(MRI.getType(Shuffle->getOperand(0).getReg()) ==
- LLT::fixed_vector(2, 16));
-
- ArrayRef<int> Mask = Shuffle->getOperand(3).getShuffleMask();
+ assert(MRI.getType(Src1) == LLT::fixed_vector(2, 16));
assert(Mask.size() == 2);
if (Mask[0] == 1 && Mask[1] <= 1) {
- Out = Shuffle->getOperand(0).getReg();
+ Out = Trunc;
return true;
}
@@ -6499,24 +6497,23 @@ AMDGPUInstructionSelector::selectMUBUFScratchOffen(MachineOperand &Root) const {
std::optional<int> FI;
Register VAddr = Root.getReg();
- const MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
Register PtrBase;
int64_t ConstOffset;
std::tie(PtrBase, ConstOffset, std::ignore) =
getPtrBaseWithConstantOffset(VAddr, *MRI);
+ int MatchedFI;
if (ConstOffset != 0) {
if (TII.isLegalMUBUFImmOffset(ConstOffset) &&
(!STI.privateMemoryResourceIsRangeChecked() ||
VT->signBitIsZero(PtrBase))) {
- const MachineInstr *PtrBaseDef = MRI->getVRegDef(PtrBase);
- if (PtrBaseDef->getOpcode() == AMDGPU::G_FRAME_INDEX)
- FI = PtrBaseDef->getOperand(1).getIndex();
+ if (mi_match(PtrBase, *MRI, m_GFrameIndex(MatchedFI)))
+ FI = MatchedFI;
else
VAddr = PtrBase;
Offset = ConstOffset;
}
- } else if (RootDef->getOpcode() == AMDGPU::G_FRAME_INDEX) {
- FI = RootDef->getOperand(1).getIndex();
+ } else if (mi_match(Root.getReg(), *MRI, m_GFrameIndex(MatchedFI))) {
+ FI = MatchedFI;
}
return {{[=](MachineInstrBuilder &MIB) { // rsrc
@@ -6736,8 +6733,8 @@ AMDGPUInstructionSelector::selectMUBUFScratchOffset(
}
std::pair<Register, unsigned>
-AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(MachineOperand &Root) const {
- const MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
+AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(
+ MachineOperand &Root) const {
int64_t ConstAddr = 0;
Register PtrBase;
@@ -6750,13 +6747,11 @@ AMDGPUInstructionSelector::selectDS1Addr1OffsetImpl(MachineOperand &Root) const
// (add n0, c0)
return std::pair(PtrBase, Offset);
}
- } else if (RootDef->getOpcode() == AMDGPU::G_SUB) {
+ } else if (mi_match(Root.getReg(), *MRI, m_GSub(m_Reg(), m_Reg()))) {
// TODO
-
} else if (mi_match(Root.getReg(), *MRI, m_ICst(ConstAddr))) {
// TODO
-
}
return std::pair(Root.getReg(), 0);
@@ -6799,7 +6794,6 @@ AMDGPUInstructionSelector::selectDSReadWrite2(MachineOperand &Root,
std::pair<Register, unsigned>
AMDGPUInstructionSelector::selectDSReadWrite2Impl(MachineOperand &Root,
unsigned Size) const {
- const MachineInstr *RootDef = MRI->getVRegDef(Root.getReg());
int64_t ConstAddr = 0;
Register PtrBase;
@@ -6814,12 +6808,11 @@ AMDGPUInstructionSelector::selectDSReadWrite2Impl(MachineOperand &Root,
// (add n0, c0)
return std::pair(PtrBase, OffsetValue0 / Size);
}
- } else if (RootDef->getOpcode() == AMDGPU::G_SUB) {
+ } else if (mi_match(Root.getReg(), *MRI, m_GSub(m_Reg(), m_Reg()))) {
// TODO
} else if (mi_match(Root.getReg(), *MRI, m_ICst(ConstAddr))) {
// TODO
-
}
return std::pair(Root.getReg(), 0);
>From ee5ef6f5e52fbec8ea96d1b7813f27bcb33effbd Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 17 Aug 2026 19:09:58 +0200
Subject: [PATCH 2/2] Simplify but changes test
---
.../AMDGPU/AMDGPUInstructionSelector.cpp | 23 ++++++++-----------
.../AMDGPU/GlobalISel/strict_fma.f16.ll | 16 ++++++-------
.../AMDGPU/GlobalISel/strict_fma.f32.ll | 6 ++---
llvm/test/CodeGen/AMDGPU/strict_fsub.f16.ll | 4 ++--
4 files changed, 23 insertions(+), 26 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
index 0c6bbf39508d4..ac78540589e3a 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPUInstructionSelector.cpp
@@ -5424,29 +5424,25 @@ static bool checkRB(Register Reg, unsigned int RBNo,
// Thus
// 1. If RootOp is SGPR, then NewOp can be SGPR or VGPR.
// 2. If RootOp is VGPR, then NewOp must be VGPR.
-static Register getLegalRegBank(Register NewReg, Register RootReg,
- const AMDGPURegisterBankInfo &RBI,
- MachineRegisterInfo &MRI,
- const TargetRegisterInfo &TRI,
- const SIInstrInfo &TII) {
+static Register
+getLegalRegBank(Register NewReg, Register RootReg, MachineInstr &Use,
+ const AMDGPURegisterBankInfo &RBI, MachineRegisterInfo &MRI,
+ const TargetRegisterInfo &TRI, const SIInstrInfo &TII) {
// RootOp can only be VGPR or SGPR (some hand written cases such as.
// inst-select-ashr.v2s16.mir::ashr_v2s16_vs).
if (checkRB(RootReg, AMDGPU::SGPRRegBankID, RBI, MRI, TRI) ||
checkRB(NewReg, AMDGPU::VGPRRegBankID, RBI, MRI, TRI))
return NewReg;
- MachineInstr *MI = MRI.getVRegDef(RootReg);
- if (MI->getOpcode() == AMDGPU::COPY && NewReg == MI->getOperand(1).getReg()) {
+ if (mi_match(RootReg, MRI, m_Copy(m_SpecificReg(NewReg)))) {
// RootOp is VGPR, NewOp is not VGPR, but RootOp = COPY NewOp.
return RootReg;
}
- MachineBasicBlock *BB = MI->getParent();
Register DstReg = MRI.cloneVirtualRegister(RootReg);
-
- MachineInstrBuilder MIB =
- BuildMI(*BB, MI, MI->getDebugLoc(), TII.get(AMDGPU::COPY), DstReg)
- .addReg(NewReg);
+ MachineInstrBuilder MIB = BuildMI(*Use.getParent(), Use, Use.getDebugLoc(),
+ TII.get(AMDGPU::COPY), DstReg)
+ .addReg(NewReg);
// Only accept VGPR.
return MIB->getOperand(0).getReg();
@@ -5460,7 +5456,8 @@ AMDGPUInstructionSelector::selectVOP3PRetHelper(MachineOperand &Root,
unsigned Mods;
std::tie(Reg, Mods) = selectVOP3PModsImpl(Root.getReg(), MRI, IsDOT);
- Reg = getLegalRegBank(Reg, Root.getReg(), RBI, MRI, TRI, TII);
+ Reg = getLegalRegBank(Reg, Root.getReg(), *Root.getParent(), RBI, MRI, TRI,
+ TII);
return {{
[=](MachineInstrBuilder &MIB) { MIB.addReg(Reg); },
[=](MachineInstrBuilder &MIB) { MIB.addImm(Mods); } // src_mods
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/strict_fma.f16.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/strict_fma.f16.ll
index 893cb7f237055..b833480c267f0 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/strict_fma.f16.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/strict_fma.f16.ll
@@ -849,9 +849,9 @@ define void @v_constained_fma_v2f16_fpexcept_strict_fneg_fneg_uni(<2 x half> inr
; GFX900-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg_uni:
; GFX900: ; %bb.0:
; GFX900-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX900-NEXT: v_mov_b32_e32 v2, s17
-; GFX900-NEXT: v_mov_b32_e32 v3, s18
-; GFX900-NEXT: v_pk_fma_f16 v2, s16, v2, v3 neg_lo:[1,1,0] neg_hi:[1,1,0]
+; GFX900-NEXT: v_mov_b32_e32 v2, s16
+; GFX900-NEXT: v_mov_b32_e32 v3, s17
+; GFX900-NEXT: v_pk_fma_f16 v2, v2, v3, s18 neg_lo:[1,1,0] neg_hi:[1,1,0]
; GFX900-NEXT: global_store_dword v[0:1], v2, off
; GFX900-NEXT: s_waitcnt vmcnt(0)
; GFX900-NEXT: s_setpc_b64 s[30:31]
@@ -859,9 +859,9 @@ define void @v_constained_fma_v2f16_fpexcept_strict_fneg_fneg_uni(<2 x half> inr
; GFX942-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg_uni:
; GFX942: ; %bb.0:
; GFX942-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX942-NEXT: v_mov_b32_e32 v2, s1
-; GFX942-NEXT: v_mov_b32_e32 v3, s2
-; GFX942-NEXT: v_pk_fma_f16 v2, s0, v2, v3 neg_lo:[1,1,0] neg_hi:[1,1,0]
+; GFX942-NEXT: v_mov_b32_e32 v2, s0
+; GFX942-NEXT: v_mov_b32_e32 v3, s1
+; GFX942-NEXT: v_pk_fma_f16 v2, v2, v3, s2 neg_lo:[1,1,0] neg_hi:[1,1,0]
; GFX942-NEXT: global_store_dword v[0:1], v2, off
; GFX942-NEXT: s_waitcnt vmcnt(0)
; GFX942-NEXT: s_setpc_b64 s[30:31]
@@ -869,9 +869,9 @@ define void @v_constained_fma_v2f16_fpexcept_strict_fneg_fneg_uni(<2 x half> inr
; GFX11-LABEL: v_constained_fma_v2f16_fpexcept_strict_fneg_fneg_uni:
; GFX11: ; %bb.0:
; GFX11-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX11-NEXT: v_mov_b32_e32 v2, s2
+; GFX11-NEXT: v_mov_b32_e32 v2, s1
; GFX11-NEXT: s_delay_alu instid0(VALU_DEP_1)
-; GFX11-NEXT: v_pk_fma_f16 v2, s0, s1, v2 neg_lo:[1,1,0] neg_hi:[1,1,0]
+; GFX11-NEXT: v_pk_fma_f16 v2, s0, v2, s2 neg_lo:[1,1,0] neg_hi:[1,1,0]
; GFX11-NEXT: global_store_b32 v[0:1], v2, off
; GFX11-NEXT: s_setpc_b64 s[30:31]
;
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/strict_fma.f32.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/strict_fma.f32.ll
index 7ef6adb8fcc4d..cd2f12548aec6 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/strict_fma.f32.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/strict_fma.f32.ll
@@ -910,9 +910,9 @@ define void @v_constained_fma_v2f32_fpexcept_strict_fneg_fneg_uni(<2 x float> in
; GFX942-LABEL: v_constained_fma_v2f32_fpexcept_strict_fneg_fneg_uni:
; GFX942: ; %bb.0:
; GFX942-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX942-NEXT: v_mov_b64_e32 v[2:3], s[2:3]
-; GFX942-NEXT: v_mov_b64_e32 v[4:5], s[16:17]
-; GFX942-NEXT: v_pk_fma_f32 v[2:3], s[0:1], v[2:3], v[4:5] neg_lo:[1,1,0] neg_hi:[1,1,0]
+; GFX942-NEXT: v_mov_b64_e32 v[2:3], s[0:1]
+; GFX942-NEXT: v_mov_b64_e32 v[4:5], s[2:3]
+; GFX942-NEXT: v_pk_fma_f32 v[2:3], v[2:3], v[4:5], s[16:17] neg_lo:[1,1,0] neg_hi:[1,1,0]
; GFX942-NEXT: global_store_dwordx2 v[0:1], v[2:3], off
; GFX942-NEXT: s_waitcnt vmcnt(0)
; GFX942-NEXT: s_setpc_b64 s[30:31]
diff --git a/llvm/test/CodeGen/AMDGPU/strict_fsub.f16.ll b/llvm/test/CodeGen/AMDGPU/strict_fsub.f16.ll
index b78a0871784cb..3fa3a3c5a98e0 100644
--- a/llvm/test/CodeGen/AMDGPU/strict_fsub.f16.ll
+++ b/llvm/test/CodeGen/AMDGPU/strict_fsub.f16.ll
@@ -785,8 +785,8 @@ define amdgpu_ps <2 x half> @s_constained_fsub_v2f16_fpexcept_strict(<2 x half>
;
; GFX9-GISEL-LABEL: s_constained_fsub_v2f16_fpexcept_strict:
; GFX9-GISEL: ; %bb.0:
-; GFX9-GISEL-NEXT: v_mov_b32_e32 v0, s2
-; GFX9-GISEL-NEXT: v_pk_add_f16 v0, v0, s3 neg_lo:[0,1] neg_hi:[0,1]
+; GFX9-GISEL-NEXT: v_mov_b32_e32 v0, s3
+; GFX9-GISEL-NEXT: v_pk_add_f16 v0, s2, v0 neg_lo:[0,1] neg_hi:[0,1]
; GFX9-GISEL-NEXT: ; return to shader part epilog
;
; GFX8-SDAG-LABEL: s_constained_fsub_v2f16_fpexcept_strict:
More information about the llvm-commits
mailing list