diff options
author | François-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2007-07-28 15:23:11 +0000 |
---|---|---|
committer | François-Xavier Coudert <fxcoudert@gcc.gnu.org> | 2007-07-28 15:23:11 +0000 |
commit | 5fcb93f1387118d919887c5f22cfc32b5adfc0ea (patch) | |
tree | 9929c388cc73a98ff25ef599b9a7375c67cab0a8 /gcc/fortran | |
parent | 6ea2b70d9ccabc6f1d86e79f3f4d3a553a155080 (diff) | |
download | gcc-5fcb93f1387118d919887c5f22cfc32b5adfc0ea.zip gcc-5fcb93f1387118d919887c5f22cfc32b5adfc0ea.tar.gz gcc-5fcb93f1387118d919887c5f22cfc32b5adfc0ea.tar.bz2 |
re PR fortran/32048 (max/min and NaN)
PR fortran/32048
* f95-lang.c (gfc_init_builtin_functions): Add declaration for
__builtin_isnan.
* trans-intrinsic.c (gfc_conv_intrinsic_minmax): Handled NaNs.
* gfortran.dg/nan_1.f90: New test.
From-SVN: r127019
Diffstat (limited to 'gcc/fortran')
-rw-r--r-- | gcc/fortran/f95-lang.c | 5 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 15 |
2 files changed, 17 insertions, 3 deletions
diff --git a/gcc/fortran/f95-lang.c b/gcc/fortran/f95-lang.c index 314fc37..3e03ef6 100644 --- a/gcc/fortran/f95-lang.c +++ b/gcc/fortran/f95-lang.c @@ -1004,6 +1004,11 @@ gfc_init_builtin_functions (void) "malloc", false); DECL_IS_MALLOC (built_in_decls[BUILT_IN_MALLOC]) = 1; + tmp = tree_cons (NULL_TREE, void_type_node, void_list_node); + ftype = build_function_type (integer_type_node, tmp); + gfc_define_builtin ("__builtin_isnan", ftype, BUILT_IN_ISNAN, + "__builtin_isnan", true); + #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \ builtin_types[(int) ENUM] = VALUE; #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \ diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index 02a64e5..8f57ae1 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -1407,11 +1407,11 @@ gfc_conv_intrinsic_ttynam (gfc_se * se, gfc_expr * expr) /* Get the minimum/maximum value of all the parameters. minmax (a1, a2, a3, ...) { - if (a2 .op. a1) + if (a2 .op. a1 || isnan(a1)) mvar = a2; else mvar = a1; - if (a3 .op. mvar) + if (a3 .op. mvar || isnan(mvar)) mvar = a3; ... return mvar @@ -1487,7 +1487,7 @@ gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, int op) elsecase = build2_v (MODIFY_EXPR, mvar, limit); for (i = 1, argexpr = argexpr->next; i < nargs; i++) { - tree cond; + tree cond, isnan; val = args[i]; @@ -1509,6 +1509,15 @@ gfc_conv_intrinsic_minmax (gfc_se * se, gfc_expr * expr, int op) thencase = build2_v (MODIFY_EXPR, mvar, convert (type, val)); tmp = build2 (op, boolean_type_node, convert (type, val), limit); + + /* FIXME: When the IEEE_ARITHMETIC module is implemented, the call to + __builtin_isnan might be made dependent on that module being loaded, + to help performance of programs that don't rely on IEEE semantics. */ + if (FLOAT_TYPE_P (TREE_TYPE (limit))) + { + isnan = build_call_expr (built_in_decls[BUILT_IN_ISNAN], 1, limit); + tmp = fold_build2 (TRUTH_OR_EXPR, boolean_type_node, tmp, isnan); + } tmp = build3_v (COND_EXPR, tmp, thencase, elsecase); if (cond != NULL_TREE) |