Patchwork [middle,end] : Introduce BUILT_IN_I{CEIL_FLOOR_ROUND_RINT} FP-to-int conversion functions

login
register
mail settings
Submitter Uros Bizjak
Date Aug. 11, 2011, 12:34 p.m.
Message ID <CAFULd4Ztp32x0cD-WhFi=tsxteHqH1pPT86_VdnZNK91y=5mRQ@mail.gmail.com>
Download mbox | patch
Permalink /patch/109607/
State New
Headers show

Comments

Uros Bizjak - Aug. 11, 2011, 12:34 p.m.
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  <ubizjak@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.
Richard Guenther - Aug. 11, 2011, 12:50 p.m.
On Thu, 11 Aug 2011, Uros Bizjak wrote:

> 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

Please document those in doc/extend.texi and make sure they do not
leak into the global namespace as ifloor, etc., but are only available
as __builtin_ifloor, etc..  Please also add at least a testcase
that excercises expanding all of the variants - like by simply
writing wrappers with the non-__builtin_ name variant like

int ifloor (double f) { return __builtin_ifloor (f); }
int main () {}

all variants should link correctly.

I'm not sure about the naming - shouldn't we name those internal
builtins after the mode, thus sifloor or even SIfloor?  Is there
precedent for the 'i' prefix?

Thanks,
Richard.

> 2011-08-11  Uros Bizjak  <ubizjak@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.
>
Uros Bizjak - Aug. 11, 2011, 8:40 p.m.
On Thu, Aug 11, 2011 at 2:50 PM, Richard Guenther <rguenther@suse.de> wrote:

>> 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.

> I'm not sure about the naming - shouldn't we name those internal
> builtins after the mode, thus sifloor or even SIfloor?  Is there
> precedent for the 'i' prefix?

I have taken precedent from ilogb conversion function that converts to
"int". This function also has its non-converting counterpart, logb.
IMO, this naming also fits in a general scheme where a prefix
encodes output type. So, "l" corresponds to "long", "ll" to "long
long" and from this sequence, and taking ilogb name into account, most
logical choice would be "i" for "int".

I will prepare a new patch with a documentation and requested tests tomorrow.

Thanks,
Uros.
Uros Bizjak - Aug. 12, 2011, 10:05 a.m.
On Thu, Aug 11, 2011 at 2:50 PM, Richard Guenther <rguenther@suse.de> wrote:

>> 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.

> Please document those in doc/extend.texi and make sure they do not
> leak into the global namespace as ifloor, etc., but are only available
> as __builtin_ifloor, etc..  Please also add at least a testcase
> that excercises expanding all of the variants - like by simply
> writing wrappers with the non-__builtin_ name variant like

Regarding the documentation, I found this in the @section Other
built-in functions provided by GCC:

<quote>

GCC provides a large number of built-in functions other than the ones
mentioned above.  Some of these are for internal use in the processing
of exceptions or variable-length argument lists and will not be
documented here because they may change from time to time; we do not
recommend general use of these functions.

The remaining functions are provided for optimization purposes.

</quote>

These new functions definitely fall under this category, and for the
same reason we didn't document lceil/lfloor builtins. They are used
internally for optimization purposes and the same functionality can be
achieved by simply writing (int) ceil (...).

Uros.
Richard Guenther - Aug. 12, 2011, 10:14 a.m.
On Fri, 12 Aug 2011, Uros Bizjak wrote:

> On Thu, Aug 11, 2011 at 2:50 PM, Richard Guenther <rguenther@suse.de> wrote:
> 
> >> 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.
> 
> > Please document those in doc/extend.texi and make sure they do not
> > leak into the global namespace as ifloor, etc., but are only available
> > as __builtin_ifloor, etc..  Please also add at least a testcase
> > that excercises expanding all of the variants - like by simply
> > writing wrappers with the non-__builtin_ name variant like
> 
> Regarding the documentation, I found this in the @section Other
> built-in functions provided by GCC:
> 
> <quote>
> 
> GCC provides a large number of built-in functions other than the ones
> mentioned above.  Some of these are for internal use in the processing
> of exceptions or variable-length argument lists and will not be
> documented here because they may change from time to time; we do not
> recommend general use of these functions.
> 
> The remaining functions are provided for optimization purposes.
> 
> </quote>
> 
> These new functions definitely fall under this category, and for the
> same reason we didn't document lceil/lfloor builtins. They are used
> internally for optimization purposes and the same functionality can be
> achieved by simply writing (int) ceil (...).

Hmm, I see.  It's unfortunate that we have no place to document
their semantics though, even if just internal (for lceil we have
the named pattern docs in md.texi).  Now, our internal documentation
is in a sorry enough state to not bother trying to add a new section
about internal builtins somewhere ... (?)  I'd add it to gimple.texi
in a new section 'Internal builtin functions'.

Richard.

Patch

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))