diff mbox series

[03/77] Allow machine modes to be classes

Message ID 87shi0n33j.fsf@linaro.org
State New
Headers show
Series Add wrapper classes for machine_modes | expand

Commit Message

Richard Sandiford July 13, 2017, 8:38 a.m. UTC
This patch makes various changes that allow modes like SImode to be
classes rather than enums.

Firstly, it adds inline functions for all mode size properties,
with the macros being simple wrappers around them.  This is necessary
for the __builtin_constant_p trick to continue working effectively when
the mode arguments are slightly more complex (but still foldable at
compile time).

These inline functions are trivial and heavily used.  There's not much
point keeping them out-of-line at -O0: if anything it would make
debugging harder rather than easier, and it would also slow things down.
The patch therefore marks them as "always_inline", if that's available.
Later patches use this approach too.

Using inline functions means that it's no longer possible to pass
an int to GET_MODE_PRECISION etc.  The Fortran and powerpcspe-c.c
parts are needed to avoid instances of that.

The patch continues to use enums for gencondmd.c, so that more
mode comparisons are integer constant expressions when checking
for always-true or always-false conditions.  This is the only
intended use of USE_ENUM_MODES.

The patch also enforces the previous replacement of case statements
by defining modes as:

  #define FOOmode ((void) 0, E_FOOmode)

This adds no overhead but makes sure that new uses of "case FOOmode:"
don't accidentally creep in when FOOmode has no specific class associated
with it.

2017-07-13  Richard Sandiford  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

gcc/
	* genconditions.c (write_header): Add a "#define USE_ENUM_MODES".
	* genmodes.c (emit_insn_modes_h): Define FOOmode to E_FOOmode if
	USE_ENUM_MODES is defined and to ((void) 0, E_FOOmode) otherwise.
	* machmode.h (mode_size): Move earlier in file.
	(mode_precision): Likewise.
	(mode_inner): Likewise.
	(mode_nunits): Likewise.
	(mode_unit_size): Likewise.
	(unit_unit_precision): Likewise.
	(mode_wider): Likewise.
	(mode_2xwider): Likewise.
	(machine_mode): New class.
	(mode_to_bytes): New function.
	(mode_to_bits): Likewise.
	(mode_to_precision): Likewise.
	(mode_to_inner): Likewise.
	(mode_to_unit_size): Likewise.
	(mode_to_unit_precision): Likewise.
	(mode_to_nunits): Likewise.
	(GET_MODE_SIZE): Use mode_to_bytes.
	(GET_MODE_BITSIZE): Use mode_to_bits.
	(GET_MODE_PRECISION): Use mode_to_precision.
	(GET_MODE_INNER): Use mode_to_inner.
	(GET_MODE_UNIT_SIZE): Use mode_to_unit_size.
	(GET_MODE_UNIT_PRECISION): Use mode_to_unit_precision.
	(GET_MODE_NUNITS): Use mode_to_nunits.
	* system.h (ALWAYS_INLINE): New macro.
	* config/powerpcspe/powerpcspe-c.c
	(altivec_resolve_overloaded_builtin): Use machine_mode instead of
	int for arg1_mode and arg2_mode.

gcc/fortran/
	* trans-types.c (gfc_init_kinds): Use machine_mode instead of int
	for "mode".

Comments

Jeff Law Aug. 11, 2017, 4:48 p.m. UTC | #1
On 07/13/2017 02:38 AM, Richard Sandiford wrote:
> This patch makes various changes that allow modes like SImode to be

> classes rather than enums.

> 

> Firstly, it adds inline functions for all mode size properties,

> with the macros being simple wrappers around them.  This is necessary

> for the __builtin_constant_p trick to continue working effectively when

> the mode arguments are slightly more complex (but still foldable at

> compile time).

> 

> These inline functions are trivial and heavily used.  There's not much

> point keeping them out-of-line at -O0: if anything it would make

> debugging harder rather than easier, and it would also slow things down.

> The patch therefore marks them as "always_inline", if that's available.

> Later patches use this approach too.

> 

> Using inline functions means that it's no longer possible to pass

> an int to GET_MODE_PRECISION etc.  The Fortran and powerpcspe-c.c

> parts are needed to avoid instances of that.

> 

> The patch continues to use enums for gencondmd.c, so that more

> mode comparisons are integer constant expressions when checking

> for always-true or always-false conditions.  This is the only

> intended use of USE_ENUM_MODES.

> 

> The patch also enforces the previous replacement of case statements

> by defining modes as:

> 

>   #define FOOmode ((void) 0, E_FOOmode)

> 

> This adds no overhead but makes sure that new uses of "case FOOmode:"

> don't accidentally creep in when FOOmode has no specific class associated

> with it.

> 

> 2017-07-13  Richard Sandiford  <richard.sandiford@linaro.org>

> 	    Alan Hayward  <alan.hayward@arm.com>

> 	    David Sherwood  <david.sherwood@arm.com>

> 

> gcc/

> 	* genconditions.c (write_header): Add a "#define USE_ENUM_MODES".

> 	* genmodes.c (emit_insn_modes_h): Define FOOmode to E_FOOmode if

> 	USE_ENUM_MODES is defined and to ((void) 0, E_FOOmode) otherwise.

> 	* machmode.h (mode_size): Move earlier in file.

> 	(mode_precision): Likewise.

> 	(mode_inner): Likewise.

> 	(mode_nunits): Likewise.

> 	(mode_unit_size): Likewise.

> 	(unit_unit_precision): Likewise.

> 	(mode_wider): Likewise.

> 	(mode_2xwider): Likewise.

> 	(machine_mode): New class.

> 	(mode_to_bytes): New function.

> 	(mode_to_bits): Likewise.

> 	(mode_to_precision): Likewise.

> 	(mode_to_inner): Likewise.

> 	(mode_to_unit_size): Likewise.

> 	(mode_to_unit_precision): Likewise.

> 	(mode_to_nunits): Likewise.

> 	(GET_MODE_SIZE): Use mode_to_bytes.

> 	(GET_MODE_BITSIZE): Use mode_to_bits.

> 	(GET_MODE_PRECISION): Use mode_to_precision.

> 	(GET_MODE_INNER): Use mode_to_inner.

> 	(GET_MODE_UNIT_SIZE): Use mode_to_unit_size.

> 	(GET_MODE_UNIT_PRECISION): Use mode_to_unit_precision.

> 	(GET_MODE_NUNITS): Use mode_to_nunits.

> 	* system.h (ALWAYS_INLINE): New macro.

> 	* config/powerpcspe/powerpcspe-c.c

> 	(altivec_resolve_overloaded_builtin): Use machine_mode instead of

> 	int for arg1_mode and arg2_mode.

> 

> gcc/fortran/

> 	* trans-types.c (gfc_init_kinds): Use machine_mode instead of int

> 	for "mode".

OK.
Jeff
diff mbox series

Patch

Index: gcc/genconditions.c
===================================================================
--- gcc/genconditions.c	2017-02-23 19:54:12.000000000 +0000
+++ gcc/genconditions.c	2017-07-13 09:18:20.866501621 +0100
@@ -67,6 +67,7 @@  #define CHECKING_P 0\n\
 #undef ENABLE_RTL_FLAG_CHECKING\n\
 #undef ENABLE_GC_CHECKING\n\
 #undef ENABLE_GC_ALWAYS_COLLECT\n\
+#define USE_ENUM_MODES\n\
 \n\
 #include \"coretypes.h\"\n\
 #include \"tm.h\"\n\
Index: gcc/genmodes.c
===================================================================
--- gcc/genmodes.c	2017-07-13 09:18:17.576867543 +0100
+++ gcc/genmodes.c	2017-07-13 09:18:20.866501621 +0100
@@ -1155,8 +1155,12 @@  enum machine_mode\n{");
 	printf ("%*s/* %s:%d */\n", 27 - count_, "",
 		 trim_filename (m->file), m->line);
 	printf ("#define HAVE_%smode\n", m->name);
-	printf ("#define %smode E_%smode\n",
+	printf ("#ifdef USE_ENUM_MODES\n");
+	printf ("#define %smode E_%smode\n", m->name, m->name);
+	printf ("#else\n");
+	printf ("#define %smode ((void) 0, E_%smode)\n",
 		m->name, m->name);
+	printf ("#endif\n");
       }
 
   puts ("  MAX_MACHINE_MODE,\n");
Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-07-02 10:05:20.996539436 +0100
+++ gcc/machmode.h	2017-07-13 09:18:20.866501621 +0100
@@ -20,6 +20,15 @@  Software Foundation; either version 3, o
 #ifndef HAVE_MACHINE_MODES
 #define HAVE_MACHINE_MODES
 
+extern CONST_MODE_SIZE unsigned short mode_size[NUM_MACHINE_MODES];
+extern const unsigned short mode_precision[NUM_MACHINE_MODES];
+extern const unsigned char mode_inner[NUM_MACHINE_MODES];
+extern const unsigned char mode_nunits[NUM_MACHINE_MODES];
+extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];
+extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
+extern const unsigned char mode_wider[NUM_MACHINE_MODES];
+extern const unsigned char mode_2xwider[NUM_MACHINE_MODES];
+
 /* Get the name of mode MODE as a string.  */
 
 extern const char * const mode_name[NUM_MACHINE_MODES];
@@ -174,22 +183,98 @@  #define CLASS_HAS_WIDER_MODES_P(CLASS)
 #define POINTER_BOUNDS_MODE_P(MODE)      \
   (GET_MODE_CLASS (MODE) == MODE_POINTER_BOUNDS)
 
-/* Get the size in bytes and bits of an object of mode MODE.  */
+/* Return the base GET_MODE_SIZE value for MODE.  */
 
-extern CONST_MODE_SIZE unsigned short mode_size[NUM_MACHINE_MODES];
+ALWAYS_INLINE unsigned short
+mode_to_bytes (machine_mode mode)
+{
+#if GCC_VERSION >= 4001
+  return (__builtin_constant_p (mode)
+	  ? mode_size_inline (mode) : mode_size[mode]);
+#else
+  return mode_size[mode];
+#endif
+}
+
+/* Return the base GET_MODE_BITSIZE value for MODE.  */
+
+ALWAYS_INLINE unsigned short
+mode_to_bits (machine_mode mode)
+{
+  return mode_to_bytes (mode) * BITS_PER_UNIT;
+}
+
+/* Return the base GET_MODE_PRECISION value for MODE.  */
+
+ALWAYS_INLINE unsigned short
+mode_to_precision (machine_mode mode)
+{
+  return mode_precision[mode];
+}
+
+/* Return the base GET_MODE_INNER value for MODE.  */
+
+ALWAYS_INLINE machine_mode
+mode_to_inner (machine_mode mode)
+{
+#if GCC_VERSION >= 4001
+  return (machine_mode) (__builtin_constant_p (mode)
+			 ? mode_inner_inline (mode) : mode_inner[mode]);
+#else
+  return (machine_mode) mode_inner[mode];
+#endif
+}
+
+/* Return the base GET_MODE_UNIT_SIZE value for MODE.  */
+
+ALWAYS_INLINE unsigned char
+mode_to_unit_size (machine_mode mode)
+{
 #if GCC_VERSION >= 4001
-#define GET_MODE_SIZE(MODE) \
-  ((unsigned short) (__builtin_constant_p (MODE) \
-		     ? mode_size_inline (MODE) : mode_size[MODE]))
+  return (__builtin_constant_p (mode)
+	  ? mode_unit_size_inline (mode) : mode_unit_size[mode]);
 #else
-#define GET_MODE_SIZE(MODE)    ((unsigned short) mode_size[MODE])
+  return mode_unit_size[mode];
 #endif
-#define GET_MODE_BITSIZE(MODE) \
-  ((unsigned short) (GET_MODE_SIZE (MODE) * BITS_PER_UNIT))
+}
+
+/* Return the base GET_MODE_UNIT_PRECISION value for MODE.  */
+
+ALWAYS_INLINE unsigned short
+mode_to_unit_precision (machine_mode mode)
+{
+#if GCC_VERSION >= 4001
+  return (__builtin_constant_p (mode)
+	  ? mode_unit_precision_inline (mode) : mode_unit_precision[mode]);
+#else
+  return mode_unit_precision[mode];
+#endif
+}
+
+/* Return the base GET_MODE_NUNITS value for MODE.  */
+
+ALWAYS_INLINE unsigned short
+mode_to_nunits (machine_mode mode)
+{
+#if GCC_VERSION >= 4001
+  return (__builtin_constant_p (mode)
+	  ? mode_nunits_inline (mode) : mode_nunits[mode]);
+#else
+  return mode_nunits[mode];
+#endif
+}
+
+/* Get the size in bytes of an object of mode MODE.  */
+
+#define GET_MODE_SIZE(MODE) (mode_to_bytes (MODE))
+
+/* Get the size in bits of an object of mode MODE.  */
+
+#define GET_MODE_BITSIZE(MODE) (mode_to_bits (MODE))
 
 /* Get the number of value bits of an object of mode MODE.  */
-extern const unsigned short mode_precision[NUM_MACHINE_MODES];
-#define GET_MODE_PRECISION(MODE)  mode_precision[MODE]
+
+#define GET_MODE_PRECISION(MODE) (mode_to_precision (MODE))
 
 /* Get the number of integral bits of an object of mode MODE.  */
 extern CONST_MODE_IBIT unsigned char mode_ibit[NUM_MACHINE_MODES];
@@ -210,51 +295,22 @@  #define GET_MODE_MASK(MODE) mode_mask_ar
    mode of the vector elements.  For complex modes it is the mode of the real
    and imaginary parts.  For other modes it is MODE itself.  */
 
-extern const unsigned char mode_inner[NUM_MACHINE_MODES];
-#if GCC_VERSION >= 4001
-#define GET_MODE_INNER(MODE) \
-  ((machine_mode) (__builtin_constant_p (MODE) \
-			? mode_inner_inline (MODE) : mode_inner[MODE]))
-#else
-#define GET_MODE_INNER(MODE) ((machine_mode) mode_inner[MODE])
-#endif
+#define GET_MODE_INNER(MODE) (mode_to_inner (MODE))
 
 /* Get the size in bytes or bits of the basic parts of an
    object of mode MODE.  */
 
-extern CONST_MODE_UNIT_SIZE unsigned char mode_unit_size[NUM_MACHINE_MODES];
-#if GCC_VERSION >= 4001
-#define GET_MODE_UNIT_SIZE(MODE) \
-  ((unsigned char) (__builtin_constant_p (MODE) \
-		   ? mode_unit_size_inline (MODE) : mode_unit_size[MODE]))
-#else
-#define GET_MODE_UNIT_SIZE(MODE) mode_unit_size[MODE]
-#endif
+#define GET_MODE_UNIT_SIZE(MODE) mode_to_unit_size (MODE)
 
 #define GET_MODE_UNIT_BITSIZE(MODE) \
   ((unsigned short) (GET_MODE_UNIT_SIZE (MODE) * BITS_PER_UNIT))
 
-extern const unsigned short mode_unit_precision[NUM_MACHINE_MODES];
-#if GCC_VERSION >= 4001
-#define GET_MODE_UNIT_PRECISION(MODE) \
-  ((unsigned short) (__builtin_constant_p (MODE) \
-		    ? mode_unit_precision_inline (MODE)\
-		    : mode_unit_precision[MODE]))
-#else
-#define GET_MODE_UNIT_PRECISION(MODE) mode_unit_precision[MODE]
-#endif
-
+#define GET_MODE_UNIT_PRECISION(MODE) (mode_to_unit_precision (MODE))
 
-/* Get the number of units in the object.  */
+/* Get the number of units in an object of mode MODE.  This is 2 for
+   complex modes and the number of elements for vector modes.  */
 
-extern const unsigned char mode_nunits[NUM_MACHINE_MODES];
-#if GCC_VERSION >= 4001
-#define GET_MODE_NUNITS(MODE) \
-  ((unsigned char) (__builtin_constant_p (MODE) \
-		    ? mode_nunits_inline (MODE) : mode_nunits[MODE]))
-#else
-#define GET_MODE_NUNITS(MODE)  mode_nunits[MODE]
-#endif
+#define GET_MODE_NUNITS(MODE) (mode_to_nunits (MODE))
 
 /* Get the next wider natural mode (eg, QI -> HI -> SI -> DI -> TI).  */
 
Index: gcc/system.h
===================================================================
--- gcc/system.h	2017-06-12 17:05:23.281759459 +0100
+++ gcc/system.h	2017-07-13 09:18:20.866501621 +0100
@@ -745,6 +745,12 @@  #define gcc_checking_assert(EXPR) gcc_as
 #define gcc_checking_assert(EXPR) ((void)(0 && (EXPR)))
 #endif
 
+#if GCC_VERSION >= 4000
+#define ALWAYS_INLINE inline __attribute__ ((always_inline))
+#else
+#define ALWAYS_INLINE inline
+#endif
+
 /* Use gcc_unreachable() to mark unreachable locations (like an
    unreachable default case of a switch.  Do not use gcc_assert(0).  */
 #if (GCC_VERSION >= 4005) && !ENABLE_ASSERT_CHECKING
Index: gcc/config/powerpcspe/powerpcspe-c.c
===================================================================
--- gcc/config/powerpcspe/powerpcspe-c.c	2017-07-13 09:18:19.088697749 +0100
+++ gcc/config/powerpcspe/powerpcspe-c.c	2017-07-13 09:18:20.865501731 +0100
@@ -6504,8 +6504,8 @@  altivec_resolve_overloaded_builtin (loca
     if (fcode == P6_OV_BUILTIN_CMPB)
       {
 	int overloaded_code;
-	int arg1_mode = TYPE_MODE (types[0]);
-	int arg2_mode = TYPE_MODE (types[1]);
+	machine_mode arg1_mode = TYPE_MODE (types[0]);
+	machine_mode arg2_mode = TYPE_MODE (types[1]);
 
 	if (nargs != 2)
 	  {
Index: gcc/fortran/trans-types.c
===================================================================
--- gcc/fortran/trans-types.c	2017-05-03 08:46:30.890861653 +0100
+++ gcc/fortran/trans-types.c	2017-07-13 09:18:20.865501731 +0100
@@ -362,22 +362,23 @@  #define NAMED_SUBROUTINE(a,b,c,d) \
 void
 gfc_init_kinds (void)
 {
-  unsigned int mode;
+  machine_mode mode;
   int i_index, r_index, kind;
   bool saw_i4 = false, saw_i8 = false;
   bool saw_r4 = false, saw_r8 = false, saw_r10 = false, saw_r16 = false;
 
-  for (i_index = 0, mode = MIN_MODE_INT; mode <= MAX_MODE_INT; mode++)
+  for (i_index = 0, mode = MIN_MODE_INT; mode <= MAX_MODE_INT;
+       mode = (machine_mode) ((int) mode + 1))
     {
       int kind, bitsize;
 
-      if (!targetm.scalar_mode_supported_p ((machine_mode) mode))
+      if (!targetm.scalar_mode_supported_p (mode))
 	continue;
 
       /* The middle end doesn't support constants larger than 2*HWI.
 	 Perhaps the target hook shouldn't have accepted these either,
 	 but just to be safe...  */
-      bitsize = GET_MODE_BITSIZE ((machine_mode) mode);
+      bitsize = GET_MODE_BITSIZE (mode);
       if (bitsize > 2*HOST_BITS_PER_WIDE_INT)
 	continue;
 
@@ -417,15 +418,16 @@  gfc_init_kinds (void)
   /* Set the maximum integer kind.  Used with at least BOZ constants.  */
   gfc_max_integer_kind = gfc_integer_kinds[i_index - 1].kind;
 
-  for (r_index = 0, mode = MIN_MODE_FLOAT; mode <= MAX_MODE_FLOAT; mode++)
+  for (r_index = 0, mode = MIN_MODE_FLOAT; mode <= MAX_MODE_FLOAT;
+       mode = (machine_mode) ((int) mode + 1))
     {
       const struct real_format *fmt =
-	REAL_MODE_FORMAT ((machine_mode) mode);
+	REAL_MODE_FORMAT (mode);
       int kind;
 
       if (fmt == NULL)
 	continue;
-      if (!targetm.scalar_mode_supported_p ((machine_mode) mode))
+      if (!targetm.scalar_mode_supported_p (mode))
 	continue;
 
       /* Only let float, double, long double and __float128 go through.