aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTobias Burnus <burnus@net-b.de>2009-07-08 21:34:49 +0200
committerTobias Burnus <burnus@gcc.gnu.org>2009-07-08 21:34:49 +0200
commit60d340efa77c1ae01cf3e7a66bcf402ca7793d7f (patch)
tree0a5ea8221f10c4245ae6b6625bf67d42c5a11bf1
parent0f158db0bf587d51a8527e7399d258b5391bdfef (diff)
downloadgcc-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/ChangeLog8
-rw-r--r--gcc/fortran/invoke.texi9
-rw-r--r--gcc/fortran/simplify.c13
-rw-r--r--gcc/fortran/trans-intrinsic.c21
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gfortran.dg/nosigned_zero_1.f9024
-rw-r--r--gcc/testsuite/gfortran.dg/nosigned_zero_2.f9025
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