This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH/RFC] Fix PR19402, __builtin_powi[lf]
- From: Richard Guenther <rguenth at tat dot physik dot uni-tuebingen dot de>
- To: gcc-patches at gcc dot gnu dot org
- Date: Mon, 31 Jan 2005 14:12:51 +0100 (CET)
- Subject: [PATCH/RFC] Fix PR19402, __builtin_powi[lf]
Hi!
This is a first try to fix PR19402, provide a __builtin_powi[lf]
for integer exponents (to be used by libstdc++). I chose the
most simple approach (and in fact the only one I got working),
namely have the __builtin_powi[lf] in libgcc with exactly this
name. It seems to work with both constant and non-constant
integer powers.
Any suggestions on how to do it "right" wrt libgcc? I'm sure
I got the #ifdefery wrong there and maybe the machine modes.
And for sure I don't like the name.
The patch bootstrapped ok on i686-linux.
Suggestions?
Thanks,
Richard.
2005-01-31 Richard Guenther <richard.guenther@uni-tuebingen.de>
PR middle-end/19402
* builtins.def: New __builtin_powi[lf].
* builtins.c (mathfn_built_in): Handle BUILT_IN_POWI.
(expand_builtin_powi): New function.
(expand_builtin): Dispatch to expand_builtin_powi.
* libgcc2.h: Add prototypes for __builtin_powi[lf].
* libgcc2.c: Add __builtin_powi[lf] implementation.
* mklibgcc.in: Add __builtin_powi[lf] to lib2funcs.
* gcc.dg/pr19402-1.c: New testcase.
* gcc.dg/pr19402-2.c: likewise.
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.414
diff -u -c -3 -p -r1.414 builtins.c
*** builtins.c 24 Jan 2005 08:59:19 -0000 1.414
--- builtins.c 31 Jan 2005 12:54:01 -0000
*************** mathfn_built_in (tree type, enum built_i
*** 1563,1568 ****
--- 1563,1569 ----
CASE_MATHFN (BUILT_IN_NEXTAFTER)
CASE_MATHFN (BUILT_IN_NEXTTOWARD)
CASE_MATHFN (BUILT_IN_POW)
+ CASE_MATHFN (BUILT_IN_POWI)
CASE_MATHFN (BUILT_IN_POW10)
CASE_MATHFN (BUILT_IN_REMAINDER)
CASE_MATHFN (BUILT_IN_REMQUO)
*************** expand_builtin_pow (tree exp, rtx target
*** 2349,2354 ****
--- 2350,2399 ----
return expand_builtin_mathfn_2 (exp, target, subtarget);
}
+ /* Expand a call to the pow built-in mathematical function. Return 0 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
+ function; if convenient, the result should be placed in TARGET. */
+
+ static rtx
+ expand_builtin_powi (tree exp, rtx target ATTRIBUTE_UNUSED, rtx subtarget)
+ {
+ tree arglist = TREE_OPERAND (exp, 1);
+ tree arg0, arg1;
+
+ if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
+ return 0;
+
+ arg0 = TREE_VALUE (arglist);
+ arg1 = TREE_VALUE (TREE_CHAIN (arglist));
+
+ if (TREE_CODE (arg1) == INTEGER_CST
+ && ! TREE_CONSTANT_OVERFLOW (arg1))
+ {
+ HOST_WIDE_INT n;
+
+ n = TREE_INT_CST_LOW (arg1);
+
+ /* If the exponent is -1, 0, 1 or 2, then expand_powi is exact.
+ Otherwise, check the number of multiplications required.
+ Note that pow never sets errno for an integer exponent. */
+ if ((TREE_INT_CST_HIGH (arg1) == 0
+ || TREE_INT_CST_HIGH (arg1) == -1)
+ && ((n >= -1 && n <= 2)
+ || (flag_unsafe_math_optimizations
+ && ! optimize_size
+ && powi_cost (n) <= POWI_MAX_MULTS)))
+ {
+ enum machine_mode mode = TYPE_MODE (TREE_TYPE (exp));
+ rtx op = expand_expr (arg0, subtarget, VOIDmode, 0);
+ op = force_reg (mode, op);
+ return expand_powi (op, mode, n);
+ }
+ }
+
+ return NULL_RTX;
+ }
+
/* Expand expression EXP which is a call to the strlen builtin. Return 0
if we failed the caller should emit a normal call, otherwise
try to get the result in TARGET, if convenient. */
*************** expand_builtin (tree exp, rtx target, rt
*** 5155,5160 ****
--- 5200,5213 ----
return target;
break;
+ case BUILT_IN_POWI:
+ case BUILT_IN_POWIF:
+ case BUILT_IN_POWIL:
+ target = expand_builtin_powi (exp, target, subtarget);
+ if (target)
+ return target;
+ break;
+
case BUILT_IN_ATAN2:
case BUILT_IN_ATAN2F:
case BUILT_IN_ATAN2L:
Index: builtins.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.def,v
retrieving revision 1.92
diff -u -c -3 -p -r1.92 builtins.def
*** builtins.def 29 Sep 2004 09:06:49 -0000 1.92
--- builtins.def 31 Jan 2005 12:54:01 -0000
*************** DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10,
*** 306,311 ****
--- 306,314 ----
DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10F, "pow10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10L, "pow10l", BT_FN_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_C90RES_BUILTIN (BUILT_IN_POWF, "powf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
+ DEF_GCC_BUILTIN (BUILT_IN_POWI, "powi", BT_FN_DOUBLE_DOUBLE_INT, ATTR_MATHFN_FPROUNDING)
+ DEF_GCC_BUILTIN (BUILT_IN_POWIF, "powif", BT_FN_FLOAT_FLOAT_INT, ATTR_MATHFN_FPROUNDING)
+ DEF_GCC_BUILTIN (BUILT_IN_POWIL, "powil", BT_FN_LONGDOUBLE_LONGDOUBLE_INT, ATTR_MATHFN_FPROUNDING)
DEF_C99_C90RES_BUILTIN (BUILT_IN_POWL, "powl", BT_FN_LONGDOUBLE_LONGDOUBLE_LONGDOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_REMAINDER, "remainder", BT_FN_DOUBLE_DOUBLE_DOUBLE, ATTR_MATHFN_FPROUNDING_ERRNO)
DEF_C99_BUILTIN (BUILT_IN_REMAINDERF, "remainderf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
Index: libgcc2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc2.c,v
retrieving revision 1.179
diff -u -c -3 -p -r1.179 libgcc2.c
*** libgcc2.c 15 Dec 2004 12:30:24 -0000 1.179
--- libgcc2.c 31 Jan 2005 12:54:01 -0000
*************** __fixunssfSI (SFtype a)
*** 1465,1470 ****
--- 1465,1503 ----
}
#endif
+ /* Integer power helper used from __builtin_powi for non-constant
+ exponents. */
+
+ #define EXPAND_POWI_HELPER(name, mode) \
+ mode \
+ name (mode x, SItype m) \
+ { \
+ USItype n = m < 0 ? -m : m; \
+ mode y = n % 2 ? x : 1; \
+ while (n >>= 1) \
+ { \
+ x = x * x; \
+ if (n % 2) \
+ y = y * x; \
+ } \
+ return m < 0 ? (mode)1.0/y : y; \
+ }
+ #ifdef L_builtin_powif
+ EXPAND_POWI_HELPER(__builtin_powif, SFtype)
+ #endif
+ #ifdef L_builtin_powi
+ EXPAND_POWI_HELPER(__builtin_powi, DFtype)
+ #endif
+ #ifdef L_builtin_powil
+ #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80
+ EXPAND_POWI_HELPER(__builtin_powil, XFtype)
+ #endif
+ #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
+ EXPAND_POWI_HELPER(__builtin_powil, TFtype)
+ #endif
+ #endif
+ #undef EXPAND_POWI_HELPER
+
/* From here on down, the routines use normal data types. */
#define SItype bogus_type
Index: libgcc2.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc2.h,v
retrieving revision 1.33
diff -u -c -3 -p -r1.33 libgcc2.h
*** libgcc2.h 15 Dec 2004 12:30:27 -0000 1.33
--- libgcc2.h 31 Jan 2005 12:54:01 -0000
*************** extern UWtype __fixunsdfSI (DFtype);
*** 305,322 ****
--- 305,326 ----
extern UWtype __fixunssfSI (SFtype);
extern DWtype __fixunsdfDI (DFtype);
extern DWtype __fixunssfDI (SFtype);
+ extern SFtype __builtin_powif (SFtype, SItype);
+ extern DFtype __builtin_powi (DFtype, SItype);
#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80
extern DWtype __fixxfdi (XFtype);
extern DWtype __fixunsxfDI (XFtype);
extern XFtype __floatdixf (DWtype);
extern UWtype __fixunsxfSI (XFtype);
+ extern XFtype __builtin_powil (XFtype, SItype);
#endif
#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
extern DWtype __fixunstfDI (TFtype);
extern DWtype __fixtfdi (TFtype);
extern TFtype __floatditf (DWtype);
+ extern TFtype __builtin_powil (TFtype, SItype);
#endif
#endif /* BITS_PER_UNIT == 8 */
Index: mklibgcc.in
===================================================================
RCS file: /cvs/gcc/gcc/gcc/mklibgcc.in,v
retrieving revision 1.80
diff -u -c -3 -p -r1.80 mklibgcc.in
*** mklibgcc.in 15 Dec 2004 07:43:48 -0000 1.80
--- mklibgcc.in 31 Jan 2005 12:54:01 -0000
*************** lib2funcs='_muldi3 _negdi2 _lshrdi3 _ash
*** 61,67 ****
_enable_execute_stack _trampoline __main _absvsi2 _absvdi2 _addvsi3
_addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
_ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab
! _popcountsi2 _popcountdi2 _paritysi2 _paritydi2'
# Disable SHLIB_LINK if shared libgcc not enabled.
if [ "@enable_shared@" = "no" ]; then
--- 61,68 ----
_enable_execute_stack _trampoline __main _absvsi2 _absvdi2 _addvsi3
_addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
_ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab
! _popcountsi2 _popcountdi2 _paritysi2 _paritydi2 _builtin_powi
! _builtin_powif _builtin_powil'
# Disable SHLIB_LINK if shared libgcc not enabled.
if [ "@enable_shared@" = "no" ]; then
/* { dg-do compile } */
/* { dg-options "" } */
float test_powif(float x)
{
return __builtin_powif(x, -1)
+ __builtin_powif(x, 0)
+ __builtin_powif(x, 1)
+ __builtin_powif(x, 2);
}
double test_powi(double x)
{
return __builtin_powi(x, -1)
+ __builtin_powi(x, 0)
+ __builtin_powi(x, 1)
+ __builtin_powi(x, 2);
}
long double test_powil(long double x)
{
return __builtin_powil(x, -1)
+ __builtin_powil(x, 0)
+ __builtin_powil(x, 1)
+ __builtin_powil(x, 2);
}
/* { dg-final { scan-assembler-not "__builtin_" } } */
/* { dg-do run } */
void abort(void);
int main()
{
if (__builtin_powi(1.0, 5) != 1.0)
abort();
return 0;
}