From: Richard Sandiford Date: Wed, 3 Jan 2018 21:43:28 +0000 (+0000) Subject: Add support for adjusting the number of units in a mode X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c6561a1af68d6439cedde6dc79d19eda9981a4be;p=gcc.git Add support for adjusting the number of units in a mode 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 Alan Hayward David Sherwood 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 Co-Authored-By: David Sherwood From-SVN: r256204 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 29154ccb5ff..dd5d70306f0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2018-01-03 Richard Sandiford + Alan Hayward + David Sherwood + + * 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 * machmode.def (VECTOR_MODES_WITH_PREFIX): Document. diff --git a/gcc/genmodes.c b/gcc/genmodes.c index 7d58865ca96..c0964345a93 100644 --- a/gcc/genmodes.c +++ b/gcc/genmodes.c @@ -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 will be defined */ }; @@ -85,7 +87,7 @@ static const struct mode_data blank_mode = { 0, "", MAX_MODE_CLASS, -1U, -1U, -1U, -1U, 0, 0, 0, 0, 0, 0, - "", 0, 0, 0, 0, false, 0 + "", 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); diff --git a/gcc/machmode.def b/gcc/machmode.def index c9d17f1300e..d5d5efc22ab 100644 --- a/gcc/machmode.def +++ b/gcc/machmode.def @@ -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. */ diff --git a/gcc/machmode.h b/gcc/machmode.h index 5eaa868527d..b938eeaa26b 100644 --- a/gcc/machmode.h +++ b/gcc/machmode.h @@ -23,9 +23,9 @@ along with GCC; see the file COPYING3. If not see typedef opt_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];