diff options
author | Tobias Burnus <burnus@net-b.de> | 2009-07-08 21:34:49 +0200 |
---|---|---|
committer | Tobias Burnus <burnus@gcc.gnu.org> | 2009-07-08 21:34:49 +0200 |
commit | 60d340efa77c1ae01cf3e7a66bcf402ca7793d7f (patch) | |
tree | 0a5ea8221f10c4245ae6b6625bf67d42c5a11bf1 | |
parent | 0f158db0bf587d51a8527e7399d258b5391bdfef (diff) | |
download | gcc-60d340efa77c1ae01cf3e7a66bcf402ca7793d7f.zip gcc-60d340efa77c1ae01cf3e7a66bcf402ca7793d7f.tar.gz gcc-60d340efa77c1ae01cf3e7a66bcf402ca7793d7f.tar.bz2 |
re PR fortran/40675 (Support -fnosign-zero for SIGN intrinsic for Fortran 77 compatibility)
2009-07-08 Tobias Burnus <burnus@net-b.de>
PR fortran/40675
* simplify.c (gfc_simplify_sign): Handle signed zero correctly.
* trans-intrinsic.c (gfc_conv_intrinsic_sign): Support
-fno-sign-zero.
* invoke.texi (-fno-sign-zero): Add text regarding SIGN
* intrinsic.
2009-07-08 Tobias Burnus <burnus@net-b.de>
PR fortran/40675
* gfortran.dg/nosigned_zero_1.f90: New test.
* gfortran.dg/nosigned_zero_2.f90: New test.
From-SVN: r149390
-rw-r--r-- | gcc/fortran/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/fortran/invoke.texi | 9 | ||||
-rw-r--r-- | gcc/fortran/simplify.c | 13 | ||||
-rw-r--r-- | gcc/fortran/trans-intrinsic.c | 21 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/nosigned_zero_1.f90 | 24 | ||||
-rw-r--r-- | gcc/testsuite/gfortran.dg/nosigned_zero_2.f90 | 25 |
7 files changed, 95 insertions, 11 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog index 371fdde..77c5f61 100644 --- a/gcc/fortran/ChangeLog +++ b/gcc/fortran/ChangeLog @@ -1,3 +1,11 @@ +2009-07-08 Tobias Burnus <burnus@net-b.de> + + PR fortran/40675 + * simplify.c (gfc_simplify_sign): Handle signed zero correctly. + * trans-intrinsic.c (gfc_conv_intrinsic_sign): Support + -fno-sign-zero. + * invoke.texi (-fno-sign-zero): Add text regarding SIGN intrinsic. + 2008-07-08 Paul Thomas <pault@gcc.gnu.org> PR fortran/40591 diff --git a/gcc/fortran/invoke.texi b/gcc/fortran/invoke.texi index 5d0448f..68cc012 100644 --- a/gcc/fortran/invoke.texi +++ b/gcc/fortran/invoke.texi @@ -1024,9 +1024,12 @@ really useful for use by the gfortran testsuite. @item -fsign-zero @opindex @code{fsign-zero} -When writing zero values, show the negative sign if the sign bit is set. -@code{fno-sign-zero} does not print the negative sign of zero values for -compatibility with F77. Default behavior is to show the negative sign. +When enabled, floating point numbers of value zero with the sign bit set +are written as negative number in formatted output and treated as +negative in the @code{SIGN} intrinsic. @code{fno-sign-zero} does not +print the negative sign of zero values and regards zero as positive +number in the @code{SIGN} intrinsic for compatibility with F77. +Default behavior is to show the negative sign. @end table @node Code Gen Options diff --git a/gcc/fortran/simplify.c b/gcc/fortran/simplify.c index f57f68e..c619f14 100644 --- a/gcc/fortran/simplify.c +++ b/gcc/fortran/simplify.c @@ -4957,16 +4957,15 @@ gfc_simplify_sign (gfc_expr *x, gfc_expr *y) mpz_abs (result->value.integer, x->value.integer); if (mpz_sgn (y->value.integer) < 0) mpz_neg (result->value.integer, result->value.integer); - break; case BT_REAL: - /* TODO: Handle -0.0 and +0.0 correctly on machines that support - it. */ - mpfr_abs (result->value.real, x->value.real, GFC_RND_MODE); - if (mpfr_sgn (y->value.real) < 0) - mpfr_neg (result->value.real, result->value.real, GFC_RND_MODE); - + if (gfc_option.flag_sign_zero) + mpfr_copysign (result->value.real, x->value.real, y->value.real, + GFC_RND_MODE); + else + mpfr_setsign (result->value.real, x->value.real, + mpfr_sgn (y->value.real) < 0 ? 1 : 0, GFC_RND_MODE); break; default: diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c index dd3b3cd..89b98ec 100644 --- a/gcc/fortran/trans-intrinsic.c +++ b/gcc/fortran/trans-intrinsic.c @@ -1263,22 +1263,41 @@ gfc_conv_intrinsic_sign (gfc_se * se, gfc_expr * expr) gfc_conv_intrinsic_function_args (se, expr, args, 2); if (expr->ts.type == BT_REAL) { + tree abs; + switch (expr->ts.kind) { case 4: tmp = built_in_decls[BUILT_IN_COPYSIGNF]; + abs = built_in_decls[BUILT_IN_FABSF]; break; case 8: tmp = built_in_decls[BUILT_IN_COPYSIGN]; + abs = built_in_decls[BUILT_IN_FABS]; break; case 10: case 16: tmp = built_in_decls[BUILT_IN_COPYSIGNL]; + abs = built_in_decls[BUILT_IN_FABSL]; break; default: gcc_unreachable (); } - se->expr = build_call_expr (tmp, 2, args[0], args[1]); + + /* We explicitly have to ignore the minus sign. We do so by using + result = (arg1 == 0) ? abs(arg0) : copysign(arg0, arg1). */ + if (!gfc_option.flag_sign_zero + && MODE_HAS_SIGNED_ZEROS (TYPE_MODE (TREE_TYPE (args[1])))) + { + tree cond, zero; + zero = build_real_from_int_cst (TREE_TYPE (args[1]), integer_zero_node); + cond = fold_build2 (EQ_EXPR, boolean_type_node, args[1], zero); + se->expr = fold_build3 (COND_EXPR, TREE_TYPE (args[0]), cond, + build_call_expr (abs, 1, args[0]), + build_call_expr (tmp, 2, args[0], args[1])); + } + else + se->expr = build_call_expr (tmp, 2, args[0], args[1]); return; } diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5955370..fa2998a 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2009-07-08 Tobias Burnus <burnus@net-b.de> + + PR fortran/40675 + * gfortran.dg/nosigned_zero_1.f90: New test. + * gfortran.dg/nosigned_zero_2.f90: New test. + 2009-07-08 Richard Guenther <rguenther@suse.de> * gcc.dg/torture/ssa-pta-fn-1.c: Fix invalid testcase again. diff --git a/gcc/testsuite/gfortran.dg/nosigned_zero_1.f90 b/gcc/testsuite/gfortran.dg/nosigned_zero_1.f90 new file mode 100644 index 0000000..51ac879 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nosigned_zero_1.f90 @@ -0,0 +1,24 @@ +! { dg-do run } +! +! PR fortran/40675 +! +! Fortran 77 just had: "The value of a signed zero is the same as +! the value of an unsigned zero." and g77 returned for SIGN(1.0, -0.0) = 1.0 +! +! Fortran 95+ has for SIGN: "Case (iv): If B is of type real and is zero, +! then ... (c) If B is negative real zero, the value of the result is -|A|". +! On architectures, where signed zeros are supported, gfortran's SIGN thus +! returns for B=-0.0 the -|A|. +! +program s + x = sign(1.,0.) + y = sign(1.,-0.) + if (x /= 1.) call abort() + if (y /= -1.) call abort() + x = 1. + y = 0. + x = sign(x, y) + y = sign(x, -y) + if (x /= 1.) call abort() + if (y /= -1.) call abort() +end program s diff --git a/gcc/testsuite/gfortran.dg/nosigned_zero_2.f90 b/gcc/testsuite/gfortran.dg/nosigned_zero_2.f90 new file mode 100644 index 0000000..af05574 --- /dev/null +++ b/gcc/testsuite/gfortran.dg/nosigned_zero_2.f90 @@ -0,0 +1,25 @@ +! { dg-do run } +! { dg-options "-fno-sign-zero" } +! +! PR fortran/40675 +! +! Fortran 77 just had: "The value of a signed zero is the same as +! the value of an unsigned zero." and g77 returned for SIGN(1.0, -0.0) = 1.0 +! +! Fortran 95+ has for SIGN: "Case (iv): If B is of type real and is zero, +! then ... (c) If B is negative real zero, the value of the result is -|A|". +! On architectures, where signed zeros are supported, gfortran's SIGN thus +! returns for B=-0.0 the -|A|. +! +program s + x = sign(1.,0.) + y = sign(1.,-0.) + if (x /= 1.) call abort() + if (y /= 1.) call abort() + x = 1. + y = 0. + x = sign(x, y) + y = sign(x, -y) + if (x /= 1.) call abort() + if (y /= 1.) call abort() +end program s |