Commit c6561a1a by Richard Sandiford Committed by Richard Sandiford

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  <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
parent 6ce12f6a
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.
* genmodes.c (VECTOR_MODES_WITH_PREFIX): New macro.
......
......@@ -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);
......
......@@ -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. */
......
......@@ -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];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment