[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