From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id 3B56E3858C5F; Thu, 9 Feb 2023 15:50:26 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 3B56E3858C5F DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1675957826; bh=damcHUNFrtk5N/KvuYCA0sRd8/b60XnEPEvCOOA1098=; h=From:To:Subject:Date:From; b=JrCc96HACSW4EHTidO78gqOyu4GviisogX5riXUHg/MpXpzTJwdg0nCEqPY44ART2 5NnkXjk2E+H+NP2C+T78jPBDcB46+QBDukuXV+6IWhoa9LnsJraAjKOlbbTAoFCvDQ XCbLRO6B3DRHnIwJZ4qHZKpEphWr6BXNDKDXyRUM= From: "matz at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug middle-end/108742] New: Incorrect constant folding with (or exposed by) -fexcess-precision=standard Date: Thu, 09 Feb 2023 15:50:25 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: middle-end X-Bugzilla-Version: 12.2.1 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: matz at gcc dot gnu.org X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Resolution: X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter target_milestone Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 List-Id: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D108742 Bug ID: 108742 Summary: Incorrect constant folding with (or exposed by) -fexcess-precision=3Dstandard Product: gcc Version: 12.2.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: matz at gcc dot gnu.org Target Milestone: --- This came from a discussion about a user wondering why g++ behaved different between GCC 12 and GCC 13, regarding equality comparisons of floating point values on x87, i.e. -m32, which ultimately was because GCC 13 activated -fexcess-precision=3Dstandard with -std=3Dc++17. Now this is not in itself surprising, but I think something is still wrong. From commit 98e341130f87984af07c884fea773c0bb3cc8821 (adding this to c++17): ... The existing testcases tweaks were for cases on i686-linux where excess precision breaks those tests, e.g. if we have double d =3D 4.2; if (d =3D=3D 4.2) then it does the expected thing only with -fexcess-precision=3Dfast, because with -fexcess-precision=3Dstandard it is actually double d =3D 4.2; if ((long double) d =3D=3D 4.2L) where 4.2L is different from 4.2. ... And indeed a simple testcase about this (for C, but it demonstrates the same thing):=20 % cat float.c #define bool _Bool int main() { double d =3D 4.2; bool eq1 =3D (long double)d =3D=3D (long double)4.2; bool eq2 =3D (long double)d =3D=3D 4.2L; bool eq3 =3D (long double)d =3D=3D (long double)(double)4.2; __builtin_printf ("equal: %d/%d/%d\n", eq1, eq2, eq3); __builtin_printf ("1: %La\n", 4.2L); __builtin_printf ("2: %La\n", (long double)4.2); __builtin_printf ("3: %La\n", (long double)(double)4.2); return 0; } % gcc -m32 -O0 -fexcess-precision=3Dfast -o fast float.c % gcc -m32 -O0 -fexcess-precision=3Dstandard -o standard float.c % ./fast equal: 1/0/1 1: 0x8.666666666666666p-1 2: 0x8.6666666666668p-1 3: 0x8.6666666666668p-1 % ./standard equal: 0/0/1 1: 0x8.666666666666666p-1 2: 0x8.666666666666666p-1 3: 0x8.6666666666668p-1 The bug I think exists is that also with =3Dstandard the first comparison should yield 'true' and that irrespective of the excess-prec setting result= (2) should always be the same as (3). As the comment for the commit correctly says: (long double)4.2 !=3D 4.2L hence, even with -fexcess-precision=3Dstandard the former should _not_ be const-folded into the latter, but rather into the exact long double value t= hat corresponds to (double)4.2. Namely: (gdb) p/x (long double)4.2 $1 =3D 0x40018666666666666800 (gdb) p/x (long double)4.2L $2 =3D 0x40018666666666666666 The former is the correct long double value to use for the casted double literal, not the latter. IOW: it's fine that -fexcess-precision=3Dstandard tries to emulate the exce= ss precision on the hardware by doing all arithmetics in the larger type. But then also the constants need to be folded exactly as the hardware would be doing. In still other words: I think we have a bug in our constant folders and I d= on't think it has anything directly to do with -fexcess-precision=3Dstandard, bu= t is merely exposed by it. The wrong value is already present in 005t.original: __builtin_printf ((const char *) "1: %La\n", 4.19999999999999999982652765240231929055880755186080932617e+0); __builtin_printf ((const char *) "2: %La\n", 4.19999999999999999982652765240231929055880755186080932617e+0); __builtin_printf ((const char *) "3: %La\n", 4.20000000000000017763568394002504646778106689453125e+0);=