From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from esa2.mentor.iphmx.com (esa2.mentor.iphmx.com [68.232.141.98]) by sourceware.org (Postfix) with ESMTPS id 065693858D28 for ; Fri, 6 Jan 2023 19:34:18 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 065693858D28 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=codesourcery.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=mentor.com X-IronPort-AV: E=Sophos;i="5.96,306,1665475200"; d="scan'208";a="93268458" Received: from orw-gwy-01-in.mentorg.com ([192.94.38.165]) by esa2.mentor.iphmx.com with ESMTP; 06 Jan 2023 11:32:52 -0800 IronPort-SDR: tFCjHw/0sfzNDr6j05YhwO+G+7+SpQtTjKCM8ptnpgMovPtpNnvlCmRo4EJCMfTqGVgrer4Bl7 Stm0iroPxme0EfH47g1XdmwWPw4bewgxaULmhF+Ed3MR23bQiqHeamBaBDzexQXqCJcsiAjsng xwCzNEeWt8kA+hNgo4Sxj50B32LxbHvv670yXBiI2pL2qP/3rKozLuWu2vFHcRdMVreKqaLfrQ MYfrDp5cO+UfTBN926Aj8rVQUfYF+r8ir4+riSbJPbPbvXYGTq3j7szkpAjlQXhVg0wy21lrC1 Adg= Date: Fri, 6 Jan 2023 19:32:48 +0000 From: Joseph Myers To: Subject: [committed] c: C2x semantics for __builtin_tgmath Message-ID: MIME-Version: 1.0 Content-Type: text/plain; charset="US-ASCII" X-Originating-IP: [137.202.0.90] X-ClientProxiedBy: svr-ies-mbx-11.mgc.mentorg.com (139.181.222.11) To svr-ies-mbx-10.mgc.mentorg.com (139.181.222.10) X-Spam-Status: No, score=-3115.1 required=5.0 tests=BAYES_00,GIT_PATCH_0,HEADER_FROM_DIFFERENT_DOMAINS,KAM_DMARC_STATUS,RCVD_IN_MSPIKE_H2,SPF_HELO_PASS,SPF_PASS,TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: __builtin_tgmath implements semantics for integer generic arguments that handle cases involving _FloatN / _FloatNx types as specified in TS 18661-3 plus some defect fixes. C2x has further changes to the semantics for macros with such types, which should also be considered defect fixes (although handled through the integration of TS 18661-3 in C2x rather than through an issue tracking process). Specifically, the rules were changed because of problems raised with using the macros with the evaluation format types such as float_t and _Float32_t: the older version of the rules didn't allow passing _FloatN / _FloatNx types to the narrowing macros returning float or double, or passing float / double / long double to the narrowing macros returning _FloatN / _FloatNx, which was a problem with the evaluation format types which could be either kind of type depending on the value of FLT_EVAL_METHOD. Thus the new rules allow cases of mixing types which were not allowed before - which is not itself a problem for __builtin_tgmath - and, as part of the changes, the handling of integer arguments was also changed: if there is any _FloatNx generic argument, integer generic arguments are treated as _Float32x (not double), while the rule about treating integer arguments to narrowing macros returning _FloatN or _FloatNx as _Float64 not double was removed (no longer needed now double is a valid argument to such macros). Implement the changes for __builtin_tgmath. (The changes also added a rule that if any argument is _DecimalNx, integer arguments are treated as _Decimal64x, but GCC doesn't support _DecimalNx types so nothing is done about that.) I have a corresponding glibc patch to update glibc test expectations for C2x and also ensure that appropriate semantics are followed when GCC 7 through 12 are used with (avoiding __builtin_tgmath in cases where it doesn't match the C2x semantics). Bootstrapped with no regressions for x86_64-pc-linux-gnu. gcc/ * doc/extend.texi (__builtin_tgmath): Do not restate standard rule for handling real integer types. gcc/c/ * c-parser.cc (c_parser_postfix_expression): Handle integer generic arguments to functions passed to __builtin_tgmath as _Float32x if any argument has _FloatNx or _Complex _FloatNx type. Do not handle integer arguments to some narrowing functions as _Float64. gcc/testsuite/ * gcc.dg/builtin-tgmath-3.c: Update expectations and add more tests. diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc index 7d6960fffbb..3a5998007a9 100644 --- a/gcc/c/c-parser.cc +++ b/gcc/c/c-parser.cc @@ -10276,16 +10276,17 @@ c_parser_postfix_expression (c_parser *parser) types are treated as _Decimal64 if any type-generic argument is decimal, or if the only alternatives for type-generic arguments are of decimal types, and are - otherwise treated as double (or _Complex double for - complex integer types, or _Float64 or _Complex _Float64 - if all the return types are the same _FloatN or - _FloatNx type). After that adjustment, types are - combined following the usual arithmetic conversions. - If the function only accepts complex arguments, a - complex type is produced. */ + otherwise treated as _Float32x (or _Complex _Float32x + for complex integer types) if any type-generic argument + has _FloatNx type, otherwise as double (or _Complex + double for complex integer types). After that + adjustment, types are combined following the usual + arithmetic conversions. If the function only accepts + complex arguments, a complex type is produced. */ bool arg_complex = all_complex; bool arg_binary = all_binary; bool arg_int_decimal = all_decimal; + bool arg_int_floatnx = false; for (unsigned int j = 1; j <= nargs; j++) { if (parm_kind[j] == tgmath_fixed) @@ -10380,20 +10381,17 @@ c_parser_postfix_expression (c_parser *parser) goto out; } } + tree rtype = TYPE_MAIN_VARIANT (type); + if (TREE_CODE (rtype) == COMPLEX_TYPE) + rtype = TREE_TYPE (rtype); + if (SCALAR_FLOAT_TYPE_P (rtype)) + for (unsigned int j = 0; j < NUM_FLOATNX_TYPES; j++) + if (rtype == FLOATNX_TYPE_NODE (j)) + { + arg_int_floatnx = true; + break; + } } - /* For a macro rounding its result to a narrower type, map - integer types to _Float64 not double if the return type - is a _FloatN or _FloatNx type. */ - bool arg_int_float64 = false; - if (parm_kind[0] == tgmath_fixed - && SCALAR_FLOAT_TYPE_P (parm_first[0]) - && float64_type_node != NULL_TREE) - for (unsigned int j = 0; j < NUM_FLOATN_NX_TYPES; j++) - if (parm_first[0] == FLOATN_TYPE_NODE (j)) - { - arg_int_float64 = true; - break; - } tree arg_real = NULL_TREE; for (unsigned int j = 1; j <= nargs; j++) { @@ -10406,8 +10404,8 @@ c_parser_postfix_expression (c_parser *parser) if (INTEGRAL_TYPE_P (type)) type = (arg_int_decimal ? dfloat64_type_node - : arg_int_float64 - ? float64_type_node + : arg_int_floatnx + ? float32x_type_node : double_type_node); if (arg_real == NULL_TREE) arg_real = type; diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi index 68d7760bd0c..1103e9936f7 100644 --- a/gcc/doc/extend.texi +++ b/gcc/doc/extend.texi @@ -13923,9 +13923,8 @@ corresponding to @var{t} for each function. The standard rules for @code{} macros are used to find a common type @var{u} from the types of the arguments for parameters whose types vary between the functions; complex integer types (a GNU -extension) are treated like @code{_Complex double} for this purpose -(or @code{_Complex _Float64} if all the function return types are the -same @code{_Float@var{n}} or @code{_Float@var{n}x} type). +extension) are treated like the complex type corresponding to the real +floating type that would be chosen for the corresponding real integer type. If the function return types vary, or are all the same integer type, the function called is the one for which @var{t} is @var{u}, and it is an error if there is no such function. If the function return types diff --git a/gcc/testsuite/gcc.dg/builtin-tgmath-3.c b/gcc/testsuite/gcc.dg/builtin-tgmath-3.c index 35364ea3ee3..652113088a6 100644 --- a/gcc/testsuite/gcc.dg/builtin-tgmath-3.c +++ b/gcc/testsuite/gcc.dg/builtin-tgmath-3.c @@ -1,10 +1,12 @@ -/* Test __builtin_tgmath: integer arguments mapped to _Float64. */ +/* Test __builtin_tgmath: integer arguments with _FloatN / _FloatNx. */ /* { dg-do run } */ /* { dg-options "" } */ /* { dg-add-options float32 } */ /* { dg-add-options float64 } */ +/* { dg-add-options float32x } */ /* { dg-require-effective-target float32_runtime } */ /* { dg-require-effective-target float64_runtime } */ +/* { dg-require-effective-target float32x_runtime } */ extern void abort (void); extern void exit (int); @@ -18,7 +20,11 @@ extern void exit (int); } \ while (0) +extern double var_d; extern _Float32 var_f32; +extern _Float64 var_f64; +extern _Float32x var_f32x; +extern _Complex _Float32x var_cf32x; _Float32 t1f (float x) { return x + 1; } _Float32 t1d (double x) { return x + 2; } @@ -39,12 +45,45 @@ test_1 (void) CHECK_CALL (t1v (d), 4, var_f32); CHECK_CALL (t1v (ld), 6, var_f32); CHECK_CALL (t1v (f64), 8, var_f32); - CHECK_CALL (t1v (i), 9, var_f32); + CHECK_CALL (t1v (i), 7, var_f32); +} + +float t2f (float x, float y) { return 10 * x + y; } +double t2d (double x, double y) { return 100 * x + y; } +long double t2l (long double x, long double y) { return 1000 * x + y; } +_Float32x t2f32x (_Float32x x, _Float32x y) { return 10000 * x + y; } +_Float64 t2f64 (_Float64 x, _Float64 y) { return 100000 * x + y; } + +_Complex _Float32x +ct2f32x (_Complex _Float32x x, _Complex _Float32x y) +{ + return 1000000 * x + y; +} + +#define t2v(x, y) __builtin_tgmath (t2f, t2d, t2l, t2f32x, t2f64, ct2f32x, x, y) + +static void +test_2 (void) +{ + double d = 3; + _Float64 f64 = 6; + _Float32x f32x = 7; + int i = 5; + _Complex _Float32x cf32x = 8; + CHECK_CALL (t2v (f32x, i), 70005, var_f32x); + CHECK_CALL (t2v (i, f32x), 50007, var_f32x); + CHECK_CALL (t2v (f64, i), 600005, var_f64); + CHECK_CALL (t2v (i, f64), 500006, var_f64); + CHECK_CALL (t2v (d, i), 305, var_d); + CHECK_CALL (t2v (i, d), 503, var_d); + CHECK_CALL (t2v (cf32x, i), 8000005, var_cf32x); + CHECK_CALL (t2v (i, cf32x), 5000008, var_cf32x); } int main (void) { test_1 (); + test_2 (); exit (0); } -- Joseph S. Myers joseph@codesourcery.com