OSDN Git Service

PR middle-end/43419
authormatz <matz@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 18 Mar 2010 16:07:53 +0000 (16:07 +0000)
committerMasaki Muranaka <monaka@monami-software.com>
Sun, 23 May 2010 00:28:57 +0000 (09:28 +0900)
* builtins.c (expand_builtin_pow): Don't transform pow(x, 0.5)
into sqrt(x) if we need to preserve signed zeros.

testsuite/
* gcc.dg/pr43419.c: New testcase.

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

gcc/ChangeLog
gcc/builtins.c
gcc/testsuite/ChangeLog

index a4254a8..31b4340 100644 (file)
@@ -1,3 +1,9 @@
+2010-03-18  Michael Matz  <matz@suse.de>
+
+       PR middle-end/43419
+       * builtins.c (expand_builtin_pow): Don't transform pow(x, 0.5)
+       into sqrt(x) if we need to preserve signed zeros.
+
 2010-03-18  Steven Bosscher  <steven@gcc.gnu.org>
            Eric Botcazou  <ebotcazou@adacore.com>
 
index 871d670..705a255 100644 (file)
@@ -24,9 +24,9 @@ along with GCC; see the file COPYING3.  If not see
 #include "coretypes.h"
 #include "tm.h"
 #include "machmode.h"
+#include "real.h"
 #include "rtl.h"
 #include "tree.h"
-#include "realmpfr.h"
 #include "gimple.h"
 #include "flags.h"
 #include "regs.h"
@@ -560,7 +560,7 @@ c_readstr (const char *str, enum machine_mode mode)
          && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
        j = j + UNITS_PER_WORD - 2 * (j % UNITS_PER_WORD) - 1;
       j *= BITS_PER_UNIT;
-      gcc_assert (j < 2 * HOST_BITS_PER_WIDE_INT);
+      gcc_assert (j <= 2 * HOST_BITS_PER_WIDE_INT);
 
       if (ch)
        ch = (unsigned char) str[i];
@@ -1322,7 +1322,7 @@ apply_result_size (void)
       size = 0;
 
       for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
-       if (targetm.calls.function_value_regno_p (regno))
+       if (FUNCTION_VALUE_REGNO_P (regno))
          {
            mode = reg_raw_mode[regno];
 
@@ -2312,12 +2312,9 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
 
   if (icode != CODE_FOR_nothing)
     {
-      rtx last = get_last_insn ();
-      tree orig_arg = arg;
       /* Make a suitable register to place result in.  */
       if (!target
-         || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp))
-         || !insn_data[icode].operand[0].predicate (target, GET_MODE (target)))
+         || GET_MODE (target) != TYPE_MODE (TREE_TYPE (exp)))
          target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
 
       gcc_assert (insn_data[icode].operand[0].predicate
@@ -2335,10 +2332,8 @@ expand_builtin_interclass_mathfn (tree exp, rtx target, rtx subtarget)
 
       /* Compute into TARGET.
         Set TARGET to wherever the result comes back.  */
-      if (maybe_emit_unop_insn (icode, target, op0, UNKNOWN))
-       return target;
-      delete_insns_since (last);
-      CALL_EXPR_ARG (exp, 0) = orig_arg;
+      emit_unop_insn (icode, target, op0, UNKNOWN);
+      return target;
     }
 
   return NULL_RTX;
@@ -2923,95 +2918,6 @@ expand_powi (rtx x, enum machine_mode mode, HOST_WIDE_INT n)
   return result;
 }
 
-/* Fold a builtin function call to pow, powf, or powl into a series of sqrts or
-   cbrts.  Return NULL_RTX if no simplification can be made or expand the tree
-   if we can simplify it.  */
-static rtx
-expand_builtin_pow_root (location_t loc, tree arg0, tree arg1, tree type,
-                        rtx subtarget)
-{
-  if (TREE_CODE (arg1) == REAL_CST
-      && !TREE_OVERFLOW (arg1)
-      && flag_unsafe_math_optimizations)
-    {
-      enum machine_mode mode = TYPE_MODE (type);
-      tree sqrtfn = mathfn_built_in (type, BUILT_IN_SQRT);
-      tree cbrtfn = mathfn_built_in (type, BUILT_IN_CBRT);
-      REAL_VALUE_TYPE c = TREE_REAL_CST (arg1);
-      tree op = NULL_TREE;
-
-      if (sqrtfn)
-       {
-         /* Optimize pow (x, 0.5) into sqrt.  */
-         if (REAL_VALUES_EQUAL (c, dconsthalf))
-           op = build_call_nofold_loc (loc, sqrtfn, 1, arg0);
-
-         else
-           {
-             REAL_VALUE_TYPE dconst1_4 = dconst1;
-             REAL_VALUE_TYPE dconst3_4;
-             SET_REAL_EXP (&dconst1_4, REAL_EXP (&dconst1_4) - 2);
-
-             real_from_integer (&dconst3_4, VOIDmode, 3, 0, 0);
-             SET_REAL_EXP (&dconst3_4, REAL_EXP (&dconst3_4) - 2);
-
-             /* Optimize pow (x, 0.25) into sqrt (sqrt (x)).  Assume on most
-                machines that a builtin sqrt instruction is smaller than a
-                call to pow with 0.25, so do this optimization even if
-                -Os.  */
-             if (REAL_VALUES_EQUAL (c, dconst1_4))
-               {
-                 op = build_call_nofold_loc (loc, sqrtfn, 1, arg0);
-                 op = build_call_nofold_loc (loc, sqrtfn, 1, op);
-               }
-
-             /* Optimize pow (x, 0.75) = sqrt (x) * sqrt (sqrt (x)) unless we
-                are optimizing for space.  */
-             else if (optimize_insn_for_speed_p ()
-                      && !TREE_SIDE_EFFECTS (arg0)
-                      && REAL_VALUES_EQUAL (c, dconst3_4))
-               {
-                 tree sqrt1 = build_call_expr_loc (loc, sqrtfn, 1, arg0);
-                 tree sqrt2 = builtin_save_expr (sqrt1);
-                 tree sqrt3 = build_call_expr_loc (loc, sqrtfn, 1, sqrt1);
-                 op = fold_build2_loc (loc, MULT_EXPR, type, sqrt2, sqrt3);
-               }
-           }
-       }
-
-      /* Check whether we can do cbrt insstead of pow (x, 1./3.) and
-        cbrt/sqrts instead of pow (x, 1./6.).  */
-      if (cbrtfn && ! op
-         && (tree_expr_nonnegative_p (arg0) || !HONOR_NANS (mode)))
-       {
-         /* First try 1/3.  */
-         REAL_VALUE_TYPE dconst1_3
-           = real_value_truncate (mode, dconst_third ());
-
-         if (REAL_VALUES_EQUAL (c, dconst1_3))
-           op = build_call_nofold_loc (loc, cbrtfn, 1, arg0);
-
-             /* Now try 1/6.  */
-         else if (optimize_insn_for_speed_p ())
-           {
-             REAL_VALUE_TYPE dconst1_6 = dconst1_3;
-             SET_REAL_EXP (&dconst1_6, REAL_EXP (&dconst1_6) - 1);
-
-             if (REAL_VALUES_EQUAL (c, dconst1_6))
-               {
-                 op = build_call_nofold_loc (loc, sqrtfn, 1, arg0);
-                 op = build_call_nofold_loc (loc, cbrtfn, 1, op);
-               }
-           }
-       }
-
-      if (op)
-       return expand_expr (op, subtarget, mode, EXPAND_NORMAL);
-    }
-
-  return NULL_RTX;
-}
-
 /* Expand a call to the pow built-in mathematical function.  Return NULL_RTX if
    a normal call should be emitted rather than expanding the function
    in-line.  EXP is the expression that is a call to the builtin
@@ -3074,16 +2980,10 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget)
          && ((flag_unsafe_math_optimizations
               && optimize_insn_for_speed_p ()
               && powi_cost (n/2) <= POWI_MAX_MULTS)
-             /* Even the c == 0.5 case cannot be done unconditionally
+             /* Even the c==0.5 case cannot be done unconditionally
                 when we need to preserve signed zeros, as
                 pow (-0, 0.5) is +0, while sqrt(-0) is -0.  */
-             || (!HONOR_SIGNED_ZEROS (mode) && n == 1)
-             /* For c == 1.5 we can assume that x * sqrt (x) is always
-                smaller than pow (x, 1.5) if sqrt will not be expanded
-                as a call.  */
-             || (n == 3
-                 && (optab_handler (sqrt_optab, mode)->insn_code
-                     != CODE_FOR_nothing))))
+             || (!HONOR_SIGNED_ZEROS (mode) && n == 1)))
        {
          tree call_expr = build_call_nofold (fn, 1, narg0);
          /* Use expand_expr in case the newly built call expression
@@ -3106,13 +3006,6 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget)
        }
     }
 
-  /* Check whether we can do a series of sqrt or cbrt's instead of the pow
-     call.  */
-  op = expand_builtin_pow_root (EXPR_LOCATION (exp), arg0, arg1, type,
-                               subtarget);
-  if (op)
-    return op;
-
   /* Try if the exponent is a third of an integer.  In this case
      we can expand to x**(n/3) * cbrt(x)**(n%3).  As cbrt (x) is
      different from pow (x, 1./3.) due to rounding and behavior
@@ -5279,6 +5172,7 @@ expand_builtin_signbit (tree exp, rtx target)
 {
   const struct real_format *fmt;
   enum machine_mode fmode, imode, rmode;
+  HOST_WIDE_INT hi, lo;
   tree arg;
   int word, bitpos;
   enum insn_code icode;
@@ -5303,11 +5197,9 @@ expand_builtin_signbit (tree exp, rtx target)
   icode = signbit_optab->handlers [(int) fmode].insn_code;
   if (icode != CODE_FOR_nothing)
     {
-      rtx last = get_last_insn ();
       target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));
-      if (maybe_emit_unop_insn (icode, target, temp, UNKNOWN))
-       return target;
-      delete_insns_since (last);
+      emit_unop_insn (icode, target, temp, UNKNOWN);
+      return target;
     }
 
   /* For floating point formats without a sign bit, implement signbit
@@ -5354,12 +5246,21 @@ expand_builtin_signbit (tree exp, rtx target)
 
   if (bitpos < GET_MODE_BITSIZE (rmode))
     {
-      double_int mask = double_int_setbit (double_int_zero, bitpos);
+      if (bitpos < HOST_BITS_PER_WIDE_INT)
+       {
+         hi = 0;
+         lo = (HOST_WIDE_INT) 1 << bitpos;
+       }
+      else
+       {
+         hi = (HOST_WIDE_INT) 1 << (bitpos - HOST_BITS_PER_WIDE_INT);
+         lo = 0;
+       }
 
       if (GET_MODE_SIZE (imode) > GET_MODE_SIZE (rmode))
        temp = gen_lowpart (rmode, temp);
       temp = expand_binop (rmode, and_optab, temp,
-                          immed_double_int_const (mask, rmode),
+                          immed_double_const (lo, hi, rmode),
                           NULL_RTX, 1, OPTAB_LIB_WIDEN);
     }
   else
@@ -7042,77 +6943,6 @@ fold_builtin_cabs (location_t loc, tree arg, tree type, tree fndecl)
   return NULL_TREE;
 }
 
-/* Build a complex (inf +- 0i) for the result of cproj.  TYPE is the
-   complex tree type of the result.  If NEG is true, the imaginary
-   zero is negative.  */
-
-static tree
-build_complex_cproj (tree type, bool neg)
-{
-  REAL_VALUE_TYPE rinf, rzero = dconst0;
-  
-  real_inf (&rinf);
-  rzero.sign = neg;
-  return build_complex (type, build_real (TREE_TYPE (type), rinf),
-                       build_real (TREE_TYPE (type), rzero));
-}
-
-/* Fold call to builtin cproj, cprojf or cprojl with argument ARG.  TYPE is the
-   return type.  Return NULL_TREE if no simplification can be made.  */
-
-static tree
-fold_builtin_cproj (location_t loc, tree arg, tree type)
-{
-  if (!validate_arg (arg, COMPLEX_TYPE)
-      || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
-    return NULL_TREE;
-
-  /* If there are no infinities, return arg.  */
-  if (! HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (type))))
-    return non_lvalue_loc (loc, arg);
-
-  /* Calculate the result when the argument is a constant.  */
-  if (TREE_CODE (arg) == COMPLEX_CST)
-    {
-      const REAL_VALUE_TYPE *real = TREE_REAL_CST_PTR (TREE_REALPART (arg));
-      const REAL_VALUE_TYPE *imag = TREE_REAL_CST_PTR (TREE_IMAGPART (arg));
-      
-      if (real_isinf (real) || real_isinf (imag))
-       return build_complex_cproj (type, imag->sign);
-      else
-       return arg;
-    }
-  else if (TREE_CODE (arg) == COMPLEX_EXPR)
-    {
-      tree real = TREE_OPERAND (arg, 0);
-      tree imag = TREE_OPERAND (arg, 1);
-
-      STRIP_NOPS (real);
-      STRIP_NOPS (imag);
-      
-      /* If the real part is inf and the imag part is known to be
-        nonnegative, return (inf + 0i).  Remember side-effects are
-        possible in the imag part.  */
-      if (TREE_CODE (real) == REAL_CST
-         && real_isinf (TREE_REAL_CST_PTR (real))
-         && tree_expr_nonnegative_p (imag))
-       return omit_one_operand_loc (loc, type,
-                                    build_complex_cproj (type, false),
-                                    arg);
-      
-      /* If the imag part is inf, return (inf+I*copysign(0,imag)).
-        Remember side-effects are possible in the real part.  */
-      if (TREE_CODE (imag) == REAL_CST
-         && real_isinf (TREE_REAL_CST_PTR (imag)))
-       return
-         omit_one_operand_loc (loc, type,
-                               build_complex_cproj (type, TREE_REAL_CST_PTR
-                                                    (imag)->sign), arg);
-    }
-
-  return NULL_TREE;
-}
-
 /* Fold a builtin function call to sqrt, sqrtf, or sqrtl with argument ARG.
    Return NULL_TREE if no simplification can be made.  */
 
@@ -9817,6 +9647,7 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
   enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
   switch (fcode)
     {
+
     case BUILT_IN_CONSTANT_P:
       {
        tree val = fold_builtin_constant_p (arg0);
@@ -9869,9 +9700,6 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
     CASE_FLT_FN (BUILT_IN_CCOSH):
       return fold_builtin_ccos(loc, arg0, type, fndecl, /*hyper=*/ true);
 
-    CASE_FLT_FN (BUILT_IN_CPROJ):
-      return fold_builtin_cproj(loc, arg0, type);
-
     CASE_FLT_FN (BUILT_IN_CSIN):
       if (validate_arg (arg0, COMPLEX_TYPE)
          && TREE_CODE (TREE_TYPE (TREE_TYPE (arg0))) == REAL_TYPE)
@@ -10198,11 +10026,6 @@ fold_builtin_1 (location_t loc, tree fndecl, tree arg0, bool ignore)
     case BUILT_IN_VPRINTF:
       return fold_builtin_printf (loc, fndecl, arg0, NULL_TREE, ignore, fcode);
 
-    case BUILT_IN_FREE:
-      if (integer_zerop (arg0))
-       return build_empty_stmt (loc);
-      break;
-
     default:
       break;
     }
@@ -10701,9 +10524,9 @@ fold_call_expr (location_t loc, tree exp, bool ignore)
       if (avoid_folding_inline_builtin (fndecl))
        return NULL_TREE;
 
+      /* FIXME: Don't use a list in this interface.  */
       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
-        return targetm.fold_builtin (fndecl, call_expr_nargs (exp),
-                                    CALL_EXPR_ARGP (exp), ignore);
+         return targetm.fold_builtin (fndecl, CALL_EXPR_ARGS (exp), ignore);
       else
        {
          if (nargs <= MAX_ARGS_TO_FOLD_BUILTIN)
@@ -10767,6 +10590,7 @@ fold_builtin_call_array (location_t loc, tree type,
                         tree *argarray)
 {
   tree ret = NULL_TREE;
+  int i;
    tree exp;
 
   if (TREE_CODE (fn) == ADDR_EXPR)
@@ -10790,10 +10614,12 @@ fold_builtin_call_array (location_t loc, tree type,
          return build_call_array_loc (loc, type, fn, n, argarray);
         if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
           {
-           ret = targetm.fold_builtin (fndecl, n, argarray, false);
-           if (ret)
-             return ret;
-
+            tree arglist = NULL_TREE;
+           for (i = n - 1; i >= 0; i--)
+             arglist = tree_cons (NULL_TREE, argarray[i], arglist);
+            ret = targetm.fold_builtin (fndecl, arglist, false);
+            if (ret)
+              return ret;
            return build_call_array_loc (loc, type, fn, n, argarray);
           }
         else if (n <= MAX_ARGS_TO_FOLD_BUILTIN)
@@ -13696,12 +13522,14 @@ fold_call_stmt (gimple stmt, bool ignore)
 
       if (avoid_folding_inline_builtin (fndecl))
        return NULL_TREE;
+      /* FIXME: Don't use a list in this interface.  */
       if (DECL_BUILT_IN_CLASS (fndecl) == BUILT_IN_MD)
         {
-         return targetm.fold_builtin (fndecl, nargs,
-                                      (nargs > 0
-                                       ? gimple_call_arg_ptr (stmt, 0)
-                                       : &error_mark_node), ignore);
+          tree arglist = NULL_TREE;
+          int i;
+          for (i = nargs - 1; i >= 0; i--)
+            arglist = tree_cons (NULL_TREE, gimple_call_arg (stmt, i), arglist);
+         return targetm.fold_builtin (fndecl, arglist, ignore);
         }
       else
        {
index 4b69cb7..4a0ef16 100644 (file)
@@ -1,3 +1,8 @@
+2010-03-18  Michael Matz  <matz@suse.de>
+
+       PR middle-end/43419
+       * gcc.dg/pr43419.c: New testcase.
+
 2010-03-18  H.J. Lu  <hongjiu.lu@intel.com>
 
        PR rtl-optimization/43360
 2010-03-17  Jerry DeLisle  <jvdelisle@gcc.gnu.org>
 
        PR libfortran/43265
-       *gfortran.dg/read_empty_file.f: New test.
-       *gfortran.dg/read_eof_all.f90: New test.
-       *gfortran.dg/namelist_27.f90: Eliminate infinite loop posibility.
-       *gfortran.dg/namelist_28.f90: Eliminate infinite loop posibility.
+       * gfortran.dg/read_empty_file.f: New test.
+       * gfortran.dg/read_eof_all.f90: New test.
+       * gfortran.dg/namelist_27.f90: Eliminate infinite loop posibility.
+       * gfortran.dg/namelist_28.f90: Eliminate infinite loop posibility.
 
 2010-03-17  Michael Matz  <matz@suse.de>