aboutsummaryrefslogtreecommitdiff
path: root/gcc/fortran
diff options
context:
space:
mode:
authorTobias Schlüter <tobias.schlueter@physik.uni-muenchen.de>2004-12-27 18:13:07 +0100
committerTobias Schlüter <tobi@gcc.gnu.org>2004-12-27 18:13:07 +0100
commite98a8b5b621c4c9be4cc5efa38cf34ff14e27d67 (patch)
tree9ab5af294501132cc7f07c24458d26d441ed96c0 /gcc/fortran
parent201a97b4799fd44526a65abbcc2621f7d27766f7 (diff)
downloadgcc-e98a8b5b621c4c9be4cc5efa38cf34ff14e27d67.zip
gcc-e98a8b5b621c4c9be4cc5efa38cf34ff14e27d67.tar.gz
gcc-e98a8b5b621c4c9be4cc5efa38cf34ff14e27d67.tar.bz2
re PR libfortran/19032 (modulo generates wrong result for divisor 1 and -1)
fortran/ PR fortran/19032 * trans-intrinsic.c (gfc_conv_intrinsic_mod): Update comment in front of function to match the standard. Correct handling of MODULO. testsuite/ PR fortran/19032 * gfortran.dg/intrinsic_modulo_1.f90: New. * gfortran.fortran-torture/execute/intrinsic_mod_ulo.f90: Add tests with divisor -1. From-SVN: r92645
Diffstat (limited to 'gcc/fortran')
-rw-r--r--gcc/fortran/ChangeLog15
-rw-r--r--gcc/fortran/trans-intrinsic.c31
2 files changed, 20 insertions, 26 deletions
diff --git a/gcc/fortran/ChangeLog b/gcc/fortran/ChangeLog
index d1b20a7..7654b04 100644
--- a/gcc/fortran/ChangeLog
+++ b/gcc/fortran/ChangeLog
@@ -1,8 +1,3 @@
-2004-12-27 Andrew Pinski <pinskia@physics.uc.edu>
-
- * trans-expr.c (gfc_conv_cst_int_power): Only check for
- flag_unsafe_math_optimizations if we have a float type.
-
2004-12-27 Tobias Schlueter <tobias.schlueter@physik.uni-muenchen.de>
* trans-intrinsic.c (gfc_conv_intrinsic_ishft): Change to
@@ -11,6 +6,16 @@
4 bytes bits. Convert 2nd and 3rd argument to 4 bytes. Convert
result if width(arg 1) < 4 bytes. Call fold.
+ PR fortran/19032
+ * trans-intrinsic.c (gfc_conv_intrinsic_mod): Update comment
+ in front of function to match the standard. Correct handling
+ of MODULO.
+
+2004-12-27 Andrew Pinski <pinskia@physics.uc.edu>
+
+ * trans-expr.c (gfc_conv_cst_int_power): Only check for
+ flag_unsafe_math_optimizations if we have a float type.
+
2004-12-23 Steven G. Kargl <kargls@comcast.net>
* gfortran.texi: Fix typo.
diff --git a/gcc/fortran/trans-intrinsic.c b/gcc/fortran/trans-intrinsic.c
index 56def1a..455dfb8 100644
--- a/gcc/fortran/trans-intrinsic.c
+++ b/gcc/fortran/trans-intrinsic.c
@@ -771,8 +771,8 @@ gfc_conv_intrinsic_cmplx (gfc_se * se, gfc_expr * expr, int both)
se->expr = fold (build2 (COMPLEX_EXPR, type, real, imag));
}
-/* Remainder function MOD(A, P) = A - INT(A / P) * P.
- MODULO(A, P) = (A==0 .or. !(A>0 .xor. P>0))? MOD(A,P):MOD(A,P)+P. */
+/* Remainder function MOD(A, P) = A - INT(A / P) * P
+ MODULO(A, P) = A - FLOOR (A / P) * P */
/* TODO: MOD(x, 0) */
static void
@@ -783,7 +783,6 @@ gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
tree type;
tree itype;
tree tmp;
- tree zero;
tree test;
tree test2;
mpfr_t huge;
@@ -798,7 +797,10 @@ gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
{
case BT_INTEGER:
/* Integer case is easy, we've got a builtin op. */
- se->expr = build2 (TRUNC_MOD_EXPR, type, arg, arg2);
+ if (modulo)
+ se->expr = build2 (FLOOR_MOD_EXPR, type, arg, arg2);
+ else
+ se->expr = build2 (TRUNC_MOD_EXPR, type, arg, arg2);
break;
case BT_REAL:
@@ -821,7 +823,10 @@ gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
test2 = build2 (TRUTH_AND_EXPR, boolean_type_node, test, test2);
itype = gfc_get_int_type (expr->ts.kind);
- tmp = build_fix_expr (&se->pre, tmp, itype, FIX_TRUNC_EXPR);
+ if (modulo)
+ tmp = build_fix_expr (&se->pre, tmp, itype, FIX_FLOOR_EXPR);
+ else
+ tmp = build_fix_expr (&se->pre, tmp, itype, FIX_TRUNC_EXPR);
tmp = convert (type, tmp);
tmp = build3 (COND_EXPR, type, test2, tmp, arg);
tmp = build2 (MULT_EXPR, type, tmp, arg2);
@@ -832,22 +837,6 @@ gfc_conv_intrinsic_mod (gfc_se * se, gfc_expr * expr, int modulo)
default:
gcc_unreachable ();
}
-
- if (modulo)
- {
- zero = gfc_build_const (type, integer_zero_node);
- /* Build !(A > 0 .xor. P > 0). */
- test = build2 (GT_EXPR, boolean_type_node, arg, zero);
- test2 = build2 (GT_EXPR, boolean_type_node, arg2, zero);
- test = build2 (TRUTH_XOR_EXPR, boolean_type_node, test, test2);
- test = build1 (TRUTH_NOT_EXPR, boolean_type_node, test);
- /* Build (A == 0) .or. !(A > 0 .xor. P > 0). */
- test2 = build2 (EQ_EXPR, boolean_type_node, arg, zero);
- test = build2 (TRUTH_OR_EXPR, boolean_type_node, test, test2);
-
- se->expr = build3 (COND_EXPR, type, test, se->expr,
- build2 (PLUS_EXPR, type, se->expr, arg2));
- }
}
/* Positive difference DIM (x, y) = ((x - y) < 0) ? 0 : x - y. */