Hello!

Currently, conversion from floating point to integer on 64bit targets
goes through DImode temporary, due to missing BUILT_IN_ICEIL (and
other) builtins that can convert directly from FP to integer.

Attached patch introduces these builtins and improves i.e.:

int
test (double a)
{
  return round (a);
}

using -ffast-math -O2 from:

        ...
        cvttsd2siq      %xmm1, %rax
        ret

to
        ...
        cvttsd2si       %xmm1, %eax
        ret

2011-08-11  Uros Bizjak  <ubiz...@gmail.com>

        * builtins.def (BUILT_IN_ICEIL{,F,L}, BUILT_IN_IFLOOR{,F,L},
        BUILT_IN_IRINT{,F,L}, BUILT_IN_IROUND{,F,L}: New builtin definitions.
        * convert.c (convert_to_integer): Convert to BUILT_IN_ICEIL,
        BUILT_IN_IFLOOR, BUILT_IN_IRINT or BUILT_INT_IROUND when converting
        to integer_type_node.
        * fold-const.c (tree_call_nonnegative_warnv_p): Handle BUILT_IN_ICEIL,
        BUILT_IN_IFLOOR, BUILT_IN_IRINT and BUILT_INT_IROUND.
        * builtins.c (expand_builtin_in): Ditto.
        (mathfn_built_in_1): Ditto.
        (expand_builtin_int_roundingfn): Handle BUILT_IN_ICEIL and
        BUILT_IN_IFLOOR.
        (expand_builtin_int_roundingfn_2): Handle BUILT_IN_IRINT and
        BUILT_IN_IROUND.
        (fold_fixed_mathfn): Canonicalize BUILT_IN_ICEIL, BUILTIN_IN_IFLOOR,
        BUILT_IN_IRINT and BUILT_IN_IROUND to BUILT_IN_LCEIL,
        BUILTIN_IN_LFLOOR, BUILT_IN_LRINT and BUILT_IN_LROUND on ILP32 targets.

Patch was bootstrapped and regression tested on x86_64-pc-linux-gnu {,-m32}.

OK for mainline?

Uros.
Index: gcc/builtins.c
===================================================================
--- gcc/builtins.c      (revision 177647)
+++ gcc/builtins.c      (working copy)
@@ -1837,7 +1837,11 @@ mathfn_built_in_1 (tree type, enum built_in_functi
       CASE_MATHFN (BUILT_IN_HUGE_VAL)
       CASE_MATHFN (BUILT_IN_HYPOT)
       CASE_MATHFN (BUILT_IN_ILOGB)
+      CASE_MATHFN (BUILT_IN_ICEIL)
+      CASE_MATHFN (BUILT_IN_IFLOOR)
       CASE_MATHFN (BUILT_IN_INF)
+      CASE_MATHFN (BUILT_IN_IRINT)
+      CASE_MATHFN (BUILT_IN_IROUND)
       CASE_MATHFN (BUILT_IN_ISINF)
       CASE_MATHFN (BUILT_IN_J0)
       CASE_MATHFN (BUILT_IN_J1)
@@ -2662,12 +2666,14 @@ expand_builtin_int_roundingfn (tree exp, rtx targe
 
   switch (DECL_FUNCTION_CODE (fndecl))
     {
+    CASE_FLT_FN (BUILT_IN_ICEIL):
     CASE_FLT_FN (BUILT_IN_LCEIL):
     CASE_FLT_FN (BUILT_IN_LLCEIL):
       builtin_optab = lceil_optab;
       fallback_fn = BUILT_IN_CEIL;
       break;
 
+    CASE_FLT_FN (BUILT_IN_IFLOOR):
     CASE_FLT_FN (BUILT_IN_LFLOOR):
     CASE_FLT_FN (BUILT_IN_LLFLOOR):
       builtin_optab = lfloor_optab;
@@ -2720,26 +2726,32 @@ expand_builtin_int_roundingfn (tree exp, rtx targe
 
       switch (DECL_FUNCTION_CODE (fndecl))
        {
+       case BUILT_IN_ICEIL:
        case BUILT_IN_LCEIL:
        case BUILT_IN_LLCEIL:
          name = "ceil";
          break;
+       case BUILT_IN_ICEILF:
        case BUILT_IN_LCEILF:
        case BUILT_IN_LLCEILF:
          name = "ceilf";
          break;
+       case BUILT_IN_ICEILL:
        case BUILT_IN_LCEILL:
        case BUILT_IN_LLCEILL:
          name = "ceill";
          break;
+       case BUILT_IN_IFLOOR:
        case BUILT_IN_LFLOOR:
        case BUILT_IN_LLFLOOR:
          name = "floor";
          break;
+       case BUILT_IN_IFLOORF:
        case BUILT_IN_LFLOORF:
        case BUILT_IN_LLFLOORF:
          name = "floorf";
          break;
+       case BUILT_IN_IFLOORL:
        case BUILT_IN_LFLOORL:
        case BUILT_IN_LLFLOORL:
          name = "floorl";
@@ -2791,12 +2803,16 @@ expand_builtin_int_roundingfn_2 (tree exp, rtx tar
 
   switch (DECL_FUNCTION_CODE (fndecl))
     {
+    CASE_FLT_FN (BUILT_IN_IRINT):
     CASE_FLT_FN (BUILT_IN_LRINT):
     CASE_FLT_FN (BUILT_IN_LLRINT):
       builtin_optab = lrint_optab; break;
+
+    CASE_FLT_FN (BUILT_IN_IROUND):
     CASE_FLT_FN (BUILT_IN_LROUND):
     CASE_FLT_FN (BUILT_IN_LLROUND):
       builtin_optab = lround_optab; break;
+
     default:
       gcc_unreachable ();
     }
@@ -5401,17 +5417,21 @@ expand_builtin (tree exp, rtx target, rtx subtarge
        return target;
       break;
 
+    CASE_FLT_FN (BUILT_IN_ICEIL):
     CASE_FLT_FN (BUILT_IN_LCEIL):
     CASE_FLT_FN (BUILT_IN_LLCEIL):
     CASE_FLT_FN (BUILT_IN_LFLOOR):
+    CASE_FLT_FN (BUILT_IN_IFLOOR):
     CASE_FLT_FN (BUILT_IN_LLFLOOR):
       target = expand_builtin_int_roundingfn (exp, target);
       if (target)
        return target;
       break;
 
+    CASE_FLT_FN (BUILT_IN_IRINT):
     CASE_FLT_FN (BUILT_IN_LRINT):
     CASE_FLT_FN (BUILT_IN_LLRINT):
+    CASE_FLT_FN (BUILT_IN_IROUND):
     CASE_FLT_FN (BUILT_IN_LROUND):
     CASE_FLT_FN (BUILT_IN_LLROUND):
       target = expand_builtin_int_roundingfn_2 (exp, target);
@@ -6521,6 +6541,42 @@ fold_fixed_mathfn (location_t loc, tree fndecl, tr
                                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)
@@ -7220,16 +7276,19 @@ fold_builtin_int_roundingfn (location_t loc, tree
 
          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);
@@ -9758,14 +9817,18 @@ fold_builtin_1 (location_t loc, tree fndecl, tree
     CASE_FLT_FN (BUILT_IN_RINT):
       return fold_trunc_transparent_mathfn (loc, fndecl, arg0);
 
+    CASE_FLT_FN (BUILT_IN_ICEIL):
     CASE_FLT_FN (BUILT_IN_LCEIL):
     CASE_FLT_FN (BUILT_IN_LLCEIL):
     CASE_FLT_FN (BUILT_IN_LFLOOR):
+    CASE_FLT_FN (BUILT_IN_IFLOOR):
     CASE_FLT_FN (BUILT_IN_LLFLOOR):
+    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);
 
+    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);
Index: gcc/fold-const.c
===================================================================
--- gcc/fold-const.c    (revision 177647)
+++ gcc/fold-const.c    (working copy)
@@ -14670,6 +14670,10 @@ tree_call_nonnegative_warnv_p (tree type, tree fnd
        CASE_FLT_FN (BUILT_IN_FLOOR):
        CASE_FLT_FN (BUILT_IN_FMOD):
        CASE_FLT_FN (BUILT_IN_FREXP):
+       CASE_FLT_FN (BUILT_IN_ICEIL):
+       CASE_FLT_FN (BUILT_IN_IFLOOR):
+       CASE_FLT_FN (BUILT_IN_IRINT):
+       CASE_FLT_FN (BUILT_IN_IROUND):
        CASE_FLT_FN (BUILT_IN_LCEIL):
        CASE_FLT_FN (BUILT_IN_LDEXP):
        CASE_FLT_FN (BUILT_IN_LFLOOR):
Index: gcc/builtins.def
===================================================================
--- gcc/builtins.def    (revision 177647)
+++ gcc/builtins.def    (working copy)
@@ -267,6 +267,12 @@ DEF_GCC_BUILTIN        (BUILT_IN_HUGE_VALL, "huge_
 DEF_C99_BUILTIN        (BUILT_IN_HYPOT, "hypot", BT_FN_DOUBLE_DOUBLE_DOUBLE, 
ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_HYPOTF, "hypotf", BT_FN_FLOAT_FLOAT_FLOAT, 
ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_HYPOTL, "hypotl", 
BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN        (BUILT_IN_ICEIL, "iceil", BT_FN_INT_DOUBLE, 
ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_ICEILF, "iceilf", BT_FN_INT_FLOAT, 
ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_ICEILL, "iceill", BT_FN_INT_LONGDOUBLE, 
ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_IFLOOR, "ifloor", BT_FN_INT_DOUBLE, 
ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_IFLOORF, "ifloorf", BT_FN_INT_FLOAT, 
ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_IFLOORL, "ifloorl", BT_FN_INT_LONGDOUBLE, 
ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_C99_BUILTIN        (BUILT_IN_ILOGB, "ilogb", BT_FN_INT_DOUBLE, 
ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_ILOGBF, "ilogbf", BT_FN_INT_FLOAT, 
ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_C99_BUILTIN        (BUILT_IN_ILOGBL, "ilogbl", BT_FN_INT_LONGDOUBLE, 
ATTR_MATHFN_FPROUNDING_ERRNO)
@@ -276,6 +282,12 @@ DEF_GCC_BUILTIN        (BUILT_IN_INFL, "infl", BT_
 DEF_GCC_BUILTIN               (BUILT_IN_INFD32, "infd32", BT_FN_DFLOAT32, 
ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_INFD64, "infd64", BT_FN_DFLOAT64, 
ATTR_CONST_NOTHROW_LEAF_LIST)
 DEF_GCC_BUILTIN        (BUILT_IN_INFD128, "infd128", BT_FN_DFLOAT128, 
ATTR_CONST_NOTHROW_LEAF_LIST)
+DEF_GCC_BUILTIN        (BUILT_IN_IRINT, "irint", BT_FN_INT_DOUBLE, 
ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN        (BUILT_IN_IRINTF, "irintf", BT_FN_INT_FLOAT, 
ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN        (BUILT_IN_IRINTL, "irintl", BT_FN_INT_LONGDOUBLE, 
ATTR_MATHFN_FPROUNDING_ERRNO)
+DEF_GCC_BUILTIN        (BUILT_IN_IROUND, "iround", BT_FN_INT_DOUBLE, 
ATTR_MATHFN_ERRNO)
+DEF_GCC_BUILTIN        (BUILT_IN_IROUNDF, "iroundf", BT_FN_INT_FLOAT, 
ATTR_MATHFN_ERRNO)
+DEF_GCC_BUILTIN        (BUILT_IN_IROUNDL, "iroundl", BT_FN_INT_LONGDOUBLE, 
ATTR_MATHFN_ERRNO)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_J0, "j0", BT_FN_DOUBLE_DOUBLE, 
ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_J0F, "j0f", BT_FN_FLOAT_FLOAT, 
ATTR_MATHFN_FPROUNDING_ERRNO)
 DEF_EXT_LIB_BUILTIN    (BUILT_IN_J0L, "j0l", BT_FN_LONGDOUBLE_LONGDOUBLE, 
ATTR_MATHFN_FPROUNDING_ERRNO)
Index: gcc/convert.c
===================================================================
--- gcc/convert.c       (revision 177647)
+++ gcc/convert.c       (working copy)
@@ -440,9 +440,12 @@ convert_to_integer (tree type, tree expr)
          /* Only convert in ISO C99 mode.  */
          if (!TARGET_C99_FUNCTIONS)
            break;
-         if (outprec < TYPE_PRECISION (long_integer_type_node)
-             || (outprec == TYPE_PRECISION (long_integer_type_node)
+         if (outprec < TYPE_PRECISION (integer_type_node)
+             || (outprec == TYPE_PRECISION (integer_type_node)
                  && !TYPE_UNSIGNED (type)))
+           fn = mathfn_built_in (s_intype, BUILT_IN_ICEIL);
+         else if (outprec == TYPE_PRECISION (long_integer_type_node)
+                  && !TYPE_UNSIGNED (type))
            fn = mathfn_built_in (s_intype, BUILT_IN_LCEIL);
          else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
                   && !TYPE_UNSIGNED (type))
@@ -453,9 +456,12 @@ convert_to_integer (tree type, tree expr)
          /* Only convert in ISO C99 mode.  */
          if (!TARGET_C99_FUNCTIONS)
            break;
-         if (outprec < TYPE_PRECISION (long_integer_type_node)
-             || (outprec == TYPE_PRECISION (long_integer_type_node)
+         if (outprec < TYPE_PRECISION (integer_type_node)
+             || (outprec == TYPE_PRECISION (integer_type_node)
                  && !TYPE_UNSIGNED (type)))
+           fn = mathfn_built_in (s_intype, BUILT_IN_IFLOOR);
+         else if (outprec == TYPE_PRECISION (long_integer_type_node)
+                  && !TYPE_UNSIGNED (type))
            fn = mathfn_built_in (s_intype, BUILT_IN_LFLOOR);
          else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
                   && !TYPE_UNSIGNED (type))
@@ -463,9 +469,12 @@ convert_to_integer (tree type, tree expr)
          break;
 
        CASE_FLT_FN (BUILT_IN_ROUND):
-         if (outprec < TYPE_PRECISION (long_integer_type_node)
-             || (outprec == TYPE_PRECISION (long_integer_type_node)
+         if (outprec < TYPE_PRECISION (integer_type_node)
+             || (outprec == TYPE_PRECISION (integer_type_node)
                  && !TYPE_UNSIGNED (type)))
+           fn = mathfn_built_in (s_intype, BUILT_IN_IROUND);
+         else if (outprec == TYPE_PRECISION (long_integer_type_node)
+                  && !TYPE_UNSIGNED (type))
            fn = mathfn_built_in (s_intype, BUILT_IN_LROUND);
          else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
                   && !TYPE_UNSIGNED (type))
@@ -478,9 +487,12 @@ convert_to_integer (tree type, tree expr)
            break;
          /* ... Fall through ...  */
        CASE_FLT_FN (BUILT_IN_RINT):
-         if (outprec < TYPE_PRECISION (long_integer_type_node)
-             || (outprec == TYPE_PRECISION (long_integer_type_node)
+         if (outprec < TYPE_PRECISION (integer_type_node)
+             || (outprec == TYPE_PRECISION (integer_type_node)
                  && !TYPE_UNSIGNED (type)))
+           fn = mathfn_built_in (s_intype, BUILT_IN_IRINT);
+         else if (outprec < TYPE_PRECISION (long_integer_type_node)
+                  && !TYPE_UNSIGNED (type))
            fn = mathfn_built_in (s_intype, BUILT_IN_LRINT);
          else if (outprec == TYPE_PRECISION (long_long_integer_type_node)
                   && !TYPE_UNSIGNED (type))

Reply via email to