> -----Original Message-----
> From: H.J. Lu <[email protected]>
> Sent: Monday, August 24, 2026 4:48 PM
> To: Liu, Hongtao <[email protected]>
> Cc: GCC Patches <[email protected]>; Uros Bizjak
> <[email protected]>
> Subject: [v4 PATCH] x86: Expand the default truncsfbf2 like vcvtneps2bf16
> 
> On Mon, Aug 24, 2026 at 4:31 PM H.J. Lu <[email protected]> wrote:
> >
> > On Mon, Aug 24, 2026 at 3:44 PM Liu, Hongtao <[email protected]>
> wrote:
> > >
> > > With this patch the float -> __bf16 conversion still gives a
> > > different result with and without AVX512BF16 for the same float input:
> > >
> > > /* { dg-do run } */
> > > /* { dg-options "-O2 -ffast-math -march=x86-64" } */
> > >
> > > #include <stdio.h>
> > > #include <stdint.h>
> > > #include <string.h>
> > >
> > > /* Both functions are just "return a;".  FOO is compiled for plain
> > >    x86-64, so it uses the inline expansion; BAR uses vcvtneps2bf16.
> > > */
> > >
> > > __attribute__ ((noipa, noinline))
> > > static __bf16
> > > foo (float a)
> > > {
> > >   return a;
> > > }
> > >
> > > __attribute__ ((noipa, noinline, target ("avx512vl,avx512bf16")))
> > > static __bf16 bar (float a) {
> > >   return a;
> > > }
> > >
> > > static uint16_t
> > > bits16 (__bf16 x)
> > > {
> > >   uint16_t r;
> > >   memcpy (&r, &x, sizeof (r));
> > >   return r;
> > > }
> > >
> > > int
> > > main (void)
> > > {
> > >   uint32_t v[] = { 0x007f8000, 0x807f8000, 0x007fffff, 0x807fffff,
> > >                    0x007f7fff, 0x00367000, 0x00800000 };
> > >
> > >   for (unsigned i = 0; i < sizeof v / sizeof v[0]; i++)
> > >     {
> > >       float f;
> > >       memcpy (&f, &v[i], sizeof (f));
> > >       uint16_t a = bits16 (foo (f));
> > >       uint16_t b = bits16 (bar (f));
> > >       printf ("0x%08x  foo=0x%04x  bar=0x%04x  %s\n",
> > >               v[i], a, b, a == b ? "same" : "DIFFER");
> > >     }
> > >   return 0;
> > > }
> > >
> > > On AVX512BF16 hardware this prints:
> > >
> > > 0x007f8000  foo=0x0080  bar=0x0000  DIFFER
> > > 0x807f8000  foo=0x8080  bar=0x8000  DIFFER 0x007fffff  foo=0x0080
> > > bar=0x0000  DIFFER 0x807fffff  foo=0x8080  bar=0x8000  DIFFER
> > > 0x007f7fff  foo=0x0000  bar=0x0000  same
> > > 0x00367000  foo=0x0000  bar=0x0000  same
> > > 0x00800000  foo=0x0080  bar=0x0080  same
> > >
> > > These are SFmode denormals: vcvtneps2bf16 returns a sign preserving
> > > zero, the inline expansion returns +-0x0080, i.e. +-2^-126.
> > > Sweeping the whole SFmode denormal range, 65536 inputs differ, the
> > > 32768 mantissas in [0x7f8000, 0x7fffff] for each sign.
> > >
> > > The reason is that the flush test is applied to the rounded result
> > > rather than to the input:
> > >
> > > > +  /* TMP1 is zero or denormal if (TMP1 & 0x7f80) == 0.  */
> > > > +  tmp0 = expand_simple_binop (SImode, AND, tmp1, GEN_INT(0x7f80),
> > > > +                              nullptr, 0, OPTAB_DIRECT);
> > >
> > > Testing REG1_SI & 0x7f800000 instead makes the two agree for all
> > > 2^32 non-NaN inputs.
> > >
> 
> Here is the v4 patch:
> 
> 1. Mark input denormal branch as unlikely.
> 2. Remove -mtune=generic from truncsfbf-1.c.
Ok.

> 
> > Fixed in the v3 patch with tests.
> >
> > Changes in v3:
> >
> > 1. Test (REG1_SI & 0x7f800000) == 0 for input denormals.
> > 2. Add tests for input denormals.
> > 3. Update expected codegen in truncsfbf-1.c.
> >
> > > Changes in v2:
> > >
> > > 1. Remove duplicated codes in ix86_expand_truncsfbf2 2. Scan cmov,
> > > instead of branch, in gcc.target/i386/truncsfbf-1.c.
> > >
> >
> > Thanks.
> >
> > --
> > H.J.
> > ---
> > Expand default truncsfbf2 like vcvtneps2bf16, which doesn't honor
> > SNAN, turns sNAN into qNAN quietly, it always rounds to nearest even
> > and flushes input denormals to zero, with
> >
> > (fromi + 0x7fff + ((fromi >> 16) & 1)) >> 16
> >
> > and flush input 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 and
> > update comments.
> > (truncsfbf2_vcvtneps2bf16): New.
> >
> > gcc/testsuite/
> >
> > PR target/126933
> > * gcc.target/i386/truncsfbf-1.c (dg-options): Add -mno-avxneconvert
> > -mno-avx512bf16.  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 input denormal
> > to zero.
> > (main): Add tests for float denormal inputs.
> > * 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.
> 
> 
> 
> --
> H.J.

Reply via email to