> + /* TMP1 is zero or denormal if (TMP1 & 0x7f80) == 0. */
> + tmp0 = expand_simple_binop (SImode, AND, tmp1, GEN_INT(0x7f80),
> + nullptr, 0, OPTAB_DIRECT);
The flush-to-zero test is applied to the rounded result instead of to
the input, so the emulation is not equivalent to vcvtneps2bf16.
The SDM pseudo code for convert_fp32_to_bfloat16 tests the input, before
the rounding add:
IF x is zero or denormal:
dest[15] := x[31] // sign preserving zero (denormal go to zero)
dest[14:0] := 0
...
ELSE // normal number
LSB := x[16]
rounding_bias := 0x00007FFF + LSB
temp[31:0] := x[31:0] + rounding_bias
dest[15:0] := temp[31:16]
Since BFmode and SFmode share the exponent width and the bias, testing
the result exponent is equivalent to testing the input exponent, except
when the rounding bias carries out of the SFmode mantissa into the
exponent.
________________________________________
From: H.J. Lu <[email protected]>
Sent: Sunday, 23 August 2026 23:20:50
To: GCC Patches; Uros Bizjak; Liu, Hongtao
Subject: [v2 PATCH] x86: Expand the default truncsfbf2 like vcvtneps2bf16
On Wed, Aug 19, 2026 at 9:51 PM H.J. Lu <[email protected]> wrote:
>
> Expand the default truncsfbf2 like vcvtneps2bf16, which doesn't honor
> SNAN, turns sNAN into qNAN quietly, it always rounds to nearest even
> and flushes denormals to zero, with
>
> (fromi + 0x7fff + ((fromi >> 16) & 1)) >> 16
>
> and flush denormals to zero.
>
> gcc/
>
> PR target/126933
> * config/i386/i386-expand.cc (ix86_expand_truncsfbf2): New.
> * config/i386/i386-protos.h (ix86_expand_truncsfbf2): Likewise.
> * config/i386/i386.md (truncsfbf2): Changed to define_expand.
> (truncsfbf2_vcvtneps2bf16): New.
>
> gcc/testsuite/
>
> PR target/126933
> * gcc.target/i386/truncsfbf-1.c (dg-options): Add
> -mno-avxneconvert -mno-avx512bf16 -fno-asynchronous-unwind-tables.
> Use check-function-bodies to check updated codegen.
> * gcc.target/i386/truncsfbf-2.c (dg-options): Add
> -mno-avxneconvert -mno-avx512bf16.
> (foo): Make it static with __attribute__ ((noipa, noinline)).
> (CALC): Add __attribute__ ((noipa, noinline)). Flush denormal
> to zero.
> * gcc.target/i386/truncsfbf-3.c: New test.
> * gcc.target/i386/truncsfbf-4.c: Likewise.
> * gcc.target/i386/truncsfbf-5.c: Likewise.
> * gcc.target/i386/truncsfbf-6.c: Likewise.
>
truncsfbf2 should behave the same with -funsafe-math-optimizations
regardless if AVXNECONVERT or AVX512BF16 are available or not.
Changes in v2:
1. Remove duplicated codes in ix86_expand_truncsfbf2
2. Scan cmov, instead of branch, in gcc.target/i386/truncsfbf-1.c.
--
H.J.