[gnu.gcc.bug] builtin math functions

self@BAYES.ARC.NASA.GOV (Matthew Self) (05/12/89)

  Here are my changes to 1.35 which create builtin functions for the
math library functions.  Try them out to see what you think of this
approach.  I believe there are several advantages over the inline math
library I posted earlier:

  (1) It makes better code.  The 68881 needs different opcodes
      depending on the adressing mode, but asm's can't handle this so I had
      to impose stricter constraints than were really necessary.  Now all
      addressing modes are used as needed, resulting in fewer move insn's.

  (2) Compilation is much faster.  I don't know why.

  (3) Peephole optimization of math functions is now possible.  I have
      included one to turn sin and cos insn's into sincos insn's.  If
      div/mod insn's ever get handled better, it will presumably work for
      sin/cos insn's also.

  (4) It is cleaner.  The 68881 opcodes are now all in the machine
      description, where they ought to be.  We don't have to have lots
      of machine-dependent header files (yuck).

  (5) I have provided support for the FPA (although I haven't tested
      this since I don't have one).  Extending the md of other machines
      should be quite easy.

  I have written a single header file which points the math functions
at the builtins.  This file should be included _in addition_ to the
regular <math.h> file.  This is better because the system's existing
math.h file (with whatever weirdness it might have) can be used.

  The old caveats about these functions not necessarily setting errno
still hold.

  One new file and several context diffs follow:

============= start of builtin-math.h ======================

/* builtin-math.h -- May 10, 1989 */

/* Please send bug reports pertaining to builtin math functions to
   Matthew Self -- self@bayes.arc.nasa.gov */

#ifndef BUILTIN_MATH_H
#define BUILTIN_MATH_H

#ifdef __GNUC__

/* ANSI math functions */

#define sin(x)  __builtin_sin (x)
#define cos(x)  __builtin_cos (x)
#define tan(x)  __builtin_tan (x)
#define asin(x)  __builtin_asin (x)
#define acos(x)  __builtin_acos (x)
#define atan(x)  __builtin_atan (x)
#define sinh(x)  __builtin_sinh (x)
#define cosh(x)  __builtin_cosh (x)
#define tanh(x)  __builtin_tanh (x)
#define exp(x)  __builtin_exp (x)
#define log(x)  __builtin_log (x)
#define log10(x) __builtin_log10 (x)
#define sqrt(x)  __builtin_sqrt (x)
#define fabs(x)  __builtin_fabs (x)

/* BSD 4.3 math functions */

#define asinh(x) __builtin_asinh (x)
#define acosh(x) __builtin_acosh (x)
#define atanh(x) __builtin_atanh (x)
#define expm1(x) __builtin_expm1 (x)
#define log1p(x) __builtin_log1p (x)
#define cbrt(x)  __builtin_cbrt (x)

/* FORTRAN math functions */

#define exp2(x)  __builtin_exp2 (x)
#define exp10(x) __builtin_exp10 (x)
#define log2(x)  __builtin_log2 (x)
#define aint(x)  __builtin_aint (x)

#endif /* __GNUC__ */

#endif /* BUILTIN_MATH_H */

============= end of builtin-math.h ======================

Here are the context diffs to make this all work:

*** gcc-1.35/c-decl.c.orig	Tue Apr 25 23:44:58 1989
--- gcc-1.35/c-decl.c	Wed May 10 15:03:09 1989
***************
*** 1525,1532 ****
    builtin_function ("__builtin_memcmp", int_ftype_ptr_ptr_int, BUILT_IN_MEMCMP);
    builtin_function ("__builtin_memset", void_ftype_ptr_int_int, BUILT_IN_MEMSET);
-   builtin_function ("__builtin_fsqrt", double_ftype_double, BUILT_IN_FSQRT);
    builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP);
    builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN);
  #endif
  }
  
--- 1525,1558 ----
    builtin_function ("__builtin_memcmp", int_ftype_ptr_ptr_int, BUILT_IN_MEMCMP);
    builtin_function ("__builtin_memset", void_ftype_ptr_int_int, BUILT_IN_MEMSET);
    builtin_function ("__builtin_getexp", double_ftype_double, BUILT_IN_GETEXP);
    builtin_function ("__builtin_getman", double_ftype_double, BUILT_IN_GETMAN);
  #endif
+ 
+   /* math extensions */
+   /* May 10, 1989 -- self@bayes.arc.nasa.gov */
+ 
+   builtin_function ("__builtin_exp", double_ftype_double, BUILT_IN_EXP);
+   builtin_function ("__builtin_expm1", double_ftype_double, BUILT_IN_EXPM1);
+   builtin_function ("__builtin_exp2", double_ftype_double, BUILT_IN_EXP2);
+   builtin_function ("__builtin_exp10", double_ftype_double, BUILT_IN_EXP10);
+   builtin_function ("__builtin_log", double_ftype_double, BUILT_IN_LOG);
+   builtin_function ("__builtin_log1p", double_ftype_double, BUILT_IN_LOG1P);
+   builtin_function ("__builtin_log2", double_ftype_double, BUILT_IN_LOG2);
+   builtin_function ("__builtin_log10", double_ftype_double, BUILT_IN_LOG10);
+   builtin_function ("__builtin_sqrt", double_ftype_double, BUILT_IN_SQRT);
+   builtin_function ("__builtin_cbrt", double_ftype_double, BUILT_IN_CBRT);
+   builtin_function ("__builtin_aint", double_ftype_double, BUILT_IN_AINT);
+   builtin_function ("__builtin_sin", double_ftype_double, BUILT_IN_SIN);
+   builtin_function ("__builtin_cos", double_ftype_double, BUILT_IN_COS);
+   builtin_function ("__builtin_tan", double_ftype_double, BUILT_IN_TAN);
+   builtin_function ("__builtin_asin", double_ftype_double, BUILT_IN_ASIN);
+   builtin_function ("__builtin_acos", double_ftype_double, BUILT_IN_ACOS);
+   builtin_function ("__builtin_atan", double_ftype_double, BUILT_IN_ATAN);
+   builtin_function ("__builtin_sinh", double_ftype_double, BUILT_IN_SINH);
+   builtin_function ("__builtin_cosh", double_ftype_double, BUILT_IN_COSH);
+   builtin_function ("__builtin_tanh", double_ftype_double, BUILT_IN_TANH);
+   builtin_function ("__builtin_asinh", double_ftype_double, BUILT_IN_ASINH);
+   builtin_function ("__builtin_acosh", double_ftype_double, BUILT_IN_ACOSH);
+   builtin_function ("__builtin_atanh", double_ftype_double, BUILT_IN_ATANH);
  }
  
*** gcc-1.35/expr.c.orig	Tue Apr 25 12:47:06 1989
--- gcc-1.35/expr.c	Wed May 10 15:23:07 1989
***************
*** 3152,3155 ****
--- 3152,3211 ----
  }
  
+ /* optab associated with built-in function (if any) */
+ /* May 10, 1989 -- self@bayes.arc.nasa.gov */
+ 
+ optab *built_in_optab[] =
+ {
+   0,		/* NOT_BUILT_IN */
+   0,		/* BUILT_IN_ALLOCA */
+   0,		/* BUILT_IN_ABS */
+   0,		/* BUILT_IN_FABS */
+   0,		/* BUILT_IN_LABS */
+   &ffs_optab,	/* BUILT_IN_FFS */
+   0,		/* BUILT_IN_DIV */
+   0,		/* BUILT_IN_LDIV */
+   0,		/* BUILT_IN_FFLOOR */
+   0,		/* BUILT_IN_FCEIL */
+   0,		/* BUILT_IN_FMOD */
+   0,		/* BUILT_IN_FREM */
+   0,		/* BUILT_IN_MEMCPY */
+   0,		/* BUILT_IN_MEMCMP */
+   0,		/* BUILT_IN_MEMSET */
+   0,		/* BUILT_IN_GETEXP */
+   0,		/* BUILT_IN_GETMAN */
+   0,		/* BUILT_IN_SAVEREGS */
+ 
+   /* C++ extensions */
+   0,		/* BUILT_IN_NEW */
+   0,		/* BUILT_IN_VEC_NEW */
+   0,		/* BUILT_IN_DELETE */
+   0,		/* BUILT_IN_VEC_DELETE */
+ 
+   /* math extensions */
+   &exp_optab,	/* BUILT_IN_EXP */
+   &expm1_optab,	/* BUILT_IN_EXPM1 */
+   &exp2_optab,	/* BUILT_IN_EXP2 */
+   &exp10_optab,	/* BUILT_IN_EXP10 */
+   &log_optab,	/* BUILT_IN_LOG */
+   &log1p_optab,	/* BUILT_IN_LOG1P */
+   &log2_optab,	/* BUILT_IN_LOG2 */
+   &log10_optab,	/* BUILT_IN_LOG10 */
+   &sqrt_optab,	/* BUILT_IN_SQRT */
+   &cbrt_optab,	/* BUILT_IN_CBRT */
+   &ftrunc_optab,	/* BUILT_IN_AINT */
+   &sin_optab,	/* BUILT_IN_SIN */
+   &cos_optab,	/* BUILT_IN_COS */
+   &tan_optab,	/* BUILT_IN_TAN */
+   &asin_optab,	/* BUILT_IN_ASIN */
+   &acos_optab,	/* BUILT_IN_ACOS */
+   &atan_optab,	/* BUILT_IN_ATAN */
+   &sinh_optab,	/* BUILT_IN_SINH */
+   &cosh_optab,	/* BUILT_IN_COSH */
+   &tanh_optab,	/* BUILT_IN_TANH */
+   &asinh_optab,	/* BUILT_IN_ASINH */
+   &acosh_optab,	/* BUILT_IN_ACOSH */
+   &atanh_optab,	/* BUILT_IN_ATANH */
+ };
+ 
  /* Expand an expression EXP that calls a built-in function,
     with result going to TARGET if that's convenient
***************
*** 3258,3261 ****
--- 3314,3364 ----
  	 Set TARGET to wherever the result comes back.  */
        target = expand_unop (mode, ffs_optab, op0, target, 1);
+       if (target == 0)
+ 	abort ();
+       return target;
+ 
+     /* math extensions */
+     /* May 10, 1989 -- self@bayes.arc.nasa.gov */
+ 
+     case BUILT_IN_EXP:
+     case BUILT_IN_EXPM1:
+     case BUILT_IN_EXP2:
+     case BUILT_IN_EXP10:
+     case BUILT_IN_LOG:
+     case BUILT_IN_LOG1P:
+     case BUILT_IN_LOG2:
+     case BUILT_IN_LOG10:
+     case BUILT_IN_SQRT:
+     case BUILT_IN_CBRT:
+     case BUILT_IN_AINT:
+     case BUILT_IN_SIN:
+     case BUILT_IN_COS:
+     case BUILT_IN_TAN:
+     case BUILT_IN_ASIN:
+     case BUILT_IN_ACOS:
+     case BUILT_IN_ATAN:
+     case BUILT_IN_SINH:
+     case BUILT_IN_COSH:
+     case BUILT_IN_TANH:
+     case BUILT_IN_ASINH:
+     case BUILT_IN_ACOSH:
+     case BUILT_IN_ATANH:
+ 
+       if (arglist == 0
+ 	  /* Arg could be non-real if user redeclared this function wrong. */
+ 	  || TREE_CODE (TREE_TYPE (TREE_VALUE (arglist))) != REAL_TYPE)
+ 	return const0_rtx;
+ 
+       /* Compute the argument.  */
+       op0 = expand_expr (TREE_VALUE (arglist), subtarget, VOIDmode, 0);
+ 
+       if (built_in_optab[DECL_FUNCTION_CODE (fndecl)] == 0)
+ 	abort ();
+ 
+       /* Compute function, into TARGET if possible.
+ 	 Set TARGET to wherever the result comes back.  */
+       target = expand_unop (DFmode,
+ 			    *(built_in_optab[DECL_FUNCTION_CODE (fndecl)]),
+ 			    op0, target, 1);
        if (target == 0)
  	abort ();
*** gcc-1.35/expr.h.orig	Wed Mar 29 13:56:02 1989
--- gcc-1.35/expr.h	Wed May 10 15:03:12 1989
***************
*** 189,192 ****
--- 189,229 ----
  extern optab ffs_optab;		/* Find first bit set */
  
+ /* math extensions */
+ /* May 10, 1989 -- self@bayes.arc.nasa.gov */
+ 
+ extern optab exp_optab;
+ extern optab expm1_optab;
+ extern optab exp2_optab;
+ extern optab exp10_optab;
+ extern optab pow_optab;
+ 
+ extern optab log_optab;
+ extern optab log1p_optab;
+ extern optab log2_optab;
+ extern optab log10_optab;
+ 
+ extern optab sqrt_optab;
+ extern optab cbrt_optab;
+ 
+ extern optab ceil_optab;
+ extern optab floor_optab;
+ 
+ extern optab sin_optab;
+ extern optab cos_optab;
+ extern optab tan_optab;
+ 
+ extern optab asin_optab;
+ extern optab acos_optab;
+ extern optab atan_optab;
+ extern optab atan2_optab;
+ 
+ extern optab sinh_optab;
+ extern optab cosh_optab;
+ extern optab tanh_optab;
+ 
+ extern optab asinh_optab;
+ extern optab acosh_optab;
+ extern optab atanh_optab;
+ 
  /* Passed to expand_binop and expand_unop to say which options to try to use
     if the requested operation can't be open-coded on the requisite mode.
*** gcc-1.35/gcc.texinfo.orig	Sun Apr 23 23:27:30 1989
--- gcc-1.35/gcc.texinfo	Wed May 10 15:03:25 1989
***************
*** 2023,2026 ****
--- 2023,2027 ----
  * Global Reg Vars::     Defining global variables which reside in registers.
  * Alternate Keywords::  @code{__const}, @code{__asm}, etc., for header files.
+ * Built-in Functions::	GNU C built-in functions.
  @end menu
  
***************
*** 2893,2897 ****
  executable file has no means to supply initial contents for a register.
  
! @node Alternate Keywords,, Global Reg Vars, Extensions
  @section Alternate Keywords
  
--- 2894,2898 ----
  executable file has no means to supply initial contents for a register.
  
! @node Alternate Keywords, Built-in Functions, Global Reg Vars, Extensions
  @section Alternate Keywords
  
***************
*** 2921,2924 ****
--- 2922,2986 ----
  @end example
  
+ @node Built-in Functions,,Alternate Keywords, Extensions
+ @section Built-in Functions
+ 
+ GNU C provides many built-in functions which are available to the
+ programmer.  Built-in functions are provided when the built-in version
+ is able to produce significantly more efficient code than the use of
+ inline functions alone is able to achieve.  The names of all built-in
+ functions begin with @samp{__builtin_}, so they will never conflict with
+ user-defined symbols.
+ 
+ Built-in functions are provided for many of the ANSI C and BSD math
+ library functions.  On machines which have machine instructions to
+ perform these functions, the built-in functions result in the direct use
+ of these instructions.  On machines without such instructions, the
+ built-in function expands to a library call to the library function of
+ the same name, just as if you had written @code{sin (x)} rather than
+ @code{__builtin_sin (x)}.
+ 
+ The built-in math functions do not always comply exactly to the ANSI or
+ BSD specifications, but when they don't they are usually faster than the
+ corresponding library function.  None of the built-in math functions
+ below are guaranteed to conform to the standard specifications for
+ handling error conditions or overflow.  On most machines which support
+ IEEE arithmetic, they will conform to the IEEE specification for out of
+ range operands or overflow by returning NaN's or infinities, but they
+ will not usually set the @code{errno} error indicator.
+ 
+ Due to the lack of portability of these built-in functions to other
+ compilers, it is better to restrict their use to a header file which
+ defines macros to map the library functions to the built-in functions.
+ Because of the aforementioned non-compliance, this header file should
+ not usually be the standard system header file.
+ 
+ The following built-in math functions are provided:
+ 
+ @table @code
+ @item __builtin_exp
+ @item __builtin_expm1
+ @item __builtin_exp2
+ @item __builtin_exp10
+ @item __builtin_log
+ @item __builtin_log1p
+ @item __builtin_log2
+ @item __builtin_log10
+ @item __builtin_sqrt
+ @item __builtin_cbrt
+ @item __builtin_aint
+ @item __builtin_sin
+ @item __builtin_cos
+ @item __builtin_tan
+ @item __builtin_asin
+ @item __builtin_acos
+ @item __builtin_atan
+ @item __builtin_sinh
+ @item __builtin_cosh
+ @item __builtin_tanh
+ @item __builtin_asinh
+ @item __builtin_acosh
+ @item __builtin_atanh
+ @end table
+ 
  @node Bugs, Portability, Extensions, Top
  @chapter Reporting Bugs
***************
*** 4383,4391 ****
  @var{x} must be valid for @var{m}.
  
- @item (sqrt:@var{m} @var{x})
- Represents the square root of @var{x}, computed in mode @var{m}.
- @var{x} must be valid for @var{m}.  Most often @var{m} will be
- a floating point mode.
- 
  @item (ffs:@var{m} @var{x})
  Represents the one plus the index of the least significant 1-bit in
--- 4445,4448 ----
***************
*** 4394,4397 ****
--- 4451,4506 ----
  depending on the target machine, various mode combinations may be
  valid.
+ 
+ @item (exp:@var{m} @var{x})
+ Represents the exponential of @var{x}, computed in the floating-point
+ mode @var{m}.
+ 
+ @item (expm1:@var{m} @var{x})
+ Same as @samp{exp}, but represents @samp{exp (@var{x}) - 1}.
+ 
+ @item (exp2:@var{m} @var{x})
+ @itemx (exp10:@var{m} @var{x})
+ Same as @samp{exp}, but represent @samp{2^@var{x}} and
+ @samp{10^@var{x}}.
+ 
+ @item (log:@var{m} @var{x})
+ Represents the natural logarithm of @var{x}, computed in the
+ floating-point mode @var{m}.
+ 
+ @item (expm1:@var{m} @var{x})
+ Same as @samp{log}, but represents @samp{log (@var{x} + 1)}.
+ 
+ @item (log2:@var{m} @var{x})
+ @itemx (log10:@var{m} @var{x})
+ Same as @samp{log}, but represent logarithms to base 2 and 10.
+ 
+ @item (sqrt:@var{m} @var{x})
+ Represents the square root of @var{x}, computed in mode @var{m}.
+ @var{x} must be valid for @var{m}.  Most often @var{m} will be
+ a floating point mode.
+ 
+ @item (cbrt:@var{m} @var{x})
+ Same as @samp{sqrt}, but represents the cube root.
+ 
+ @item (sin:@var{m} @var{x})
+ @itemx (cos:@var{m} @var{x})
+ @itemx (tan:@var{m} @var{x})
+ Represent the trigonometric functions.  @var{x} is expressed in radians,
+ and must be in the floating-point mode @var{m}.
+ 
+ @item (asin:@var{m} @var{x})
+ @itemx (acos:@var{m} @var{x})
+ @itemx (atan:@var{m} @var{x})
+ The inverse trig functions.
+ 
+ @item (sinh:@var{m} @var{x})
+ @itemx (cosh:@var{m} @var{x})
+ @itemx (tanh:@var{m} @var{x})
+ The hyperbolic trig functions.
+ 
+ @item (asinh:@var{m} @var{x})
+ @itemx (acosh:@var{m} @var{x})
+ @itemx (atanh:@var{m} @var{x})
+ The inverse hyperbolic trig functions.
  @end table
  
*** gcc-1.35/optabs.c.orig	Tue Apr  4 16:47:48 1989
--- gcc-1.35/optabs.c	Wed May 10 15:03:28 1989
***************
*** 79,82 ****
--- 79,108 ----
  optab tst_optab;
  
+ /* math extensions */
+ /* May 10, 1989 -- self@bayes.arc.nasa.gov */
+ 
+ optab exp_optab;
+ optab expm1_optab;
+ optab exp2_optab;
+ optab exp10_optab;
+ optab log_optab;
+ optab log1p_optab;
+ optab log2_optab;
+ optab log10_optab;
+ optab sqrt_optab;
+ optab cbrt_optab;
+ optab sin_optab;
+ optab cos_optab;
+ optab tan_optab;
+ optab asin_optab;
+ optab acos_optab;
+ optab atan_optab;
+ optab sinh_optab;
+ optab cosh_optab;
+ optab tanh_optab;
+ optab asinh_optab;
+ optab acosh_optab;
+ optab atanh_optab;
+ 
  /* Indexed by the rtx-code for a conditional (eg. EQ, LT,...)
     gives the gen_function to make a branch to test that condition.  */
***************
*** 1370,1373 ****
--- 1396,1425 ----
    ffs_optab = init_optab (FFS);
  
+ /* math extensions */
+ /* May 10, 1989 -- self@bayes.arc.nasa.gov */
+ 
+ exp_optab = init_optab(EXP);
+ expm1_optab = init_optab(EXPM1);
+ exp2_optab = init_optab(EXP2);
+ exp10_optab = init_optab(EXP10);
+ log_optab = init_optab(LOG);
+ log1p_optab = init_optab(LOG1P);
+ log2_optab = init_optab(LOG2);
+ log10_optab = init_optab(LOG10);
+ sqrt_optab = init_optab(SQRT);
+ cbrt_optab = init_optab(CBRT);
+ sin_optab = init_optab(SIN);
+ cos_optab = init_optab(COS);
+ tan_optab = init_optab(TAN);
+ asin_optab = init_optab(ASIN);
+ acos_optab = init_optab(ACOS);
+ atan_optab = init_optab(ATAN);
+ sinh_optab = init_optab(SINH);
+ cosh_optab = init_optab(COSH);
+ tanh_optab = init_optab(TANH);
+ asinh_optab = init_optab(ASINH);
+ acosh_optab = init_optab(ACOSH);
+ atanh_optab = init_optab(ATANH);
+ 
  #ifdef HAVE_addqi3
    if (HAVE_addqi3)
***************
*** 1948,1951 ****
--- 2000,2138 ----
  #endif
    ffs_optab->handlers[(int) SImode].lib_call = "ffs"; 
+ 
+   /* math extensions */
+   /* May 10, 1989 -- self@bayes.arc.nasa.gov */
+ 
+ #ifdef HAVE_expdf2
+   if (HAVE_expdf2)
+     exp_optab->handlers[(int) DFmode].insn_code = CODE_FOR_expdf2;
+ #endif
+   exp_optab->handlers[(int) DFmode].lib_call = "exp";
+ 
+ #ifdef HAVE_expm1df2
+   if (HAVE_expm1df2)
+     expm1_optab->handlers[(int) DFmode].insn_code = CODE_FOR_expm1df2;
+ #endif
+   expm1_optab->handlers[(int) DFmode].lib_call = "expm1";
+ 
+ #ifdef HAVE_exp2df2
+   if (HAVE_exp2df2)
+     exp2_optab->handlers[(int) DFmode].insn_code = CODE_FOR_exp2df2;
+ #endif
+   exp2_optab->handlers[(int) DFmode].lib_call = "exp2";
+ 
+ #ifdef HAVE_exp10df2
+   if (HAVE_exp10df2)
+     exp10_optab->handlers[(int) DFmode].insn_code = CODE_FOR_exp10df2;
+ #endif
+   exp10_optab->handlers[(int) DFmode].lib_call = "exp10";
+ 
+ #ifdef HAVE_logdf2
+   if (HAVE_logdf2)
+     log_optab->handlers[(int) DFmode].insn_code = CODE_FOR_logdf2;
+ #endif
+   log_optab->handlers[(int) DFmode].lib_call = "log";
+ 
+ #ifdef HAVE_log1pdf2
+   if (HAVE_log1pdf2)
+     log1p_optab->handlers[(int) DFmode].insn_code = CODE_FOR_log1pdf2;
+ #endif
+   log1p_optab->handlers[(int) DFmode].lib_call = "log1p";
+ 
+ #ifdef HAVE_log2df2
+   if (HAVE_log2df2)
+     log2_optab->handlers[(int) DFmode].insn_code = CODE_FOR_log2df2;
+ #endif
+   log2_optab->handlers[(int) DFmode].lib_call = "log2";
+ 
+ #ifdef HAVE_log10df2
+   if (HAVE_log10df2)
+     log10_optab->handlers[(int) DFmode].insn_code = CODE_FOR_log10df2;
+ #endif
+   log10_optab->handlers[(int) DFmode].lib_call = "log10";
+ 
+ #ifdef HAVE_sqrtdf2
+   if (HAVE_sqrtdf2)
+     sqrt_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sqrtdf2;
+ #endif
+   sqrt_optab->handlers[(int) DFmode].lib_call = "sqrt";
+ 
+ #ifdef HAVE_cbrtdf2
+   if (HAVE_cbrtdf2)
+     cbrt_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cbrtdf2;
+ #endif
+   cbrt_optab->handlers[(int) DFmode].lib_call = "cbrt";
+ 
+ #ifdef HAVE_sindf2
+   if (HAVE_sindf2)
+     sin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sindf2;
+ #endif
+   sin_optab->handlers[(int) DFmode].lib_call = "sin";
+ 
+ #ifdef HAVE_cosdf2
+   if (HAVE_cosdf2)
+     cos_optab->handlers[(int) DFmode].insn_code = CODE_FOR_cosdf2;
+ #endif
+   cos_optab->handlers[(int) DFmode].lib_call = "cos";
+ 
+ #ifdef HAVE_tandf2
+   if (HAVE_tandf2)
+     tan_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tandf2;
+ #endif
+   tan_optab->handlers[(int) DFmode].lib_call = "tan";
+ 
+ #ifdef HAVE_asindf2
+   if (HAVE_asindf2)
+     asin_optab->handlers[(int) DFmode].insn_code = CODE_FOR_asindf2;
+ #endif
+   asin_optab->handlers[(int) DFmode].lib_call = "asin";
+ 
+ #ifdef HAVE_acosdf2
+   if (HAVE_acosdf2)
+     acos_optab->handlers[(int) DFmode].insn_code = CODE_FOR_acosdf2;
+ #endif
+   acos_optab->handlers[(int) DFmode].lib_call = "acos";
+ 
+ #ifdef HAVE_atandf2
+   if (HAVE_atandf2)
+     atan_optab->handlers[(int) DFmode].insn_code = CODE_FOR_atandf2;
+ #endif
+   atan_optab->handlers[(int) DFmode].lib_call = "atan";
+ 
+ #ifdef HAVE_sinhdf2
+   if (HAVE_sinhdf2)
+     sinh_optab->handlers[(int) DFmode].insn_code = CODE_FOR_sinhdf2;
+ #endif
+   sinh_optab->handlers[(int) DFmode].lib_call = "sinh";
+ 
+ #ifdef HAVE_coshdf2
+   if (HAVE_coshdf2)
+     cosh_optab->handlers[(int) DFmode].insn_code = CODE_FOR_coshdf2;
+ #endif
+   cosh_optab->handlers[(int) DFmode].lib_call = "cosh";
+ 
+ #ifdef HAVE_tanhdf2
+   if (HAVE_tanhdf2)
+     tanh_optab->handlers[(int) DFmode].insn_code = CODE_FOR_tanhdf2;
+ #endif
+   tanh_optab->handlers[(int) DFmode].lib_call = "tanh";
+ 
+ #ifdef HAVE_asinhdf2
+   if (HAVE_asinhdf2)
+     asinh_optab->handlers[(int) DFmode].insn_code = CODE_FOR_asinhdf2;
+ #endif
+   asinh_optab->handlers[(int) DFmode].lib_call = "asinh";
+ 
+ #ifdef HAVE_acoshdf2
+   if (HAVE_acoshdf2)
+     acosh_optab->handlers[(int) DFmode].insn_code = CODE_FOR_acoshdf2;
+ #endif
+   acosh_optab->handlers[(int) DFmode].lib_call = "acosh";
+ 
+ #ifdef HAVE_atanhdf2
+   if (HAVE_atanhdf2)
+     atanh_optab->handlers[(int) DFmode].insn_code = CODE_FOR_atanhdf2;
+ #endif
+   atanh_optab->handlers[(int) DFmode].lib_call = "atanh";
  
  #ifdef HAVE_movqi
*** gcc-1.35/rtl.def.orig	Sat Apr  1 11:32:30 1989
--- gcc-1.35/rtl.def	Wed May 10 15:03:28 1989
***************
*** 513,519 ****
  DEF_RTL_EXPR(ABS, "abs", "e")
  
- /* Square root */
- DEF_RTL_EXPR(SQRT, "sqrt", "e")
- 
  /* Find first bit that is set.
     Value is 1 + number of trailing zeros in the arg.,
--- 513,516 ----
***************
*** 520,523 ****
--- 517,573 ----
     or 0 if arg is 0.  */
  DEF_RTL_EXPR(FFS, "ffs", "e")
+ 
+ /* math extensions */
+ /* May 10, 1989 -- self@bayes.arc.nasa.gov */
+ 
+ /* Exponential function */
+ DEF_RTL_EXPR(EXP, "exp", "e")
+ 
+ /* e^x - 1 */
+ DEF_RTL_EXPR(EXPM1, "expm1", "e")
+ 
+ /* 2^x */
+ DEF_RTL_EXPR(EXP2, "exp2", "e")
+ 
+ /* 10^x */
+ DEF_RTL_EXPR(EXP10, "exp10", "e")
+ 
+ /* Natural logarithm */
+ DEF_RTL_EXPR(LOG, "log", "e")
+ 
+ /* log (x + 1) */
+ DEF_RTL_EXPR(LOG1P, "log1p", "e")
+ 
+ /* Logarithm to base 2 */
+ DEF_RTL_EXPR(LOG2, "log2", "e")
+ 
+ /* Logarithm to base 10 */
+ DEF_RTL_EXPR(LOG10, "log10", "e")
+ 
+ /* Square root */
+ DEF_RTL_EXPR(SQRT, "sqrt", "e")
+ 
+ /* Cube root */
+ DEF_RTL_EXPR(CBRT, "cbrt", "e")
+ 
+ /* Trigonometric functions */
+ DEF_RTL_EXPR(SIN, "sin", "e")
+ DEF_RTL_EXPR(COS, "cos", "e")
+ DEF_RTL_EXPR(TAN, "tan", "e")
+ 
+ /* Inverse trig */
+ DEF_RTL_EXPR(ASIN, "asin", "e")
+ DEF_RTL_EXPR(ACOS, "acos", "e")
+ DEF_RTL_EXPR(ATAN, "atan", "e")
+ 
+ /* Hyperbolic trig */
+ DEF_RTL_EXPR(SINH, "sinh", "e")
+ DEF_RTL_EXPR(COSH, "cosh", "e")
+ DEF_RTL_EXPR(TANH, "tanh", "e")
+ 
+ /* Inverse hyperbolic trig */
+ DEF_RTL_EXPR(ASINH, "asinh", "e")
+ DEF_RTL_EXPR(ACOSH, "acosh", "e")
+ DEF_RTL_EXPR(ATANH, "atanh", "e")
  
  /* Reference to a signed bit-field of specified size and position.
*** gcc-1.35/tree.h.orig	Wed Feb 22 09:27:10 1989
--- gcc-1.35/tree.h	Wed May 10 15:03:29 1989
***************
*** 85,89 ****
    BUILT_IN_MEMCMP,
    BUILT_IN_MEMSET,
-   BUILT_IN_FSQRT,
    BUILT_IN_GETEXP,
    BUILT_IN_GETMAN,
--- 85,88 ----
***************
*** 95,98 ****
--- 94,124 ----
    BUILT_IN_DELETE,
    BUILT_IN_VEC_DELETE,
+ 
+   /* math extensions */
+   /* May 10, 1989 -- self@bayes.arc.nasa.gov */
+ 
+   BUILT_IN_EXP,
+   BUILT_IN_EXPM1,
+   BUILT_IN_EXP2,
+   BUILT_IN_EXP10,
+   BUILT_IN_LOG,
+   BUILT_IN_LOG1P,
+   BUILT_IN_LOG2,
+   BUILT_IN_LOG10,
+   BUILT_IN_SQRT,
+   BUILT_IN_CBRT,
+   BUILT_IN_AINT,
+   BUILT_IN_SIN,
+   BUILT_IN_COS,
+   BUILT_IN_TAN,
+   BUILT_IN_ASIN,
+   BUILT_IN_ACOS,
+   BUILT_IN_ATAN,
+   BUILT_IN_SINH,
+   BUILT_IN_COSH,
+   BUILT_IN_TANH,
+   BUILT_IN_ASINH,
+   BUILT_IN_ACOSH,
+   BUILT_IN_ATANH,
  };
  
*** gcc-1.35/config/m68k.md.orig	Wed Apr 12 19:03:52 1989
--- gcc-1.35/config/m68k.md	Wed May 10 16:09:19 1989
***************
*** 2493,2496 ****
--- 2493,2853 ----
  }")
  
+ ;; math extensions
+ ;; May 10, 1989 -- self@bayes.arc.nasa.gov
+ 
+ ;; exp
+ (define_expand "expdf2"
+   [(set (match_operand:DF 0 "general_operand" "")
+ 	(exp:DF (match_operand:DF 1 "general_operand" "")))]
+   "TARGET_68881 || TARGET_FPA"
+   "")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=x,y")
+ 	(exp:DF (match_operand:DF 1 "general_operand" "xH,dmF")))]
+   "TARGET_FPA"
+   "fpetox%.d %x1,%0")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(exp:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fetox%.x %1,%0\";
+   return \"fetox%.d %f1,%0\";
+ }")
+ 
+ ;; expm1
+ (define_expand "expm1df2"
+   [(set (match_operand:DF 0 "general_operand" "")
+ 	(expm1:DF (match_operand:DF 1 "general_operand" "")))]
+   "TARGET_68881 || TARGET_FPA"
+   "")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=x,y")
+ 	(expm1:DF (match_operand:DF 1 "general_operand" "xH,dmF")))]
+   "TARGET_FPA"
+   "fpetoxm1%.d %x1,%0")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(expm1:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fetoxm1%.x %1,%0\";
+   return \"fetoxm1%.d %f1,%0\";
+ }")
+ 
+ ;; exp10
+ (define_insn "exp10df2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(exp10:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"ftentox%.x %1,%0\";
+   return \"ftentox%.d %f1,%0\";
+ }")
+ 
+ ;; exp2
+ (define_insn "exp2df2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(exp2:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"ftwotox%.x %1,%0\";
+   return \"ftwotox%.d %f1,%0\";
+ }")
+ 
+ ;; log
+ (define_expand "logdf2"
+   [(set (match_operand:DF 0 "general_operand" "")
+ 	(log:DF (match_operand:DF 1 "general_operand" "")))]
+   "TARGET_68881 || TARGET_FPA"
+   "")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=x,y")
+ 	(log:DF (match_operand:DF 1 "general_operand" "xH,dmF")))]
+   "TARGET_FPA"
+   "fplogn%.d %x1,%0")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(log:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"flogn%.x %1,%0\";
+   return \"flogn%.d %f1,%0\";
+ }")
+ 
+ ;; log1p
+ (define_expand "log1pdf2"
+   [(set (match_operand:DF 0 "general_operand" "")
+ 	(log1p:DF (match_operand:DF 1 "general_operand" "")))]
+   "TARGET_68881 || TARGET_FPA"
+   "")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=x,y")
+ 	(log1p:DF (match_operand:DF 1 "general_operand" "xH,dmF")))]
+   "TARGET_FPA"
+   "fplognp1%.d %x1,%0")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(log1p:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"flognp1%.x %1,%0\";
+   return \"flognp1%.d %f1,%0\";
+ }")
+ 
+ (define_insn "log2df2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(log2:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"flog2%.x %1,%0\";
+   return \"flog2%.d %f1,%0\";
+ }")
+ 
+ (define_insn "log10df2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(log10:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"flog10%.x %1,%0\";
+   return \"flog10%.d %f1,%0\";
+ }")
+ 
+ ;; sqrt
+ (define_insn "sqrtdf2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(sqrt:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fsqrt%.x %1,%0\";
+   return \"fsqrt%.d %f1,%0\";
+ }")
+ 
+ ;; sin
+ (define_expand "sindf2"
+   [(set (match_operand:DF 0 "general_operand" "")
+ 	(sin:DF (match_operand:DF 1 "general_operand" "")))]
+   "TARGET_68881 || TARGET_FPA"
+   "")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=x,y")
+ 	(sin:DF (match_operand:DF 1 "general_operand" "xH,dmF")))]
+   "TARGET_FPA"
+   "fpsin%.d %x1,%0")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(sin:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fsin%.x %1,%0\";
+   return \"fsin%.d %f1,%0\";
+ }")
+ 
+ ;; cos
+ (define_expand "cosdf2"
+   [(set (match_operand:DF 0 "general_operand" "")
+ 	(cos:DF (match_operand:DF 1 "general_operand" "")))]
+   "TARGET_68881 || TARGET_FPA"
+   "")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=x,y")
+ 	(cos:DF (match_operand:DF 1 "general_operand" "xH,dmF")))]
+   "TARGET_FPA"
+   "fpcos%.d %x1,%0")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(cos:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fcos%.x %1,%0\";
+   return \"fcos%.d %f1,%0\";
+ }")
+ 
+ ;; tan
+ (define_insn "tandf2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(tan:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"ftan%.x %1,%0\";
+   return \"ftan%.d %f1,%0\";
+ }")
+ 
+ ;; sincos
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=x,y")
+ 	(sin:DF (match_operand:DF 2 "general_operand" "xH,dmF")))
+    (set (match_operand:DF 1 "general_operand" "=x,y")
+ 	(cos:DF (match_operand:DF 2 "general_operand" "xH,dmF")))]
+   "TARGET_FPA"
+   "fpsincos%.d %x2,%1:%0")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(sin:DF (match_operand:DF 2 "general_operand" "fmG")))
+    (set (match_operand:DF 1 "general_operand" "=f")
+ 	(cos:DF (match_operand:DF 2 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fsincos%.x %2,%1:%0\";
+   return \"fsincos%.d %f2,%1:%0\";
+ }")
+ 
+ ;; peephole optimizer to do the same thing.
+ (define_peephole
+   [(set (match_operand:DF 0 "general_operand" "=x,y")
+ 	(sin:DF (match_operand:DF 2 "general_operand" "xH,dmF")))
+    (set (match_operand:DF 1 "general_operand" "=x,y")
+ 	(cos:DF (match_operand:DF 2 "general_operand" "xH,dmF")))]
+   "TARGET_FPA"
+   "fpsincos%.d %x2,%1:%0")
+ 
+ (define_peephole
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(sin:DF (match_operand:DF 2 "general_operand" "fmG")))
+    (set (match_operand:DF 1 "general_operand" "=f")
+ 	(cos:DF (match_operand:DF 2 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fsincos%.x %2,%1:%0\";
+   return \"fsincos%.d %f2,%1:%0\";
+ }")
+ 
+ ;; asin
+ (define_insn "asindf2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(asin:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fasin%.x %1,%0\";
+   return \"fasin%.d %f1,%0\";
+ }")
+ 
+ ;; acos
+ (define_insn "acosdf2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(acos:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"facos%.x %1,%0\";
+   return \"facos%.d %f1,%0\";
+ }")
+ 
+ ;; atan
+ (define_expand "atandf2"
+   [(set (match_operand:DF 0 "general_operand" "")
+ 	(atan:DF (match_operand:DF 1 "general_operand" "")))]
+   "TARGET_68881 || TARGET_FPA"
+   "")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=x,y")
+ 	(atan:DF (match_operand:DF 1 "general_operand" "xH,dmF")))]
+   "TARGET_FPA"
+   "fpatan%.d %x1,%0")
+ 
+ (define_insn ""
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(atan:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fatan%.x %1,%0\";
+   return \"fatan%.d %f1,%0\";
+ }")
+ 
+ ;; sinh
+ (define_insn "sinhdf2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(sinh:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fsinh%.x %1,%0\";
+   return \"fsinh%.d %f1,%0\";
+ }")
+ 
+ ;; cosh
+ (define_insn "coshdf2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(cosh:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fcosh%.x %1,%0\";
+   return \"fcosh%.d %f1,%0\";
+ }")
+ 
+ ;; tanh
+ (define_insn "tanhdf2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(tanh:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"ftanh%.x %1,%0\";
+   return \"ftanh%.d %f1,%0\";
+ }")
+ 
+ ;; atanh
+ (define_insn "atanhdf2"
+   [(set (match_operand:DF 0 "general_operand" "=f")
+ 	(atanh:DF (match_operand:DF 1 "general_operand" "fmG")))]
+   "TARGET_68881"
+   "*
+ {
+   if (REG_P (operands[1]))
+     return \"fatanh%.x %1,%0\";
+   return \"fatanh%.d %f1,%0\";
+ }")
+ 
  ;; one complement instructions
  

grunwald@flute.cs.uiuc.edu (05/12/89)

given that Matthew Self has the builtins defined, and that they don't
*preclude* not having them (libm is still there), then this seems like
a reasonable idea; better in someways than using e.g., math-68881.h.
--
Dirk Grunwald
Univ. of Illinois
grunwald@flute.cs.uiuc.edu