On Fri, Oct 23, 2015 at 11:47 AM, Richard Sandiford
<richard.sandif...@arm.com> wrote:
> Tested on x86_64-linux-gnu, aarch64-linux-gnu and arm-linux-gnueabi.
> OK to install?

Ok.

Thanks,
Richard.

> Thanks,
> Richard
>
>
> gcc/
>         * builtins.c (do_real_to_int_conversion): New function.
>         (fold_fixed_mathfn, fold_builtin_int_roundingfn): Delete.
>         (fold_builtin_1): Handle constant {i,l,ll}{ceil,floor,round}{f,,l}
>         arguments here.
>         * match.pd: Add rules previously handled by fold_fixed_mathfn
>         and fold_builtin_int_roundingfn.
>
> gcc/testsuite/
>         * gcc.dg/torture/builtin-minmax-1.c: Don't run at -O0.
>
> diff --git a/gcc/builtins.c b/gcc/builtins.c
> index c70bbfd..f947f1e 100644
> --- a/gcc/builtins.c
> +++ b/gcc/builtins.c
> @@ -158,7 +158,6 @@ static rtx expand_builtin_fabs (tree, rtx, rtx);
>  static rtx expand_builtin_signbit (tree, rtx);
>  static tree fold_builtin_pow (location_t, tree, tree, tree, tree);
>  static tree fold_builtin_powi (location_t, tree, tree, tree, tree);
> -static tree fold_builtin_int_roundingfn (location_t, tree, tree);
>  static tree fold_builtin_bitop (tree, tree);
>  static tree fold_builtin_strchr (location_t, tree, tree, tree);
>  static tree fold_builtin_memchr (location_t, tree, tree, tree, tree);
> @@ -7273,6 +7272,35 @@ fold_builtin_strlen (location_t loc, tree type, tree 
> arg)
>      }
>  }
>
> +/* If ARG is a foldable constant real, use FN to round it to an integer
> +   value and try to represent the result in integer type ITYPE.  Return
> +   the value on success, otherwise return null.  */
> +
> +static tree
> +do_real_to_int_conversion (tree itype, tree arg,
> +                          void (*fn) (REAL_VALUE_TYPE *, machine_mode,
> +                                      const REAL_VALUE_TYPE *))
> +{
> +  if (TREE_CODE (arg) != REAL_CST || TREE_OVERFLOW (arg))
> +    return NULL_TREE;
> +
> +  const REAL_VALUE_TYPE *value = TREE_REAL_CST_PTR (arg);
> +  if (!real_isfinite (value))
> +    return NULL_TREE;
> +
> +  tree ftype = TREE_TYPE (arg);
> +  REAL_VALUE_TYPE rounded;
> +  fn (&rounded, TYPE_MODE (ftype), value);
> +
> +  bool fail = false;
> +  wide_int ival = real_to_integer (&rounded, &fail, TYPE_PRECISION (itype));
> +  if (fail)
> +    return NULL_TREE;
> +
> +  return wide_int_to_tree (itype, ival);
> +}
> +
> +
>  /* Fold a call to __builtin_inf or __builtin_huge_val.  */
>
>  static tree
> @@ -7314,112 +7342,6 @@ fold_builtin_nan (tree arg, tree type, int quiet)
>    return build_real (type, real);
>  }
>
> -/* FNDECL is assumed to be builtin which can narrow the FP type of
> -   the argument, for instance lround((double)f) -> lroundf (f).
> -   Do the transformation for a call with argument ARG.  */
> -
> -static tree
> -fold_fixed_mathfn (location_t loc, tree fndecl, tree arg)
> -{
> -  enum built_in_function fcode = DECL_FUNCTION_CODE (fndecl);
> -
> -  if (!validate_arg (arg, REAL_TYPE))
> -    return NULL_TREE;
> -
> -  /* If argument is already integer valued, and we don't need to worry
> -     about setting errno, there's no need to perform rounding.  */
> -  if (! flag_errno_math && integer_valued_real_p (arg))
> -    return fold_build1_loc (loc, FIX_TRUNC_EXPR,
> -                       TREE_TYPE (TREE_TYPE (fndecl)), arg);
> -
> -  if (optimize)
> -    {
> -      tree ftype = TREE_TYPE (arg);
> -      tree arg0 = strip_float_extensions (arg);
> -      tree newtype = TREE_TYPE (arg0);
> -      tree decl;
> -
> -      if (TYPE_PRECISION (newtype) < TYPE_PRECISION (ftype)
> -         && (decl = mathfn_built_in (newtype, fcode)))
> -       return build_call_expr_loc (loc, decl, 1,
> -                               fold_convert_loc (loc, newtype, arg0));
> -    }
> -
> -  /* Canonicalize iround (x) to lround (x) on ILP32 targets where
> -     sizeof (int) == sizeof (long).  */
> -  if (TYPE_PRECISION (integer_type_node)
> -      == TYPE_PRECISION (long_integer_type_node))
> -    {
> -      tree newfn = NULL_TREE;
> -      switch (fcode)
> -       {
> -       CASE_FLT_FN (BUILT_IN_ICEIL):
> -         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
> -         break;
> -
> -       CASE_FLT_FN (BUILT_IN_IFLOOR):
> -         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
> -         break;
> -
> -       CASE_FLT_FN (BUILT_IN_IROUND):
> -         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
> -         break;
> -
> -       CASE_FLT_FN (BUILT_IN_IRINT):
> -         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
> -         break;
> -
> -       default:
> -         break;
> -       }
> -
> -      if (newfn)
> -       {
> -         tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
> -         return fold_convert_loc (loc,
> -                                  TREE_TYPE (TREE_TYPE (fndecl)), newcall);
> -       }
> -    }
> -
> -  /* Canonicalize llround (x) to lround (x) on LP64 targets where
> -     sizeof (long long) == sizeof (long).  */
> -  if (TYPE_PRECISION (long_long_integer_type_node)
> -      == TYPE_PRECISION (long_integer_type_node))
> -    {
> -      tree newfn = NULL_TREE;
> -      switch (fcode)
> -       {
> -       CASE_FLT_FN (BUILT_IN_LLCEIL):
> -         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LCEIL);
> -         break;
> -
> -       CASE_FLT_FN (BUILT_IN_LLFLOOR):
> -         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LFLOOR);
> -         break;
> -
> -       CASE_FLT_FN (BUILT_IN_LLROUND):
> -         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LROUND);
> -         break;
> -
> -       CASE_FLT_FN (BUILT_IN_LLRINT):
> -         newfn = mathfn_built_in (TREE_TYPE (arg), BUILT_IN_LRINT);
> -         break;
> -
> -       default:
> -         break;
> -       }
> -
> -      if (newfn)
> -       {
> -         tree newcall = build_call_expr_loc (loc, newfn, 1, arg);
> -         return fold_convert_loc (loc,
> -                                  TREE_TYPE (TREE_TYPE (fndecl)), newcall);
> -       }
> -    }
> -
> -  return NULL_TREE;
> -}
> -
>  /* Fold function call to builtin sincos, sincosf, or sincosl.  Return
>     NULL_TREE if no simplification can be made.  */
>
> @@ -7460,74 +7382,6 @@ fold_builtin_sincos (location_t loc,
>                          build1 (REALPART_EXPR, type, call)));
>  }
>
> -/* Fold function call to builtin lround, lroundf or lroundl (or the
> -   corresponding long long versions) and other rounding functions.  ARG
> -   is the argument to the call.  Return NULL_TREE if no simplification
> -   can be made.  */
> -
> -static tree
> -fold_builtin_int_roundingfn (location_t loc, tree fndecl, tree arg)
> -{
> -  if (!validate_arg (arg, REAL_TYPE))
> -    return NULL_TREE;
> -
> -  /* Optimize lround of constant value.  */
> -  if (TREE_CODE (arg) == REAL_CST && !TREE_OVERFLOW (arg))
> -    {
> -      const REAL_VALUE_TYPE x = TREE_REAL_CST (arg);
> -
> -      if (real_isfinite (&x))
> -       {
> -         tree itype = TREE_TYPE (TREE_TYPE (fndecl));
> -         tree ftype = TREE_TYPE (arg);
> -         REAL_VALUE_TYPE r;
> -         bool fail = false;
> -
> -         switch (DECL_FUNCTION_CODE (fndecl))
> -           {
> -           CASE_FLT_FN (BUILT_IN_IFLOOR):
> -           CASE_FLT_FN (BUILT_IN_LFLOOR):
> -           CASE_FLT_FN (BUILT_IN_LLFLOOR):
> -             real_floor (&r, TYPE_MODE (ftype), &x);
> -             break;
> -
> -           CASE_FLT_FN (BUILT_IN_ICEIL):
> -           CASE_FLT_FN (BUILT_IN_LCEIL):
> -           CASE_FLT_FN (BUILT_IN_LLCEIL):
> -             real_ceil (&r, TYPE_MODE (ftype), &x);
> -             break;
> -
> -           CASE_FLT_FN (BUILT_IN_IROUND):
> -           CASE_FLT_FN (BUILT_IN_LROUND):
> -           CASE_FLT_FN (BUILT_IN_LLROUND):
> -             real_round (&r, TYPE_MODE (ftype), &x);
> -             break;
> -
> -           default:
> -             gcc_unreachable ();
> -           }
> -
> -         wide_int val = real_to_integer (&r, &fail, TYPE_PRECISION (itype));
> -         if (!fail)
> -           return wide_int_to_tree (itype, val);
> -       }
> -    }
> -
> -  switch (DECL_FUNCTION_CODE (fndecl))
> -    {
> -    CASE_FLT_FN (BUILT_IN_LFLOOR):
> -    CASE_FLT_FN (BUILT_IN_LLFLOOR):
> -      /* Fold lfloor (x) where x is nonnegative to FIX_TRUNC (x).  */
> -      if (tree_expr_nonnegative_p (arg))
> -       return fold_build1_loc (loc, FIX_TRUNC_EXPR,
> -                           TREE_TYPE (TREE_TYPE (fndecl)), arg);
> -      break;
> -    default:;
> -    }
> -
> -  return fold_fixed_mathfn (loc, fndecl, arg);
> -}
> -
>  /* Fold function call to builtin ffs, clz, ctz, popcount and parity
>     and their long and long long variants (i.e. ffsl and ffsll).  ARG is
>     the argument to the call.  Return NULL_TREE if no simplification can
> @@ -9453,18 +9307,23 @@ fold_builtin_1 (location_t loc, tree fndecl, tree 
> arg0)
>      CASE_FLT_FN (BUILT_IN_ICEIL):
>      CASE_FLT_FN (BUILT_IN_LCEIL):
>      CASE_FLT_FN (BUILT_IN_LLCEIL):
> +      return do_real_to_int_conversion (type, arg0, real_ceil);
> +
>      CASE_FLT_FN (BUILT_IN_LFLOOR):
>      CASE_FLT_FN (BUILT_IN_IFLOOR):
>      CASE_FLT_FN (BUILT_IN_LLFLOOR):
> +      return do_real_to_int_conversion (type, arg0, real_floor);
> +
>      CASE_FLT_FN (BUILT_IN_IROUND):
>      CASE_FLT_FN (BUILT_IN_LROUND):
>      CASE_FLT_FN (BUILT_IN_LLROUND):
> -      return fold_builtin_int_roundingfn (loc, fndecl, arg0);
> +      return do_real_to_int_conversion (type, arg0, real_round);
>
>      CASE_FLT_FN (BUILT_IN_IRINT):
>      CASE_FLT_FN (BUILT_IN_LRINT):
>      CASE_FLT_FN (BUILT_IN_LLRINT):
> -      return fold_fixed_mathfn (loc, fndecl, arg0);
> +      /* Not yet folded to a constant.  */
> +      return NULL_TREE;
>
>      case BUILT_IN_BSWAP16:
>      case BUILT_IN_BSWAP32:
> diff --git a/gcc/match.pd b/gcc/match.pd
> index f7a1fee..78725cd 100644
> --- a/gcc/match.pd
> +++ b/gcc/match.pd
> @@ -52,6 +52,30 @@ along with GCC; see the file COPYING3.  If not see
>  #define DEFINE_MATH_FN(FN) \
>    (define_operator_list FN BUILT_IN_##FN##F BUILT_IN_##FN BUILT_IN_##FN##L)
>
> +/* Define operand lists for math rounding functions {,i,l,ll}FN,
> +   where the versions prefixed with "i" return an int, those prefixed with
> +   "l" return a long and those prefixed with "ll" return a long long.
> +
> +   Also define operand lists:
> +
> +     X<FN>F for all float functions, in the order i, l, ll
> +     X<FN> for all double functions, in the same order
> +     X<FN>L for all long double functions, in the same order.  */
> +#define DEFINE_INT_AND_FLOAT_ROUND_FN(FN) \
> +  DEFINE_MATH_FN (FN) \
> +  DEFINE_MATH_FN (I##FN) \
> +  DEFINE_MATH_FN (L##FN) \
> +  DEFINE_MATH_FN (LL##FN) \
> +  (define_operator_list X##FN##F BUILT_IN_I##FN##F \
> +                                BUILT_IN_L##FN##F \
> +                                BUILT_IN_LL##FN##F) \
> +  (define_operator_list X##FN BUILT_IN_I##FN \
> +                             BUILT_IN_L##FN \
> +                             BUILT_IN_LL##FN) \
> +  (define_operator_list X##FN##L BUILT_IN_I##FN##L \
> +                                BUILT_IN_L##FN##L \
> +                                BUILT_IN_LL##FN##L)
> +
>  DEFINE_MATH_FN (LOG)
>  DEFINE_MATH_FN (EXP)
>  DEFINE_MATH_FN (LOG2)
> @@ -76,11 +100,12 @@ DEFINE_MATH_FN (HYPOT)
>  DEFINE_MATH_FN (COPYSIGN)
>  DEFINE_MATH_FN (CABS)
>  DEFINE_MATH_FN (TRUNC)
> -DEFINE_MATH_FN (FLOOR)
> -DEFINE_MATH_FN (CEIL)
> -DEFINE_MATH_FN (ROUND)
>  DEFINE_MATH_FN (NEARBYINT)
> -DEFINE_MATH_FN (RINT)
> +
> +DEFINE_INT_AND_FLOAT_ROUND_FN (FLOOR)
> +DEFINE_INT_AND_FLOAT_ROUND_FN (CEIL)
> +DEFINE_INT_AND_FLOAT_ROUND_FN (ROUND)
> +DEFINE_INT_AND_FLOAT_ROUND_FN (RINT)
>
>  /* Simplifications of operations with one constant operand and
>     simplifications to constants or single values.  */
> @@ -2632,6 +2657,65 @@ DEFINE_MATH_FN (RINT)
>     (froms (convert float_value_p@0))
>     (convert (tos @0)))))
>
> +(for froms (XFLOORL XCEILL XROUNDL XRINTL)
> +     tos (XFLOOR XCEIL XROUND XRINT)
> + /* llfloorl(extend(x)) -> llfloor(x), etc., if x is a double.  */
> + (if (optimize && canonicalize_math_p ())
> +  (simplify
> +   (froms (convert double_value_p@0))
> +   (tos @0))))
> +
> +(for froms (XFLOORL XCEILL XROUNDL XRINTL
> +           XFLOOR XCEIL XROUND XRINT)
> +     tos (XFLOORF XCEILF XROUNDF XRINTF)
> + /* llfloorl(extend(x)) and llfloor(extend(x)) -> llfloorf(x), etc.,
> +    if x is a float.  */
> + (if (optimize && canonicalize_math_p ())
> +  (simplify
> +   (froms (convert float_value_p@0))
> +   (tos @0))))
> +
> +(if (canonicalize_math_p ())
> + /* xfloor(x) -> fix_trunc(x) if x is nonnegative.  */
> + (for floors (IFLOOR LFLOOR LLFLOOR)
> +  (simplify
> +   (floors tree_expr_nonnegative_p@0)
> +   (fix_trunc @0))))
> +
> +(if (canonicalize_math_p ())
> + /* xfloor(x) -> fix_trunc(x), etc., if x is integer valued.  */
> + (for fns (IFLOOR LFLOOR LLFLOOR
> +          ICEIL LCEIL LLCEIL
> +          IROUND LROUND LLROUND)
> +  (simplify
> +   (fns integer_valued_real_p@0)
> +   (fix_trunc @0)))
> + (if (!flag_errno_math)
> +  /* xrint(x) -> fix_trunc(x), etc., if x is integer valued.  */
> +  (for rints (IRINT LRINT LLRINT)
> +   (simplify
> +    (rints integer_valued_real_p@0)
> +    (fix_trunc @0)))))
> +
> +(if (canonicalize_math_p ())
> + (for ifn (IFLOOR ICEIL IROUND IRINT)
> +      lfn (LFLOOR LCEIL LROUND LRINT)
> +      llfn (LLFLOOR LLCEIL LLROUND LLRINT)
> +  /* Canonicalize iround (x) to lround (x) on ILP32 targets where
> +     sizeof (int) == sizeof (long).  */
> +  (if (TYPE_PRECISION (integer_type_node)
> +       == TYPE_PRECISION (long_integer_type_node))
> +   (simplify
> +    (ifn @0)
> +    (lfn:long_integer_type_node @0)))
> +  /* Canonicalize llround (x) to lround (x) on LP64 targets where
> +     sizeof (long long) == sizeof (long).  */
> +  (if (TYPE_PRECISION (long_long_integer_type_node)
> +       == TYPE_PRECISION (long_integer_type_node))
> +   (simplify
> +    (llfn @0)
> +    (lfn:long_integer_type_node @0)))))
> +
>  /* cproj(x) -> x if we're ignoring infinities.  */
>  (simplify
>   (CPROJ @0)
> diff --git a/gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c 
> b/gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c
> index 13831ad..a7c05b6 100644
> --- a/gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c
> +++ b/gcc/testsuite/gcc.dg/torture/builtin-minmax-1.c
> @@ -7,6 +7,7 @@
>
>  /* { dg-do link } */
>  /* { dg-options "-fno-math-errno" } */
> +/* { dg-skip-if "" { *-*-* } { "-O0" } { "" } } */
>
>  /* All references to link_error should go away at compile-time.  */
>  extern void link_error(int);
>

Reply via email to