This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH]: Additional fixes for PR 30789
- From: "Kaveh R. GHAZI" <ghazi at caip dot rutgers dot edu>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 30 Aug 2009 03:12:47 -0400 (EDT)
- Subject: [PATCH]: Additional fixes for PR 30789
This patch fixes the issues remaining in PR30789 pointed out by Joseph
here: http://gcc.gnu.org/ml/gcc-patches/2009-08/msg00738.html
I.e. the issues were folding everything (even Inf/NaN values) in static
initializers and adding a missing testcase. I added a flag to do_mpc_arg2
and do_mpc_ckconv to force folding in these situations. I also added the
missing testcase to builtin-math-7.c.
There were some problems with MPC's C99 Annex G conformance that required
fixing in the library. Those fixes now are in the svn repo version of
MPC, But not in mpc-0.6. So I had to update the effective target test in
builtin-math-7.c. Note the next MPC should be released in a few weeks.
Tested on x86_64-unknown-linux-gnu without MPC, with mpc-0.6 and with mpc
svn revision 666. No regressions, okay for mainline?
Thanks,
--Kaveh
2009-08-29 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
PR middle-end/30789
* builtins.c (do_mpc_arg2): Accept DO_NONFINITE parameter.
(do_mpc_ckconv): Accept FORCE_CONVERT parameter.
(fold_builtin_2, do_mpc_arg1): Update accordingly.
* fold-const.c (const_binop): Likewise.
* real.h (do_mpc_arg2): Update prototype.
testsuite:
* gcc.dg/torture/builtin-math-7.c: Update for testing Annex G
cases in static initializers.
diff -rup orig/egcc-SVN20090828/gcc/builtins.c egcc-SVN20090828/gcc/builtins.c
--- orig/egcc-SVN20090828/gcc/builtins.c 2009-08-19 02:00:28.000000000 +0200
+++ egcc-SVN20090828/gcc/builtins.c 2009-08-28 15:51:10.000000000 +0200
@@ -10732,7 +10732,7 @@ fold_builtin_2 (location_t loc, tree fnd
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE
&& validate_arg (arg1, COMPLEX_TYPE)
&& TREE_CODE (TREE_TYPE (TREE_TYPE (arg1))) == REAL_TYPE)
- return do_mpc_arg2 (arg0, arg1, type, mpc_pow);
+ return do_mpc_arg2 (arg0, arg1, type, /*do_nonfinite=*/ 0, mpc_pow);
break;
#endif
@@ -13338,17 +13338,19 @@ do_mpfr_ckconv (mpfr_srcptr m, tree type
was not exactly calculated. TYPE is the tree type for the result.
This function assumes that you cleared the MPFR flags and then
calculated M to see if anything subsequently set a flag prior to
- entering this function. Return NULL_TREE if any checks fail. */
+ entering this function. Return NULL_TREE if any checks fail, if
+ FORCE_CONVERT is true, then bypass the checks. */
static tree
-do_mpc_ckconv (mpc_srcptr m, tree type, int inexact)
+do_mpc_ckconv (mpc_srcptr m, tree type, int inexact, int force_convert)
{
/* Proceed iff we get a normal number, i.e. not NaN or Inf and no
overflow/underflow occurred. If -frounding-math, proceed iff the
result of calling FUNC was exact. */
- if (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
- && !mpfr_overflow_p () && !mpfr_underflow_p ()
- && (!flag_rounding_math || !inexact))
+ if (force_convert
+ || (mpfr_number_p (mpc_realref (m)) && mpfr_number_p (mpc_imagref (m))
+ && !mpfr_overflow_p () && !mpfr_underflow_p ()
+ && (!flag_rounding_math || !inexact)))
{
REAL_VALUE_TYPE re, im;
@@ -13358,16 +13360,19 @@ do_mpc_ckconv (mpc_srcptr m, tree type,
check for overflow/underflow. If the REAL_VALUE_TYPE is zero
but the mpft_t is not, then we underflowed in the
conversion. */
- if (real_isfinite (&re) && real_isfinite (&im)
- && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
- && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0))
+ if (force_convert
+ || (real_isfinite (&re) && real_isfinite (&im)
+ && (re.cl == rvc_zero) == (mpfr_zero_p (mpc_realref (m)) != 0)
+ && (im.cl == rvc_zero) == (mpfr_zero_p (mpc_imagref (m)) != 0)))
{
REAL_VALUE_TYPE re_mode, im_mode;
real_convert (&re_mode, TYPE_MODE (TREE_TYPE (type)), &re);
real_convert (&im_mode, TYPE_MODE (TREE_TYPE (type)), &im);
/* Proceed iff the specified mode can hold the value. */
- if (real_identical (&re_mode, &re) && real_identical (&im_mode, &im))
+ if (force_convert
+ || (real_identical (&re_mode, &re)
+ && real_identical (&im_mode, &im)))
return build_complex (type, build_real (TREE_TYPE (type), re_mode),
build_real (TREE_TYPE (type), im_mode));
}
@@ -13810,7 +13815,7 @@ do_mpc_arg1 (tree arg, tree type, int (*
mpfr_from_real (mpc_imagref(m), im, rnd);
mpfr_clear_flags ();
inexact = func (m, m, crnd);
- result = do_mpc_ckconv (m, type, inexact);
+ result = do_mpc_ckconv (m, type, inexact, /*force_convert=*/ 0);
mpc_clear (m);
}
}
@@ -13822,11 +13827,13 @@ do_mpc_arg1 (tree arg, tree type, int (*
mpc function FUNC on it and return the resulting value as a tree
with type TYPE. The mpfr precision is set to the precision of
TYPE. We assume that function FUNC returns zero if the result
- could be calculated exactly within the requested precision. */
+ could be calculated exactly within the requested precision. If
+ DO_NONFINITE is true, then fold expressions containing Inf or NaN
+ in the arguments and/or results. */
#ifdef HAVE_mpc
tree
-do_mpc_arg2 (tree arg0, tree arg1, tree type,
+do_mpc_arg2 (tree arg0, tree arg1, tree type, int do_nonfinite,
int (*func)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t))
{
tree result = NULL_TREE;
@@ -13847,8 +13854,9 @@ do_mpc_arg2 (tree arg0, tree arg1, tree
const REAL_VALUE_TYPE *const re1 = TREE_REAL_CST_PTR (TREE_REALPART (arg1));
const REAL_VALUE_TYPE *const im1 = TREE_REAL_CST_PTR (TREE_IMAGPART (arg1));
- if (real_isfinite (re0) && real_isfinite (im0)
- && real_isfinite (re1) && real_isfinite (im1))
+ if (do_nonfinite
+ || (real_isfinite (re0) && real_isfinite (im0)
+ && real_isfinite (re1) && real_isfinite (im1)))
{
const struct real_format *const fmt =
REAL_MODE_FORMAT (TYPE_MODE (TREE_TYPE (type)));
@@ -13866,7 +13874,7 @@ do_mpc_arg2 (tree arg0, tree arg1, tree
mpfr_from_real (mpc_imagref(m1), im1, rnd);
mpfr_clear_flags ();
inexact = func (m0, m0, m1, crnd);
- result = do_mpc_ckconv (m0, type, inexact);
+ result = do_mpc_ckconv (m0, type, inexact, do_nonfinite);
mpc_clear (m0);
mpc_clear (m1);
}
diff -rup orig/egcc-SVN20090828/gcc/fold-const.c egcc-SVN20090828/gcc/fold-const.c
--- orig/egcc-SVN20090828/gcc/fold-const.c 2009-08-15 02:00:54.000000000 +0200
+++ egcc-SVN20090828/gcc/fold-const.c 2009-08-28 15:51:10.000000000 +0200
@@ -1974,7 +1974,9 @@ const_binop (enum tree_code code, tree a
case MULT_EXPR:
#ifdef HAVE_mpc
if (COMPLEX_FLOAT_TYPE_P (type))
- return do_mpc_arg2 (arg1, arg2, type, mpc_mul);
+ return do_mpc_arg2 (arg1, arg2, type,
+ /* do_nonfinite= */ folding_initializer,
+ mpc_mul);
#endif
real = const_binop (MINUS_EXPR,
@@ -1990,7 +1992,9 @@ const_binop (enum tree_code code, tree a
case RDIV_EXPR:
#ifdef HAVE_mpc
if (COMPLEX_FLOAT_TYPE_P (type))
- return do_mpc_arg2 (arg1, arg2, type, mpc_div);
+ return do_mpc_arg2 (arg1, arg2, type,
+ /* do_nonfinite= */ folding_initializer,
+ mpc_div);
#endif
{
diff -rup orig/egcc-SVN20090828/gcc/real.h egcc-SVN20090828/gcc/real.h
--- orig/egcc-SVN20090828/gcc/real.h 2009-08-15 02:00:54.000000000 +0200
+++ egcc-SVN20090828/gcc/real.h 2009-08-28 15:51:10.000000000 +0200
@@ -27,7 +27,7 @@
#ifdef HAVE_mpc
#include <mpc.h>
# ifdef HAVE_mpc
-extern tree do_mpc_arg2 (tree, tree, tree, int (*)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t));
+extern tree do_mpc_arg2 (tree, tree, tree, int, int (*)(mpc_ptr, mpc_srcptr, mpc_srcptr, mpc_rnd_t));
# endif
# if MPC_VERSION >= MPC_VERSION_NUM(0,6,1)
# define HAVE_mpc_pow
diff -rup orig/egcc-SVN20090828/gcc/testsuite/gcc.dg/torture/builtin-math-7.c egcc-SVN20090828/gcc/testsuite/gcc.dg/torture/builtin-math-7.c
--- orig/egcc-SVN20090828/gcc/testsuite/gcc.dg/torture/builtin-math-7.c 2009-08-26 02:01:20.000000000 +0200
+++ egcc-SVN20090828/gcc/testsuite/gcc.dg/torture/builtin-math-7.c 2009-08-29 05:45:36.000000000 +0200
@@ -5,7 +5,7 @@
Origin: Kaveh R. Ghazi, August 13, 2009. */
/* { dg-do run } */
-/* { dg-require-effective-target mpc } */
+/* { dg-require-effective-target mpc_pow } */
/* { dg-options "-mieee" { target sh*-*-* } } */
extern void link_error(int);
@@ -16,23 +16,43 @@ extern void link_error(int);
link_error(__LINE__); \
} while (0)
+/* Use this error function for cases which only evaluate at
+ compile-time when optimizing. */
+#ifdef __OPTIMIZE__
+# define ERROR_FUNC(X) link_error(X)
+#else
+# define ERROR_FUNC(X) __builtin_abort()
+#endif
+
+/* Evaluate this expression at compile-time using static initializers. */
+#define STATICINIT_TESTIT(TYPE,X,OP,Y,RES) do { \
+ static const _Complex TYPE foo = (_Complex TYPE)(X) OP (_Complex TYPE)(Y); \
+ if (foo != (_Complex TYPE)(RES)) \
+ ERROR_FUNC (__LINE__); \
+} while (0)
+
/* Evaluate this expression at runtime. */
#define RUNTIME_TESTIT(TYPE,X,OP,Y,RES) do { \
- volatile _Complex TYPE foo = (_Complex TYPE)(X); \
+ volatile _Complex TYPE foo; \
+ foo = (_Complex TYPE)(X); \
foo OP##= (_Complex TYPE)(Y); \
- if (foo != (_Complex TYPE)(RES)) __builtin_abort(); \
+ if (foo != (_Complex TYPE)(RES)) \
+ __builtin_abort(); \
} while (0)
/* Evaluate this expression at compile-time and runtime. */
#define TESTIT(TYPE,X,OP,Y,RES) do { \
+ STATICINIT_TESTIT(TYPE,X,OP,Y,RES); \
COMPILETIME_TESTIT(TYPE,X,OP,Y,RES); \
RUNTIME_TESTIT(TYPE,X,OP,Y,RES); \
} while (0)
/* Either the real or imaginary parts should be infinity. */
#define TEST_ONE_PART_INF(VAL) do { \
- if (! __builtin_isinf(__real (VAL)) \
- && ! __builtin_isinf(__imag (VAL))) \
+ static const _Complex double foo = (VAL); \
+ if (! __builtin_isinf(__real foo) && ! __builtin_isinf(__imag foo)) \
+ ERROR_FUNC (__LINE__); \
+ if (! __builtin_isinf(__real (VAL)) && ! __builtin_isinf(__imag (VAL))) \
__builtin_abort(); \
} while (0)
@@ -71,5 +91,8 @@ int main()
TEST_ONE_PART_INF ((_Complex double)1 / (_Complex double)0);
TEST_ONE_PART_INF ((VAL1) / (_Complex double)1);
+ RUNTIME_TESTIT (double, 1, /, VAL1, 0);
+ STATICINIT_TESTIT (double, 1, /, VAL1, 0);
+
return 0;
}