Commit 17684d46 by Richard Guenther Committed by Richard Biener

re PR middle-end/19402 (__builtin_powi? still missing)

2005-02-09  Richard Guenther  <rguenth@gcc.gnu.org>

	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.
	* optabs.h: Add powi_optab.
	* optabs.c (init_optabs): Initialize powi_optab.
	* doc/extend.texi: Document __builtin_powi[lf].

	* gcc.dg/pr19402-1.c: New testcase.
	* gcc.dg/pr19402-2.c: likewise.

From-SVN: r94774
parent 8ca3515f
2005-02-09 Richard Guenther <rguenth@gcc.gnu.org>
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.
* optabs.h: Add powi_optab.
* optabs.c (init_optabs): Initialize powi_optab.
* doc/extend.texi: Document __builtin_powi[lf].
2005-02-09 Dorit Naishlos <dorit@il.ibm.com> 2005-02-09 Dorit Naishlos <dorit@il.ibm.com>
* tree-vectorizer.c (vect_set_dump_settings): Check that dump_file * tree-vectorizer.c (vect_set_dump_settings): Check that dump_file
......
...@@ -1563,6 +1563,7 @@ mathfn_built_in (tree type, enum built_in_function fn) ...@@ -1563,6 +1563,7 @@ mathfn_built_in (tree type, enum built_in_function fn)
CASE_MATHFN (BUILT_IN_NEXTAFTER) CASE_MATHFN (BUILT_IN_NEXTAFTER)
CASE_MATHFN (BUILT_IN_NEXTTOWARD) CASE_MATHFN (BUILT_IN_NEXTTOWARD)
CASE_MATHFN (BUILT_IN_POW) CASE_MATHFN (BUILT_IN_POW)
CASE_MATHFN (BUILT_IN_POWI)
CASE_MATHFN (BUILT_IN_POW10) CASE_MATHFN (BUILT_IN_POW10)
CASE_MATHFN (BUILT_IN_REMAINDER) CASE_MATHFN (BUILT_IN_REMAINDER)
CASE_MATHFN (BUILT_IN_REMQUO) CASE_MATHFN (BUILT_IN_REMQUO)
...@@ -2349,6 +2350,66 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget) ...@@ -2349,6 +2350,66 @@ expand_builtin_pow (tree exp, rtx target, rtx subtarget)
return expand_builtin_mathfn_2 (exp, target, subtarget); return expand_builtin_mathfn_2 (exp, target, subtarget);
} }
/* Expand a call to the powi 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, rtx subtarget)
{
tree arglist = TREE_OPERAND (exp, 1);
tree arg0, arg1;
rtx op0, op1;
enum machine_mode mode;
if (! validate_arglist (arglist, REAL_TYPE, INTEGER_TYPE, VOID_TYPE))
return 0;
arg0 = TREE_VALUE (arglist);
arg1 = TREE_VALUE (TREE_CHAIN (arglist));
mode = TYPE_MODE (TREE_TYPE (exp));
/* Handle constant power. */
if (TREE_CODE (arg1) == INTEGER_CST
&& ! TREE_CONSTANT_OVERFLOW (arg1))
{
HOST_WIDE_INT 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. */
if ((TREE_INT_CST_HIGH (arg1) == 0
|| TREE_INT_CST_HIGH (arg1) == -1)
&& ((n >= -1 && n <= 2)
|| (! optimize_size
&& powi_cost (n) <= POWI_MAX_MULTS)))
{
op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
op0 = force_reg (mode, op0);
return expand_powi (op0, mode, n);
}
}
/* Emit a libcall to libgcc. */
if (target == NULL_RTX)
target = gen_reg_rtx (mode);
op0 = expand_expr (arg0, subtarget, mode, 0);
if (GET_MODE (op0) != mode)
op0 = convert_to_mode (mode, op0, 0);
op1 = expand_expr (arg1, 0, word_mode, 0);
if (GET_MODE (op1) != word_mode)
op1 = convert_to_mode (word_mode, op1, 0);
target = emit_library_call_value (powi_optab->handlers[(int) mode].libfunc,
target, LCT_CONST_MAKE_BLOCK, mode, 2,
op0, mode, op1, word_mode);
return target;
}
/* Expand expression EXP which is a call to the strlen builtin. Return 0 /* Expand expression EXP which is a call to the strlen builtin. Return 0
if we failed the caller should emit a normal call, otherwise if we failed the caller should emit a normal call, otherwise
try to get the result in TARGET, if convenient. */ try to get the result in TARGET, if convenient. */
...@@ -5186,6 +5247,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode, ...@@ -5186,6 +5247,14 @@ expand_builtin (tree exp, rtx target, rtx subtarget, enum machine_mode mode,
return target; return target;
break; 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_ATAN2:
case BUILT_IN_ATAN2F: case BUILT_IN_ATAN2F:
case BUILT_IN_ATAN2L: case BUILT_IN_ATAN2L:
......
...@@ -306,6 +306,9 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10, "pow10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHF ...@@ -306,6 +306,9 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10, "pow10", BT_FN_DOUBLE_DOUBLE, ATTR_MATHF
DEF_EXT_LIB_BUILTIN (BUILT_IN_POW10F, "pow10f", BT_FN_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO) 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_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_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_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_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) DEF_C99_BUILTIN (BUILT_IN_REMAINDERF, "remainderf", BT_FN_FLOAT_FLOAT_FLOAT, ATTR_MATHFN_FPROUNDING_ERRNO)
......
...@@ -4507,6 +4507,9 @@ identifier, or a sequence of member accesses and array references. ...@@ -4507,6 +4507,9 @@ identifier, or a sequence of member accesses and array references.
@findex __builtin_islessequal @findex __builtin_islessequal
@findex __builtin_islessgreater @findex __builtin_islessgreater
@findex __builtin_isunordered @findex __builtin_isunordered
@findex __builtin_powi
@findex __builtin_powif
@findex __builtin_powil
@findex _Exit @findex _Exit
@findex _exit @findex _exit
@findex abort @findex abort
...@@ -5368,6 +5371,21 @@ Similar to @code{__builtin_parity}, except the argument type is ...@@ -5368,6 +5371,21 @@ Similar to @code{__builtin_parity}, except the argument type is
@code{unsigned long long}. @code{unsigned long long}.
@end deftypefn @end deftypefn
@deftypefn {Built-in Function} double __builtin_powi (double, int)
Returns the first argument raised to the power of the second. Unlike the
@code{pow} function no guarantees about precision and rounding are made.
@end deftypefn
@deftypefn {Built-in Function} float __builtin_powif (float, int)
Similar to @code{__builtin_powi}, except the argument and return types
are @code{float}.
@end deftypefn
@deftypefn {Built-in Function} {long double} __builtin_powil (long double, int)
Similar to @code{__builtin_powi}, except the argument and return types
are @code{long double}.
@end deftypefn
@node Target Builtins @node Target Builtins
@section Built-in Functions Specific to Particular Target Machines @section Built-in Functions Specific to Particular Target Machines
......
...@@ -233,3 +233,12 @@ GCC_3.4.4 { ...@@ -233,3 +233,12 @@ GCC_3.4.4 {
__negvti2 __negvti2
__subvti3 __subvti3
} }
%inherit GCC_4.0.0 GCC_3.4.4
GCC_4.0.0 {
# libgcc2 __builtin_powi helpers.
__powisf2
__powidf2
__powixf2
__powitf2
}
\ No newline at end of file
...@@ -1465,6 +1465,42 @@ __fixunssfSI (SFtype a) ...@@ -1465,6 +1465,42 @@ __fixunssfSI (SFtype a)
} }
#endif #endif
/* Integer power helper used from __builtin_powi for non-constant
exponents. */
#if defined(L_powisf2) || defined(L_powidf2) \
|| (defined(L_powixf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80) \
|| (defined(L_powitf2) && LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128)
# if defined(L_powisf2)
# define TYPE SFtype
# define NAME __powisf2
# elif defined(L_powidf2)
# define TYPE DFtype
# define NAME __powidf2
# elif defined(L_powixf2)
# define TYPE XFtype
# define NAME __powixf2
# elif defined(L_powitf2)
# define TYPE TFtype
# define NAME __powitf2
# endif
TYPE
NAME (TYPE x, Wtype m)
{
UWtype n = m < 0 ? -m : m;
TYPE y = n % 2 ? x : 1;
while (n >>= 1)
{
x = x * x;
if (n % 2)
y = y * x;
}
return m < 0 ? 1/y : y;
}
#endif
/* From here on down, the routines use normal data types. */ /* From here on down, the routines use normal data types. */
#define SItype bogus_type #define SItype bogus_type
......
...@@ -305,18 +305,22 @@ extern UWtype __fixunsdfSI (DFtype); ...@@ -305,18 +305,22 @@ extern UWtype __fixunsdfSI (DFtype);
extern UWtype __fixunssfSI (SFtype); extern UWtype __fixunssfSI (SFtype);
extern DWtype __fixunsdfDI (DFtype); extern DWtype __fixunsdfDI (DFtype);
extern DWtype __fixunssfDI (SFtype); extern DWtype __fixunssfDI (SFtype);
extern SFtype __powisf2 (SFtype, Wtype);
extern DFtype __powidf2 (DFtype, Wtype);
#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 80
extern DWtype __fixxfdi (XFtype); extern DWtype __fixxfdi (XFtype);
extern DWtype __fixunsxfDI (XFtype); extern DWtype __fixunsxfDI (XFtype);
extern XFtype __floatdixf (DWtype); extern XFtype __floatdixf (DWtype);
extern UWtype __fixunsxfSI (XFtype); extern UWtype __fixunsxfSI (XFtype);
extern XFtype __powixf2 (XFtype, Wtype);
#endif #endif
#if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128 #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
extern DWtype __fixunstfDI (TFtype); extern DWtype __fixunstfDI (TFtype);
extern DWtype __fixtfdi (TFtype); extern DWtype __fixtfdi (TFtype);
extern TFtype __floatditf (DWtype); extern TFtype __floatditf (DWtype);
extern TFtype __powitf2 (TFtype, Wtype);
#endif #endif
#endif /* BITS_PER_UNIT == 8 */ #endif /* BITS_PER_UNIT == 8 */
......
...@@ -61,7 +61,8 @@ lib2funcs='_muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3 ...@@ -61,7 +61,8 @@ lib2funcs='_muldi3 _negdi2 _lshrdi3 _ashldi3 _ashrdi3
_enable_execute_stack _trampoline __main _absvsi2 _absvdi2 _addvsi3 _enable_execute_stack _trampoline __main _absvsi2 _absvdi2 _addvsi3
_addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors _addvdi3 _subvsi3 _subvdi3 _mulvsi3 _mulvdi3 _negvsi2 _negvdi2 _ctors
_ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab _ffssi2 _ffsdi2 _clz _clzsi2 _clzdi2 _ctzsi2 _ctzdi2 _popcount_tab
_popcountsi2 _popcountdi2 _paritysi2 _paritydi2' _popcountsi2 _popcountdi2 _paritysi2 _paritydi2 _powisf2 _powidf2
_powixf2 _powitf2'
# Disable SHLIB_LINK if shared libgcc not enabled. # Disable SHLIB_LINK if shared libgcc not enabled.
if [ "@enable_shared@" = "no" ]; then if [ "@enable_shared@" = "no" ]; then
......
...@@ -5049,6 +5049,8 @@ init_optabs (void) ...@@ -5049,6 +5049,8 @@ init_optabs (void)
vec_realign_load_optab = init_optab (UNKNOWN); vec_realign_load_optab = init_optab (UNKNOWN);
movmisalign_optab = init_optab (UNKNOWN); movmisalign_optab = init_optab (UNKNOWN);
powi_optab = init_optab (UNKNOWN);
/* Conversions. */ /* Conversions. */
sext_optab = init_convert_optab (SIGN_EXTEND); sext_optab = init_convert_optab (SIGN_EXTEND);
zext_optab = init_convert_optab (ZERO_EXTEND); zext_optab = init_convert_optab (ZERO_EXTEND);
...@@ -5135,6 +5137,8 @@ init_optabs (void) ...@@ -5135,6 +5137,8 @@ init_optabs (void)
init_floating_libfuncs (le_optab, "le", '2'); init_floating_libfuncs (le_optab, "le", '2');
init_floating_libfuncs (unord_optab, "unord", '2'); init_floating_libfuncs (unord_optab, "unord", '2');
init_floating_libfuncs (powi_optab, "powi", '2');
/* Conversions. */ /* Conversions. */
init_interclass_conv_libfuncs (sfloat_optab, "float", init_interclass_conv_libfuncs (sfloat_optab, "float",
MODE_INT, MODE_FLOAT); MODE_INT, MODE_FLOAT);
......
...@@ -235,6 +235,9 @@ enum optab_index ...@@ -235,6 +235,9 @@ enum optab_index
/* Extract specified elements from vectors, for vector load. */ /* Extract specified elements from vectors, for vector load. */
OTI_vec_realign_load, OTI_vec_realign_load,
/* Perform a raise to the power of integer. */
OTI_powi,
OTI_MAX OTI_MAX
}; };
...@@ -340,6 +343,8 @@ extern GTY(()) optab optab_table[OTI_MAX]; ...@@ -340,6 +343,8 @@ extern GTY(()) optab optab_table[OTI_MAX];
#define vec_init_optab (optab_table[OTI_vec_init]) #define vec_init_optab (optab_table[OTI_vec_init])
#define vec_realign_load_optab (optab_table[OTI_vec_realign_load]) #define vec_realign_load_optab (optab_table[OTI_vec_realign_load])
#define powi_optab (optab_table[OTI_powi])
/* Conversion optabs have their own table and indexes. */ /* Conversion optabs have their own table and indexes. */
enum convert_optab_index enum convert_optab_index
{ {
......
2005-02-09 Richard Guenther <rguenth@gcc.gnu.org> 2005-02-09 Richard Guenther <rguenth@gcc.gnu.org>
PR middle-end/19402
* gcc.dg/pr19402-1.c: New testcase.
* gcc.dg/pr19402-2.c: likewise.
2005-02-09 Richard Guenther <rguenth@gcc.gnu.org>
PR middle-end/19854 PR middle-end/19854
* g++.dg/tree-ssa/tmmti.C: New testcase. * g++.dg/tree-ssa/tmmti.C: New testcase.
......
/* { 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 } */
/* { dg-options "-fno-inline -Os" } */
void abort(void);
float powif(float x, int n)
{
return __builtin_powif(x, n);
}
double powi(double x, int n)
{
return __builtin_powi(x, n);
}
long double powil(long double x, int n)
{
return __builtin_powil(x, n);
}
float powcif(float x)
{
return __builtin_powif(x, 5);
}
double powci(double x)
{
return __builtin_powi(x, 5);
}
long double powcil(long double x)
{
return __builtin_powil(x, 5);
}
float powicf(int n)
{
return __builtin_powif(2.0, n);
}
double powic(int n)
{
return __builtin_powi(2.0, n);
}
long double powicl(int n)
{
return __builtin_powil(2.0, n);
}
int main()
{
if (__builtin_powi(1.0, 5) != 1.0)
abort();
if (__builtin_powif(1.0, 5) != 1.0)
abort();
if (__builtin_powil(1.0, 5) != 1.0)
abort();
if (powci(1.0) != 1.0)
abort();
if (powcif(1.0) != 1.0)
abort();
if (powcil(1.0) != 1.0)
abort();
if (powi(1.0, -5) != 1.0)
abort();
if (powif(1.0, -5) != 1.0)
abort();
if (powil(1.0, -5) != 1.0)
abort();
if (powic(1) != 2.0)
abort();
if (powicf(1) != 2.0)
abort();
if (powicl(1) != 2.0)
abort();
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment