+2018-08-21 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * trans-intrinsic.c (gfc_conv_intrinsic_minmax): Use
+ MAX_EXPR/MIN_EXPR unconditionally for real arguments.
+ * gfortran.texi (Compiler Characteristics): Document MAX/MIN
+ behavior wrt NaN.
+
2018-08-21 Nicolas Koenig <koenigni@gcc.gnu.org>
Thomas Koenig <tkoenig@gcc.gnu.org>
* KIND Type Parameters::
* Internal representation of LOGICAL variables::
* Evaluation of logical expressions::
+* MAX and MIN intrinsics with REAL NaN arguments::
* Thread-safety of the runtime library::
* Data consistency and durability::
* Files opened without an explicit ACTION= specifier::
situations with the @option{-Wfunction-elimination} flag.
+@node MAX and MIN intrinsics with REAL NaN arguments
+@section MAX and MIN intrinsics with REAL NaN arguments
+@cindex MAX, MIN, NaN
+
+The Fortran standard does not specify what the result of the
+@code{MAX} and @code{MIN} intrinsics are if one of the arguments is a
+@code{NaN}. Accordingly, the GNU Fortran compiler does not specify
+that either, as this allows for faster and more compact code to be
+generated. If the programmer wishes to take some specific action in
+case one of the arguments is a @code{NaN}, it is necessary to
+explicitly test the arguments before calling @code{MAX} or @code{MIN},
+e.g. with the @code{IEEE_IS_NAN} function from the intrinsic module
+@code{IEEE_ARITHMETIC}.
+
+
@node Thread-safety of the runtime library
@section Thread-safety of the runtime library
@cindex thread-safety, threads
mvar = gfc_create_var (type, "M");
gfc_add_modify (&se->pre, mvar, args[0]);
- internal_fn ifn = op == GT_EXPR ? IFN_FMAX : IFN_FMIN;
-
for (i = 1, argexpr = argexpr->next; i < nargs; i++, argexpr = argexpr->next)
{
tree cond = NULL_TREE;
val = gfc_evaluate_now (val, &se->pre);
tree calc;
- /* If we dealing with integral types or we don't care about NaNs
- just do a MIN/MAX_EXPR. */
- if (!HONOR_NANS (type) && !HONOR_SIGNED_ZEROS (type))
- {
-
- tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
- calc = fold_build2_loc (input_location, code, type,
- convert (type, val), mvar);
- tmp = build2_v (MODIFY_EXPR, mvar, calc);
-
- }
- /* If we care about NaNs and we have internal functions available for
- fmin/fmax to perform the comparison, use those. */
- else if (SCALAR_FLOAT_TYPE_P (type)
- && direct_internal_fn_supported_p (ifn, type, OPTIMIZE_FOR_SPEED))
- {
- calc = build_call_expr_internal_loc (input_location, ifn, type,
- 2, mvar, convert (type, val));
- tmp = build2_v (MODIFY_EXPR, mvar, calc);
-
- }
- /* Otherwise expand to:
- mvar = a1;
- if (a2 .op. mvar || isnan (mvar))
- mvar = a2;
- if (a3 .op. mvar || isnan (mvar))
- mvar = a3;
- ... */
- else
- {
- tree isnan = build_call_expr_loc (input_location,
- builtin_decl_explicit (BUILT_IN_ISNAN),
- 1, mvar);
- tmp = fold_build2_loc (input_location, op, logical_type_node,
- convert (type, val), mvar);
-
- tmp = fold_build2_loc (input_location, TRUTH_OR_EXPR,
- logical_type_node, tmp,
- fold_convert (logical_type_node, isnan));
- tmp = build3_v (COND_EXPR, tmp,
- build2_v (MODIFY_EXPR, mvar, convert (type, val)),
- build_empty_stmt (input_location));
- }
+ /* For floating point types, the question is what MAX(a, NaN) or
+ MIN(a, NaN) should return (where "a" is a normal number).
+ There are valid usecase for returning either one, but the
+ Fortran standard doesn't specify which one should be chosen.
+ Also, there is no consensus among other tested compilers. In
+ short, it's a mess. So lets just do whatever is fastest. */
+ tree_code code = op == GT_EXPR ? MAX_EXPR : MIN_EXPR;
+ calc = fold_build2_loc (input_location, code, type,
+ convert (type, val), mvar);
+ tmp = build2_v (MODIFY_EXPR, mvar, calc);
if (cond != NULL_TREE)
tmp = build3_v (COND_EXPR, cond, tmp,
+2018-08-21 Janne Blomqvist <jb@gcc.gnu.org>
+
+ * gfortran.dg/nan_1.f90: Remove tests that test MAX/MIN with NaNs.
+
2018-08-21 Nicolas Koenig <koenigni@gcc.gnu.org>
Thomas Koenig <tkoenig@gcc.gnu.org>
if (isinf(-nan) .or. isinf(-large) .or. .not. isinf(-inf)) STOP 4
! Check that MIN and MAX behave correctly
- if (max(2.0, nan) /= 2.0) STOP 5
- if (min(2.0, nan) /= 2.0) STOP 6
- if (max(nan, 2.0) /= 2.0) STOP 7
- if (min(nan, 2.0) /= 2.0) STOP 8
-
- if (max(2.d0, nan) /= 2.d0) STOP 9! { dg-warning "Extension: Different type kinds" }
- if (min(2.d0, nan) /= 2.d0) STOP 10! { dg-warning "Extension: Different type kinds" }
- if (max(nan, 2.d0) /= 2.d0) STOP 11! { dg-warning "Extension: Different type kinds" }
- if (min(nan, 2.d0) /= 2.d0) STOP 12! { dg-warning "Extension: Different type kinds" }
if (.not. isnan(min(nan,nan))) STOP 13
if (.not. isnan(max(nan,nan))) STOP 14
! Same thing, with more arguments
- if (max(3.0, 2.0, nan) /= 3.0) STOP 15
- if (min(3.0, 2.0, nan) /= 2.0) STOP 16
- if (max(3.0, nan, 2.0) /= 3.0) STOP 17
- if (min(3.0, nan, 2.0) /= 2.0) STOP 18
- if (max(nan, 3.0, 2.0) /= 3.0) STOP 19
- if (min(nan, 3.0, 2.0) /= 2.0) STOP 20
-
- if (max(3.d0, 2.d0, nan) /= 3.d0) STOP 21! { dg-warning "Extension: Different type kinds" }
- if (min(3.d0, 2.d0, nan) /= 2.d0) STOP 22! { dg-warning "Extension: Different type kinds" }
- if (max(3.d0, nan, 2.d0) /= 3.d0) STOP 23! { dg-warning "Extension: Different type kinds" }
- if (min(3.d0, nan, 2.d0) /= 2.d0) STOP 24! { dg-warning "Extension: Different type kinds" }
- if (max(nan, 3.d0, 2.d0) /= 3.d0) STOP 25! { dg-warning "Extension: Different type kinds" }
- if (min(nan, 3.d0, 2.d0) /= 2.d0) STOP 26! { dg-warning "Extension: Different type kinds" }
-
if (.not. isnan(min(nan,nan,nan))) STOP 27
if (.not. isnan(max(nan,nan,nan))) STOP 28
if (.not. isnan(min(nan,nan,nan,nan))) STOP 29
! Large values, INF and NaNs
if (.not. isinf(max(large, inf))) STOP 33
if (isinf(min(large, inf))) STOP 34
- if (.not. isinf(max(nan, large, inf))) STOP 35
- if (isinf(min(nan, large, inf))) STOP 36
- if (.not. isinf(max(large, nan, inf))) STOP 37
- if (isinf(min(large, nan, inf))) STOP 38
- if (.not. isinf(max(large, inf, nan))) STOP 39
- if (isinf(min(large, inf, nan))) STOP 40
if (.not. isinf(min(-large, -inf))) STOP 41
if (isinf(max(-large, -inf))) STOP 42
- if (.not. isinf(min(nan, -large, -inf))) STOP 43
- if (isinf(max(nan, -large, -inf))) STOP 44
- if (.not. isinf(min(-large, nan, -inf))) STOP 45
- if (isinf(max(-large, nan, -inf))) STOP 46
- if (.not. isinf(min(-large, -inf, nan))) STOP 47
- if (isinf(max(-large, -inf, nan))) STOP 48
end program test