public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [committed] c: C2x semantics for __builtin_tgmath
@ 2023-01-06 19:32 Joseph Myers
  0 siblings, 0 replies; only message in thread
From: Joseph Myers @ 2023-01-06 19:32 UTC (permalink / raw)
  To: gcc-patches

__builtin_tgmath implements <tgmath.h> 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 <tgmath.h> 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 <tgmath.h> (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{<tgmath.h>} 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

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-01-06 19:34 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-06 19:32 [committed] c: C2x semantics for __builtin_tgmath Joseph Myers

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).