aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran/trans-intrinsic.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/fortran/trans-intrinsic.cc')
-rw-r--r--gcc/fortran/trans-intrinsic.cc176
1 files changed, 176 insertions, 0 deletions
diff --git a/gcc/fortran/trans-intrinsic.cc b/gcc/fortran/trans-intrinsic.cc
index b6ea26e..e0f86b1 100644
--- a/gcc/fortran/trans-intrinsic.cc
+++ b/gcc/fortran/trans-intrinsic.cc
@@ -10376,6 +10376,178 @@ conv_intrinsic_ieee_minmax (gfc_se * se, gfc_expr * expr, int max,
}
+/* Generate code for comparison functions IEEE_QUIET_* and
+ IEEE_SIGNALING_*. */
+
+static void
+conv_intrinsic_ieee_comparison (gfc_se * se, gfc_expr * expr, int signaling,
+ const char *name)
+{
+ tree args[2];
+ tree arg1, arg2, res;
+
+ /* Evaluate arguments only once. */
+ conv_ieee_function_args (se, expr, args, 2);
+ arg1 = gfc_evaluate_now (args[0], &se->pre);
+ arg2 = gfc_evaluate_now (args[1], &se->pre);
+
+ if (startswith (name, "eq"))
+ {
+ if (signaling)
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISEQSIG),
+ 2, arg1, arg2);
+ else
+ res = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
+ arg1, arg2);
+ }
+ else if (startswith (name, "ne"))
+ {
+ if (signaling)
+ {
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISEQSIG),
+ 2, arg1, arg2);
+ res = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
+ logical_type_node, res);
+ }
+ else
+ res = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ arg1, arg2);
+ }
+ else if (startswith (name, "ge"))
+ {
+ if (signaling)
+ res = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
+ arg1, arg2);
+ else
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL),
+ 2, arg1, arg2);
+ }
+ else if (startswith (name, "gt"))
+ {
+ if (signaling)
+ res = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
+ arg1, arg2);
+ else
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISGREATER),
+ 2, arg1, arg2);
+ }
+ else if (startswith (name, "le"))
+ {
+ if (signaling)
+ res = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
+ arg1, arg2);
+ else
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISLESSEQUAL),
+ 2, arg1, arg2);
+ }
+ else if (startswith (name, "lt"))
+ {
+ if (signaling)
+ res = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
+ arg1, arg2);
+ else
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISLESS),
+ 2, arg1, arg2);
+ }
+ else
+ gcc_unreachable ();
+
+ se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), res);
+}
+
+
+/* Generate code for comparison functions IEEE_QUIET_* and
+ IEEE_SIGNALING_*. */
+
+static void
+conv_intrinsic_ieee_comparison (gfc_se * se, gfc_expr * expr, int signaling,
+ const char *name)
+{
+ tree args[2];
+ tree arg1, arg2, res;
+
+ /* Evaluate arguments only once. */
+ conv_ieee_function_args (se, expr, args, 2);
+ arg1 = gfc_evaluate_now (args[0], &se->pre);
+ arg2 = gfc_evaluate_now (args[1], &se->pre);
+
+ if (startswith (name, "eq"))
+ {
+ if (signaling)
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISEQSIG),
+ 2, arg1, arg2);
+ else
+ res = fold_build2_loc (input_location, EQ_EXPR, logical_type_node,
+ arg1, arg2);
+ }
+ else if (startswith (name, "ne"))
+ {
+ if (signaling)
+ {
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISEQSIG),
+ 2, arg1, arg2);
+ res = fold_build1_loc (input_location, TRUTH_NOT_EXPR,
+ logical_type_node, res);
+ }
+ else
+ res = fold_build2_loc (input_location, NE_EXPR, logical_type_node,
+ arg1, arg2);
+ }
+ else if (startswith (name, "ge"))
+ {
+ if (signaling)
+ res = fold_build2_loc (input_location, GE_EXPR, logical_type_node,
+ arg1, arg2);
+ else
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISGREATEREQUAL),
+ 2, arg1, arg2);
+ }
+ else if (startswith (name, "gt"))
+ {
+ if (signaling)
+ res = fold_build2_loc (input_location, GT_EXPR, logical_type_node,
+ arg1, arg2);
+ else
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISGREATER),
+ 2, arg1, arg2);
+ }
+ else if (startswith (name, "le"))
+ {
+ if (signaling)
+ res = fold_build2_loc (input_location, LE_EXPR, logical_type_node,
+ arg1, arg2);
+ else
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISLESSEQUAL),
+ 2, arg1, arg2);
+ }
+ else if (startswith (name, "lt"))
+ {
+ if (signaling)
+ res = fold_build2_loc (input_location, LT_EXPR, logical_type_node,
+ arg1, arg2);
+ else
+ res = build_call_expr_loc (input_location,
+ builtin_decl_explicit (BUILT_IN_ISLESS),
+ 2, arg1, arg2);
+ }
+ else
+ gcc_unreachable ();
+
+ se->expr = fold_convert (gfc_typenode_for_spec (&expr->ts), res);
+}
+
+
/* Generate code for an intrinsic function from the IEEE_ARITHMETIC
module. */
@@ -10418,6 +10590,10 @@ gfc_conv_ieee_arithmetic_function (gfc_se * se, gfc_expr * expr)
conv_intrinsic_ieee_minmax (se, expr, 0, name + 23);
else if (startswith (name, "_gfortran_ieee_max_num_"))
conv_intrinsic_ieee_minmax (se, expr, 1, name + 23);
+ else if (startswith (name, "_gfortran_ieee_quiet_"))
+ conv_intrinsic_ieee_comparison (se, expr, 0, name + 21);
+ else if (startswith (name, "_gfortran_ieee_signaling_"))
+ conv_intrinsic_ieee_comparison (se, expr, 1, name + 25);
else
/* It is not among the functions we translate directly. We return
false, so a library function call is emitted. */