diff mbox

[3,of,5] , Add suport for PowerPC IEEE 128-bit floating point

Message ID 20140715183803.GC3263@ibm-tiger.the-meissners.org
State New
Headers show

Commit Message

Michael Meissner July 15, 2014, 6:38 p.m. UTC
These patches are the machine independent changes needed to add IEEE 128-bit
floating point to the PowerPC.  The change is to add a new mode macro,
SPECIAL_FLOATING_MODE, that is similar to FRACTIONAL_FLOATING_MODE, except that
the normal widening functions skip SPECIAL_FLOATING_MODE's modes.  In
particular, on the PowerPC, the existing long double functions are faster, than
the IEEE 128-bit emulation functions, so it is desirable that double widens to
long double instead of __float128.

As a consequence of the way I implemented SPECIAL_FLOATING_MODE, some of the
changes involved code that starts at the narrowest type, and goes up by
widening types, until an appropriate mode is found, or we find the mode
itself.  I needed to check whether the wider mode was VOIDmode as well as the
original type.

2014-07-15  Michael Meissner  <meissner@linux.vnet.ibm.com>

	* cse.c (cse_insn): When going through the list of smaller types,
	exit the loop if the type is VOIDmode in addition to the type we
	are looking at, to allow special modes that aren't normally
	considered when widening types.  This is used by the PowerPC, so
	that floating point is widened from double to long double, and
	does not get converted to the slower __float128 (IEEE 128-bit
	floating point).
	* dse.c (find_shift_sequence): Likewise.
	* combine.c (simplify_comparison): Likewise.
	* rtlanal.c (init_num_sign_bit_copies_in_rep): Likewise.

	* machmode.h (GET_MODE_WIDER_MODE_SPECIAL): New macro to get the
	wider types, including special modes that are normally skipped in
	looking for a wider type.

	* machmode.def (SPECIAL_FLOAT_MODE): Document the use of
	SPECIAL_FLOAT_MODE in comments.

	* expr.c (init_expr_target): Use the GET_MODE_WIDER_MODE_SPECIAL
	macro to include special modes in doing the initialization.
	(compress_float_constant): Likewise.

	* genmodes.c (struct mode_data): Add support for
	SPECIAL_FLOAT_MODE that creates floating point modes that are
	normally skipped in widening types, but are available if the user
	explicitly uses the type.
	(complete_mode): Likewise.
	(FLOAT_MODE): Likewise.
	(FRACTIONAL_FLOAT_MODE): Likewise.
	(SPECIAL_FLOAT_MODE): Likewise.
	(FLOAT_MODE_INTERNAL): Likewise.
	(make_float_mode): Likewise.
	(emit_mode_wider): Likewise.

	* emit-rtl.c (init_derived_machine_modes): Use the
	GET_MODE_WIDER_MODE_SPECIAL macro to include special modes in
	doing the initialization.
	(init_emit_once): Likewise.
diff mbox

Patch

Index: gcc/cse.c
===================================================================
--- gcc/cse.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 212529)
+++ gcc/cse.c	(working copy)
@@ -4823,7 +4823,7 @@  cse_insn (rtx insn)
 	  rtx new_and = gen_rtx_AND (VOIDmode, NULL_RTX, XEXP (src, 1));
 
 	  for (tmode = GET_MODE_WIDER_MODE (mode);
-	       GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
+	       GET_MODE_SIZE (tmode) <= UNITS_PER_WORD && tmode != VOIDmode;
 	       tmode = GET_MODE_WIDER_MODE (tmode))
 	    {
 	      rtx inner = gen_lowpart (tmode, XEXP (src, 0));
@@ -4875,7 +4875,7 @@  cse_insn (rtx insn)
 	  XEXP (memory_extend_rtx, 0) = src;
 
 	  for (tmode = GET_MODE_WIDER_MODE (mode);
-	       GET_MODE_SIZE (tmode) <= UNITS_PER_WORD;
+	       GET_MODE_SIZE (tmode) <= UNITS_PER_WORD && tmode != VOIDmode;
 	       tmode = GET_MODE_WIDER_MODE (tmode))
 	    {
 	      struct table_elt *larger_elt;
Index: gcc/dse.c
===================================================================
--- gcc/dse.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 212529)
+++ gcc/dse.c	(working copy)
@@ -1738,7 +1738,7 @@  find_shift_sequence (int access_size,
 
   for (new_mode = smallest_mode_for_size (access_size * BITS_PER_UNIT,
 					  MODE_INT);
-       GET_MODE_BITSIZE (new_mode) <= BITS_PER_WORD;
+       GET_MODE_BITSIZE (new_mode) <= BITS_PER_WORD && new_mode != VOIDmode;
        new_mode = GET_MODE_WIDER_MODE (new_mode))
     {
       rtx target, new_reg, shift_seq, insn, new_lhs;
Index: gcc/combine.c
===================================================================
--- gcc/combine.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 212529)
+++ gcc/combine.c	(working copy)
@@ -11118,7 +11118,8 @@  simplify_comparison (enum rtx_code code,
 	  else if (c0 == c1)
 	    for (tmode = GET_CLASS_NARROWEST_MODE
 		 (GET_MODE_CLASS (GET_MODE (op0)));
-		 tmode != GET_MODE (op0); tmode = GET_MODE_WIDER_MODE (tmode))
+		 tmode != GET_MODE (op0) && tmode != VOIDmode;
+		 tmode = GET_MODE_WIDER_MODE (tmode))
 	      if ((unsigned HOST_WIDE_INT) c0 == GET_MODE_MASK (tmode))
 		{
 		  op0 = gen_lowpart (tmode, inner_op0);
Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 212529)
+++ gcc/machmode.h	(working copy)
@@ -249,6 +249,12 @@  extern const unsigned char mode_nunits[N
 extern const unsigned char mode_wider[NUM_MACHINE_MODES];
 #define GET_MODE_WIDER_MODE(MODE) ((enum machine_mode) mode_wider[MODE])
 
+/* Special modes are not listed in the normal widening tables, but they are
+   listed in the widening tables used for initialization, etc.  */
+extern const unsigned char mode_wider_special[NUM_MACHINE_MODES];
+#define GET_MODE_WIDER_MODE_SPECIAL(MODE) \
+  ((enum machine_mode) mode_wider_special[MODE])
+
 /* For scalars, this is a mode with twice the precision.  For vectors,
    this is a mode with the same inner mode but with twice the elements.  */
 extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
Index: gcc/rtlanal.c
===================================================================
--- gcc/rtlanal.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 212529)
+++ gcc/rtlanal.c	(working copy)
@@ -5278,7 +5278,8 @@  init_num_sign_bit_copies_in_rep (void)
 
   for (in_mode = GET_CLASS_NARROWEST_MODE (MODE_INT); in_mode != VOIDmode;
        in_mode = GET_MODE_WIDER_MODE (mode))
-    for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT); mode != in_mode;
+    for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
+	 mode != in_mode && mode != VOIDmode;
 	 mode = GET_MODE_WIDER_MODE (mode))
       {
 	enum machine_mode i;
Index: gcc/machmode.def
===================================================================
--- gcc/machmode.def	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 212529)
+++ gcc/machmode.def	(working copy)
@@ -90,6 +90,15 @@  along with GCC; see the file COPYING3.  
 	storage, but with only PRECISION significant bits, using
 	floating point format FORMAT.
 
+     SPECIAL_FLOAT_MODE (MODE, BYTESIZE, FORMAT);
+        declares MODE to be of class FLOAT and BYTESIZE bytes wide, using
+	floating point format FORMAT.  MODE is arranged so that other scalar
+	floating point mode's of the same size are preferred when the compiler
+	is trying to widen the floating point.  The intention is to support the
+	PowerPC which has 2 128-bit floating point types (IEEE 128-bit and the
+	IBM extended double format), and have DFmode widen to TFmode (IBM
+	format) instead of KFmode (IEEE 128-bit).
+
      DECIMAL_FLOAT_MODE (MODE, BYTESIZE, FORMAT);
 	declares MODE to be of class DECIMAL_FLOAT and BYTESIZE bytes
 	wide.  All of the bits of its representation are significant.
Index: gcc/expr.c
===================================================================
--- gcc/expr.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 212529)
+++ gcc/expr.c	(working copy)
@@ -264,11 +264,11 @@  init_expr_target (void)
   mem = gen_rtx_MEM (VOIDmode, gen_rtx_raw_REG (Pmode, 10000));
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       enum machine_mode srcmode;
       for (srcmode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT); srcmode != mode;
-	   srcmode = GET_MODE_WIDER_MODE (srcmode))
+	   srcmode = GET_MODE_WIDER_MODE_SPECIAL (srcmode))
 	{
 	  enum insn_code ic;
 
@@ -3645,7 +3645,7 @@  compress_float_constant (rtx x, rtx y)
     oldcost = set_src_cost (force_const_mem (dstmode, y), speed);
 
   for (srcmode = GET_CLASS_NARROWEST_MODE (GET_MODE_CLASS (orig_srcmode));
-       srcmode != orig_srcmode;
+       srcmode != orig_srcmode && srcmode != VOIDmode;
        srcmode = GET_MODE_WIDER_MODE (srcmode))
     {
       enum insn_code ic;
Index: gcc/genmodes.c
===================================================================
--- gcc/genmodes.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 212529)
+++ gcc/genmodes.c	(working copy)
@@ -74,6 +74,8 @@  struct mode_data
   unsigned int fbit;		/* the number of fractional bits */
   bool need_bytesize_adj;	/* true if this mode need dynamic size
 				   adjustment */
+  bool special;			/* true if this mode is special and should be
+				   skipped with the normal widening rules.  */
 };
 
 static struct mode_data *modes[MAX_MODE_CLASS];
@@ -84,7 +86,7 @@  static const struct mode_data blank_mode
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
   0, 0, 0, 0, 0,
-  "<unknown>", 0, 0, 0, 0, false
+  "<unknown>", 0, 0, 0, 0, false, false
 };
 
 static htab_t modes_by_name;
@@ -368,6 +370,7 @@  complete_mode (struct mode_data *m)
       /* Complex modes should have a component indicated, but no more.  */
       validate_mode (m, UNSET, UNSET, SET, UNSET, UNSET);
       m->ncomponents = 2;
+      m->special = m->component->special;
       if (m->component->precision != (unsigned int)-1)
 	m->precision = 2 * m->component->precision;
       m->bytesize = 2 * m->component->bytesize;
@@ -384,6 +387,7 @@  complete_mode (struct mode_data *m)
       if (m->component->precision != (unsigned int)-1)
 	m->precision = m->ncomponents * m->component->precision;
       m->bytesize = m->ncomponents * m->component->bytesize;
+      m->special = m->component->special;
       break;
 
     default:
@@ -579,20 +583,29 @@  make_fixed_point_mode (enum mode_class c
   m->fbit = fbit;
 }
 
-#define FLOAT_MODE(N, Y, F)             FRACTIONAL_FLOAT_MODE (N, -1U, Y, F)
-#define FRACTIONAL_FLOAT_MODE(N, B, Y, F) \
-  make_float_mode (#N, B, Y, #F, __FILE__, __LINE__)
+#define FLOAT_MODE(N, Y, F)				\
+  FLOAT_MODE_INTERNAL (N, -1U, Y, F, false)
+
+#define FRACTIONAL_FLOAT_MODE(N, B, Y, F)		\
+  FLOAT_MODE_INTERNAL (N, B, Y, F, false)
+
+#define SPECIAL_FLOAT_MODE(N, B, Y, F)			\
+  FLOAT_MODE_INTERNAL (N, B, Y, F, true)
+
+#define FLOAT_MODE_INTERNAL(N, B, Y, F, SPECIAL)	\
+  make_float_mode (#N, B, Y, #F, SPECIAL, __FILE__, __LINE__)
 
 static void
 make_float_mode (const char *name,
 		 unsigned int precision, unsigned int bytesize,
-		 const char *format,
+		 const char *format, bool special,
 		 const char *file, unsigned int line)
 {
   struct mode_data *m = new_mode (MODE_FLOAT, name, file, line);
   m->bytesize = bytesize;
   m->precision = precision;
   m->format = format;
+  m->special = special;
 }
 
 #define DECIMAL_FLOAT_MODE(N, Y, F)	\
@@ -1194,7 +1207,9 @@  emit_mode_wider (void)
   int c;
   struct mode_data *m;
 
-  print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES");
+  /* Special modes are not listed in the normal widening tables, but they are
+     listed in the widening tables used for initialization, etc.  */
+  print_decl ("unsigned char", "mode_wider_special", "NUM_MACHINE_MODES");
 
   for_all_modes (c, m)
     tagged_printf ("%smode",
@@ -1202,6 +1217,37 @@  emit_mode_wider (void)
 		   m->name);
 
   print_closer ();
+  print_decl ("unsigned char", "mode_wider", "NUM_MACHINE_MODES");
+
+  for_all_modes (c, m)
+    {
+      const char *name;
+
+      if (!m->wider)
+	name = void_mode->name;
+      else if (!m->wider->special || m->special)
+	name = m->wider->name;
+      else
+	{
+	  struct mode_data * m2;
+
+	  name = void_mode->name;
+	  for (m2 = m->wider->wider;
+	       m2 && m2 != void_mode;
+	       m2 = m2->wider)
+	    {
+	      if (!m2->special)
+		{
+		  name = m2->name;
+		  break;
+		}
+	    }
+	}
+
+      tagged_printf ("%smode", name, m->name);
+    }
+
+  print_closer ();
   print_decl ("unsigned char", "mode_2xwider", "NUM_MACHINE_MODES");
 
   for_all_modes (c, m)
@@ -1212,6 +1258,8 @@  emit_mode_wider (void)
 	   m2 && m2 != void_mode;
 	   m2 = m2->wider)
 	{
+	  if (m2->special && !m->special)
+	    continue;
 	  if (m2->bytesize < 2 * m->bytesize)
 	    continue;
 	  if (m->precision != (unsigned int) -1)
@@ -1242,8 +1290,10 @@  emit_mode_wider (void)
 
 	  break;
 	}
+
       if (m2 == void_mode)
 	m2 = 0;
+
       tagged_printf ("%smode",
 		     m2 ? m2->name : void_mode->name,
 		     m->name);
Index: gcc/emit-rtl.c
===================================================================
--- gcc/emit-rtl.c	(.../svn+ssh://meissner@gcc.gnu.org/svn/gcc/trunk)	(revision 212529)
+++ gcc/emit-rtl.c	(working copy)
@@ -5786,7 +5786,7 @@  init_derived_machine_modes (void)
 
   for (enum machine_mode mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       if (GET_MODE_BITSIZE (mode) == BITS_PER_UNIT
 	  && byte_mode == VOIDmode)
@@ -5868,13 +5868,13 @@  init_emit_once (void)
 
       for (mode = GET_CLASS_NARROWEST_MODE (MODE_FLOAT);
 	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+	   mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
 	const_tiny_rtx[i][(int) mode] =
 	  CONST_DOUBLE_FROM_REAL_VALUE (*r, mode);
 
       for (mode = GET_CLASS_NARROWEST_MODE (MODE_DECIMAL_FLOAT);
 	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+	   mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
 	const_tiny_rtx[i][(int) mode] =
 	  CONST_DOUBLE_FROM_REAL_VALUE (*r, mode);
 
@@ -5882,7 +5882,7 @@  init_emit_once (void)
 
       for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
 	   mode != VOIDmode;
-	   mode = GET_MODE_WIDER_MODE (mode))
+	   mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
 	const_tiny_rtx[i][(int) mode] = GEN_INT (i);
 
       for (mode = MIN_MODE_PARTIAL_INT;
@@ -5895,7 +5895,7 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     const_tiny_rtx[3][(int) mode] = constm1_rtx;
 
   for (mode = MIN_MODE_PARTIAL_INT;
@@ -5905,7 +5905,7 @@  init_emit_once (void)
       
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_INT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       rtx inner = const_tiny_rtx[0][(int)GET_MODE_INNER (mode)];
       const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
@@ -5913,7 +5913,7 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_COMPLEX_FLOAT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       rtx inner = const_tiny_rtx[0][(int)GET_MODE_INNER (mode)];
       const_tiny_rtx[0][(int) mode] = gen_rtx_CONCAT (mode, inner, inner);
@@ -5921,7 +5921,7 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_INT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
@@ -5930,7 +5930,7 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FLOAT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
@@ -5938,7 +5938,7 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_FRACT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       FCONST0 (mode).data.high = 0;
       FCONST0 (mode).data.low = 0;
@@ -5949,7 +5949,7 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_UFRACT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       FCONST0 (mode).data.high = 0;
       FCONST0 (mode).data.low = 0;
@@ -5960,7 +5960,7 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_ACCUM);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       FCONST0 (mode).data.high = 0;
       FCONST0 (mode).data.low = 0;
@@ -5982,7 +5982,7 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_UACCUM);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       FCONST0 (mode).data.high = 0;
       FCONST0 (mode).data.low = 0;
@@ -6004,21 +6004,21 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_FRACT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
     }
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_UFRACT);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
     }
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_ACCUM);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);
@@ -6026,7 +6026,7 @@  init_emit_once (void)
 
   for (mode = GET_CLASS_NARROWEST_MODE (MODE_VECTOR_UACCUM);
        mode != VOIDmode;
-       mode = GET_MODE_WIDER_MODE (mode))
+       mode = GET_MODE_WIDER_MODE_SPECIAL (mode))
     {
       const_tiny_rtx[0][(int) mode] = gen_const_vector (mode, 0);
       const_tiny_rtx[1][(int) mode] = gen_const_vector (mode, 1);