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] pow and atan2 builtin functions (part 2)


This is the second installment of my series of patches to support
pow and atan2 as built-in math functions.  This patch provides the
functionality to implement these builtins using pow?f3 and atan2?f3
patterns specified in the target's .md file.  This bit contains
the logic to create/use the new optabs.

This patch has been tested by a complete bootstrap, all languages
except Ada and treelang, on i686-pc-linux-gnu, with no new regressions
reported by "make -k check".  To test that it actually works, its
also been tested in combination with part 3 (to be posted in a few
minutes) that implements the atan2?f3 patterns in the i386 backend.

Ok for mainline?


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

	* optabs.h (enum optab_index): Add new OTI_pow and OTI_atan2.
	(pow_optab, atan2_optab): Define corresponding macros.
	* optabs.c (init_optabs): Initialize pow_optab and atan2_optab.
	* genopinit.c (optabs): Implement pow_optab and atan2_optab
	using pow?f3 and atan2?f3 patterns.
	* builtins.c (expand_errno_check): New function to update errno
	if necessary, split out from expand_builtin_mathfn.
	(expand_builtin_mathfn): Use expand_errno_check.
	(expand_builtin_mathfn_2): New function to handle expanding binary
	math functions, reusing the code in expand_errno_check.
	(expand_builtin): Handle the pow and atan2 math built-ins,
	BUILT_IN_{POW,POWF,POWL,ATAN2,ATAN2F,ATAN2L} via the new function
	expand_builtin_mathfn_2.

	* doc/md.texi: Document new pow?f3 and atan2?f3 patterns.


Index: optabs.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.h,v
retrieving revision 1.11
diff -c -3 -p -r1.11 optabs.h
*** optabs.h	1 Feb 2003 18:59:46 -0000	1.11
--- optabs.h	10 Feb 2003 15:08:23 -0000
***************
*** 1,5 ****
  /* Definitions for code generation pass of GNU compiler.
!    Copyright (C) 2001, 2002 Free Software Foundation, Inc.

  This file is part of GCC.

--- 1,5 ----
  /* Definitions for code generation pass of GNU compiler.
!    Copyright (C) 2001, 2002, 2003 Free Software Foundation, Inc.

  This file is part of GCC.

*************** enum optab_index
*** 108,113 ****
--- 108,117 ----
    OTI_umin,
    /* Unsigned maximum value */
    OTI_umax,
+   /* Power */
+   OTI_pow,
+   /* Arc tangent of y/x */
+   OTI_atan2,

    /* Move instruction.  */
    OTI_mov,
*************** extern GTY(()) optab optab_table[OTI_MAX
*** 202,207 ****
--- 206,213 ----
  #define smax_optab (optab_table[OTI_smax])
  #define umin_optab (optab_table[OTI_umin])
  #define umax_optab (optab_table[OTI_umax])
+ #define pow_optab (optab_table[OTI_pow])
+ #define atan2_optab (optab_table[OTI_atan2])

  #define mov_optab (optab_table[OTI_mov])
  #define movstrict_optab (optab_table[OTI_movstrict])
Index: optabs.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/optabs.c,v
retrieving revision 1.161
diff -c -3 -p -r1.161 optabs.c
*** optabs.c	7 Feb 2003 19:38:04 -0000	1.161
--- optabs.c	10 Feb 2003 15:08:25 -0000
*************** init_optabs ()
*** 5491,5496 ****
--- 5491,5498 ----
    smax_optab = init_optab (SMAX);
    umin_optab = init_optab (UMIN);
    umax_optab = init_optab (UMAX);
+   pow_optab = init_optab (UNKNOWN);
+   atan2_optab = init_optab (UNKNOWN);

    /* These three have codes assigned exclusively for the sake of
       have_insn_for.  */
Index: genopinit.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/genopinit.c,v
retrieving revision 1.56
diff -c -3 -p -r1.56 genopinit.c
*** genopinit.c	1 Feb 2003 18:59:45 -0000	1.56
--- genopinit.c	10 Feb 2003 15:08:26 -0000
***************
*** 1,6 ****
  /* Generate code to initialize optabs from machine description.
!    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998,
!    1999, 2000 Free Software Foundation, Inc.

  This file is part of GCC.

--- 1,6 ----
  /* Generate code to initialize optabs from machine description.
!    Copyright (C) 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
!    2001, 2002, 2003 Free Software Foundation, Inc.

  This file is part of GCC.

*************** static const char * const optabs[] =
*** 105,110 ****
--- 105,112 ----
    "smax_optab->handlers[$A].insn_code = CODE_FOR_$(max$F$a3$)",
    "umin_optab->handlers[$A].insn_code = CODE_FOR_$(umin$I$a3$)",
    "umax_optab->handlers[$A].insn_code = CODE_FOR_$(umax$I$a3$)",
+   "pow_optab->handlers[$A].insn_code = CODE_FOR_$(pow$a3$)",
+   "atan2_optab->handlers[$A].insn_code = CODE_FOR_$(atan2$a3$)",
    "neg_optab->handlers[$A].insn_code = CODE_FOR_$(neg$P$a2$)",
    "negv_optab->handlers[(int) $A].insn_code =\n\
      neg_optab->handlers[(int) $A].insn_code = CODE_FOR_$(neg$F$a2$)",
Index: builtins.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/builtins.c,v
retrieving revision 1.175
diff -c -3 -p -r1.175 builtins.c
*** builtins.c	7 Feb 2003 22:37:53 -0000	1.175
--- builtins.c	10 Feb 2003 15:08:26 -0000
*************** static rtx expand_builtin_apply		PARAMS
*** 99,105 ****
--- 99,107 ----
  static void expand_builtin_return	PARAMS ((rtx));
  static enum type_class type_to_class	PARAMS ((tree));
  static rtx expand_builtin_classify_type	PARAMS ((tree));
+ static void expand_errno_check		PARAMS ((tree, rtx));
  static rtx expand_builtin_mathfn	PARAMS ((tree, rtx, rtx));
+ static rtx expand_builtin_mathfn_2	PARAMS ((tree, rtx, rtx));
  static rtx expand_builtin_constant_p	PARAMS ((tree));
  static rtx expand_builtin_args_info	PARAMS ((tree));
  static rtx expand_builtin_next_arg	PARAMS ((tree));
*************** mathfn_built_in (type, fn)
*** 1655,1660 ****
--- 1657,1706 ----
    return implicit_built_in_decls[fcode];
  }

+ /* If errno must be maintained, expand the RTL to check if the result,
+    TARGET, of a built-in function call, EXP, is NaN, and if so set
+    errno to EDOM.  */
+
+ static void
+ expand_errno_check (exp, target)
+      tree exp;
+      rtx target;
+ {
+   rtx lab;
+
+   if (flag_errno_math && errno_set && HONOR_NANS (GET_MODE (target)))
+     {
+       lab = gen_label_rtx ();
+
+       /* Test the result; if it is NaN, set errno=EDOM because
+ 	 the argument was not in the domain.  */
+       emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
+ 			       0, lab);
+
+ #ifdef TARGET_EDOM
+       {
+ #ifdef GEN_ERRNO_RTX
+ 	rtx errno_rtx = GEN_ERRNO_RTX;
+ #else
+ 	rtx errno_rtx
+ 	  = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
+ #endif
+
+ 	emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
+       }
+ #else
+       /* We can't set errno=EDOM directly; let the library call do it.
+ 	 Pop the arguments right away in case the call gets deleted.  */
+       NO_DEFER_POP;
+       expand_call (exp, target, 0);
+       OK_DEFER_POP;
+ #endif
+
+       emit_label (lab);
+     }
+ }
+
+
  /* Expand a call to one of the builtin math functions (sin, cos, or sqrt).
     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
*************** expand_builtin_mathfn (exp, target, subt
*** 1760,1800 ****
        return 0;
      }

!   /* If errno must be maintained, we must set it to EDOM for NaN results.  */

!   if (flag_errno_math && errno_set && HONOR_NANS (argmode))
      {
!       rtx lab1;

!       lab1 = gen_label_rtx ();

!       /* Test the result; if it is NaN, set errno=EDOM because
! 	 the argument was not in the domain.  */
!       emit_cmp_and_jump_insns (target, target, EQ, 0, GET_MODE (target),
! 			       0, lab1);

! #ifdef TARGET_EDOM
!       {
! #ifdef GEN_ERRNO_RTX
! 	rtx errno_rtx = GEN_ERRNO_RTX;
! #else
! 	rtx errno_rtx
! 	  = gen_rtx_MEM (word_mode, gen_rtx_SYMBOL_REF (Pmode, "errno"));
! #endif

! 	emit_move_insn (errno_rtx, GEN_INT (TARGET_EDOM));
!       }
! #else
!       /* We can't set errno=EDOM directly; let the library call do it.
! 	 Pop the arguments right away in case the call gets deleted.  */
!       NO_DEFER_POP;
!       expand_call (exp, target, 0);
!       OK_DEFER_POP;
! #endif

!       emit_label (lab1);
      }

    /* Output the entire sequence.  */
    insns = get_insns ();
    end_sequence ();
--- 1806,1910 ----
        return 0;
      }

!   expand_errno_check (exp, target);
!
!   /* Output the entire sequence.  */
!   insns = get_insns ();
!   end_sequence ();
!   emit_insn (insns);
!
!   return target;
! }
!
! /* Expand a call to the builtin binary math functions (pow and atan2).
!    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.
!    SUBTARGET may be used as the target for computing one of EXP's
!    operands.  */
!
! static rtx
! expand_builtin_mathfn_2 (exp, target, subtarget)
!      tree exp;
!      rtx target, subtarget;
! {
!   optab builtin_optab;
!   rtx op0, op1, insns;
!   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
!   tree arglist = TREE_OPERAND (exp, 1);
!   tree arg0, arg1;
!   enum machine_mode argmode;
!   bool errno_set = true;
!   bool stable = true;

!   if (!validate_arglist (arglist, REAL_TYPE, REAL_TYPE, VOID_TYPE))
!     return 0;
!
!   arg0 = TREE_VALUE (arglist);
!   arg1 = TREE_VALUE (TREE_CHAIN (arglist));
!
!   /* Stabilize the arguments.  */
!   if (TREE_CODE (arg0) != VAR_DECL && TREE_CODE (arg0) != PARM_DECL)
      {
!       arg0 = save_expr (arg0);
!       TREE_VALUE (arglist) = arg0;
!       stable = false;
!     }
!   if (TREE_CODE (arg1) != VAR_DECL && TREE_CODE (arg1) != PARM_DECL)
!     {
!       arg1 = save_expr (arg1);
!       TREE_VALUE (TREE_CHAIN (arglist)) = arg1;
!       stable = false;
!     }

!   if (! stable)
!     {
!       exp = copy_node (exp);
!       arglist = tree_cons (NULL_TREE, arg0,
! 			   build_tree_list (NULL_TREE, arg1));
!       TREE_OPERAND (exp, 1) = arglist;
!     }

!   op0 = expand_expr (arg0, subtarget, VOIDmode, 0);
!   op1 = expand_expr (arg1, 0, VOIDmode, 0);

!   /* Make a suitable register to place result in.  */
!   target = gen_reg_rtx (TYPE_MODE (TREE_TYPE (exp)));

!   emit_queue ();
!   start_sequence ();
!
!   switch (DECL_FUNCTION_CODE (fndecl))
!     {
!     case BUILT_IN_POW:
!     case BUILT_IN_POWF:
!     case BUILT_IN_POWL:
!       builtin_optab = pow_optab; break;
!     case BUILT_IN_ATAN2:
!     case BUILT_IN_ATAN2F:
!     case BUILT_IN_ATAN2L:
!       builtin_optab = atan2_optab; break;
!     default:
!       abort ();
!     }
!
!   /* Compute into TARGET.
!      Set TARGET to wherever the result comes back.  */
!   argmode = TYPE_MODE (TREE_TYPE (arg0));
!   target = expand_binop (argmode, builtin_optab, op0, op1,
! 			 target, 0, OPTAB_DIRECT);

!   /* If we were unable to expand via the builtin, stop the
!      sequence (without outputting the insns) and return 0, causing
!      a call to the library function.  */
!   if (target == 0)
!     {
!       end_sequence ();
!       return 0;
      }

+   expand_errno_check (exp, target);
+
    /* Output the entire sequence.  */
    insns = get_insns ();
    end_sequence ();
*************** expand_builtin (exp, target, subtarget,
*** 4043,4048 ****
--- 4153,4171 ----
      case BUILT_IN_NEARBYINTF:
      case BUILT_IN_NEARBYINTL:
        target = expand_builtin_mathfn (exp, target, subtarget);
+       if (target)
+ 	return target;
+       break;
+
+     case BUILT_IN_POW:
+     case BUILT_IN_POWF:
+     case BUILT_IN_POWL:
+     case BUILT_IN_ATAN2:
+     case BUILT_IN_ATAN2F:
+     case BUILT_IN_ATAN2L:
+       if (! flag_unsafe_math_optimizations)
+ 	break;
+       target = expand_builtin_mathfn_2 (exp, target, subtarget);
        if (target)
  	return target;
        break;
Index: doc/md.texi
===================================================================
RCS file: /cvs/gcc/gcc/gcc/doc/md.texi,v
retrieving revision 1.63
diff -c -3 -p -r1.63 md.texi
*** doc/md.texi	1 Feb 2003 19:00:00 -0000	1.63
--- doc/md.texi	10 Feb 2003 15:08:30 -0000
***************
*** 1,5 ****
! @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001, 2002
! @c Free Software Foundation, Inc.
  @c This is part of the GCC manual.
  @c For copying conditions, see the file gcc.texi.

--- 1,5 ----
! @c Copyright (C) 1988, 1989, 1992, 1993, 1994, 1996, 1998, 1999, 2000, 2001,
! @c 2002, 2003 Free Software Foundation, Inc.
  @c This is part of the GCC manual.
  @c For copying conditions, see the file gcc.texi.

*************** Store the natural logarithm of operand 1
*** 2604,2609 ****
--- 2604,2630 ----

  The @code{log} built-in function of C always uses the mode which
  corresponds to the C data type @code{double} and the @code{logf}
+ built-in function uses the mode which corresponds to the C data
+ type @code{float}.
+
+ @cindex @code{pow@var{m}3} instruction pattern
+ @item @samp{pow@var{m}3}
+ Store the value of operand 1 raised to the exponent operand 2
+ into operand 0.
+
+ The @code{pow} built-in function of C always uses the mode which
+ corresponds to the C data type @code{double} and the @code{powf}
+ built-in function uses the mode which corresponds to the C data
+ type @code{float}.
+
+ @cindex @code{atan2@var{m}3} instruction pattern
+ @item @samp{atan2@var{m}3}
+ Store the arc tangent (inverse tangent) of operand 1 divided by
+ operand 2 into operand 0, using the signs of both arguments to
+ determine the quadrant of the result.
+
+ The @code{atan2} built-in function of C always uses the mode which
+ corresponds to the C data type @code{double} and the @code{atan2f}
  built-in function uses the mode which corresponds to the C data
  type @code{float}.


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]