[llvm] [AMDGPU][GlobalISel] Form min3/max3 from minimumnum and maximumnum (PR #225795)
via llvm-commits
llvm-commits at lists.llvm.org
Wed Sep 23 07:28:41 PDT 2026
llvmorg-github-actions[bot] wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-amdgpu
Author: Arseniy Obolenskiy (aobolensk)
<details>
<summary>Changes</summary>
Map these to FMAX3/FMIN3 as SelectionDAG does, not the NaN-propagating FMAXIMUM3/FMINIMUM3
---
Full diff: https://github.com/llvm/llvm-project/pull/225795.diff
3 Files Affected:
- (modified) llvm/lib/Target/AMDGPU/AMDGPUCombine.td (+10-3)
- (modified) llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp (+2-2)
- (modified) llvm/test/CodeGen/AMDGPU/GlobalISel/fmin3-fmax3-combine.ll (+110)
``````````diff
diff --git a/llvm/lib/Target/AMDGPU/AMDGPUCombine.td b/llvm/lib/Target/AMDGPU/AMDGPUCombine.td
index 2f0ff66668f2b..15e6793309fdf 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPUCombine.td
+++ b/llvm/lib/Target/AMDGPU/AMDGPUCombine.td
@@ -222,6 +222,15 @@ def fmaximum_to_minmax3 : minmax_to_minmax3_opcodes<G_FMAXIMUM>;
def fminimum_to_minmax3 : minmax_to_minmax3_opcodes<G_FMINIMUM>;
def fmax_ieee_to_minmax3 : minmax_to_minmax3_opcodes<G_FMAXNUM_IEEE>;
def fmin_ieee_to_minmax3 : minmax_to_minmax3_opcodes<G_FMINNUM_IEEE>;
+def fmaximumnum_to_minmax3 : minmax_to_minmax3_opcodes<G_FMAXIMUMNUM>;
+def fminimumnum_to_minmax3 : minmax_to_minmax3_opcodes<G_FMINIMUMNUM>;
+
+def minmax_to_minmax3_combines : GICombineGroup<[
+ smax_to_minmax3, smin_to_minmax3, umax_to_minmax3, umin_to_minmax3,
+ fmax_to_minmax3, fmin_to_minmax3, fmaximum_to_minmax3, fminimum_to_minmax3,
+ fmax_ieee_to_minmax3, fmin_ieee_to_minmax3, fmaximumnum_to_minmax3,
+ fminimumnum_to_minmax3
+]>;
// (and/or i64:x, i64:y) -> i64:(merge (and/or lo_32(x), lo_32(y)), (and/or hi_32(x), hi_32(y)))
// when either x or y is all ones in low or high parts
@@ -336,7 +345,5 @@ def AMDGPURegBankCombiner : GICombiner<
fp_minmax_to_clamp, fp_minmax_to_med3, fmed3_intrinsic_to_clamp,
identity_combines, redundant_and, constant_fold_cast_op,
cast_of_cast_combines, sext_trunc, zext_of_shift_amount_combines,
- d16_load, smax_to_minmax3, smin_to_minmax3, umax_to_minmax3,
- umin_to_minmax3, fmax_to_minmax3, fmin_to_minmax3, fmaximum_to_minmax3,
- fminimum_to_minmax3, fmax_ieee_to_minmax3, fmin_ieee_to_minmax3]> {
+ d16_load, minmax_to_minmax3_combines]> {
}
diff --git a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp
index ed1531fccb5ed..0af8886ea10bb 100644
--- a/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp
+++ b/llvm/lib/Target/AMDGPU/AMDGPURegBankCombiner.cpp
@@ -554,18 +554,18 @@ bool AMDGPURegBankCombinerImpl::matchMinMaxToMinMax3(
break;
case AMDGPU::G_FMAXNUM:
case AMDGPU::G_FMAXNUM_IEEE:
+ case AMDGPU::G_FMAXIMUMNUM:
AMDGPUOpc = AMDGPU::G_AMDGPU_FMAX3;
break;
case AMDGPU::G_FMINNUM:
case AMDGPU::G_FMINNUM_IEEE:
+ case AMDGPU::G_FMINIMUMNUM:
AMDGPUOpc = AMDGPU::G_AMDGPU_FMIN3;
break;
case AMDGPU::G_FMAXIMUM:
- case AMDGPU::G_FMAXIMUMNUM:
AMDGPUOpc = AMDGPU::G_AMDGPU_FMAXIMUM3;
break;
case AMDGPU::G_FMINIMUM:
- case AMDGPU::G_FMINIMUMNUM:
AMDGPUOpc = AMDGPU::G_AMDGPU_FMINIMUM3;
break;
default:
diff --git a/llvm/test/CodeGen/AMDGPU/GlobalISel/fmin3-fmax3-combine.ll b/llvm/test/CodeGen/AMDGPU/GlobalISel/fmin3-fmax3-combine.ll
index 7b5d1b02c07df..d12fd16b00578 100644
--- a/llvm/test/CodeGen/AMDGPU/GlobalISel/fmin3-fmax3-combine.ll
+++ b/llvm/test/CodeGen/AMDGPU/GlobalISel/fmin3-fmax3-combine.ll
@@ -652,3 +652,113 @@ define half @fminimum3_f16(half %a, half %b, half %c) {
%m2 = call half @llvm.minimum.f16(half %m1, half %c)
ret half %m2
}
+
+define float @fmaximumnum3_f32(float %a, float %b, float %c) {
+; GFX10-LABEL: fmaximumnum3_f32:
+; GFX10: ; %bb.0:
+; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT: v_max_f32_e32 v0, v0, v0
+; GFX10-NEXT: v_max_f32_e32 v1, v1, v1
+; GFX10-NEXT: v_max_f32_e32 v2, v2, v2
+; GFX10-NEXT: v_max3_f32 v0, v0, v1, v2
+; GFX10-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX12-LABEL: fmaximumnum3_f32:
+; GFX12: ; %bb.0:
+; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX12-NEXT: s_wait_expcnt 0x0
+; GFX12-NEXT: s_wait_samplecnt 0x0
+; GFX12-NEXT: s_wait_bvhcnt 0x0
+; GFX12-NEXT: s_wait_kmcnt 0x0
+; GFX12-NEXT: v_dual_max_num_f32 v0, v0, v0 :: v_dual_max_num_f32 v1, v1, v1
+; GFX12-NEXT: v_max_num_f32_e32 v2, v2, v2
+; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX12-NEXT: v_max3_num_f32 v0, v0, v1, v2
+; GFX12-NEXT: s_setpc_b64 s[30:31]
+ %m1 = call float @llvm.maximumnum.f32(float %a, float %b)
+ %m2 = call float @llvm.maximumnum.f32(float %m1, float %c)
+ ret float %m2
+}
+
+define float @fminimumnum3_f32(float %a, float %b, float %c) {
+; GFX10-LABEL: fminimumnum3_f32:
+; GFX10: ; %bb.0:
+; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT: v_max_f32_e32 v0, v0, v0
+; GFX10-NEXT: v_max_f32_e32 v1, v1, v1
+; GFX10-NEXT: v_max_f32_e32 v2, v2, v2
+; GFX10-NEXT: v_min3_f32 v0, v0, v1, v2
+; GFX10-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX12-LABEL: fminimumnum3_f32:
+; GFX12: ; %bb.0:
+; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX12-NEXT: s_wait_expcnt 0x0
+; GFX12-NEXT: s_wait_samplecnt 0x0
+; GFX12-NEXT: s_wait_bvhcnt 0x0
+; GFX12-NEXT: s_wait_kmcnt 0x0
+; GFX12-NEXT: v_dual_max_num_f32 v0, v0, v0 :: v_dual_max_num_f32 v1, v1, v1
+; GFX12-NEXT: v_max_num_f32_e32 v2, v2, v2
+; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX12-NEXT: v_min3_num_f32 v0, v0, v1, v2
+; GFX12-NEXT: s_setpc_b64 s[30:31]
+ %m1 = call float @llvm.minimumnum.f32(float %a, float %b)
+ %m2 = call float @llvm.minimumnum.f32(float %m1, float %c)
+ ret float %m2
+}
+
+define half @fmaximumnum3_f16(half %a, half %b, half %c) {
+; GFX10-LABEL: fmaximumnum3_f16:
+; GFX10: ; %bb.0:
+; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT: v_max_f16_e32 v0, v0, v0
+; GFX10-NEXT: v_max_f16_e32 v1, v1, v1
+; GFX10-NEXT: v_max_f16_e32 v2, v2, v2
+; GFX10-NEXT: v_max3_f16 v0, v0, v1, v2
+; GFX10-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX12-LABEL: fmaximumnum3_f16:
+; GFX12: ; %bb.0:
+; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX12-NEXT: s_wait_expcnt 0x0
+; GFX12-NEXT: s_wait_samplecnt 0x0
+; GFX12-NEXT: s_wait_bvhcnt 0x0
+; GFX12-NEXT: s_wait_kmcnt 0x0
+; GFX12-NEXT: v_max_num_f16_e32 v0.l, v0.l, v0.l
+; GFX12-NEXT: v_max_num_f16_e32 v0.h, v1.l, v1.l
+; GFX12-NEXT: v_max_num_f16_e32 v1.l, v2.l, v2.l
+; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX12-NEXT: v_max3_num_f16 v0.l, v0.l, v0.h, v1.l
+; GFX12-NEXT: s_setpc_b64 s[30:31]
+ %m1 = call half @llvm.maximumnum.f16(half %a, half %b)
+ %m2 = call half @llvm.maximumnum.f16(half %m1, half %c)
+ ret half %m2
+}
+
+define half @fminimumnum3_f16(half %a, half %b, half %c) {
+; GFX10-LABEL: fminimumnum3_f16:
+; GFX10: ; %bb.0:
+; GFX10-NEXT: s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX10-NEXT: v_max_f16_e32 v0, v0, v0
+; GFX10-NEXT: v_max_f16_e32 v1, v1, v1
+; GFX10-NEXT: v_max_f16_e32 v2, v2, v2
+; GFX10-NEXT: v_min3_f16 v0, v0, v1, v2
+; GFX10-NEXT: s_setpc_b64 s[30:31]
+;
+; GFX12-LABEL: fminimumnum3_f16:
+; GFX12: ; %bb.0:
+; GFX12-NEXT: s_wait_loadcnt_dscnt 0x0
+; GFX12-NEXT: s_wait_expcnt 0x0
+; GFX12-NEXT: s_wait_samplecnt 0x0
+; GFX12-NEXT: s_wait_bvhcnt 0x0
+; GFX12-NEXT: s_wait_kmcnt 0x0
+; GFX12-NEXT: v_max_num_f16_e32 v0.l, v0.l, v0.l
+; GFX12-NEXT: v_max_num_f16_e32 v0.h, v1.l, v1.l
+; GFX12-NEXT: v_max_num_f16_e32 v1.l, v2.l, v2.l
+; GFX12-NEXT: s_delay_alu instid0(VALU_DEP_1)
+; GFX12-NEXT: v_min3_num_f16 v0.l, v0.l, v0.h, v1.l
+; GFX12-NEXT: s_setpc_b64 s[30:31]
+ %m1 = call half @llvm.minimumnum.f16(half %a, half %b)
+ %m2 = call half @llvm.minimumnum.f16(half %m1, half %c)
+ ret half %m2
+}
``````````
</details>
https://github.com/llvm/llvm-project/pull/225795
More information about the llvm-commits
mailing list