OSDN Git Service

PR middle-end/30789
authorghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 20 Sep 2009 15:39:22 +0000 (15:39 +0000)
committerghazi <ghazi@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 20 Sep 2009 15:39:22 +0000 (15:39 +0000)
* 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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@151904 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/builtins.c
gcc/fold-const.c
gcc/real.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/torture/builtin-math-7.c

index bb7dc70..af2d02c 100644 (file)
@@ -1,3 +1,12 @@
+2009-09-20  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.
+
 2009-09-20  Jan Hubicka  <jh@suse.cz>
 
        * dwarf2out.c (add_const_value_attribute): Return true if successful.
index 8ef9607..fddb36c 100644 (file)
@@ -10741,7 +10741,7 @@ fold_builtin_2 (location_t loc, tree fndecl, tree arg0, tree arg1, bool ignore)
          && 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
 
@@ -13347,17 +13347,19 @@ do_mpfr_ckconv (mpfr_srcptr m, tree type, int inexact)
    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;
 
@@ -13367,16 +13369,19 @@ do_mpc_ckconv (mpc_srcptr m, tree type, int inexact)
         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));
        }
@@ -13819,7 +13824,7 @@ do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
          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);
        }
     }
@@ -13831,11 +13836,13 @@ do_mpc_arg1 (tree arg, tree type, int (*func)(mpc_ptr, mpc_srcptr, mpc_rnd_t))
    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;
@@ -13856,8 +13863,9 @@ do_mpc_arg2 (tree arg0, tree arg1, tree type,
       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)));
@@ -13875,7 +13883,7 @@ do_mpc_arg2 (tree arg0, tree arg1, tree type,
          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);
        }
index 1ce0013..34e47c1 100644 (file)
@@ -1974,7 +1974,9 @@ const_binop (enum tree_code code, tree arg1, tree arg2, int notrunc)
        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 arg1, tree arg2, int notrunc)
        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
 
          {
index c93435b..e72723e 100644 (file)
@@ -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
index 6481b99..127d213 100644 (file)
@@ -1,3 +1,8 @@
+2009-09-20  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
+
+       * gcc.dg/torture/builtin-math-7.c: Update for testing Annex G
+       cases in static initializers.
+
 2009-09-20  Kai Tietz  <kai.tietz@onevision.com>
 
        * gcc.c-tortue/compile/pr39886.c: New.
index edd82e0..0d6307d 100644 (file)
@@ -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-add-options ieee } */
 
 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;
 }