> -----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.
