Add support for adjusting the number of units in a mode
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 3 Jan 2018 21:43:28 +0000 (21:43 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 3 Jan 2018 21:43:28 +0000 (21:43 +0000)
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.

2018-01-03  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.

Co-Authored-By: Alan Hayward <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>
From-SVN: r256204

gcc/ChangeLog
gcc/genmodes.c
gcc/machmode.def
gcc/machmode.h

index 29154ccb5ffc490bd468623952bf27c313e69ff3..dd5d70306f02ef8df8416151ffddff95681376b5 100644 (file)
@@ -1,3 +1,29 @@
+2018-01-03  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * 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.
+
 2018-01-03  Richard Sandiford  <richard.sandiford@linaro.org>
 
        * machmode.def (VECTOR_MODES_WITH_PREFIX): Document.
index 7d58865ca96e5a5b7ec392e9cdae97c4d252c734..c0964345a939823bfe15cb32bd85191685bc2a8b 100644 (file)
@@ -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;
@@ -780,6 +783,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)
@@ -949,9 +953,9 @@ calc_wider_mode (void)
 #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 ("};")
 
@@ -1009,6 +1013,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\
@@ -1021,7 +1030,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)
@@ -1040,7 +1049,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\
@@ -1049,12 +1061,13 @@ extern __inline__ __attribute__((__always_inline__, __gnu_inline__))\n\
 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\
@@ -1271,7 +1284,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 */
@@ -1386,7 +1402,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)
@@ -1405,7 +1422,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);
@@ -1419,7 +1436,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);
@@ -1557,7 +1575,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",
@@ -1598,7 +1616,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);
@@ -1679,6 +1697,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)
@@ -1819,7 +1854,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);
@@ -1837,7 +1872,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);
index c9d17f1300eee69e38de0c2d112f032943329773..d5d5efc22ab318d0910822c3e2a445f10aa894ed 100644 (file)
@@ -174,6 +174,12 @@ along with GCC; see the file COPYING3.  If not see
        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 5eaa868527dfa46df36ac0f903071092a66eac27..b938eeaa26bfa6fa9460cf710a95cdf94e87a3ee 100644 (file)
@@ -23,9 +23,9 @@ along with GCC; see the file COPYING3.  If not see
 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];