[llvm-branch-commits] [llvm] [AMDGPU] Require flushed FP16 denormals for the mad-mix f16 results (PR #224911)

Dmitry Sidorov via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sun Sep 20 11:26:37 PDT 2026


https://github.com/MrSidims updated https://github.com/llvm/llvm-project/pull/224911

>From ca6a32cde73f4ee690b083db156fad2ad87d6408 Mon Sep 17 00:00:00 2001
From: Dmitry Sidorov <Dmitry.Sidorov at amd.com>
Date: Sat, 19 Sep 2026 02:30:41 +0200
Subject: [PATCH] [AMDGPU] Require flushed FP16 denormals for the mad-mix f16
 results

v_mad_mixlo_f16 and v_mad_mixhi_f16 are the unfused gfx900 forms and flush
16-bit denormals, so a denormal half result is written as zero even when the
FP16 mode asks for it to be kept, while the patterns only required the FP32
mode to flush and that is the one a HIP compile turns off on its own.

Assisted-by: Claude Code Opus 5
---
 llvm/lib/Target/AMDGPU/VOP3PInstructions.td   |  2 ++
 .../AMDGPU/mad-mix-fptrunc-rounding.ll        |  6 ++---
 llvm/test/CodeGen/AMDGPU/mad-mix-hi.ll        | 22 ++++++++++++++-----
 llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll        |  3 ++-
 4 files changed, 23 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Target/AMDGPU/VOP3PInstructions.td b/llvm/lib/Target/AMDGPU/VOP3PInstructions.td
index e9b6731b1623b..d086b59001b1e 100644
--- a/llvm/lib/Target/AMDGPU/VOP3PInstructions.td
+++ b/llvm/lib/Target/AMDGPU/VOP3PInstructions.td
@@ -502,6 +502,8 @@ defm V_MAD_MIXHI_F16 : VOP3_VOP3PInst<"v_mad_mixhi_f16", VOP3P_Mix_Profile<VOP_F
 }
 
 defm : MadFmaMixFP32Pats<fmad, V_MAD_MIX_F32>;
+
+let OtherPredicates = [NoFP32Denormals, NoFP16Denormals] in
 defm : MadFmaMixFP16Pats<fmad, V_MAD_MIXLO_F16, V_MAD_MIXHI_F16>;
 } // OtherPredicates = [NoFP32Denormals]
 } // End SubtargetPredicate = HasMadMixInsts
diff --git a/llvm/test/CodeGen/AMDGPU/mad-mix-fptrunc-rounding.ll b/llvm/test/CodeGen/AMDGPU/mad-mix-fptrunc-rounding.ll
index b426183fd5892..bcd5c14b2bed7 100644
--- a/llvm/test/CodeGen/AMDGPU/mad-mix-fptrunc-rounding.ll
+++ b/llvm/test/CodeGen/AMDGPU/mad-mix-fptrunc-rounding.ll
@@ -12,8 +12,8 @@
 ; they match an fptrunc of an f32 multiply or multiply-add bit for bit and
 ; need no contract flag. Where a shape appears both unflagged and with
 ; contract the two must select the same instructions. gfx803 has no mix
-; instructions. gfx900 uses V_MAD_MIX* and needs f32 denormals off, hence the
-; denormal_fpenv attribute below.
+; instructions. gfx900 uses V_MAD_MIX* and needs both f32 and f16 denormals
+; off, hence the denormal_fpenv attribute below.
 
 define half @fptrunc_fmul_to_f16(float %a, float %b) #0 {
 ; GFX803-LABEL: fptrunc_fmul_to_f16:
@@ -834,7 +834,7 @@ define float @fmul_to_f32_neg_zero_addend(half %a, float %b) #0 {
   ret float %mul
 }
 
-attributes #0 = { nounwind denormal_fpenv(float: preservesign) }
+attributes #0 = { nounwind denormal_fpenv(preservesign) }
 ;; NOTE: These prefixes are unused and the list is autogenerated. Do not add tests below this line:
 ; GISEL-GFX906: {{.*}}
 ; SDAG-GFX906: {{.*}}
diff --git a/llvm/test/CodeGen/AMDGPU/mad-mix-hi.ll b/llvm/test/CodeGen/AMDGPU/mad-mix-hi.ll
index 9aeef7abb3473..e918222a8993c 100644
--- a/llvm/test/CodeGen/AMDGPU/mad-mix-hi.ll
+++ b/llvm/test/CodeGen/AMDGPU/mad-mix-hi.ll
@@ -767,12 +767,14 @@ define <2 x half> @mixhi_fptrunc_f16_denormals(float %a, float %b, half %lo) #2
 ; SDAG-GFX11-FAKE16-NEXT:    v_mov_b32_e32 v0, v2
 ; SDAG-GFX11-FAKE16-NEXT:    s_setpc_b64 s[30:31]
 ;
-; GFX9-LABEL: mixhi_fptrunc_f16_denormals:
-; GFX9:       ; %bb.0: ; %.entry
-; GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX9-NEXT:    v_mad_mixhi_f16 v2, v0, v1, neg(0)
-; GFX9-NEXT:    v_mov_b32_e32 v0, v2
-; GFX9-NEXT:    s_setpc_b64 s[30:31]
+; SDAG-GFX9-LABEL: mixhi_fptrunc_f16_denormals:
+; SDAG-GFX9:       ; %bb.0: ; %.entry
+; SDAG-GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; SDAG-GFX9-NEXT:    v_mul_f32_e32 v0, v0, v1
+; SDAG-GFX9-NEXT:    v_cvt_f16_f32_e32 v0, v0
+; SDAG-GFX9-NEXT:    s_mov_b32 s4, 0x5040100
+; SDAG-GFX9-NEXT:    v_perm_b32 v0, v0, v2, s4
+; SDAG-GFX9-NEXT:    s_setpc_b64 s[30:31]
 ;
 ; SDAG-VI-LABEL: mixhi_fptrunc_f16_denormals:
 ; SDAG-VI:       ; %bb.0: ; %.entry
@@ -800,6 +802,14 @@ define <2 x half> @mixhi_fptrunc_f16_denormals(float %a, float %b, half %lo) #2
 ; GISEL-GFX11-NEXT:    v_mov_b32_e32 v0, v2
 ; GISEL-GFX11-NEXT:    s_setpc_b64 s[30:31]
 ;
+; GISEL-GFX9-LABEL: mixhi_fptrunc_f16_denormals:
+; GISEL-GFX9:       ; %bb.0: ; %.entry
+; GISEL-GFX9-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
+; GISEL-GFX9-NEXT:    v_mul_f32_e32 v0, v0, v1
+; GISEL-GFX9-NEXT:    v_cvt_f16_f32_sdwa v0, v0 dst_sel:WORD_1 dst_unused:UNUSED_PAD src0_sel:DWORD
+; GISEL-GFX9-NEXT:    v_or_b32_sdwa v0, v0, v2 dst_sel:DWORD dst_unused:UNUSED_PAD src0_sel:DWORD src1_sel:WORD_0
+; GISEL-GFX9-NEXT:    s_setpc_b64 s[30:31]
+;
 ; GISEL-VI-LABEL: mixhi_fptrunc_f16_denormals:
 ; GISEL-VI:       ; %bb.0: ; %.entry
 ; GISEL-VI-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
diff --git a/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll b/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll
index 581c873c12058..20e64b9ee74fb 100644
--- a/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll
+++ b/llvm/test/CodeGen/AMDGPU/mad-mix-lo.ll
@@ -2867,7 +2867,8 @@ define half @mixlo_fptrunc_f16_denormals(float %a, float %b) #2 {
 ; GFX900-LABEL: mixlo_fptrunc_f16_denormals:
 ; GFX900:       ; %bb.0: ; %.entry
 ; GFX900-NEXT:    s_waitcnt vmcnt(0) expcnt(0) lgkmcnt(0)
-; GFX900-NEXT:    v_mad_mixlo_f16 v0, v0, v1, neg(0)
+; GFX900-NEXT:    v_mul_f32_e32 v0, v0, v1
+; GFX900-NEXT:    v_cvt_f16_f32_e32 v0, v0
 ; GFX900-NEXT:    s_setpc_b64 s[30:31]
 ;
 ; GFX906-LABEL: mixlo_fptrunc_f16_denormals:



More information about the llvm-branch-commits mailing list