From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 48) id E5441385C318; Fri, 14 Oct 2022 07:32:05 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org E5441385C318 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1665732725; bh=nn1HKaRCW6wK02wFHihr/0kCTFQ2SHKcFJZKMOKtQ70=; h=From:To:Subject:Date:In-Reply-To:References:From; b=WIfSwYqKupelUPsfeNzBmWH0ZAY4ruFLXiLO5Mr2TbtRaDOXsNcJoxvNPpneOgA8G iQ6pj4lX0aqjg49uIOpVD3Uy15mKIfiQUzbkmiqbhPZnr23yznmD7lyVP25mVcBQzW Vf3fzcNI4UhEX/G4/V9heEjX6+FS6vCq03IbrojU= From: "cvs-commit at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/107097] Implement floating point excess precision in C++ Date: Fri, 14 Oct 2022 07:32:02 +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: 12.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: enhancement X-Bugzilla-Who: cvs-commit at gcc dot gnu.org X-Bugzilla-Status: NEW 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: 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=3D107097 --- Comment #7 from CVS Commits --- The master branch has been updated by Jakub Jelinek : https://gcc.gnu.org/g:98e341130f87984af07c884fea773c0bb3cc8821 commit r13-3290-g98e341130f87984af07c884fea773c0bb3cc8821 Author: Jakub Jelinek Date: Fri Oct 14 09:28:57 2022 +0200 c++: Implement excess precision support for C++ [PR107097, PR323] The following patch implements excess precision support for C++. Like for C, it uses EXCESS_PRECISION_EXPR tree to say that its operand is evaluated in excess precision and what the semantic type of the expression is. In most places I've followed what the C FE does in similar spots, so e.g. for binary ops if one or both operands are already EXCESS_PRECISION_EXPR, strip those away or for operations that might ne= ed excess precision (+, -, *, /) check if the operands should use excess precision and convert to that type and at the end wrap into EXCESS_PRECISION_EXPR with the common semantic type. This patch follows the C99 handling where it differs from C11 handling. There are some cases which needed to be handled differently, the C FE c= an just strip EXCESS_PRECISION_EXPR (replace it with its operand) when handling explicit cast, but that IMHO isn't right for C++ - the discovery what e= xact conversion should be used (e.g. if user conversion or standard or their sequence) should be decided based on the semantic type (i.e. type of EXCESS_PRECISION_EXPR), and that decision continues in convert_like* wh= ere we pick the right user conversion, again, if say some class has ctor from double and long double and we are on ia32 with standard excess precision promoting float/double to long double, then we should pick the ctor from double. Or when some other class has ctor from just double, and EXCESS_PRECISION_EXPR semantic type is float, we should choose the user ctor from double, but actually just convert the long double excess precision to double and not to float first. We need to make sure even identity conversion converts from excess precision to the semantic= one though, but if identity is chained with other conversions, we don't want the identity next_conversion to drop to semantic precision only to widen afterwards. 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. I've added -fexcess-precision=3Dfast to some tests and changed other tests to use constants that are exactly representable and don't suffer from these excess precision issues. There is one exception, pr68180.C looks like a bug in the patch which is also present in the C FE (so I'd like to get it resolved incrementally in both). Reduced testcase: typedef float __attribute__((vector_size (16))) float32x4_t; float32x4_t foo(float32x4_t x, float y) { return x + y; } with -m32 -std=3Dc11 -Wno-psabi or -m32 -std=3Dc++17 -Wno-psabi it is rejected with: pr68180.c:2:52: error: conversion of scalar =C3=A2long double=C3=A2 to = vector =C3=A2float32x4_t=C3=A2 {aka =C3=A2__vector(4) float=C3=A2} involves trunca= tion but without excess precision (say just -std=3Dc11 -Wno-psabi or -std=3D= c++17 -Wno-psabi) it is accepted. Perhaps we should pass down the semantic type to scalar_to_vector and use the semantic type rather than excess precision type in the diagnostics. 2022-10-14 Jakub Jelinek PR middle-end/323 PR c++/107097 gcc/ * doc/invoke.texi (-fexcess-precision=3Dstandard): Mention that= the option now also works in C++. gcc/c-family/ * c-common.def (EXCESS_PRECISION_EXPR): Remove comment part abo= ut the tree being specific to C/ObjC. * c-opts.cc (c_common_post_options): Handle flag_excess_precisi= on in C++ the same as in C. * c-lex.cc (interpret_float): Set const_type to excess_precisio= n () even for C++. gcc/cp/ * parser.cc (cp_parser_primary_expression): Handle EXCESS_PRECISION_EXPR with REAL_CST operand the same as REAL_CS= T. * cvt.cc (cp_ep_convert_and_check): New function. * call.cc (build_conditional_expr): Add excess precision suppor= t. When type_after_usual_arithmetic_conversions returns error_mark_node, use gcc_checking_assert that it is because of uncomparable floa= ting point ranks instead of checking all those conditions and make it work also with complex types. (convert_like_internal): Likewise. Add NESTED_P argument, pass true to recursive calls to convert_like. (convert_like): Add NESTED_P argument, pass it through to convert_like_internal. For other overload pass false to it. (convert_like_with_context): Pass false to NESTED_P. (convert_arg_to_ellipsis): Add excess precision support. (magic_varargs_p): For __builtin_is{finite,inf,inf_sign,nan,nor= mal} and __builtin_fpclassify return 2 instead of 1, document what it means. (build_over_call): Don't handle former magic 2 which is no long= er used, instead for magic 1 remove EXCESS_PRECISION_EXPR. (perform_direct_initialization_if_possible): Pass false to NEST= ED_P convert_like argument. * constexpr.cc (cxx_eval_constant_expression): Handle EXCESS_PRECISION_EXPR. (potential_constant_expression_1): Likewise. * pt.cc (tsubst_copy, tsubst_copy_and_build): Likewise. * cp-tree.h (cp_ep_convert_and_check): Declare. * cp-gimplify.cc (cp_fold): Handle EXCESS_PRECISION_EXPR. * typeck.cc (cp_common_type): For COMPLEX_TYPEs, return error_mark_node if recursive call returned it. (convert_arguments): For magic 1 remove EXCESS_PRECISION_EXPR. (cp_build_binary_op): Add excess precision support. When cp_common_type returns error_mark_node, use gcc_checking_assert that it is because of uncomparable floating point ranks instead of checking all those conditions and make it work also with complex types. (cp_build_unary_op): Likewise. (cp_build_compound_expr): Likewise. (build_static_cast_1): Remove EXCESS_PRECISION_EXPR. gcc/testsuite/ * gcc.target/i386/excess-precision-1.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-2.c: Likewise. * gcc.target/i386/excess-precision-3.c: Likewise. Remove check_float_nonproto and check_double_nonproto tests for C++. * gcc.target/i386/excess-precision-7.c: For C++ wrap abort and exit declarations into extern "C" block. * gcc.target/i386/excess-precision-9.c: Likewise. * g++.target/i386/excess-precision-1.C: New test. * g++.target/i386/excess-precision-2.C: New test. * g++.target/i386/excess-precision-3.C: New test. * g++.target/i386/excess-precision-4.C: New test. * g++.target/i386/excess-precision-5.C: New test. * g++.target/i386/excess-precision-6.C: New test. * g++.target/i386/excess-precision-7.C: New test. * g++.target/i386/excess-precision-9.C: New test. * g++.target/i386/excess-precision-11.C: New test. * c-c++-common/dfp/convert-bfp-10.c: Add -fexcess-precision=3Df= ast as dg-additional-options. * c-c++-common/dfp/compare-eq-const.c: Likewise. * g++.dg/cpp1z/constexpr-96862.C: Likewise. * g++.dg/cpp1z/decomp12.C (main): Use 2.25 instead of 2.3 to avoid excess precision differences. * g++.dg/other/thunk1.C: Add -fexcess-precision=3Dfast as dg-additional-options. * g++.dg/vect/pr64410.cc: Likewise. * g++.dg/cpp1y/pr68180.C: Likewise. * g++.dg/vect/pr89653.cc: Likewise. * g++.dg/cpp0x/variadic-tuple.C: Likewise. * g++.dg/cpp0x/nsdmi-union1.C: Use 4.25 instead of 4.2 to avoid excess precision differences. * g++.old-deja/g++.brendan/copy9.C: Add -fexcess-precision=3Dfa= st as dg-additional-options. * g++.old-deja/g++.brendan/overload7.C: Likewise.=