mirror of git://gcc.gnu.org/git/gcc.git
fortran: Expand ieee_arithmetic module's ieee_class inline [PR106579]
The following patch expands IEEE_CLASS inline in the FE, using the __builtin_fpclassify, __builtin_signbit and the new __builtin_issignaling builtins. 2022-08-26 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.
This commit is contained in:
parent
387e6f1570
commit
db630423a9
|
|
@ -1017,8 +1017,9 @@ gfc_init_builtin_functions (void)
|
||||||
"__builtin_issignaling", ATTR_CONST_NOTHROW_LEAF_LIST);
|
"__builtin_issignaling", ATTR_CONST_NOTHROW_LEAF_LIST);
|
||||||
gfc_define_builtin ("__builtin_signbit", ftype, BUILT_IN_SIGNBIT,
|
gfc_define_builtin ("__builtin_signbit", ftype, BUILT_IN_SIGNBIT,
|
||||||
"__builtin_signbit", ATTR_CONST_NOTHROW_LEAF_LIST);
|
"__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,
|
gfc_define_builtin ("__builtin_isless", ftype, BUILT_IN_ISLESS,
|
||||||
"__builtin_isless", ATTR_CONST_NOTHROW_LEAF_LIST);
|
"__builtin_isless", ATTR_CONST_NOTHROW_LEAF_LIST);
|
||||||
gfc_define_builtin ("__builtin_islessequal", ftype, BUILT_IN_ISLESSEQUAL,
|
gfc_define_builtin ("__builtin_islessequal", ftype, BUILT_IN_ISLESSEQUAL,
|
||||||
|
|
|
||||||
|
|
@ -187,3 +187,23 @@ typedef enum
|
||||||
BT_ASSUMED, BT_UNION, BT_BOZ
|
BT_ASSUMED, BT_UNION, BT_BOZ
|
||||||
}
|
}
|
||||||
bt;
|
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
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -10013,6 +10013,83 @@ conv_intrinsic_ieee_copy_sign (gfc_se * se, gfc_expr * expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
/* Perform a quick sanity check that the return type is
|
||||||
|
IEEE_CLASS_TYPE derived type defined in
|
||||||
|
libgfortran/ieee/ieee_arithmetic.F90
|
||||||
|
Primarily check that it is a derived type with a single
|
||||||
|
member in it. */
|
||||||
|
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
|
/* Generate code for an intrinsic function from the IEEE_ARITHMETIC
|
||||||
module. */
|
module. */
|
||||||
|
|
||||||
|
|
@ -10043,6 +10120,8 @@ gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
|
||||||
conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
|
conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_LOGB);
|
||||||
else if (startswith (name, "_gfortran_ieee_rint"))
|
else if (startswith (name, "_gfortran_ieee_rint"))
|
||||||
conv_intrinsic_ieee_logb_rint (se, expr, BUILT_IN_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
|
else
|
||||||
/* It is not among the functions we translate directly. We return
|
/* It is not among the functions we translate directly. We return
|
||||||
false, so a library function call is emitted. */
|
false, so a library function call is emitted. */
|
||||||
|
|
|
||||||
|
|
@ -44,26 +44,6 @@ extern int ieee_class_helper_16 (GFC_REAL_16 *);
|
||||||
internal_proto(ieee_class_helper_16);
|
internal_proto(ieee_class_helper_16);
|
||||||
#endif
|
#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) \
|
#define CLASSMACRO(TYPE) \
|
||||||
int ieee_class_helper_ ## TYPE (GFC_REAL_ ## TYPE *value) \
|
int ieee_class_helper_ ## TYPE (GFC_REAL_ ## TYPE *value) \
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue