[llvm] [AMDGPU] exclude selection pattern for s_max/min_f32/16 for gfx1170 (PR #207308)
via llvm-commits
llvm-commits at lists.llvm.org
Sun Jul 5 16:56:08 PDT 2026
https://github.com/Shoreshen updated https://github.com/llvm/llvm-project/pull/207308
>From 78bed01c3b0998fe2128970fd7f4e2834b8ef567 Mon Sep 17 00:00:00 2001
From: shore <372660931 at qq.com>
Date: Fri, 3 Jul 2026 10:34:11 +0800
Subject: [PATCH 1/2] exclude selection pattern for s_max/min_f32/16 for
gfx1170
---
llvm/lib/Target/AMDGPU/AMDGPU.td | 3 +++
.../AMDGPU/AMDGPURegBankLegalizeRules.cpp | 9 ++++----
.../Target/AMDGPU/AMDGPURegisterBankInfo.cpp | 16 +++++++++----
llvm/lib/Target/AMDGPU/SOPInstructions.td | 23 +++++++++++++++----
.../GlobalISel/llvm.amdgcn.rsq.clamp.ll | 9 +++-----
llvm/test/CodeGen/AMDGPU/minmax.ll | 17 +++++---------
6 files changed, 48 insertions(+), 29 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index 9da123c517b81..eba91211e0e1f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -2794,6 +2794,9 @@ def NotHasMinMaxDenormModes : Predicate<"!Subtarget->supportsMinMaxDenormModes()
def HasFminFmaxLegacy : Predicate<"Subtarget->hasFminFmaxLegacy()">;
+def HasSALUFloatInstsNotGFX11_7 :
+Predicate<"!Subtarget->hasGFX11_7Insts() && Subtarget->hasSALUFloatInsts()">;
+
def HasSDWA8 : Predicate<"Subtarget->hasSDWA()">,
AssemblerPredicate<(all_of (not FeatureGFX9Insts), FeatureSDWA)>;
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
index 7f7225ad6d311..bacf2ea079e98 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
@@ -1672,6 +1672,7 @@ RegBankLegalizeRules::RegBankLegalizeRules(const GCNSubtarget &_ST,
.Uni(V2S16, {{UniInVgprV2S16}, {VgprV2S16, VgprV2S16}})
.Div(V2S16, {{VgprV2S16}, {VgprV2S16, VgprV2S16}});
+ bool hasSMINNUMMAXNUMPattern = hasSALUFloat && !ST->hasGFX11_7Insts();
addRulesForGOpcs({G_FMINNUM_IEEE, G_FMAXNUM_IEEE, G_FMINNUM, G_FMAXNUM,
G_FMINIMUMNUM, G_FMAXIMUMNUM},
Standard)
@@ -1681,10 +1682,10 @@ RegBankLegalizeRules::RegBankLegalizeRules(const GCNSubtarget &_ST,
.Div(S64, {{Vgpr64}, {Vgpr64, Vgpr64}})
.Uni(V2S16, {{UniInVgprV2S16}, {VgprV2S16, VgprV2S16}})
.Div(V2S16, {{VgprV2S16}, {VgprV2S16, VgprV2S16}})
- .Uni(S16, {{Sgpr16}, {Sgpr16, Sgpr16}}, hasSALUFloat)
- .Uni(S16, {{UniInVgprS16}, {Vgpr16, Vgpr16}}, !hasSALUFloat)
- .Uni(S32, {{Sgpr32}, {Sgpr32, Sgpr32}}, hasSALUFloat)
- .Uni(S32, {{UniInVgprS32}, {Vgpr32, Vgpr32}}, !hasSALUFloat);
+ .Uni(S16, {{Sgpr16}, {Sgpr16, Sgpr16}}, hasSMINNUMMAXNUMPattern)
+ .Uni(S16, {{UniInVgprS16}, {Vgpr16, Vgpr16}}, !hasSMINNUMMAXNUMPattern)
+ .Uni(S32, {{Sgpr32}, {Sgpr32, Sgpr32}}, hasSMINNUMMAXNUMPattern)
+ .Uni(S32, {{UniInVgprS32}, {Vgpr32, Vgpr32}}, !hasSMINNUMMAXNUMPattern);
addRulesForGOpcs({G_FPTRUNC})
.Any({{DivS16, S32}, {{Vgpr16}, {Vgpr32}}})
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
index 200234c23c886..c68c9b48df73f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
@@ -4091,10 +4091,6 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
case AMDGPU::G_FFLOOR:
case AMDGPU::G_FCEIL:
case AMDGPU::G_INTRINSIC_ROUNDEVEN:
- case AMDGPU::G_FMINNUM:
- case AMDGPU::G_FMAXNUM:
- case AMDGPU::G_FMINIMUMNUM:
- case AMDGPU::G_FMAXIMUMNUM:
case AMDGPU::G_INTRINSIC_TRUNC:
case AMDGPU::G_STRICT_FADD:
case AMDGPU::G_STRICT_FSUB:
@@ -4107,6 +4103,18 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
return getDefaultMappingSOP(MI);
return getDefaultMappingVOP(MI);
}
+ case AMDGPU::G_FMINNUM:
+ case AMDGPU::G_FMAXNUM:
+ case AMDGPU::G_FMINIMUMNUM:
+ case AMDGPU::G_FMAXIMUMNUM: {
+ LLT Ty = MRI.getType(MI.getOperand(0).getReg());
+ unsigned Size = Ty.getSizeInBits();
+ if (Subtarget.hasSALUFloatInsts() && Ty.isScalar() &&
+ (Size == 32 || Size == 16) && isSALUMapping(MI) &&
+ !Subtarget.hasGFX11_7Insts())
+ return getDefaultMappingSOP(MI);
+ return getDefaultMappingVOP(MI);
+ }
case AMDGPU::G_FMINIMUM:
case AMDGPU::G_FMAXIMUM: {
LLT Ty = MRI.getType(MI.getOperand(0).getReg());
diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td
index cd7c43972813c..059eb6aea7c78 100644
--- a/llvm/lib/Target/AMDGPU/SOPInstructions.td
+++ b/llvm/lib/Target/AMDGPU/SOPInstructions.td
@@ -940,8 +940,8 @@ let SubtargetPredicate = HasSALUFloatInsts, mayRaiseFPException = 1,
let isReMaterializable = 1 in {
let isCommutable = 1 in {
def S_ADD_F32 : SOP2_F32_Inst<"s_add_f32", any_fadd>;
- def S_MIN_F32 : SOP2_F32_Inst<"s_min_f32", fminnum_like>;
- def S_MAX_F32 : SOP2_F32_Inst<"s_max_f32", fmaxnum_like>;
+ def S_MIN_F32 : SOP2_F32<"s_min_f32">;
+ def S_MAX_F32 : SOP2_F32<"s_max_f32">;
def S_MUL_F32 : SOP2_F32_Inst<"s_mul_f32", any_fmul>;
let FixedSize = 1 in
@@ -956,8 +956,8 @@ let SubtargetPredicate = HasSALUFloatInsts, mayRaiseFPException = 1,
def S_MUL_F16 : SOP2_F16_Inst<"s_mul_f16", any_fmul>;
} // End FPDPRounding
- def S_MIN_F16 : SOP2_F16_Inst<"s_min_f16", fminnum_like>;
- def S_MAX_F16 : SOP2_F16_Inst<"s_max_f16", fmaxnum_like>;
+ def S_MIN_F16 : SOP2_F16<"s_min_f16">;
+ def S_MAX_F16 : SOP2_F16<"s_max_f16">;
} // End isCommutable = 1
let FPDPRounding = 1 in
@@ -995,6 +995,21 @@ let SubtargetPredicate = HasSALUFloatInsts, mayRaiseFPException = 1,
} // End SubtargetPredicate = HasSALUFloatInsts, mayRaiseFPException = 1,
// Uses = [MODE], SchedRW = [WriteSFPU]
+let OtherPredicates = [HasSALUFloatInstsNotGFX11_7] in {
+ def : GCNPat<(f32 (UniformBinFrag<fminnum_like> (f32 SSrc_f32:$src0),
+ (f32 SSrc_f32:$src1))),
+ (S_MIN_F32 SSrc_f32:$src0, SSrc_f32:$src1)>;
+ def : GCNPat<(f32 (UniformBinFrag<fmaxnum_like> (f32 SSrc_f32:$src0),
+ (f32 SSrc_f32:$src1))),
+ (S_MAX_F32 SSrc_f32:$src0, SSrc_f32:$src1)>;
+ def : GCNPat<(f16 (UniformBinFrag<fminnum_like> (f16 SSrc_f16:$src0),
+ (f16 SSrc_f16:$src1))),
+ (S_MIN_F16 SSrc_f16:$src0, SSrc_f16:$src1)>;
+ def : GCNPat<(f16 (UniformBinFrag<fmaxnum_like> (f16 SSrc_f16:$src0),
+ (f16 SSrc_f16:$src1))),
+ (S_MAX_F16 SSrc_f16:$src0, SSrc_f16:$src1)>;
+}
+
// On GFX12 MIN/MAX instructions do not read MODE register.
let SubtargetPredicate = isGFX12Plus, mayRaiseFPException = 1, isCommutable = 1,
isReMaterializable = 1, SchedRW = [WriteSFPU], AddedComplexity = 25 in {
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.rsq.clamp.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.rsq.clamp.ll
index cd79352ac7941..fc0bf16cc3215 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.rsq.clamp.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/llvm.amdgcn.rsq.clamp.ll
@@ -201,12 +201,9 @@ define float @v_rsq_clamp_undef_f32() #0 {
; GFX1170: ; %bb.0:
; GFX1170-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
; GFX1170-NEXT: v_rsq_f32_e32 v0, s0
-; GFX1170-NEXT: s_delay_alu instid0(TRANS32_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_3)
-; GFX1170-NEXT: v_readfirstlane_b32 s0, v0
-; GFX1170-NEXT: s_min_f32 s0, s0, 0x7f7fffff
-; GFX1170-NEXT: s_max_f32 s0, s0, 0xff7fffff
-; GFX1170-NEXT: s_delay_alu instid0(SALU_CYCLE_3)
-; GFX1170-NEXT: v_mov_b32_e32 v0, s0
+; GFX1170-NEXT: v_mov_b32_e32 v1, 0xff7fffff
+; GFX1170-NEXT: s_delay_alu instid0(TRANS32_DEP_1) | instid1(VALU_DEP_1)
+; GFX1170-NEXT: v_minmax_num_f32 v0, v0, 0x7f7fffff, v1
; GFX1170-NEXT: s_setpc_b64 s[30:31]
;
; GFX12-LABEL: v_rsq_clamp_undef_f32:
diff --git a/llvm/test/CodeGen/AMDGPU/minmax.ll b/llvm/test/CodeGen/AMDGPU/minmax.ll
index baaaf657478c3..889ee1fe355c6 100644
--- a/llvm/test/CodeGen/AMDGPU/minmax.ll
+++ b/llvm/test/CodeGen/AMDGPU/minmax.ll
@@ -655,12 +655,10 @@ define amdgpu_ps void @s_test_minmax_f32_ieee_false(float inreg %a, float inreg
;
; GISEL-GFX1170-LABEL: s_test_minmax_f32_ieee_false:
; GISEL-GFX1170: ; %bb.0:
-; GISEL-GFX1170-NEXT: s_max_f32 s0, s0, s1
+; GISEL-GFX1170-NEXT: v_dual_mov_b32 v0, s2 :: v_dual_mov_b32 v1, 0
; GISEL-GFX1170-NEXT: s_mov_b32 s6, s3
; GISEL-GFX1170-NEXT: s_mov_b32 s7, s4
-; GISEL-GFX1170-NEXT: v_mov_b32_e32 v1, 0
-; GISEL-GFX1170-NEXT: s_min_f32 s0, s0, s2
-; GISEL-GFX1170-NEXT: v_mov_b32_e32 v0, s0
+; GISEL-GFX1170-NEXT: v_maxmin_num_f32 v0, s0, s1, v0
; GISEL-GFX1170-NEXT: global_store_b32 v1, v0, s[6:7]
; GISEL-GFX1170-NEXT: s_endpgm
;
@@ -1073,23 +1071,20 @@ define amdgpu_ps void @s_test_minmax_f16_ieee_false(half inreg %a, half inreg %b
;
; GISEL-GFX1170-TRUE16-LABEL: s_test_minmax_f16_ieee_false:
; GISEL-GFX1170-TRUE16: ; %bb.0:
-; GISEL-GFX1170-TRUE16-NEXT: s_max_f16 s0, s0, s1
+; GISEL-GFX1170-TRUE16-NEXT: v_mov_b16_e32 v0.l, s2
; GISEL-GFX1170-TRUE16-NEXT: v_mov_b32_e32 v1, 0
; GISEL-GFX1170-TRUE16-NEXT: s_mov_b32 s6, s3
; GISEL-GFX1170-TRUE16-NEXT: s_mov_b32 s7, s4
-; GISEL-GFX1170-TRUE16-NEXT: s_min_f16 s0, s0, s2
-; GISEL-GFX1170-TRUE16-NEXT: v_mov_b16_e32 v0.l, s0
+; GISEL-GFX1170-TRUE16-NEXT: v_maxmin_num_f16 v0.l, s0, s1, v0.l
; GISEL-GFX1170-TRUE16-NEXT: global_store_b16 v1, v0, s[6:7]
; GISEL-GFX1170-TRUE16-NEXT: s_endpgm
;
; GISEL-GFX1170-FAKE16-LABEL: s_test_minmax_f16_ieee_false:
; GISEL-GFX1170-FAKE16: ; %bb.0:
-; GISEL-GFX1170-FAKE16-NEXT: s_max_f16 s0, s0, s1
+; GISEL-GFX1170-FAKE16-NEXT: v_dual_mov_b32 v0, s2 :: v_dual_mov_b32 v1, 0
; GISEL-GFX1170-FAKE16-NEXT: s_mov_b32 s6, s3
; GISEL-GFX1170-FAKE16-NEXT: s_mov_b32 s7, s4
-; GISEL-GFX1170-FAKE16-NEXT: v_mov_b32_e32 v1, 0
-; GISEL-GFX1170-FAKE16-NEXT: s_min_f16 s0, s0, s2
-; GISEL-GFX1170-FAKE16-NEXT: v_mov_b32_e32 v0, s0
+; GISEL-GFX1170-FAKE16-NEXT: v_maxmin_num_f16 v0, s0, s1, v0
; GISEL-GFX1170-FAKE16-NEXT: global_store_b16 v1, v0, s[6:7]
; GISEL-GFX1170-FAKE16-NEXT: s_endpgm
;
>From 86baa5705d00612ba2c8bd3677b8fbdb7340cfbf Mon Sep 17 00:00:00 2001
From: shore <372660931 at qq.com>
Date: Fri, 3 Jul 2026 17:51:16 +0800
Subject: [PATCH 2/2] change predicate name
---
llvm/lib/Target/AMDGPU/AMDGPU.td | 4 +++-
llvm/lib/Target/AMDGPU/SOPInstructions.td | 2 +-
2 files changed, 4 insertions(+), 2 deletions(-)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index eba91211e0e1f..df0ed4812ee04 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -2794,7 +2794,9 @@ def NotHasMinMaxDenormModes : Predicate<"!Subtarget->supportsMinMaxDenormModes()
def HasFminFmaxLegacy : Predicate<"Subtarget->hasFminFmaxLegacy()">;
-def HasSALUFloatInstsNotGFX11_7 :
+// GFX11.7 has the SALU float instructions but not the SALU float min/max
+// instructions (s_min/max_f32/f16), so those patterns must be disabled there.
+def HasSALUFloatMinMaxInsts :
Predicate<"!Subtarget->hasGFX11_7Insts() && Subtarget->hasSALUFloatInsts()">;
def HasSDWA8 : Predicate<"Subtarget->hasSDWA()">,
diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td
index 059eb6aea7c78..d155b73cb6d83 100644
--- a/llvm/lib/Target/AMDGPU/SOPInstructions.td
+++ b/llvm/lib/Target/AMDGPU/SOPInstructions.td
@@ -995,7 +995,7 @@ let SubtargetPredicate = HasSALUFloatInsts, mayRaiseFPException = 1,
} // End SubtargetPredicate = HasSALUFloatInsts, mayRaiseFPException = 1,
// Uses = [MODE], SchedRW = [WriteSFPU]
-let OtherPredicates = [HasSALUFloatInstsNotGFX11_7] in {
+let OtherPredicates = [HasSALUFloatMinMaxInsts] in {
def : GCNPat<(f32 (UniformBinFrag<fminnum_like> (f32 SSrc_f32:$src0),
(f32 SSrc_f32:$src1))),
(S_MIN_F32 SSrc_f32:$src0, SSrc_f32:$src1)>;
More information about the llvm-commits
mailing list