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 3)


As described in my previous post, this patch provides an implementation
of the atan2sf3, atan2df3, atan2xf3 and atan2tf3 patterns in i386.md
using the x87's "fpatan" instruction.

The patterns themselves are almost trivial, the hardship was the
modifications to reg-stack.c to provide support for binary built-in
functions.  Whilst I was there I also provided support for 0-arity
built-in functions.  To provide hooks to hang these changes off of,
I've added some otherwise unused UNSPEC indices to i386.md.  Once
this patch is approved, it should be a simple task to also provide
log?f2 and exp?f2 patterns using this infrastructure, to implement
log and exp respectively.

This patch has been tested, in combination with the previous patch,
on i686-pc-linux-gnu, with a full bootstrap and "make -k check", all
languages except Ada and treelang, with no new regressions.  I've
also checked that "atan2" is indeed inlined with "-O2 -ffast-math"
and that it produces the expected results for the handful of cases
that I tried.

Ok for mainline?


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

	* config/i386/i386.md: Define UNSPEC constants for FLD* insns,
	FPATAN and FYL2X.  Only FPATAN is currently used.
	(atan2sf3, atan2df3, atan2xf3, atan2tf3): New patterns.

	* reg-stack.c (subst_stack_regs_pat): Add support for 0-arity
	(e.g. "fldpi") and binary (e.g. "fpatan") UNSPEC instructions.

	* gcc.dg/i386-387-1.c: Add new test for __builtin_atan2.
	* gcc.dg/i386-387-2.c: Likewise.


Index: reg-stack.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/reg-stack.c,v
retrieving revision 1.120
diff -c -3 -p -r1.120 reg-stack.c
*** reg-stack.c	6 Jan 2003 20:02:56 -0000	1.120
--- reg-stack.c	10 Feb 2003 01:27:02 -0000
***************
*** 1,6 ****
  /* Register to Stack convert for GNU compiler.
!    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998,
!    1999, 2000, 2001, 2002 Free Software Foundation, Inc.

     This file is part of GCC.

--- 1,6 ----
  /* Register to Stack convert for GNU compiler.
!    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999,
!    2000, 2001, 2002, 2003 Free Software Foundation, Inc.

     This file is part of GCC.

*************** subst_stack_regs_pat (insn, regstack, pa
*** 1703,1708 ****
--- 1703,1720 ----
  	  case UNSPEC:
  	    switch (XINT (pat_src, 1))
  	      {
+ 	      case UNSPEC_FLDLG2:
+ 	      case UNSPEC_FLDLN2:
+ 	      case UNSPEC_FLDL2E:
+ 	      case UNSPEC_FLDL2T:
+ 	      case UNSPEC_FLDPI:
+ 		/* These insns only push a value on the stack.  */
+
+ 		regstack->reg[++regstack->top] = REGNO (*dest);
+ 		SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
+ 		replace_reg (dest, FIRST_STACK_REG);
+ 		break;
+
  	      case UNSPEC_SIN:
  	      case UNSPEC_COS:
  		/* These insns only operate on the top of the stack.  */
*************** subst_stack_regs_pat (insn, regstack, pa
*** 1724,1729 ****
--- 1736,1809 ----
  		  }

  		replace_reg (src1, FIRST_STACK_REG);
+ 		break;
+
+ 	      case UNSPEC_FPATAN:
+ 	      case UNSPEC_FYL2X:
+ 		/* These insns operate on the top two stack slots.  */
+
+ 		src1 = get_true_reg (&XVECEXP (pat_src, 0, 0));
+ 		src2 = get_true_reg (&XVECEXP (pat_src, 0, 1));
+
+ 		src1_note = find_regno_note (insn, REG_DEAD, REGNO (*src1));
+ 		src2_note = find_regno_note (insn, REG_DEAD, REGNO (*src2));
+
+ 		{
+ 		  struct stack_def temp_stack;
+ 		  int regno, j, k, temp;
+
+  		  temp_stack = *regstack;
+
+ 		  /* Place operand 1 at the top of stack.  */
+ 		  regno = get_hard_regnum (&temp_stack, *src1);
+ 		  if (regno < 0)
+ 		    abort ();
+ 		  if (regno != FIRST_STACK_REG)
+ 		    {
+ 		      k = temp_stack.top - (regno - FIRST_STACK_REG);
+ 		      j = temp_stack.top;
+
+ 		      temp = temp_stack.reg[k];
+ 		      temp_stack.reg[k] = temp_stack.reg[j];
+ 		      temp_stack.reg[j] = temp;
+ 		    }
+
+ 		  /* Place operand 2 next on the stack.  */
+ 		  regno = get_hard_regnum (&temp_stack, *src2);
+ 		  if (regno < 0)
+ 		    abort ();
+ 		  if (regno != FIRST_STACK_REG + 1)
+ 		    {
+ 		      k = temp_stack.top - (regno - FIRST_STACK_REG);
+ 		      j = temp_stack.top - 1;
+
+ 		      temp = temp_stack.reg[k];
+ 		      temp_stack.reg[k] = temp_stack.reg[j];
+ 		      temp_stack.reg[j] = temp;
+ 		    }
+
+ 		  change_stack (insn, regstack, &temp_stack, EMIT_BEFORE);
+ 		}
+
+ 		replace_reg (src1, FIRST_STACK_REG);
+ 		replace_reg (src2, FIRST_STACK_REG + 1);
+
+ 		if (src1_note)
+ 		  replace_reg (&XEXP (src1_note, 0), FIRST_STACK_REG);
+ 		if (src2_note)
+ 		  replace_reg (&XEXP (src2_note, 0), FIRST_STACK_REG + 1);
+
+ 		/* Pop both input operands from the stack.  */
+ 		CLEAR_HARD_REG_BIT (regstack->reg_set,
+ 				    regstack->reg[regstack->top]);
+ 		CLEAR_HARD_REG_BIT (regstack->reg_set,
+ 				    regstack->reg[regstack->top - 1]);
+ 		regstack->top -= 2;
+
+ 		/* Push the result back onto the stack.  */
+ 		regstack->reg[++regstack->top] = REGNO (*dest);
+ 		SET_HARD_REG_BIT (regstack->reg_set, REGNO (*dest));
+ 		replace_reg (dest, FIRST_STACK_REG);
  		break;

  	      case UNSPEC_SAHF:
Index: config/i386/i386.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.md,v
retrieving revision 1.429
diff -c -3 -p -r1.429 i386.md
*** config/i386/i386.md	7 Feb 2003 22:26:52 -0000	1.429
--- config/i386/i386.md	10 Feb 2003 01:27:07 -0000
***************
*** 109,114 ****
--- 109,124 ----
     (UNSPEC_MFENCE		59)
     (UNSPEC_LFENCE		60)
     (UNSPEC_PSADBW		61)
+
+    ; x87 Floating point
+    (UNSPEC_FLDLG2		65)
+    (UNSPEC_FLDLN2		66)
+    (UNSPEC_FLDL2E		67)
+    (UNSPEC_FLDL2T		68)
+    (UNSPEC_FLDPI		69)
+
+    (UNSPEC_FPATAN		70)
+    (UNSPEC_FYL2X		71)
    ])

  (define_constants
***************
*** 15456,15461 ****
--- 15466,15515 ----
    "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
     && flag_unsafe_math_optimizations"
    "fcos"
+   [(set_attr "type" "fpspc")
+    (set_attr "mode" "XF")])
+
+ (define_insn "atan2df3"
+   [(set (match_operand:DF 0 "register_operand" "=f")
+ 	(unspec:DF [(match_operand:DF 2 "register_operand" "0")
+ 		    (match_operand:DF 1 "register_operand" "u")]
+ 	 UNSPEC_FPATAN))]
+   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+    && flag_unsafe_math_optimizations"
+   "fpatan"
+   [(set_attr "type" "fpspc")
+    (set_attr "mode" "DF")])
+
+ (define_insn "atan2sf3"
+   [(set (match_operand:SF 0 "register_operand" "=f")
+ 	(unspec:SF [(match_operand:SF 2 "register_operand" "0")
+ 		    (match_operand:SF 1 "register_operand" "u")]
+ 	 UNSPEC_FPATAN))]
+   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+    && flag_unsafe_math_optimizations"
+   "fpatan"
+   [(set_attr "type" "fpspc")
+    (set_attr "mode" "SF")])
+
+ (define_insn "atan2xf3"
+   [(set (match_operand:XF 0 "register_operand" "=f")
+ 	(unspec:XF [(match_operand:XF 2 "register_operand" "0")
+ 		    (match_operand:XF 1 "register_operand" "u")]
+ 	 UNSPEC_FPATAN))]
+   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+    && flag_unsafe_math_optimizations"
+   "fpatan"
+   [(set_attr "type" "fpspc")
+    (set_attr "mode" "XF")])
+
+ (define_insn "atan2tf3"
+   [(set (match_operand:TF 0 "register_operand" "=f")
+ 	(unspec:TF [(match_operand:TF 2 "register_operand" "0")
+ 		    (match_operand:TF 1 "register_operand" "u")]
+ 	 UNSPEC_FPATAN))]
+   "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
+    && flag_unsafe_math_optimizations"
+   "fpatan"
    [(set_attr "type" "fpspc")
     (set_attr "mode" "XF")])


Index: gcc.dg/i386-387-1.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/i386-387-1.c,v
retrieving revision 1.3
diff -c -3 -p -r1.3 i386-387-1.c
*** gcc.dg/i386-387-1.c	14 Apr 2002 11:52:25 -0000	1.3
--- gcc.dg/i386-387-1.c	10 Feb 2003 01:29:49 -0000
***************
*** 4,10 ****
--- 4,12 ----
  /* { dg-final { scan-assembler "call\t_?sin" } } */
  /* { dg-final { scan-assembler "call\t_?cos" } } */
  /* { dg-final { scan-assembler "call\t_?sqrt" } } */
+ /* { dg-final { scan-assembler "call\t_?atan2" } } */

  double f1(double x) { return __builtin_sin(x); }
  double f2(double x) { return __builtin_cos(x); }
  double f3(double x) { return __builtin_sqrt(x); }
+ double f4(double x, double y) { return __builtin_atan2(x,y); }
Index: gcc.dg/i386-387-2.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/testsuite/gcc.dg/i386-387-2.c,v
retrieving revision 1.2
diff -c -3 -p -r1.2 i386-387-2.c
*** gcc.dg/i386-387-2.c	29 Mar 2002 23:24:20 -0000	1.2
--- gcc.dg/i386-387-2.c	10 Feb 2003 01:29:49 -0000
***************
*** 4,10 ****
--- 4,12 ----
  /* { dg-final { scan-assembler "fsin" } } */
  /* { dg-final { scan-assembler "fcos" } } */
  /* { dg-final { scan-assembler "fsqrt" } } */
+ /* { dg-final { scan-assembler "fpatan" } } */

  double f1(double x) { return __builtin_sin(x); }
  double f2(double x) { return __builtin_cos(x); }
  double f3(double x) { return __builtin_sqrt(x); }
+ double f4(double x, double y) { return __builtin_atan2(x,y); }

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]