From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id B492A3858421; Fri, 14 Apr 2023 10:08:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org B492A3858421 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1681466918; bh=EN67WlbqM+tusnB/H2bYWiLc8N5LJvD6AuAWuFY79TM=; h=From:To:Subject:Date:In-Reply-To:References:From; b=W5QRNdL1Pf33WqYsojECQa2z0Hmrj6HGTXwrIb2TKgwwtAsCyvnsucHEBBpPQO6wL 9IRt8NDmo9nYfuk6wwBMDm20E9y81UuVOthontyxalcL75PJUXSTqpIITfgYhfo0gk HaTKvBHV7QdzzUFFBXoLRTYP3IdmskaTONbgmIDs= From: "rguenth at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/109359] [12/13 Regression] Compile-time rounding of double literal to float is incorrect with -frounding-math Date: Fri, 14 Apr 2023 10:08:37 +0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 13.0 X-Bugzilla-Keywords: wrong-code X-Bugzilla-Severity: normal X-Bugzilla-Who: rguenth at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Resolution: X-Bugzilla-Priority: P2 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: 12.3 X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: 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=3D109359 --- Comment #6 from Richard Biener --- output_constant gets called with {(float) 1.91399999999999990279997419406754488591104745864868164062e-3, (fl= oat) 6.305389999999999606217215841752476990222930908203125e-1} it then eventually does /* Eliminate any conversions since we'll be outputting the underlying constant. */ while (CONVERT_EXPR_P (exp) || TREE_CODE (exp) =3D=3D NON_LVALUE_EXPR || TREE_CODE (exp) =3D=3D VIEW_CONVERT_EXPR) { HOST_WIDE_INT type_size =3D int_size_in_bytes (TREE_TYPE (exp)); HOST_WIDE_INT op_size =3D int_size_in_bytes (TREE_TYPE (TREE_OPERAND = (exp, 0))); /* Make sure eliminating the conversion is really a no-op, except with VIEW_CONVERT_EXPRs to allow for wild Ada unchecked conversions and union types to allow for Ada unchecked unions. */ if (type_size > op_size && TREE_CODE (exp) !=3D VIEW_CONVERT_EXPR && TREE_CODE (TREE_TYPE (exp)) !=3D UNION_TYPE) /* Keep the conversion. */ break; else exp =3D TREE_OPERAND (exp, 0); } where we strip conversions with type_size < op_size (aka float from double). For float conversions not sure if just keying on type size is good enough though (ibm double double vs long double 128 for example). Fixing that "improves" the behavior to t.ii:1:34: error: initializer for floating value is not a floating constant 1 | float xs[] =3D {0.001914, 0.630539}; | ^ t.ii:1:34: error: initializer for floating value is not a floating constant aka from wrong-code to rejects-valid. diff --git a/gcc/varasm.cc b/gcc/varasm.cc index cd0cd88321c..e6ab581dc5f 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -5202,7 +5202,7 @@ output_constant (tree exp, unsigned HOST_WIDE_INT siz= e, unsigned int align, /* Make sure eliminating the conversion is really a no-op, except wi= th VIEW_CONVERT_EXPRs to allow for wild Ada unchecked conversions and union types to allow for Ada unchecked unions. */ - if (type_size > op_size + if (type_size !=3D op_size && TREE_CODE (exp) !=3D VIEW_CONVERT_EXPR && TREE_CODE (TREE_TYPE (exp)) !=3D UNION_TYPE) /* Keep the conversion. */ note that for integral and pointer types we do cst =3D expand_expr (exp, NULL_RTX, VOIDmode, EXPAND_INITIALIZER); if (reverse) cst =3D flip_storage_order (TYPE_MODE (TREE_TYPE (exp)), cst); if (!assemble_integer (cst, MIN (size, thissize), align, 0)) error ("initializer for integer/fixed-point value is too complicate= d"); so we handle "narrowing" in a weird way. So in case FEs leave around nop-casts the following should be safer diff --git a/gcc/varasm.cc b/gcc/varasm.cc index cd0cd88321c..81f7288449c 100644 --- a/gcc/varasm.cc +++ b/gcc/varasm.cc @@ -5196,13 +5196,17 @@ output_constant (tree exp, unsigned HOST_WIDE_INT s= ize, unsigned int align, || TREE_CODE (exp) =3D=3D NON_LVALUE_EXPR || TREE_CODE (exp) =3D=3D VIEW_CONVERT_EXPR) { - HOST_WIDE_INT type_size =3D int_size_in_bytes (TREE_TYPE (exp)); - HOST_WIDE_INT op_size =3D int_size_in_bytes (TREE_TYPE (TREE_OPERAND= (exp, 0))); + tree type =3D TREE_TYPE (exp); + tree op_type =3D TREE_TYPE (TREE_OPERAND (exp, 0)); + HOST_WIDE_INT type_size =3D int_size_in_bytes (type); + HOST_WIDE_INT op_size =3D int_size_in_bytes (op_type); /* Make sure eliminating the conversion is really a no-op, except wi= th VIEW_CONVERT_EXPRs to allow for wild Ada unchecked conversions and union types to allow for Ada unchecked unions. */ - if (type_size > op_size + if ((type_size > op_size + || (TYPE_MAIN_VARIANT (type) !=3D TYPE_MAIN_VARIANT (op_type) + && FLOAT_TYPE_P (type))) && TREE_CODE (exp) !=3D VIEW_CONVERT_EXPR && TREE_CODE (TREE_TYPE (exp)) !=3D UNION_TYPE) /* Keep the conversion. */ The real fix is of course in the frontend, the above is just a safety net.=