[llvm] [AMDGPU] Prefer packed minimum/maximum ops for two-input ops (PR #215449)

Yaxun Liu via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 12 07:50:05 PDT 2026


https://github.com/yxsamliu updated https://github.com/llvm/llvm-project/pull/215449

>From 94e20cf6bbb194be1160233ecb83778d8ef588ed Mon Sep 17 00:00:00 2001
From: "Yaxun (Sam) Liu" <yaxun.liu at amd.com>
Date: Mon, 10 Aug 2026 22:01:15 -0400
Subject: [PATCH] [AMDGPU] Prefer packed minimum/maximum ops for two-input ops

A two-input f16 fminimum or fmaximum operation should translate to a
packed two-input minimum/maximum instruction when the target supports
one.

It currently can be selected through the minimum3/maximum3 fallback
pattern instead. That emits a three-input instruction with one input
operand duplicated.

Keep the fallback for nested min/max expressions that can use the real
three-input instruction. Add a higher-priority direct pattern for
non-nested two-input operations on targets with packed IEEE
minimum/maximum opcodes.
---
 llvm/lib/Target/AMDGPU/VOP3PInstructions.td   | 24 ++++++++++++
 .../AMDGPU/packed-minimum-maximum-f16.ll      | 37 +++++++++++++++++++
 2 files changed, 61 insertions(+)
 create mode 100644 llvm/test/CodeGen/AMDGPU/packed-minimum-maximum-f16.ll

diff --git a/llvm/lib/Target/AMDGPU/VOP3PInstructions.td b/llvm/lib/Target/AMDGPU/VOP3PInstructions.td
index 6af74a3a7e1c4..c31368d4f5f19 100644
--- a/llvm/lib/Target/AMDGPU/VOP3PInstructions.td
+++ b/llvm/lib/Target/AMDGPU/VOP3PInstructions.td
@@ -444,6 +444,30 @@ class MinimumMaximumByMinimum3Maximum3VOP3P<SDPatternOperator node,
   (inst $src0_mods, $src0, $src1_mods, $src1, $src1_mods, $src1)
 >;
 
+class MinimumMaximumVOP3P<SDPatternOperator node,
+                          Instruction inst> : GCNPat<
+  (v2f16 (node (VOP3PMods v2f16:$src0, i32:$src0_mods), (VOP3PMods v2f16:$src1, i32:$src1_mods))),
+  (inst $src0_mods, $src0, $src1_mods, $src1)
+>;
+
+def fminimum_not_nested : PatFrag<
+  (ops node:$src0, node:$src1), (fminimum $src0, $src1), [{
+  return N->getOperand(0).getOpcode() != ISD::FMINIMUM &&
+         N->getOperand(1).getOpcode() != ISD::FMINIMUM;
+}]>;
+
+def fmaximum_not_nested : PatFrag<
+  (ops node:$src0, node:$src1), (fmaximum $src0, $src1), [{
+  return N->getOperand(0).getOpcode() != ISD::FMAXIMUM &&
+         N->getOperand(1).getOpcode() != ISD::FMAXIMUM;
+}]>;
+
+let SubtargetPredicate = HasIEEEMinimumMaximumInsts,
+    AddedComplexity = 1 in {
+def : MinimumMaximumVOP3P<fminimum_not_nested, V_PK_MINIMUM_F16>;
+def : MinimumMaximumVOP3P<fmaximum_not_nested, V_PK_MAXIMUM_F16>;
+}
+
 let SubtargetPredicate = HasMinimum3Maximum3PKF16 in {
 def : MinimumMaximumByMinimum3Maximum3VOP3P<fminimum, V_PK_MINIMUM3_F16>;
 def : MinimumMaximumByMinimum3Maximum3VOP3P<fmaximum, V_PK_MAXIMUM3_F16>;
diff --git a/llvm/test/CodeGen/AMDGPU/packed-minimum-maximum-f16.ll b/llvm/test/CodeGen/AMDGPU/packed-minimum-maximum-f16.ll
new file mode 100644
index 0000000000000..b753077bce69e
--- /dev/null
+++ b/llvm/test/CodeGen/AMDGPU/packed-minimum-maximum-f16.ll
@@ -0,0 +1,37 @@
+; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6
+; RUN: llc -mtriple=amdgpu9.50-amd-amdhsa < %s | FileCheck -check-prefix=GFX950 %s
+; RUN: llc -mtriple=amdgpu12.50-amd-amdhsa < %s | FileCheck -check-prefix=GFX1250 %s
+
+define <2 x half> @maximum_v2f16(<2 x half> %src0, <2 x half> %src1) {
+; GFX950-LABEL: maximum_v2f16:
+; GFX950:       ; %bb.0:
+; GFX950-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT:    v_pk_maximum3_f16 v0, v0, v1, v1
+; GFX950-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: maximum_v2f16:
+; GFX1250:       ; %bb.0:
+; GFX1250-NEXT:    s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT:    s_wait_kmcnt 0x0
+; GFX1250-NEXT:    v_pk_maximum_f16 v0, v0, v1
+; GFX1250-NEXT:    s_set_pc_i64 s[30:31]
+  %max = call <2 x half> @llvm.maximum.v2f16(<2 x half> %src0, <2 x half> %src1)
+  ret <2 x half> %max
+}
+
+define <2 x half> @minimum_v2f16(<2 x half> %src0, <2 x half> %src1) {
+; GFX950-LABEL: minimum_v2f16:
+; GFX950:       ; %bb.0:
+; GFX950-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GFX950-NEXT:    v_pk_minimum3_f16 v0, v0, v1, v1
+; GFX950-NEXT:    s_setpc_b64 s[30:31]
+;
+; GFX1250-LABEL: minimum_v2f16:
+; GFX1250:       ; %bb.0:
+; GFX1250-NEXT:    s_wait_loadcnt_dscnt 0x0
+; GFX1250-NEXT:    s_wait_kmcnt 0x0
+; GFX1250-NEXT:    v_pk_minimum_f16 v0, v0, v1
+; GFX1250-NEXT:    s_set_pc_i64 s[30:31]
+  %min = call <2 x half> @llvm.minimum.v2f16(<2 x half> %src0, <2 x half> %src1)
+  ret <2 x half> %min
+}



More information about the llvm-commits mailing list