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] x87 constants for doubles with -ffast-math


The following patch extends GCC's use of the x87's instructions to
load special floating point constants, for example "fldpi".  These
instructions load the long double (XFmode) precision representation
of these constants, and so can't normally be used when working with
floats or doubles.

For this reason, GCC currently will generate a "fldpi" instruction
to implement "4*atanl(1)", but won't use it to implement the double
form, i.e. "4*atan(1)", with or without -ffast-math.

The following potentially controversial patch to the i386 backend,
allows the float and double rounded forms of these constants to be
approximated with extra precision when flag_unsafe_math_optimizations
is specified.  I hope this interpretation is reasonable.

The only other tweak in this patch is to use these short instructions
when optimizing for size, even on CPUs where loading the constant from
a constant pool may be faster.


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

Ok for mainline?


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

	* config/i386/i386.c (init_ext_80387_constants): Also initialize
	double and float versions of the 80387 mathematical constants.
	(standard_80387_constant_p): Use these special instructions when
	optimizing for size.  If flag_unsafe_math_optimizations, recognize
	these constants rounded to float or double precision.


Index: i386.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/i386/i386.c,v
retrieving revision 1.581
diff -c -3 -p -r1.581 i386.c
*** i386.c	25 Jun 2003 22:28:26 -0000	1.581
--- i386.c	29 Jun 2003 13:54:13 -0000
*************** static enum x86_64_reg_class merge_class
*** 924,930 ****
  						    enum x86_64_reg_class));

  /* Table of constants used by fldpi, fldln2, etc...  */
! static REAL_VALUE_TYPE ext_80387_constants_table [5];
  static bool ext_80387_constants_init = 0;
  static void init_ext_80387_constants PARAMS ((void));

--- 924,932 ----
  						    enum x86_64_reg_class));

  /* Table of constants used by fldpi, fldln2, etc...  */
! static REAL_VALUE_TYPE ext_80387_xf_constants_table [5];
! static REAL_VALUE_TYPE ext_80387_df_constants_table [5];
! static REAL_VALUE_TYPE ext_80387_sf_constants_table [5];
  static bool ext_80387_constants_init = 0;
  static void init_ext_80387_constants PARAMS ((void));

*************** init_ext_80387_constants ()
*** 4286,4311 ****
      "3.3219280948873623478083405569094566090",  /* 3: fldl2t  */
      "3.1415926535897932385128089594061862044",  /* 4: fldpi   */
    };
    int i;

    for (i = 0; i < 5; i++)
      {
!       real_from_string (&ext_80387_constants_table[i], cst[i]);
!       /* Ensure each constant is rounded to XFmode precision.  */
!       real_convert (&ext_80387_constants_table[i], XFmode,
! 		    &ext_80387_constants_table[i]);
      }

    ext_80387_constants_init = 1;
  }

! /* Return true if the constant is something that can be loaded with
!    a special instruction.  */

  int
  standard_80387_constant_p (x)
       rtx x;
  {
    if (GET_CODE (x) != CONST_DOUBLE || !FLOAT_MODE_P (GET_MODE (x)))
      return -1;

--- 4288,4320 ----
      "3.3219280948873623478083405569094566090",  /* 3: fldl2t  */
      "3.1415926535897932385128089594061862044",  /* 4: fldpi   */
    };
+   REAL_VALUE_TYPE r;
    int i;

    for (i = 0; i < 5; i++)
      {
!       real_from_string (&r, cst[i]);
!       /* Round each constant to the required precision.  */
!       real_convert (&ext_80387_xf_constants_table[i], XFmode, &r);
!       real_convert (&ext_80387_df_constants_table[i], DFmode, &r);
!       real_convert (&ext_80387_sf_constants_table[i], SFmode, &r);
      }

    ext_80387_constants_init = 1;
  }

! /* Return a positive integer index if the real constant is something that
!    can be loaded with a special instruction.  This function returns zero
!    for other constants, and -1 if the RTX isn't a floating point constant.  */

  int
  standard_80387_constant_p (x)
       rtx x;
  {
+   REAL_VALUE_TYPE *table;
+   REAL_VALUE_TYPE r;
+   int i;
+
    if (GET_CODE (x) != CONST_DOUBLE || !FLOAT_MODE_P (GET_MODE (x)))
      return -1;

*************** standard_80387_constant_p (x)
*** 4314,4336 ****
    if (x == CONST1_RTX (GET_MODE (x)))
      return 2;

!   /* For XFmode constants, try to find a special 80387 instruction on
!      those CPUs that benefit from them.  */
!   if (GET_MODE (x) == XFmode
!       && x86_ext_80387_constants & TUNEMASK)
!     {
!       REAL_VALUE_TYPE r;
!       int i;
!
!       if (! ext_80387_constants_init)
! 	init_ext_80387_constants ();

!       REAL_VALUE_FROM_CONST_DOUBLE (r, x);
!       for (i = 0; i < 5; i++)
!         if (real_identical (&r, &ext_80387_constants_table[i]))
! 	  return i + 3;
      }

    return 0;
  }

--- 4323,4354 ----
    if (x == CONST1_RTX (GET_MODE (x)))
      return 2;

!   /* Don't use these instructions on CPUs that don't benefit from them.  */
!   if (! (x86_ext_80387_constants & TUNEMASK)
!       && ! optimize_size)
!     return 0;

!   if (GET_MODE (x) == XFmode)
!     table = ext_80387_xf_constants_table;
!   else if (flag_unsafe_math_optimizations)
!     {
!       if (GET_MODE (x) == DFmode)
! 	table = ext_80387_df_constants_table;
!       else if (GET_MODE (x) == SFmode)
! 	table = ext_80387_sf_constants_table;
!       else
! 	return 0;
      }
+   else
+     return 0;

+   if (! ext_80387_constants_init)
+     init_ext_80387_constants ();
+
+   REAL_VALUE_FROM_CONST_DOUBLE (r, x);
+   for (i = 0; i < 5; i++)
+     if (real_identical (&r, &table[i]))
+       return i + 3;
    return 0;
  }

*************** standard_80387_constant_rtx (idx)
*** 4388,4394 ****
        abort ();
      }

!   return CONST_DOUBLE_FROM_REAL_VALUE (ext_80387_constants_table[i], XFmode);
  }

  /* Return 1 if X is FP constant we can load to SSE register w/o using memory.
--- 4406,4413 ----
        abort ();
      }

!   return CONST_DOUBLE_FROM_REAL_VALUE (ext_80387_xf_constants_table[i],
! 				       XFmode);
  }

  /* Return 1 if X is FP constant we can load to SSE register w/o using memory.

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]