public inbox for fortran@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] fortran: Expand ieee_arithmetic module's ieee_class inline [PR106579]
@ 2022-08-15 10:18 Jakub Jelinek
  2022-08-15 19:47 ` FX
  0 siblings, 1 reply; 3+ messages in thread
From: Jakub Jelinek @ 2022-08-15 10:18 UTC (permalink / raw)
  To: FX; +Cc: gcc-patches, fortran

Hi!

The following patch expands IEEE_CLASS inline in the FE, using the
__builtin_fpclassify, __builtin_signbit and the new __builtin_issignaling
builtins.

Bootstrapped/regtested on x86_64-linux, i686-linux, powerpc64le-linux
and powerpc64-linux, ok for trunk?

2022-08-15  Jakub Jelinek  <jakub@redhat.com>

	PR fortran/106579
gcc/fortran/
	* f95-lang.cc (gfc_init_builtin_functions): Initialize
	BUILT_IN_FPCLASSIFY.
	* libgfortran.h (IEEE_OTHER_VALUE, IEEE_SIGNALING_NAN,
	IEEE_QUIET_NAN, IEEE_NEGATIVE_INF, IEEE_NEGATIVE_NORMAL,
	IEEE_NEGATIVE_DENORMAL, IEEE_NEGATIVE_SUBNORMAL,
	IEEE_NEGATIVE_ZERO, IEEE_POSITIVE_ZERO, IEEE_POSITIVE_DENORMAL,
	IEEE_POSITIVE_SUBNORMAL, IEEE_POSITIVE_NORMAL, IEEE_POSITIVE_INF):
	New enum.
	* trans-intrinsic.cc (conv_intrinsic_ieee_class): New function.
	(gfc_conv_ieee_arithmetic_function): Handle ieee_class.
libgfortran/
	* ieee/ieee_helper.c (IEEE_OTHER_VALUE, IEEE_SIGNALING_NAN,
	IEEE_QUIET_NAN, IEEE_NEGATIVE_INF, IEEE_NEGATIVE_NORMAL,
	IEEE_NEGATIVE_DENORMAL, IEEE_NEGATIVE_SUBNORMAL,
	IEEE_NEGATIVE_ZERO, IEEE_POSITIVE_ZERO, IEEE_POSITIVE_DENORMAL,
	IEEE_POSITIVE_SUBNORMAL, IEEE_POSITIVE_NORMAL, IEEE_POSITIVE_INF):
	Move to gcc/fortran/libgfortran.h.

--- gcc/fortran/f95-lang.cc.jj	2022-08-12 17:06:33.906598328 +0200
+++ gcc/fortran/f95-lang.cc	2022-08-12 18:39:47.727073699 +0200
@@ -1017,8 +1017,9 @@ gfc_init_builtin_functions (void)
 		      "__builtin_issignaling", ATTR_CONST_NOTHROW_LEAF_LIST);
   gfc_define_builtin ("__builtin_signbit", ftype, BUILT_IN_SIGNBIT,
 		      "__builtin_signbit", ATTR_CONST_NOTHROW_LEAF_LIST);
+  gfc_define_builtin ("__builtin_fpclassify", ftype, BUILT_IN_FPCLASSIFY,
+		      "__builtin_fpclassify", ATTR_CONST_NOTHROW_LEAF_LIST);
 
-  ftype = build_function_type (integer_type_node, NULL_TREE);
   gfc_define_builtin ("__builtin_isless", ftype, BUILT_IN_ISLESS,
 		      "__builtin_isless", ATTR_CONST_NOTHROW_LEAF_LIST);
   gfc_define_builtin ("__builtin_islessequal", ftype, BUILT_IN_ISLESSEQUAL,
--- gcc/fortran/libgfortran.h.jj	2022-05-31 11:33:51.550250610 +0200
+++ gcc/fortran/libgfortran.h	2022-08-12 17:22:33.210947170 +0200
@@ -187,3 +187,23 @@ typedef enum
   BT_ASSUMED, BT_UNION, BT_BOZ
 }
 bt;
+
+/* Enumeration of the possible floating-point types. These values
+   correspond to the hidden arguments of the IEEE_CLASS_TYPE
+   derived-type of IEEE_ARITHMETIC.  */
+
+enum {
+  IEEE_OTHER_VALUE = 0,
+  IEEE_SIGNALING_NAN,
+  IEEE_QUIET_NAN,
+  IEEE_NEGATIVE_INF,
+  IEEE_NEGATIVE_NORMAL,
+  IEEE_NEGATIVE_DENORMAL,
+  IEEE_NEGATIVE_SUBNORMAL = IEEE_NEGATIVE_DENORMAL,
+  IEEE_NEGATIVE_ZERO,
+  IEEE_POSITIVE_ZERO,
+  IEEE_POSITIVE_DENORMAL,
+  IEEE_POSITIVE_SUBNORMAL = IEEE_POSITIVE_DENORMAL,
+  IEEE_POSITIVE_NORMAL,
+  IEEE_POSITIVE_INF
+};
--- gcc/fortran/trans-intrinsic.cc.jj	2022-06-28 13:14:45.322799333 +0200
+++ gcc/fortran/trans-intrinsic.cc	2022-08-12 18:51:28.095927643 +0200
@@ -10013,6 +10013,78 @@ conv_intrinsic_ieee_copy_sign (gfc_se *
 }
 
 
+/* Generate code for IEEE_CLASS.  */
+
+static void
+conv_intrinsic_ieee_class (gfc_se *se, gfc_expr *expr)
+{
+  tree arg, c, t1, t2, t3, t4;
+
+  /* Convert arg, evaluate it only once.  */
+  conv_ieee_function_args (se, expr, &arg, 1);
+  arg = gfc_evaluate_now (arg, &se->pre);
+
+  c = build_call_expr_loc (input_location,
+			   builtin_decl_explicit (BUILT_IN_FPCLASSIFY), 6,
+			   build_int_cst (integer_type_node, IEEE_QUIET_NAN),
+			   build_int_cst (integer_type_node,
+					  IEEE_POSITIVE_INF),
+			   build_int_cst (integer_type_node,
+					  IEEE_POSITIVE_NORMAL),
+			   build_int_cst (integer_type_node,
+					  IEEE_POSITIVE_DENORMAL),
+			   build_int_cst (integer_type_node,
+					  IEEE_POSITIVE_ZERO),
+			   arg);
+  c = gfc_evaluate_now (c, &se->pre);
+  t1 = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
+			c, build_int_cst (integer_type_node,
+					  IEEE_QUIET_NAN));
+  t2 = build_call_expr_loc (input_location,
+			    builtin_decl_explicit (BUILT_IN_ISSIGNALING), 1,
+			    arg);
+  t2 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+			t2, build_zero_cst (TREE_TYPE (t2)));
+  t1 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+			logical_type_node, t1, t2);
+  t3 = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
+			c, build_int_cst (integer_type_node,
+					  IEEE_POSITIVE_ZERO));
+  t4 = build_call_expr_loc (input_location,
+			    builtin_decl_explicit (BUILT_IN_SIGNBIT), 1,
+			    arg);
+  t4 = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+			t4, build_zero_cst (TREE_TYPE (t4)));
+  t3 = fold_build2_loc (input_location, TRUTH_AND_EXPR,
+			logical_type_node, t3, t4);
+  int s = IEEE_NEGATIVE_ZERO + IEEE_POSITIVE_ZERO;
+  gcc_assert (IEEE_NEGATIVE_INF == s - IEEE_POSITIVE_INF);
+  gcc_assert (IEEE_NEGATIVE_NORMAL == s - IEEE_POSITIVE_NORMAL);
+  gcc_assert (IEEE_NEGATIVE_DENORMAL == s - IEEE_POSITIVE_DENORMAL);
+  gcc_assert (IEEE_NEGATIVE_SUBNORMAL == s - IEEE_POSITIVE_SUBNORMAL);
+  gcc_assert (IEEE_NEGATIVE_ZERO == s - IEEE_POSITIVE_ZERO);
+  t4 = fold_build2_loc (input_location, MINUS_EXPR, TREE_TYPE (c),
+			build_int_cst (TREE_TYPE (c), s), c);
+  t3 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c),
+			t3, t4, c);
+  t1 = fold_build3_loc (input_location, COND_EXPR, TREE_TYPE (c), t1,
+			build_int_cst (TREE_TYPE (c), IEEE_SIGNALING_NAN),
+			t3);
+  tree type = gfc_typenode_for_spec (&expr->ts);
+  gcc_assert (TREE_CODE (type) == RECORD_TYPE);
+  tree field = NULL_TREE;
+  for (tree f = TYPE_FIELDS (type); f != NULL_TREE; f = DECL_CHAIN (f))
+    if (TREE_CODE (f) == FIELD_DECL)
+      {
+	gcc_assert (field == NULL_TREE);
+	field = f;
+      }
+  gcc_assert (field);
+  t1 = fold_convert (TREE_TYPE (field), t1);
+  se->expr = build_constructor_single (type, field, t1);
+}
+
+
 /* Generate code for an intrinsic function from the IEEE_ARITHMETIC
    module.  */
 
@@ -10043,6 +10115,8 @@ gfc_conv_ieee_arithmetic_function (gfc_s
     conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
   else if (startswith (name, "_gfortran_ieee_rint"))
     conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_RINT);
+  else if (startswith (name, "ieee_class_") && ISDIGIT (name[11]))
+    conv_intrinsic_ieee_class (se, expr);
   else
     /* It is not among the functions we translate directly.  We return
        false, so a library function call is emitted.  */
--- libgfortran/ieee/ieee_helper.c.jj	2022-08-12 13:39:50.285337026 +0200
+++ libgfortran/ieee/ieee_helper.c	2022-08-12 17:22:00.923372705 +0200
@@ -51,26 +51,6 @@ extern int ieee_class_helper_16 (GFC_REA
 internal_proto(ieee_class_helper_16);
 #endif
 
-/* Enumeration of the possible floating-point types. These values
-   correspond to the hidden arguments of the IEEE_CLASS_TYPE
-   derived-type of IEEE_ARITHMETIC.  */
-
-enum {
-  IEEE_OTHER_VALUE = 0,
-  IEEE_SIGNALING_NAN,
-  IEEE_QUIET_NAN,
-  IEEE_NEGATIVE_INF,
-  IEEE_NEGATIVE_NORMAL,
-  IEEE_NEGATIVE_DENORMAL,
-  IEEE_NEGATIVE_SUBNORMAL = IEEE_NEGATIVE_DENORMAL,
-  IEEE_NEGATIVE_ZERO,
-  IEEE_POSITIVE_ZERO,
-  IEEE_POSITIVE_DENORMAL,
-  IEEE_POSITIVE_SUBNORMAL = IEEE_POSITIVE_DENORMAL,
-  IEEE_POSITIVE_NORMAL,
-  IEEE_POSITIVE_INF
-};
-
 
 #define CLASSMACRO(TYPE) \
   int ieee_class_helper_ ## TYPE (GFC_REAL_ ## TYPE *value) \

	Jakub


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] fortran: Expand ieee_arithmetic module's ieee_class inline [PR106579]
  2022-08-15 10:18 [PATCH] fortran: Expand ieee_arithmetic module's ieee_class inline [PR106579] Jakub Jelinek
@ 2022-08-15 19:47 ` FX
  2022-08-15 20:11   ` Jakub Jelinek
  0 siblings, 1 reply; 3+ messages in thread
From: FX @ 2022-08-15 19:47 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches, fortran

Question to the Fortran maintainers:

Do you know if the standard allows IEEE_CLASS and IEEE_VALUE to be used as procedure pointers? I think not, because they do not follow (in F2008) the standard constraint C729 / R740.

If so, we need to keep these functions implementations in libgfortran for now (for ABI compatibility) but can remove them at the next breakage. Is one planned? Where is this tracked, is it still at https://gcc.gnu.org/wiki/LibgfortranAbiCleanup or do we have another place (e.g. in bugzilla)?

Thanks,
FX

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] fortran: Expand ieee_arithmetic module's ieee_class inline [PR106579]
  2022-08-15 19:47 ` FX
@ 2022-08-15 20:11   ` Jakub Jelinek
  0 siblings, 0 replies; 3+ messages in thread
From: Jakub Jelinek @ 2022-08-15 20:11 UTC (permalink / raw)
  To: FX; +Cc: gcc-patches, fortran

On Mon, Aug 15, 2022 at 09:47:45PM +0200, FX wrote:
> Question to the Fortran maintainers:
> 
> Do you know if the standard allows IEEE_CLASS and IEEE_VALUE to be used as procedure pointers? I think not, because they do not follow (in F2008) the standard constraint C729 / R740.
> 
> If so, we need to keep these functions implementations in libgfortran for now (for ABI compatibility) but can remove them at the next breakage. Is one planned? Where is this tracked, is it still at https://gcc.gnu.org/wiki/LibgfortranAbiCleanup or do we have another place (e.g. in bugzilla)?

Both are elemental generic procedures, and we have
Procedure pointer %qs at %L shall not be elemental
and
Interface %qs at %L may not be generic
errors for these 2 cases (trying to create procedure
pointer to elemental and trying to create procedure
pointer to generic procedure).

	Jakub


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-08-15 20:11 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-15 10:18 [PATCH] fortran: Expand ieee_arithmetic module's ieee_class inline [PR106579] Jakub Jelinek
2022-08-15 19:47 ` FX
2022-08-15 20:11   ` Jakub Jelinek

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