This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] Fix PR19402, add __builtin_powi[lf]


This patch adds __builtin_powi[lf] to fix PR19402 and to be
able to finally fix PR11706 the right way.

Bootstrapped and regtested on x86_64-unknown-linux-gnu with
no regressions for C and C++ (including a patch to utilize
__builtin_powi[lf] in libstdc++).

Ok for mainline?

Thanks,
Richard.


2005-02-02  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.
	* 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.


Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.415
diff -u -c -3 -p -r1.415 builtins.c
*** builtins.c	28 Jan 2005 00:54:55 -0000	1.415
--- builtins.c	2 Feb 2005 14:13:19 -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,2415 ----
    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, 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
     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
*** 5186,5191 ****
--- 5247,5260 ----
  	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	2 Feb 2005 14:13:19 -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: libgcc-std.ver
===================================================================
RCS file: /cvs/gcc/gcc/gcc/libgcc-std.ver,v
retrieving revision 1.27
diff -u -c -3 -p -r1.27 libgcc-std.ver
*** libgcc-std.ver	15 Dec 2004 12:30:27 -0000	1.27
--- libgcc-std.ver	2 Feb 2005 14:13:19 -0000
*************** GCC_3.4.4 {
*** 233,235 ****
--- 233,244 ----
    __negvti2
    __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
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	2 Feb 2005 14:13:19 -0000
*************** __fixunssfSI (SFtype a)
*** 1465,1470 ****
--- 1465,1506 ----
  }
  #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.  */

  #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	2 Feb 2005 14:13:19 -0000
*************** extern UWtype __fixunsdfSI (DFtype);
*** 305,322 ****
--- 305,326 ----
  extern UWtype __fixunssfSI (SFtype);
  extern DWtype __fixunsdfDI (DFtype);
  extern DWtype __fixunssfDI (SFtype);
+ extern SFtype __powisf2 (SFtype, Wtype);
+ extern DFtype __powidf2 (DFtype, Wtype);

  #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 __powixf2 (XFtype, Wtype);
  #endif

  #if LIBGCC2_LONG_DOUBLE_TYPE_SIZE == 128
  extern DWtype __fixunstfDI (TFtype);
  extern DWtype __fixtfdi (TFtype);
  extern TFtype __floatditf (DWtype);
+ extern TFtype __powitf2 (TFtype, Wtype);
  #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	2 Feb 2005 14:13:19 -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 _powisf2 _powidf2
! 	_powixf2 _powitf2'

  # Disable SHLIB_LINK if shared libgcc not enabled.
  if [ "@enable_shared@" = "no" ]; then
Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.257
diff -u -c -3 -p -r1.257 optabs.c
*** optabs.c	31 Jan 2005 09:02:25 -0000	1.257
--- optabs.c	2 Feb 2005 14:13:19 -0000
*************** init_optabs (void)
*** 5049,5054 ****
--- 5049,5056 ----
    vec_realign_load_optab = init_optab (UNKNOWN);
    movmisalign_optab = init_optab (UNKNOWN);

+   powi_optab = init_optab (UNKNOWN);
+
    /* Conversions.  */
    sext_optab = init_convert_optab (SIGN_EXTEND);
    zext_optab = init_convert_optab (ZERO_EXTEND);
*************** init_optabs (void)
*** 5135,5140 ****
--- 5137,5144 ----
    init_floating_libfuncs (le_optab, "le", '2');
    init_floating_libfuncs (unord_optab, "unord", '2');

+   init_floating_libfuncs (powi_optab, "powi", '2');
+
    /* Conversions.  */
    init_interclass_conv_libfuncs (sfloat_optab, "float",
  				 MODE_INT, MODE_FLOAT);
Index: optabs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.h,v
retrieving revision 1.46
diff -u -c -3 -p -r1.46 optabs.h
*** optabs.h	28 Jan 2005 00:54:58 -0000	1.46
--- optabs.h	2 Feb 2005 14:13:19 -0000
*************** enum optab_index
*** 235,240 ****
--- 235,243 ----
    /* Extract specified elements from vectors, for vector load.  */
    OTI_vec_realign_load,

+   /* Perform a raise to the power of integer.  */
+   OTI_powi,
+
    OTI_MAX
  };

*************** extern GTY(()) optab optab_table[OTI_MAX
*** 340,345 ****
--- 343,350 ----
  #define vec_init_optab (optab_table[OTI_vec_init])
  #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.  */
  enum convert_optab_index
  {
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.236
diff -u -c -3 -p -r1.236 extend.texi
*** doc/extend.texi	31 Jan 2005 23:18:49 -0000	1.236
--- doc/extend.texi	2 Feb 2005 14:13:20 -0000
*************** identifier, or a sequence of member acce
*** 4507,4512 ****
--- 4507,4515 ----
  @findex __builtin_islessequal
  @findex __builtin_islessgreater
  @findex __builtin_isunordered
+ @findex __builtin_powi
+ @findex __builtin_powif
+ @findex __builtin_powil
  @findex _Exit
  @findex _exit
  @findex abort
*************** Similar to @code{__builtin_parity}, exce
*** 5368,5373 ****
--- 5371,5391 ----
  @code{unsigned long long}.
  @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
  @section Built-in Functions Specific to Particular Target Machines


/* { 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;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]