public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug c/114347] New: wrong constant folding when casting __bf16 to int
@ 2024-03-15  4:55 eggert at cs dot ucla.edu
  2024-03-15  5:01 ` [Bug middle-end/114347] " pinskia at gcc dot gnu.org
                   ` (12 more replies)
  0 siblings, 13 replies; 14+ messages in thread
From: eggert at cs dot ucla.edu @ 2024-03-15  4:55 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

            Bug ID: 114347
           Summary: wrong constant folding when casting __bf16 to int
           Product: gcc
           Version: 13.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: eggert at cs dot ucla.edu
  Target Milestone: ---

This is gcc (GCC) 13.2.1 20231205 (Red Hat 13.2.1-6) on Fedora 39. I found this
bug when looking into a GNU coreutils report <https://bugs.gnu.org/69770>
originally reported against Clang (Clang has a different bug).

Compile and run this program:

  __bf16 x = 257.0bf16;
  int
  main (void)
  {
    return (int) x != (int) 257.0bf16;
  }

with "gcc -O2 v.c; ./a.out; echo $?". This prints "1"; it should print "0".

The problem is that GCC constant-folds '(int) 257.0bf16' to 257. This is
incorrect, as 257.0bf16 is exactly equal to 256.0bf16, due to rounding when the
constant is parsed. The expression '(int) x' correctly yields 256 at runtime,
and 256 is not equal to the 257 incorrectly yielded by the constant folding.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
@ 2024-03-15  5:01 ` pinskia at gcc dot gnu.org
  2024-03-15  5:19 ` eggert at cs dot ucla.edu
                   ` (11 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-03-15  5:01 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

--- Comment #1 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
Hmm, I am not so sure that 257.0bf16 gets rounded to 256.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
  2024-03-15  5:01 ` [Bug middle-end/114347] " pinskia at gcc dot gnu.org
@ 2024-03-15  5:19 ` eggert at cs dot ucla.edu
  2024-03-15  9:03 ` rguenth at gcc dot gnu.org
                   ` (10 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: eggert at cs dot ucla.edu @ 2024-03-15  5:19 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

--- Comment #2 from Paul Eggert <eggert at cs dot ucla.edu> ---
(In reply to Andrew Pinski from comment #1)
> I am not so sure that 257.0bf16 gets rounded to 256.

It should get rounded to 256, since 257 has no exact representation in __bf16
and 256 is the closest representable value.

And GCC does this correctly in my experiments. If I compile this:

  __bf16 w = 256.0bf16;
  __bf16 x = 257.0bf16;

with "gcc -O2 -S", the assembly code says ".value 17280" for both constants.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
  2024-03-15  5:01 ` [Bug middle-end/114347] " pinskia at gcc dot gnu.org
  2024-03-15  5:19 ` eggert at cs dot ucla.edu
@ 2024-03-15  9:03 ` rguenth at gcc dot gnu.org
  2024-03-15 16:58 ` jsm28 at gcc dot gnu.org
                   ` (9 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: rguenth at gcc dot gnu.org @ 2024-03-15  9:03 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |wrong-code
                 CC|                            |jsm28 at gcc dot gnu.org

--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> ---
I suspect we fail to round at parsing time.  I see we get to see

 <excess_precision_expr 0x7ffff6bb6500
    type <real_type 0x7ffff6a33888 __bf16 BF
        size <integer_cst 0x7ffff6a2d108 constant 16>
        unit-size <integer_cst 0x7ffff6a2d120 constant 2>
        align:16 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
0x7ffff6a33888 precision:16>

    arg:0 <real_cst 0x7ffff6be06f0
        type <real_type 0x7ffff6a332a0 float SF
            size <integer_cst 0x7ffff6a2d198 constant 32>
            unit-size <integer_cst 0x7ffff6a2d1b0 constant 4>
            align:32 warn_if_not_align:0 symtab:0 alias-set -1 canonical-type
0x7ffff6a332a0 precision:32
            pointer_to_this <pointer_type 0x7ffff6a33930>>
        constant 2.57e+2>

and then upon processing the (int) cast simply strip the excess_precision_expr.

#0  convert (type=<integer_type 0x7ffff6a2b5e8 int>, 
    expr=<real_cst 0x7ffff6be0930>)
    at /home/rguenther/src/trunk/gcc/c/c-convert.cc:253
#1  0x0000000000d8e9e2 in build_c_cast (loc=263296, 
    type=<integer_type 0x7ffff6a2b5e8 int>, expr=<real_cst 0x7ffff6be0930>)
    at /home/rguenther/src/trunk/gcc/c/c-typeck.cc:6387
#2  0x0000000000d8f01c in c_cast_expr (loc=263296, type_name=0x46c6760, 
    expr=<excess_precision_expr 0x7ffff6bb6640>)
    at /home/rguenther/src/trunk/gcc/c/c-typeck.cc:6461

/* Build an expression representing a cast to type TYPE of expression EXPR.
   LOC is the location of the cast-- typically the open paren of the cast.  */

tree
build_c_cast (location_t loc, tree type, tree expr)
{
  tree value;

  bool int_operands = EXPR_INT_CONST_OPERANDS (expr);

  if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
    expr = TREE_OPERAND (expr, 0);


But maybe that's correct behavior here?  Or we shouldn't have an
excess_precision_expr in the first place for BF16?

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (2 preceding siblings ...)
  2024-03-15  9:03 ` rguenth at gcc dot gnu.org
@ 2024-03-15 16:58 ` jsm28 at gcc dot gnu.org
  2024-03-18  8:03 ` rguenth at gcc dot gnu.org
                   ` (8 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: jsm28 at gcc dot gnu.org @ 2024-03-15 16:58 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

--- Comment #4 from Joseph S. Myers <jsm28 at gcc dot gnu.org> ---
I think it's correct that conversions (explicit or implicit) from a value with
excess precision convert only once; they don't first remove excess range and
precision and then convert to the target type.

This is not an assertion about whether we should implement __bf16 with excess
precision, though it probably makes sense to do so in general for formats for
which processors don't provide direct arithmetic support.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (3 preceding siblings ...)
  2024-03-15 16:58 ` jsm28 at gcc dot gnu.org
@ 2024-03-18  8:03 ` rguenth at gcc dot gnu.org
  2024-03-18  8:16 ` jakub at gcc dot gnu.org
                   ` (7 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: rguenth at gcc dot gnu.org @ 2024-03-18  8:03 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |liuhongt at gcc dot gnu.org,
                   |                            |rearnsha at gcc dot gnu.org
             Target|                            |x86_64-*-*

--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
I have no idea how to configure that (or whether it can be configured per
targete) nor whether it is the correct choice.  CCing arm/x86 folks (I think
those are the only ports with bf16 support).

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (4 preceding siblings ...)
  2024-03-18  8:03 ` rguenth at gcc dot gnu.org
@ 2024-03-18  8:16 ` jakub at gcc dot gnu.org
  2024-03-18  8:53 ` rguenth at gcc dot gnu.org
                   ` (6 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2024-03-18  8:16 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |jakub at gcc dot gnu.org

--- Comment #6 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
You can use -fexcess-precision=16 if you don't want treating _Float16 and
__bf16 as having excess precision.  With excess precision, I think the above
behavior is correct.
You'd need (int) (__bf16) 257.0bf16 to get 256 even with excess precision.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (5 preceding siblings ...)
  2024-03-18  8:16 ` jakub at gcc dot gnu.org
@ 2024-03-18  8:53 ` rguenth at gcc dot gnu.org
  2024-03-18  9:06 ` jakub at gcc dot gnu.org
                   ` (5 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: rguenth at gcc dot gnu.org @ 2024-03-18  8:53 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

--- Comment #7 from Richard Biener <rguenth at gcc dot gnu.org> ---
(In reply to Jakub Jelinek from comment #6)
> You can use -fexcess-precision=16 if you don't want treating _Float16 and
> __bf16 as having excess precision.  With excess precision, I think the above
> behavior is correct.
> You'd need (int) (__bf16) 257.0bf16 to get 256 even with excess precision.

Ah, -fexcess-precision=16 doesn't seem to be documented though (how does
this influence long double handling then?)

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (6 preceding siblings ...)
  2024-03-18  8:53 ` rguenth at gcc dot gnu.org
@ 2024-03-18  9:06 ` jakub at gcc dot gnu.org
  2024-03-18  9:08 ` liuhongt at gcc dot gnu.org
                   ` (4 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: jakub at gcc dot gnu.org @ 2024-03-18  9:06 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

--- Comment #8 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #7)
> (In reply to Jakub Jelinek from comment #6)
> > You can use -fexcess-precision=16 if you don't want treating _Float16 and
> > __bf16 as having excess precision.  With excess precision, I think the above
> > behavior is correct.
> > You'd need (int) (__bf16) 257.0bf16 to get 256 even with excess precision.
> 
> Ah, -fexcess-precision=16 doesn't seem to be documented though

I've noticed that too.

> (how does
> this influence long double handling then?)

ix86_get_excess_precision has all the details.  x86 has 4 different ways of
excess precision, one is not to use excess precision for anything, another only
for __bf16/_Float16 (promote to float), another one is promote everything to
long double and last is unpredictable.
With -fexcess-precision=fast, with -mavx512fp16 we don't promote anything,
without that to float.
With -fexcess-precision=16 we don't promote anything.
With -fexcess-precision=standard and the implicit case, it depends on
-mavx512fp16, -mfpmath=sse, -mfpmath=387, -mfpmath=both etc.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (7 preceding siblings ...)
  2024-03-18  9:06 ` jakub at gcc dot gnu.org
@ 2024-03-18  9:08 ` liuhongt at gcc dot gnu.org
  2024-03-20  6:02 ` eggert at cs dot ucla.edu
                   ` (3 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: liuhongt at gcc dot gnu.org @ 2024-03-18  9:08 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

--- Comment #9 from Hongtao Liu <liuhongt at gcc dot gnu.org> ---
(In reply to Richard Biener from comment #7)
> (In reply to Jakub Jelinek from comment #6)
> > You can use -fexcess-precision=16 if you don't want treating _Float16 and
> > __bf16 as having excess precision.  With excess precision, I think the above
> > behavior is correct.
> > You'd need (int) (__bf16) 257.0bf16 to get 256 even with excess precision.
> 
> Ah, -fexcess-precision=16 doesn't seem to be documented though (how does
> this influence long double handling then?)

Oh, I forgot to add that in invoke.texi.

-fexcess-precision=16 doesn't impact types with precision > 16. And it's not
compatible with -mfpmath=387.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (8 preceding siblings ...)
  2024-03-18  9:08 ` liuhongt at gcc dot gnu.org
@ 2024-03-20  6:02 ` eggert at cs dot ucla.edu
  2024-03-20  6:19 ` pinskia at gcc dot gnu.org
                   ` (2 subsequent siblings)
  12 siblings, 0 replies; 14+ messages in thread
From: eggert at cs dot ucla.edu @ 2024-03-20  6:02 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

--- Comment #10 from Paul Eggert <eggert at cs dot ucla.edu> ---
(In reply to Jakub Jelinek from comment #6)
> You can use -fexcess-precision=16 if you don't want treating _Float16 and
> __bf16 as having excess precision.  With excess precision, I think the above
> behavior is correct.

So the constant 257.0bf16 has a value that the type __bf16 cannot represent?
Although the C standard allows this sort of thing, it doesn't sound wise.

For example, it breaks a common use of 'typeof' that is given in the GCC manual
section 6.7 "Referring to a Type with 'typeof'". In this program:

  #define MAX(a, b) ((a) > (b) ? (a) : (b))
  #define max(a, b) \
    ({ typeof (a) _a = (a); \
       typeof (b) _b = (b); \
       _a > _b ? _a : _b; })

  int main (void)
  {
    return    max(257.0bf16, 256.0bf16)
           == MAX(257.0bf16, 256.0bf16);
  }

'main' surprisingly returns 0 when I expect pretty much everybody would expect
it to return 1. This is because "max" surprisingly changes the values of its
arguments before comparing, whereas MAX does not.

If GCC's "bf16" and "f16" suffixes arranged for floating point constants to be
representable as __bf16 and _Float16, respectively, we wouldn't have this sort
of confusion. Surely that would be better than the current situation.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (9 preceding siblings ...)
  2024-03-20  6:02 ` eggert at cs dot ucla.edu
@ 2024-03-20  6:19 ` pinskia at gcc dot gnu.org
  2024-03-21  0:48 ` cvs-commit at gcc dot gnu.org
  2024-03-25 22:21 ` pinskia at gcc dot gnu.org
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-03-20  6:19 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

--- Comment #11 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Paul Eggert from comment #10)
> (In reply to Jakub Jelinek from comment #6)
> > You can use -fexcess-precision=16 if you don't want treating _Float16 and
> > __bf16 as having excess precision.  With excess precision, I think the above
> > behavior is correct.
> 
> So the constant 257.0bf16 has a value that the type __bf16 cannot represent?
> Although the C standard allows this sort of thing, it doesn't sound wise.

This is also true for similar case for 32bit x86 (without using SSE) and
constants ending in f or other floating point constants. Just folks hit it
there as much as that is not used as much either.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (10 preceding siblings ...)
  2024-03-20  6:19 ` pinskia at gcc dot gnu.org
@ 2024-03-21  0:48 ` cvs-commit at gcc dot gnu.org
  2024-03-25 22:21 ` pinskia at gcc dot gnu.org
  12 siblings, 0 replies; 14+ messages in thread
From: cvs-commit at gcc dot gnu.org @ 2024-03-21  0:48 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

--- Comment #12 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The master branch has been updated by hongtao Liu <liuhongt@gcc.gnu.org>:

https://gcc.gnu.org/g:415091f09096a0ebba1fdcd4af8c2fda24cfd411

commit r14-9588-g415091f09096a0ebba1fdcd4af8c2fda24cfd411
Author: liuhongt <hongtao.liu@intel.com>
Date:   Mon Mar 18 18:53:59 2024 +0800

    Document -fexcess-precision=16.

    gcc/ChangeLog:

            PR middle-end/114347
            * doc/invoke.texi: Document -fexcess-precision=16.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [Bug middle-end/114347] wrong constant folding when casting __bf16 to int
  2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
                   ` (11 preceding siblings ...)
  2024-03-21  0:48 ` cvs-commit at gcc dot gnu.org
@ 2024-03-25 22:21 ` pinskia at gcc dot gnu.org
  12 siblings, 0 replies; 14+ messages in thread
From: pinskia at gcc dot gnu.org @ 2024-03-25 22:21 UTC (permalink / raw)
  To: gcc-bugs

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114347

Andrew Pinski <pinskia at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
           See Also|                            |https://gcc.gnu.org/bugzill
                   |                            |a/show_bug.cgi?id=92875
         Resolution|---                         |INVALID

--- Comment #13 from Andrew Pinski <pinskia at gcc dot gnu.org> ---
(In reply to Andrew Pinski from comment #11)
> This is also true for similar case for 32bit x86 (without using SSE) and
> constants ending in f or other floating point constants. Just folks hit it
> there as much as that is not used as much either.

In fact that is recorded as PR 92875 :).

The constant handling is correct here (and there too).

So closing as invalid.

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2024-03-25 22:21 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-15  4:55 [Bug c/114347] New: wrong constant folding when casting __bf16 to int eggert at cs dot ucla.edu
2024-03-15  5:01 ` [Bug middle-end/114347] " pinskia at gcc dot gnu.org
2024-03-15  5:19 ` eggert at cs dot ucla.edu
2024-03-15  9:03 ` rguenth at gcc dot gnu.org
2024-03-15 16:58 ` jsm28 at gcc dot gnu.org
2024-03-18  8:03 ` rguenth at gcc dot gnu.org
2024-03-18  8:16 ` jakub at gcc dot gnu.org
2024-03-18  8:53 ` rguenth at gcc dot gnu.org
2024-03-18  9:06 ` jakub at gcc dot gnu.org
2024-03-18  9:08 ` liuhongt at gcc dot gnu.org
2024-03-20  6:02 ` eggert at cs dot ucla.edu
2024-03-20  6:19 ` pinskia at gcc dot gnu.org
2024-03-21  0:48 ` cvs-commit at gcc dot gnu.org
2024-03-25 22:21 ` pinskia at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).