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] Support C99 cabs, cabsf and cabsl as builtins.


The following patch adds support for C99's cabs, cabsf and cabsl
functions that calculate the complex absolute value (also called
norm, modulus or magnitude) of a complex value.  This is another
step to improving Scott Ladd's Mandelbrot benchmarks.

The conversion of cabs(z) into sqrt(z.r*z.r + z.i*z.i) is only
performed under the control of flag_unsafe_math_optimizations,
i.e. -ffast-math, as many system libraries may implement this
using the more accurate hypot function in libm.  See my following
e-mail for why I didn't use GCC's ABS_EXPR functionality.

The expand_builtin_fabs function is provided to simplify the task
of providing builtin "fabs" functionality to non C-family front-ends
such as fortran and java, which currently must special case fabs.

The following patch has been tested on i686-pc-linux-gnu with a
complete "make bootstrap", all languages except treelang, and
regression checked with a top-level "make -k check" with no new
failures.

Ok for mainline?


2003-06-02  Roger Sayle  <roger@eyesopen.com>

	* builtins.def (BUILT_IN_CABS, BUILT_IN_CABSF, BUILT_IN_CABSL):
	New builtins representing ISO C99's cabs, cabsf and cabsl.
	* builtins.c (expand_builtin_fabs): New function.
	(expand_builtin_cabs): New function.
	(expand_builtin): Expand BUILT_IN_FABS{,F,L} and BUILT_IN_CABS{,F,L}
	using expand_builtin_fabs and expand_builtin_cabs respectively.

	* doc/extend.texi: Document new cabs, cabsf and cabsl builtins.

	* gcc.dg/builtins-19.c: New test case.
	* gcc.dg/builtins-20.c: New test case.


Index: builtins.def
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.def,v
retrieving revision 1.53
diff -c -3 -p -r1.53 builtins.def
*** builtins.def	23 May 2003 20:45:36 -0000	1.53
--- builtins.def	2 Jun 2003 02:09:45 -0000
*************** DEF_C99_BUILTIN(BUILT_IN_CIMAGL,
*** 285,290 ****
--- 285,302 ----
  		"__builtin_cimagl",
  		BT_FN_LONG_DOUBLE_COMPLEX_LONG_DOUBLE,
  		ATTR_CONST_NOTHROW_LIST)
+ DEF_C99_BUILTIN(BUILT_IN_CABS,
+ 		"__builtin_cabs",
+ 		BT_FN_DOUBLE_COMPLEX_DOUBLE,
+ 		ATTR_CONST_NOTHROW_LIST)
+ DEF_C99_BUILTIN(BUILT_IN_CABSF,
+ 		"__builtin_cabsf",
+ 		BT_FN_FLOAT_COMPLEX_FLOAT,
+ 		ATTR_CONST_NOTHROW_LIST)
+ DEF_C99_BUILTIN(BUILT_IN_CABSL,
+ 		"__builtin_cabsl",
+ 		BT_FN_LONG_DOUBLE_COMPLEX_LONG_DOUBLE,
+ 		ATTR_CONST_NOTHROW_LIST)

  /* The system prototypes for `bzero', 'bcopy' and `bcmp' functions
     have many variations, so don't specify parameters to avoid
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.205
diff -c -3 -p -r1.205 builtins.c
*** builtins.c	27 May 2003 18:44:55 -0000	1.205
--- builtins.c	2 Jun 2003 02:09:46 -0000
*************** static tree fold_builtin_nan		PARAMS ((t
*** 169,174 ****
--- 169,176 ----
  static int validate_arglist		PARAMS ((tree, ...));
  static tree fold_trunc_transparent_mathfn PARAMS ((tree));
  static bool readonly_data_expr		PARAMS ((tree));
+ static rtx expand_builtin_fabs		PARAMS ((tree, rtx, rtx));
+ static rtx expand_builtin_cabs		PARAMS ((tree, rtx));

  /* Return the alignment in bits of EXP, a pointer valued expression.
     But don't return more than MAX_ALIGN no matter what.
*************** expand_builtin_trap ()
*** 4279,4284 ****
--- 4281,4337 ----
      emit_library_call (abort_libfunc, LCT_NORETURN, VOIDmode, 0);
    emit_barrier ();
  }
+
+ /* Expand a call to fabs, fabsf or fabsl with arguments ARGLIST.
+    Return 0 if a normal call should be emitted rather than expanding
+    the function inline.  If convenient, the result should be placed
+    in TARGET.  SUBTARGET may be used as the target for computing
+    the operand.  */
+
+ static rtx
+ expand_builtin_fabs (arglist, target, subtarget)
+      tree arglist;
+      rtx target, subtarget;
+ {
+   enum machine_mode mode;
+   tree arg;
+   rtx op0;
+
+   if (!validate_arglist (arglist, REAL_TYPE, VOID_TYPE))
+     return 0;
+
+   arg = TREE_VALUE (arglist);
+   mode = TYPE_MODE (TREE_TYPE (arg));
+   op0 = expand_expr (arg, subtarget, VOIDmode, 0);
+   return expand_abs (mode, op0, target, 0, safe_from_p (target, arg, 1));
+ }
+
+ /* Expand a call to cabs, cabsf or cabsl with arguments ARGLIST.
+    Return 0 if a normal call should be emitted rather than expanding
+    the function inline.  If convenient, the result should be placed
+    in target.  */
+
+ static rtx
+ expand_builtin_cabs (arglist, target)
+      tree arglist;
+      rtx target;
+ {
+   enum machine_mode mode;
+   tree arg;
+   rtx op0;
+
+   if (arglist == 0 || TREE_CHAIN (arglist))
+     return 0;
+   arg = TREE_VALUE (arglist);
+   if (TREE_CODE (TREE_TYPE (arg)) != COMPLEX_TYPE
+       || TREE_CODE (TREE_TYPE (TREE_TYPE (arg))) != REAL_TYPE)
+     return 0;
+
+   mode = TYPE_MODE (TREE_TYPE (arg));
+   op0 = expand_expr (arg, NULL_RTX, VOIDmode, 0);
+   return expand_complex_abs (mode, op0, target, 0);
+ }
+

  /* Expand an expression EXP that calls a built-in function,
     with result going to TARGET if that's convenient
*************** expand_builtin (exp, target, subtarget,
*** 4431,4441 ****
      case BUILT_IN_LABS:
      case BUILT_IN_LLABS:
      case BUILT_IN_IMAXABS:
      case BUILT_IN_FABS:
      case BUILT_IN_FABSF:
      case BUILT_IN_FABSL:
!       /* build_function_call changes these into ABS_EXPR.  */
!       abort ();

      case BUILT_IN_CONJ:
      case BUILT_IN_CONJF:
--- 4484,4510 ----
      case BUILT_IN_LABS:
      case BUILT_IN_LLABS:
      case BUILT_IN_IMAXABS:
+       /* build_function_call changes these into ABS_EXPR.  */
+       abort ();
+
      case BUILT_IN_FABS:
      case BUILT_IN_FABSF:
      case BUILT_IN_FABSL:
!       target = expand_builtin_fabs (arglist, target, subtarget);
!       if (target)
!         return target;
!       break;
!
!     case BUILT_IN_CABS:
!     case BUILT_IN_CABSF:
!     case BUILT_IN_CABSL:
!       if (flag_unsafe_math_optimizations)
! 	{
! 	  target = expand_builtin_cabs (arglist, target);
! 	  if (target)
! 	    return target;
! 	}
!       break;

      case BUILT_IN_CONJ:
      case BUILT_IN_CONJF:
Index: doc/extend.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/extend.texi,v
retrieving revision 1.141
diff -c -3 -p -r1.141 extend.texi
*** doc/extend.texi	23 May 2003 20:45:39 -0000	1.141
--- doc/extend.texi	2 Jun 2003 02:09:48 -0000
*************** v4si f (v4si a, v4si b, v4si c)
*** 4598,4603 ****
--- 4598,4606 ----
  @findex atanl
  @findex bcmp
  @findex bzero
+ @findex cabs
+ @findex cabsf
+ @findex cabsl
  @findex calloc
  @findex ceil
  @findex ceilf
*************** All these functions have corresponding v
*** 4726,4733 ****
  prefixed with @code{__builtin_}, which may be used even in strict C89
  mode.

! The ISO C99 functions @code{conj}, @code{conjf}, @code{conjl}, @code{creal},
! @code{crealf}, @code{creall}, @code{cimag}, @code{cimagf}, @code{cimagl},
  @code{_Exit}, @code{imaxabs}, @code{llabs},
  @code{nearbyint}, @code{nearbyintf}, @code{nearbyintl},
  @code{round}, @code{roundf}, @code{roundl}, @code{snprintf},
--- 4729,4739 ----
  prefixed with @code{__builtin_}, which may be used even in strict C89
  mode.

! The ISO C99 functions
! @code{cabs}, @code{cabsf}, @code{cabsl},
! @code{conj}, @code{conjf}, @code{conjl},
! @code{creal}, @code{crealf}, @code{creall},
! @code{cimag}, @code{cimagf}, @code{cimagl},
  @code{_Exit}, @code{imaxabs}, @code{llabs},
  @code{nearbyint}, @code{nearbyintf}, @code{nearbyintl},
  @code{round}, @code{roundf}, @code{roundl}, @code{snprintf},


/* Copyright (C) 2003  Free Software Foundation.

   Verify that all the __builtin_cabs? functions are recognized
   by the compiler.  Complex numbers are not supported with the
   gcc.dg default "-pedantic-errors" option, so the dg-options
   overrides this.

   Written by Roger Sayle, 1st June 2003.  */

/* { dg-do compile } */
/* { dg-options "-O -ansi" } */
/* { dg-final { scan-assembler-not "__builtin_" } } */

double test(__complex__ double x)
{
  return __builtin_cabs (x);
}

float testf(__complex__ float x)
{
  return __builtin_cabsf (x);
}

long double testl(__complex__ long double x)
{
  return __builtin_cabsl (x);
}


/* Copyright (C) 2003 Free Software Foundation.

   Check that built-in cabs, cabsf and cabsl functions don't
   break anything and produces the expected results.

   Written by Roger Sayle, 1st June 2003.  */

/* { dg-do link } */
/* { dg-options "-O2 -ffast-math" } */

extern void link_error(void);

extern float cabsf (float _Complex);
extern double cabs (double _Complex);
extern long double cabsl (long double _Complex);

int
main (void)
{
  /* For each type, test both runtime and compile time (constant folding)
     optimization.  */
  float _Complex fc = 3.0F + 4.0iF;
  double _Complex dc = 3.0 + 4.0i;
  long double _Complex ldc = 3.0L + 4.0iL;

  /* Test floats.  */
  if (cabsf (fc) != 5.0F)
    link_error ();
  if (__builtin_cabsf (fc) != 5.0F)
    link_error ();
  if (cabsf (3.0F + 4.0iF) != 5.0F)
    link_failure ();
  if (__builtin_cabsf (3.0F + 4.0iF) != 5.0F)
    link_failure ();

  /* Test doubles.  */
  if (cabs (dc) != 5.0)
    link_error ();
  if (__builtin_cabs (dc) != 5.0)
    link_error ();
  if (cabs (3.0 + 4.0i) != 5.0)
    link_failure ();
  if (__builtin_cabs (3.0 + 4.0i) != 5.0)
    link_failure ();

  /* Test long doubles.  */
  if (cabsl (ldc) != 5.0L)
    link_error ();
  if (__builtin_cabsl (ldc) != 5.0L)
    link_error ();
  if (cabsl (3.0L + 4.0iL) != 5.0L)
    link_failure ();
  if (__builtin_cabsl (3.0L + 4.0iL) != 5.0L)
    link_failure ();

  return 0;
}


Roger
--
Roger Sayle,                         E-mail: roger@eyesopen.com
OpenEye Scientific Software,         WWW: http://www.eyesopen.com/
Suite 1107, 3600 Cerrillos Road,     Tel: (+1) 505-473-7385
Santa Fe, New Mexico, 87507.         Fax: (+1) 505-473-0833


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