[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 Aug 2 16:51:34 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/6] 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/6] 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)>;

>From 6e26c7456667a1dceb8d9ee1cae0e69f0b0a607b Mon Sep 17 00:00:00 2001
From: shore <372660931 at qq.com>
Date: Tue, 7 Jul 2026 10:21:30 +0800
Subject: [PATCH 3/6] fix comment

---
 llvm/lib/Target/AMDGPU/AMDGPU.td                  | 15 +++++++++++----
 .../Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp  |  3 ++-
 llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp |  2 +-
 llvm/lib/Target/AMDGPU/SOPInstructions.td         |  2 +-
 4 files changed, 15 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index df0ed4812ee04..ce7f5d1844f30 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -1136,6 +1136,14 @@ defm SALUFloatInsts : AMDGPUSubtargetFeature<"salu-float",
   "Has SALU floating point instructions"
 >;
 
+// GFX11.7 uniquely pairs the legacy s_min/max_f32/f16 (mode-based fminnum/
+// fmaxnum) with the IEEE v_min/max_num_f32/f16, so the SALU and VALU results
+// are inconsistent. Mark it to keep float min/max selection on the VALU there.
+defm NoSALUFMinNumFMaxNumInsts : AMDGPUSubtargetFeature<"no-salu-fminnum-fmaxnum-insts",
+  "Do not select SALU s_min/max_f32/f16 (fminnum/fmaxnum) instructions",
+  /*GenPredicate=*/0
+>;
+
 defm PseudoScalarTrans : AMDGPUSubtargetFeature<"pseudo-scalar-trans",
   "Has Pseudo Scalar Transcendental instructions"
 >;
@@ -2075,6 +2083,7 @@ def FeatureISAVersion11_5_2 : FeatureSet<
 def FeatureISAVersion11_7_Common : FeatureSet<
   !listconcat(FeatureISAVersion11_Common.Features,
     [FeatureGFX11_7Insts,
+     FeatureNoSALUFMinNumFMaxNumInsts,
      FeatureSALUFloatInsts,
      FeatureDPPSrc1SGPR,
      FeatureFP8ConversionInsts,
@@ -2794,10 +2803,8 @@ def NotHasMinMaxDenormModes : Predicate<"!Subtarget->supportsMinMaxDenormModes()
 
 def HasFminFmaxLegacy : Predicate<"Subtarget->hasFminFmaxLegacy()">;
 
-// 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 HasSALUFMinNumFMaxNumInsts :
+  Predicate<"Subtarget->hasSALUFloatInsts() && !Subtarget->hasNoSALUFMinNumFMaxNumInsts()">;
 
 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 bacf2ea079e98..5652365fa507c 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
@@ -1672,7 +1672,8 @@ RegBankLegalizeRules::RegBankLegalizeRules(const GCNSubtarget &_ST,
       .Uni(V2S16, {{UniInVgprV2S16}, {VgprV2S16, VgprV2S16}})
       .Div(V2S16, {{VgprV2S16}, {VgprV2S16, VgprV2S16}});
 
-  bool hasSMINNUMMAXNUMPattern = hasSALUFloat && !ST->hasGFX11_7Insts();
+  bool hasSMINNUMMAXNUMPattern =
+      hasSALUFloat && !ST->hasNoSALUFMinNumFMaxNumInsts();
   addRulesForGOpcs({G_FMINNUM_IEEE, G_FMAXNUM_IEEE, G_FMINNUM, G_FMAXNUM,
                     G_FMINIMUMNUM, G_FMAXIMUMNUM},
                    Standard)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
index c68c9b48df73f..b092dcf69b72f 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
@@ -4111,7 +4111,7 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
     unsigned Size = Ty.getSizeInBits();
     if (Subtarget.hasSALUFloatInsts() && Ty.isScalar() &&
         (Size == 32 || Size == 16) && isSALUMapping(MI) &&
-        !Subtarget.hasGFX11_7Insts())
+        !Subtarget.hasNoSALUFMinNumFMaxNumInsts())
       return getDefaultMappingSOP(MI);
     return getDefaultMappingVOP(MI);
   }
diff --git a/llvm/lib/Target/AMDGPU/SOPInstructions.td b/llvm/lib/Target/AMDGPU/SOPInstructions.td
index d155b73cb6d83..2fff901016851 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 = [HasSALUFloatMinMaxInsts] in {
+let OtherPredicates = [HasSALUFMinNumFMaxNumInsts] in {
   def : GCNPat<(f32 (UniformBinFrag<fminnum_like> (f32 SSrc_f32:$src0),
                                                   (f32 SSrc_f32:$src1))),
                (S_MIN_F32 SSrc_f32:$src0, SSrc_f32:$src1)>;

>From 0ce603196a29964e3535eb8180d8d9e84d599396 Mon Sep 17 00:00:00 2001
From: shore <shorshen at amd.com>
Date: Wed, 22 Jul 2026 11:17:40 +0800
Subject: [PATCH 4/6] fix test

---
 llvm/test/CodeGen/AMDGPU/minmax.ll | 11 ++++-------
 1 file changed, 4 insertions(+), 7 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/minmax.ll b/llvm/test/CodeGen/AMDGPU/minmax.ll
index 967dab03dcda2..8b6c4e6093687 100644
--- a/llvm/test/CodeGen/AMDGPU/minmax.ll
+++ b/llvm/test/CodeGen/AMDGPU/minmax.ll
@@ -1095,23 +1095,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 6f3f289a43ce1e1a049eef6552be2e0e37601555 Mon Sep 17 00:00:00 2001
From: shore <shorshen at amd.com>
Date: Thu, 23 Jul 2026 10:14:11 +0800
Subject: [PATCH 5/6] fix comments

---
 llvm/lib/Target/AMDGPU/AMDGPU.td                     | 12 +-----------
 .../lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp |  3 +--
 llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp    |  5 ++---
 llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h             |  5 +++++
 4 files changed, 9 insertions(+), 16 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/AMDGPU.td b/llvm/lib/Target/AMDGPU/AMDGPU.td
index 37516ce2303ce..81d42ad4faeac 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPU.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPU.td
@@ -1143,14 +1143,6 @@ defm SALUFloatInsts : AMDGPUSubtargetFeature<"salu-float",
   "Has SALU floating point instructions"
 >;
 
-// GFX11.7 uniquely pairs the legacy s_min/max_f32/f16 (mode-based fminnum/
-// fmaxnum) with the IEEE v_min/max_num_f32/f16, so the SALU and VALU results
-// are inconsistent. Mark it to keep float min/max selection on the VALU there.
-defm NoSALUFMinNumFMaxNumInsts : AMDGPUSubtargetFeature<"no-salu-fminnum-fmaxnum-insts",
-  "Do not select SALU s_min/max_f32/f16 (fminnum/fmaxnum) instructions",
-  /*GenPredicate=*/0
->;
-
 defm PseudoScalarTrans : AMDGPUSubtargetFeature<"pseudo-scalar-trans",
   "Has Pseudo Scalar Transcendental instructions"
 >;
@@ -2097,7 +2089,6 @@ def FeatureISAVersion11_5_2 : FeatureSet<
 def FeatureISAVersion11_7_Common : FeatureSet<
   !listconcat(FeatureISAVersion11_Common.Features,
     [FeatureGFX11_7Insts,
-     FeatureNoSALUFMinNumFMaxNumInsts,
      FeatureSALUFloatInsts,
      FeatureDPPSrc1SGPR,
      FeatureFP8ConversionInsts,
@@ -2821,8 +2812,7 @@ def NotHasMinMaxDenormModes : Predicate<"!Subtarget->supportsMinMaxDenormModes()
 
 def HasFminFmaxLegacy : Predicate<"Subtarget->hasFminFmaxLegacy()">;
 
-def HasSALUFMinNumFMaxNumInsts :
-  Predicate<"Subtarget->hasSALUFloatInsts() && !Subtarget->hasNoSALUFMinNumFMaxNumInsts()">;
+def HasSALUFMinNumFMaxNumInsts : Predicate<"Subtarget->hasSALUFMinNumFMaxNumInsts()">;
 
 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 95c0d19be260e..7126718ada3f9 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankLegalizeRules.cpp
@@ -1674,8 +1674,7 @@ RegBankLegalizeRules::RegBankLegalizeRules(const GCNSubtarget &_ST,
       .Uni(V2S16, {{UniInVgprV2S16}, {VgprV2S16, VgprV2S16}})
       .Div(V2S16, {{VgprV2S16}, {VgprV2S16, VgprV2S16}});
 
-  bool hasSMINNUMMAXNUMPattern =
-      hasSALUFloat && !ST->hasNoSALUFMinNumFMaxNumInsts();
+  bool hasSMINNUMMAXNUMPattern = ST->hasSALUFMinNumFMaxNumInsts();
   addRulesForGOpcs({G_FMINNUM_IEEE, G_FMAXNUM_IEEE, G_FMINNUM, G_FMAXNUM,
                     G_FMINIMUMNUM, G_FMAXIMUMNUM},
                    Standard)
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
index b092dcf69b72f..c2ae04a2b00d5 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegisterBankInfo.cpp
@@ -4109,9 +4109,8 @@ AMDGPURegisterBankInfo::getInstrMapping(const MachineInstr &MI) const {
   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.hasNoSALUFMinNumFMaxNumInsts())
+    if (Ty.isScalar() && (Size == 32 || Size == 16) && isSALUMapping(MI) &&
+        Subtarget.hasSALUFMinNumFMaxNumInsts())
       return getDefaultMappingSOP(MI);
     return getDefaultMappingVOP(MI);
   }
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h
index 71a8f064ffa11..9429c9b9a6109 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h
+++ b/llvm/lib/Target/AMDGPU/AMDGPUSubtarget.h
@@ -213,6 +213,11 @@ class AMDGPUSubtarget {
     return HasFminFmaxLegacy;
   }
 
+  bool hasSALUFMinNumFMaxNumInsts() const {
+    return (hasSALUFloatInsts() && !hasIEEEMinimumMaximumInsts()) ||
+           (hasSALUMinimumMaximumInsts() && hasIEEEMinimumMaximumInsts());
+  }
+
   unsigned getWavefrontSize() const {
     return 1 << WavefrontSizeLog2;
   }

>From 8fe9899fb7bfc99bd3754f55def8b4db37bf6a62 Mon Sep 17 00:00:00 2001
From: shore <shorshen at amd.com>
Date: Fri, 24 Jul 2026 12:13:28 +0800
Subject: [PATCH 6/6] fix test case

---
 .../GlobalISel/clamp-minmax-const-combine.ll  | 19 +++++++------------
 1 file changed, 7 insertions(+), 12 deletions(-)

diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/clamp-minmax-const-combine.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/clamp-minmax-const-combine.ll
index 03f0d12722310..7731dc56091f3 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/clamp-minmax-const-combine.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/clamp-minmax-const-combine.ll
@@ -524,10 +524,7 @@ define amdgpu_ps float @test_min_max_f32_sgpr(float inreg %a) {
 ;
 ; GFX1170-LABEL: test_min_max_f32_sgpr:
 ; GFX1170:       ; %bb.0:
-; GFX1170-NEXT:    s_max_f32 s0, s2, 0
-; GFX1170-NEXT:    s_delay_alu instid0(SALU_CYCLE_3) | instskip(NEXT) | instid1(SALU_CYCLE_3)
-; GFX1170-NEXT:    s_min_f32 s0, s0, 1.0
-; GFX1170-NEXT:    v_mov_b32_e32 v0, s0
+; GFX1170-NEXT:    v_max_num_f32_e64 v0, s2, s2 clamp
 ; GFX1170-NEXT:    ; return to shader part epilog
 ;
 ; GFX12-LABEL: test_min_max_f32_sgpr:
@@ -551,11 +548,10 @@ define amdgpu_ps float @test_min_max_f32_sgpr_1(float inreg %a) {
 ;
 ; GFX1170-LABEL: test_min_max_f32_sgpr_1:
 ; GFX1170:       ; %bb.0: ; %.entry
-; GFX1170-NEXT:    s_max_f32 s0, s2, 0
-; GFX1170-NEXT:    s_delay_alu instid0(SALU_CYCLE_3) | instskip(NEXT) | instid1(SALU_CYCLE_3)
-; GFX1170-NEXT:    s_min_f32 s0, s0, 1.0
+; GFX1170-NEXT:    v_max_num_f32_e64 v0, s2, s2 clamp
+; GFX1170-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_3)
+; GFX1170-NEXT:    v_readfirstlane_b32 s0, v0
 ; GFX1170-NEXT:    s_fmaak_f32 s0, s0, 0, 0x0
-; GFX1170-NEXT:    s_delay_alu instid0(SALU_CYCLE_3)
 ; GFX1170-NEXT:    v_mov_b32_e32 v0, s0
 ; GFX1170-NEXT:    ; return to shader part epilog
 ;
@@ -585,11 +581,10 @@ define amdgpu_ps float @test_min_max_f32_sgpr_fma_user(float inreg %a, float inr
 ;
 ; GFX1170-LABEL: test_min_max_f32_sgpr_fma_user:
 ; GFX1170:       ; %bb.0:
-; GFX1170-NEXT:    s_max_f32 s0, s2, 0
-; GFX1170-NEXT:    s_delay_alu instid0(SALU_CYCLE_3) | instskip(NEXT) | instid1(SALU_CYCLE_3)
-; GFX1170-NEXT:    s_min_f32 s0, s0, 1.0
+; GFX1170-NEXT:    v_max_num_f32_e64 v0, s2, s2 clamp
+; GFX1170-NEXT:    s_delay_alu instid0(VALU_DEP_1) | instskip(SKIP_1) | instid1(SALU_CYCLE_3)
+; GFX1170-NEXT:    v_readfirstlane_b32 s0, v0
 ; GFX1170-NEXT:    s_fmac_f32 s4, s0, s3
-; GFX1170-NEXT:    s_delay_alu instid0(SALU_CYCLE_3)
 ; GFX1170-NEXT:    v_mov_b32_e32 v0, s4
 ; GFX1170-NEXT:    ; return to shader part epilog
 ;



More information about the llvm-commits mailing list