diff mbox series

Add support for adjusting the number of units in a mode

Message ID 87k1zjte2n.fsf@linaro.org
State New
Headers show
Series Add support for adjusting the number of units in a mode | expand

Commit Message

Richard Sandiford Oct. 25, 2017, 3:57 p.m. UTC
We already allow the target to change the size and alignment of a mode.
This patch does the same thing for the number of units, which is needed
to give command-line control of the SVE vector length.

Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu,
on top of the poly_int series.  I think I can approve this under the
gen* maintainership, so if there are no comments in the menatime,
I'll apply it if the prerequisites are approved.

Thanks,
Richard


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

gcc/
	* machmode.h (mode_precision): Prefix with CONST_MODE_PRECISION.
	(mode_nunits): Likewise CONST_MODE_NUNITS.
	* machmode.def (ADJUST_NUNITS): Document.
	* genmodes.c (mode_data::need_nunits_adj): New field.
	(blank_mode): Update accordingly.
	(adj_nunits): New variable.
	(print_maybe_const_decl): Replace CATEGORY with a NEEDS_ADJ
	parameter.
	(emit_mode_size_inline): Set need_bytesize_adj for all modes
	listed in adj_nunits.
	(emit_mode_nunits_inline): Set need_nunits_adj for all modes
	listed in adj_nunits.  Don't emit case statements for such modes.
	(emit_insn_modes_h): Emit definitions of CONST_MODE_NUNITS
	and CONST_MODE_PRECISION.  Make CONST_MODE_SIZE expand to
	nothing if adj_nunits is nonnull.
	(emit_mode_precision, emit_mode_nunits): Use print_maybe_const_decl.
	(emit_mode_unit_size, emit_mode_base_align, emit_mode_ibit)
	(emit_mode_fbit): Update use of print_maybe_const_decl.
	(emit_move_size): Likewise.  Treat the array as non-const
	if adj_nunits.
	(emit_mode_adjustments): Handle adj_nunits.

Comments

Jeff Law Nov. 8, 2017, 10:40 p.m. UTC | #1
On 10/25/2017 09:57 AM, Richard Sandiford wrote:
> We already allow the target to change the size and alignment of a mode.
> This patch does the same thing for the number of units, which is needed
> to give command-line control of the SVE vector length.
> 
> Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu,
> on top of the poly_int series.  I think I can approve this under the
> gen* maintainership, so if there are no comments in the menatime,
> I'll apply it if the prerequisites are approved.
> 
> Thanks,
> Richard
> 
> 
> 2017-10-25  Richard Sandiford  <richard.sandiford@linaro.org>
> 	    Alan Hayward  <alan.hayward@arm.com>
> 	    David Sherwood  <david.sherwood@arm.com>
> 
> gcc/
> 	* machmode.h (mode_precision): Prefix with CONST_MODE_PRECISION.
> 	(mode_nunits): Likewise CONST_MODE_NUNITS.
> 	* machmode.def (ADJUST_NUNITS): Document.
> 	* genmodes.c (mode_data::need_nunits_adj): New field.
> 	(blank_mode): Update accordingly.
> 	(adj_nunits): New variable.
> 	(print_maybe_const_decl): Replace CATEGORY with a NEEDS_ADJ
> 	parameter.
> 	(emit_mode_size_inline): Set need_bytesize_adj for all modes
> 	listed in adj_nunits.
> 	(emit_mode_nunits_inline): Set need_nunits_adj for all modes
> 	listed in adj_nunits.  Don't emit case statements for such modes.
> 	(emit_insn_modes_h): Emit definitions of CONST_MODE_NUNITS
> 	and CONST_MODE_PRECISION.  Make CONST_MODE_SIZE expand to
> 	nothing if adj_nunits is nonnull.
> 	(emit_mode_precision, emit_mode_nunits): Use print_maybe_const_decl.
> 	(emit_mode_unit_size, emit_mode_base_align, emit_mode_ibit)
> 	(emit_mode_fbit): Update use of print_maybe_const_decl.
> 	(emit_move_size): Likewise.  Treat the array as non-const
> 	if adj_nunits.
> 	(emit_mode_adjustments): Handle adj_nunits.
Were all the prereqs here approved?  Or does this depend on the poly_int
stuff?

jeff
Richard Sandiford Nov. 9, 2017, 11:08 a.m. UTC | #2
Jeff Law <law@redhat.com> writes:
> On 10/25/2017 09:57 AM, Richard Sandiford wrote:
>> We already allow the target to change the size and alignment of a mode.
>> This patch does the same thing for the number of units, which is needed
>> to give command-line control of the SVE vector length.
>> 
>> Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu,
>> on top of the poly_int series.  I think I can approve this under the
>> gen* maintainership, so if there are no comments in the menatime,
>> I'll apply it if the prerequisites are approved.
>> 
>> Thanks,
>> Richard
>> 
>> 
>> 2017-10-25  Richard Sandiford  <richard.sandiford@linaro.org>
>> 	    Alan Hayward  <alan.hayward@arm.com>
>> 	    David Sherwood  <david.sherwood@arm.com>
>> 
>> gcc/
>> 	* machmode.h (mode_precision): Prefix with CONST_MODE_PRECISION.
>> 	(mode_nunits): Likewise CONST_MODE_NUNITS.
>> 	* machmode.def (ADJUST_NUNITS): Document.
>> 	* genmodes.c (mode_data::need_nunits_adj): New field.
>> 	(blank_mode): Update accordingly.
>> 	(adj_nunits): New variable.
>> 	(print_maybe_const_decl): Replace CATEGORY with a NEEDS_ADJ
>> 	parameter.
>> 	(emit_mode_size_inline): Set need_bytesize_adj for all modes
>> 	listed in adj_nunits.
>> 	(emit_mode_nunits_inline): Set need_nunits_adj for all modes
>> 	listed in adj_nunits.  Don't emit case statements for such modes.
>> 	(emit_insn_modes_h): Emit definitions of CONST_MODE_NUNITS
>> 	and CONST_MODE_PRECISION.  Make CONST_MODE_SIZE expand to
>> 	nothing if adj_nunits is nonnull.
>> 	(emit_mode_precision, emit_mode_nunits): Use print_maybe_const_decl.
>> 	(emit_mode_unit_size, emit_mode_base_align, emit_mode_ibit)
>> 	(emit_mode_fbit): Update use of print_maybe_const_decl.
>> 	(emit_move_size): Likewise.  Treat the array as non-const
>> 	if adj_nunits.
>> 	(emit_mode_adjustments): Handle adj_nunits.
> Were all the prereqs here approved?  Or does this depend on the poly_int
> stuff?

Yeah, it depends on the poly_int stuff.  Not in a major way though --
I could reorder it if necessary.

Thanks,
Richard
Jeff Law Nov. 19, 2017, 11:47 p.m. UTC | #3
On 11/09/2017 04:08 AM, Richard Sandiford wrote:
> Jeff Law <law@redhat.com> writes:
>> On 10/25/2017 09:57 AM, Richard Sandiford wrote:
>>> We already allow the target to change the size and alignment of a mode.
>>> This patch does the same thing for the number of units, which is needed
>>> to give command-line control of the SVE vector length.
>>>
>>> Tested on aarch64-linux-gnu, x86_64-linux-gnu and powerpc64le-linux-gnu,
>>> on top of the poly_int series.  I think I can approve this under the
>>> gen* maintainership, so if there are no comments in the menatime,
>>> I'll apply it if the prerequisites are approved.
>>>
>>> Thanks,
>>> Richard
>>>
>>>
>>> 2017-10-25  Richard Sandiford  <richard.sandiford@linaro.org>
>>> 	    Alan Hayward  <alan.hayward@arm.com>
>>> 	    David Sherwood  <david.sherwood@arm.com>
>>>
>>> gcc/
>>> 	* machmode.h (mode_precision): Prefix with CONST_MODE_PRECISION.
>>> 	(mode_nunits): Likewise CONST_MODE_NUNITS.
>>> 	* machmode.def (ADJUST_NUNITS): Document.
>>> 	* genmodes.c (mode_data::need_nunits_adj): New field.
>>> 	(blank_mode): Update accordingly.
>>> 	(adj_nunits): New variable.
>>> 	(print_maybe_const_decl): Replace CATEGORY with a NEEDS_ADJ
>>> 	parameter.
>>> 	(emit_mode_size_inline): Set need_bytesize_adj for all modes
>>> 	listed in adj_nunits.
>>> 	(emit_mode_nunits_inline): Set need_nunits_adj for all modes
>>> 	listed in adj_nunits.  Don't emit case statements for such modes.
>>> 	(emit_insn_modes_h): Emit definitions of CONST_MODE_NUNITS
>>> 	and CONST_MODE_PRECISION.  Make CONST_MODE_SIZE expand to
>>> 	nothing if adj_nunits is nonnull.
>>> 	(emit_mode_precision, emit_mode_nunits): Use print_maybe_const_decl.
>>> 	(emit_mode_unit_size, emit_mode_base_align, emit_mode_ibit)
>>> 	(emit_mode_fbit): Update use of print_maybe_const_decl.
>>> 	(emit_move_size): Likewise.  Treat the array as non-const
>>> 	if adj_nunits.
>>> 	(emit_mode_adjustments): Handle adj_nunits.
>> Were all the prereqs here approved?  Or does this depend on the poly_int
>> stuff?
> 
> Yeah, it depends on the poly_int stuff.  Not in a major way though --
> I could reorder it if necessary.
Your call.  I figure it's going to be at least a week working my way
through the rest of poly_int.  I keep hoping to see groups of patches
within that kit that I can trivially look at and say, yea, of course
this is good.  But it hasn't really happened yet.

jeff
diff mbox series

Patch

Index: gcc/machmode.h
===================================================================
--- gcc/machmode.h	2017-10-25 16:50:35.628184659 +0100
+++ gcc/machmode.h	2017-10-25 16:55:00.469175980 +0100
@@ -23,9 +23,9 @@  #define HAVE_MACHINE_MODES
 typedef opt_mode<machine_mode> opt_machine_mode;
 
 extern CONST_MODE_SIZE poly_uint16_pod mode_size[NUM_MACHINE_MODES];
-extern const poly_uint16_pod mode_precision[NUM_MACHINE_MODES];
+extern CONST_MODE_PRECISION poly_uint16_pod mode_precision[NUM_MACHINE_MODES];
 extern const unsigned char mode_inner[NUM_MACHINE_MODES];
-extern const poly_uint16_pod mode_nunits[NUM_MACHINE_MODES];
+extern CONST_MODE_NUNITS poly_uint16_pod 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];
Index: gcc/machmode.def
===================================================================
--- gcc/machmode.def	2017-10-25 16:50:35.628184659 +0100
+++ gcc/machmode.def	2017-10-25 16:55:00.468176022 +0100
@@ -169,6 +169,12 @@  along with GCC; see the file COPYING3.
 	Unlike a FORMAT argument, if you are adjusting a float format
 	you must put an & in front of the name of each format structure.
 
+     ADJUST_NUNITS (MODE, EXPR);
+	Like the above, but set the number of nunits of MODE to EXPR.
+	This changes the size and precision of the mode in proportion
+	to the change in the number of units; for example, doubling
+	the number of units doubles the size and precision as well.
+
    Note: If a mode is ever made which is more than 255 bytes wide,
    machmode.h and genmodes.c will have to be changed to allocate
    more space for the mode_size and mode_alignment arrays.  */
Index: gcc/genmodes.c
===================================================================
--- gcc/genmodes.c	2017-10-25 16:50:35.627184698 +0100
+++ gcc/genmodes.c	2017-10-25 16:55:00.468176022 +0100
@@ -72,7 +72,9 @@  struct mode_data
   unsigned int counter;		/* Rank ordering of modes */
   unsigned int ibit;		/* the number of integral bits */
   unsigned int fbit;		/* the number of fractional bits */
-  bool need_bytesize_adj;	/* true if this mode need dynamic size
+  bool need_nunits_adj;		/* true if this mode needs dynamic nunits
+				   adjustment */
+  bool need_bytesize_adj;	/* true if this mode needs dynamic size
 				   adjustment */
   unsigned int int_n;		/* If nonzero, then __int<INT_N> will be defined */
 };
@@ -85,7 +87,7 @@  static const struct mode_data blank_mode
   0, "<unknown>", MAX_MODE_CLASS,
   -1U, -1U, -1U, -1U,
   0, 0, 0, 0, 0, 0,
-  "<unknown>", 0, 0, 0, 0, false, 0
+  "<unknown>", 0, 0, 0, 0, false, false, 0
 };
 
 static htab_t modes_by_name;
@@ -103,6 +105,7 @@  struct mode_adjust
   unsigned int line;
 };
 
+static struct mode_adjust *adj_nunits;
 static struct mode_adjust *adj_bytesize;
 static struct mode_adjust *adj_alignment;
 static struct mode_adjust *adj_format;
@@ -786,6 +789,7 @@  make_vector_mode (enum mode_class bclass
 #define _ADD_ADJUST(A, M, X, C1, C2) \
   new_adjust (#M, &adj_##A, #A, #X, MODE_##C1, MODE_##C2, __FILE__, __LINE__)
 
+#define ADJUST_NUNITS(M, X)    _ADD_ADJUST (nunits, M, X, RANDOM, RANDOM)
 #define ADJUST_BYTESIZE(M, X)  _ADD_ADJUST (bytesize, M, X, RANDOM, RANDOM)
 #define ADJUST_ALIGNMENT(M, X) _ADD_ADJUST (alignment, M, X, RANDOM, RANDOM)
 #define ADJUST_FLOAT_FORMAT(M, X)    _ADD_ADJUST (format, M, X, FLOAT, FLOAT)
@@ -955,9 +959,9 @@  #define tagged_printf(FMT, ARG, TAG) do
 #define print_decl(TYPE, NAME, ASIZE) \
   puts ("\nconst " TYPE " " NAME "[" ASIZE "] =\n{");
 
-#define print_maybe_const_decl(TYPE, NAME, ASIZE, CATEGORY)	\
+#define print_maybe_const_decl(TYPE, NAME, ASIZE, NEEDS_ADJ)	\
   printf ("\n" TYPE " " NAME "[" ASIZE "] = \n{\n",		\
-	  adj_##CATEGORY ? "" : "const ")
+	  NEEDS_ADJ ? "" : "const ")
 
 #define print_closer() puts ("};")
 
@@ -1015,6 +1019,11 @@  emit_mode_size_inline (void)
 	m->need_bytesize_adj = true;
     }
 
+  /* Changing the number of units by a factor of X also changes the size
+     by a factor of X.  */
+  for (mode_adjust *a = adj_nunits; a; a = a->next)
+    a->mode->need_bytesize_adj = true;
+
   printf ("\
 #ifdef __cplusplus\n\
 inline __attribute__((__always_inline__))\n\
@@ -1027,7 +1036,7 @@  mode_size_inline (machine_mode mode)\n\
   extern %spoly_uint16_pod mode_size[NUM_MACHINE_MODES];\n\
   gcc_assert (mode >= 0 && mode < NUM_MACHINE_MODES);\n\
   switch (mode)\n\
-    {\n", adj_bytesize ? "" : "const ");
+    {\n", adj_nunits || adj_bytesize ? "" : "const ");
 
   for_all_modes (c, m)
     if (!m->need_bytesize_adj)
@@ -1046,7 +1055,10 @@  emit_mode_nunits_inline (void)
   int c;
   struct mode_data *m;
 
-  puts ("\
+  for (mode_adjust *a = adj_nunits; a; a = a->next)
+    a->mode->need_nunits_adj = true;
+
+  printf ("\
 #ifdef __cplusplus\n\
 inline __attribute__((__always_inline__))\n\
 #else\n\
@@ -1055,12 +1067,13 @@  extern __inline__ __attribute__((__alway
 poly_uint16\n\
 mode_nunits_inline (machine_mode mode)\n\
 {\n\
-  extern poly_uint16_pod mode_nunits[NUM_MACHINE_MODES];\n\
+  extern %spoly_uint16_pod mode_nunits[NUM_MACHINE_MODES];\n\
   switch (mode)\n\
-    {");
+    {\n", adj_nunits ? "" : "const ");
 
   for_all_modes (c, m)
-    printf ("    case E_%smode: return %u;\n", m->name, m->ncomponents);
+    if (!m->need_nunits_adj)
+      printf ("    case E_%smode: return %u;\n", m->name, m->ncomponents);
 
   puts ("\
     default: return mode_nunits[mode];\n\
@@ -1277,7 +1290,10 @@  enum machine_mode\n{");
 };\n");
 
   /* I can't think of a better idea, can you?  */
-  printf ("#define CONST_MODE_SIZE%s\n", adj_bytesize ? "" : " const");
+  printf ("#define CONST_MODE_NUNITS%s\n", adj_nunits ? "" : " const");
+  printf ("#define CONST_MODE_PRECISION%s\n", adj_nunits ? "" : " const");
+  printf ("#define CONST_MODE_SIZE%s\n",
+	  adj_bytesize || adj_nunits ? "" : " const");
   printf ("#define CONST_MODE_UNIT_SIZE%s\n", adj_bytesize ? "" : " const");
   printf ("#define CONST_MODE_BASE_ALIGN%s\n", adj_alignment ? "" : " const");
 #if 0 /* disabled for backward compatibility, temporary */
@@ -1392,7 +1408,8 @@  emit_mode_precision (void)
   int c;
   struct mode_data *m;
 
-  print_decl ("poly_uint16_pod", "mode_precision", "NUM_MACHINE_MODES");
+  print_maybe_const_decl ("%spoly_uint16_pod", "mode_precision",
+			  "NUM_MACHINE_MODES", adj_nunits);
 
   for_all_modes (c, m)
     if (m->precision != (unsigned int)-1)
@@ -1411,7 +1428,7 @@  emit_mode_size (void)
   struct mode_data *m;
 
   print_maybe_const_decl ("%spoly_uint16_pod", "mode_size",
-			  "NUM_MACHINE_MODES", bytesize);
+			  "NUM_MACHINE_MODES", adj_nunits || adj_bytesize);
 
   for_all_modes (c, m)
     tagged_printf ("{ %u" ZERO_COEFFS " }", m->bytesize, m->name);
@@ -1425,7 +1442,8 @@  emit_mode_nunits (void)
   int c;
   struct mode_data *m;
 
-  print_decl ("poly_uint16_pod", "mode_nunits", "NUM_MACHINE_MODES");
+  print_maybe_const_decl ("%spoly_uint16_pod", "mode_nunits",
+			  "NUM_MACHINE_MODES", adj_nunits);
 
   for_all_modes (c, m)
     tagged_printf ("{ %u" ZERO_COEFFS " }", m->ncomponents, m->name);
@@ -1563,7 +1581,7 @@  emit_mode_unit_size (void)
   struct mode_data *m;
 
   print_maybe_const_decl ("%sunsigned char", "mode_unit_size",
-			  "NUM_MACHINE_MODES", bytesize);
+			  "NUM_MACHINE_MODES", adj_bytesize);
 
   for_all_modes (c, m)
     tagged_printf ("%u",
@@ -1604,7 +1622,7 @@  emit_mode_base_align (void)
 
   print_maybe_const_decl ("%sunsigned short",
 			  "mode_base_align", "NUM_MACHINE_MODES",
-			  alignment);
+			  adj_alignment);
 
   for_all_modes (c, m)
     tagged_printf ("%u", m->alignment, m->name);
@@ -1685,6 +1703,23 @@  emit_mode_adjustments (void)
 \n  poly_uint16 ps ATTRIBUTE_UNUSED;\n\
   size_t s ATTRIBUTE_UNUSED;");
 
+  for (a = adj_nunits; a; a = a->next)
+    {
+      m = a->mode;
+      printf ("\n"
+	      "  {\n"
+	      "    /* %s:%d */\n  ps = %s;\n",
+	      a->file, a->line, a->adjustment);
+      printf ("    int old_factor = vector_element_size"
+	      " (mode_precision[E_%smode], mode_nunits[E_%smode]);\n",
+	      m->name, m->name);
+      printf ("    mode_precision[E_%smode] = ps * old_factor;\n",  m->name);
+      printf ("    mode_size[E_%smode] = exact_div (mode_precision[E_%smode],"
+	      " BITS_PER_UNIT);\n", m->name, m->name);
+      printf ("    mode_nunits[E_%smode] = ps;\n", m->name);
+      printf ("  }\n");
+    }
+
   /* Size adjustments must be propagated to all containing modes.
      A size adjustment forces us to recalculate the alignment too.  */
   for (a = adj_bytesize; a; a = a->next)
@@ -1825,7 +1860,7 @@  emit_mode_ibit (void)
 
   print_maybe_const_decl ("%sunsigned char",
 			  "mode_ibit", "NUM_MACHINE_MODES",
-			  ibit);
+			  adj_ibit);
 
   for_all_modes (c, m)
     tagged_printf ("%u", m->ibit, m->name);
@@ -1843,7 +1878,7 @@  emit_mode_fbit (void)
 
   print_maybe_const_decl ("%sunsigned char",
 			  "mode_fbit", "NUM_MACHINE_MODES",
-			  fbit);
+			  adj_fbit);
 
   for_all_modes (c, m)
     tagged_printf ("%u", m->fbit, m->name);