From: Kyrylo Tkachov <[email protected]>
The path that locates an operand is a string of steps down the pattern, and
a step used to be spelled as a character: a digit selected an XEXP, a
lower-case letter an XVECEXP, and an upper-case letter an XVECEXP whose
index had run past 'z'. Richard suggested using plain numbers
instead, which is what this does.
A step is now one byte, 2 * INDEX + 1 for XEXP (x, INDEX) and
2 * INDEX + 2 for XVECEXP (x, 0, INDEX). That leaves zero to terminate a
path and 255 to mark an operand number the pattern does not use, so the
walk loses its split ranges:
for (; *p; p++) for (; *p; p++)
if (ISDIGIT (*p)) {
loc = &XEXP (*loc, *p - '0'); unsigned int step = *p - 1;
else if (ISLOWER (*p)) -> if (step & 1)
loc = &XVECEXP (*loc, 0, loc = &XVECEXP (*loc, 0, step
>> 1);
*p - 'a'); else
else loc = &XEXP (*loc, step >> 1);
loc = &XVECEXP (*loc, 0, }
*p - UPPER_OFFSET);
The table becomes an array of numbers rather than a string literal, so the
terminator no longer has to be written "\000" to stop the next step being
absorbed into the escape, and a zero in the table no longer looks like the
index 0.
It also removes a silent limit. The old spelling ran out of characters:
an XEXP index above 9 produced ':', which the reader took for an XVECEXP
step, and an XVECEXP index of 58 produced 'a', which it took for index 0.
Neither is reachable from today's machine descriptions, but nothing said
so. The encoder now asserts that an index fits.
The tables grow, because a number costs more source than a printable
character: insn-extract.cc goes from 124888 to 141866 bytes on aarch64,
251020 to 260479 on riscv64, 100542 to 117344 on x86_64 and 26639 to 28958
on avr. For scale, the file was 1.04MB on aarch64 before the table-driven
rewrite.
Bootstrapped on aarch64-none-linux-gnu.
Ok for trunk?
Thanks,
Kyrill
gcc/ChangeLog:
* genextract.cc (locstr): Make it a string of bytes.
(UPPER_OFFSET, MISSING_OPERAND_CHAR): Remove.
(ENCODE_PATH_STEP, MISSING_OPERAND_STEP, MAX_PATH_INDEX): New macros.
(accum_extract::pathstr): Hold bytes.
(push_pathstr_operand): Encode the step as a number and check that
the index fits.
(VEC_safe_set_locstr, VEC_char_to_string, add_path, gen_insn): Update
for the byte paths.
(print_string_literal): Remove.
(print_extractions): Emit the paths as an array of numbers and walk
them without the character ranges.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/genextract.cc | 135 ++++++++++++++++++++--------------------------
1 file changed, 58 insertions(+), 77 deletions(-)
diff --git a/gcc/genextract.cc b/gcc/genextract.cc
index 62babeb3982..57616d39aa6 100644
--- a/gcc/genextract.cc
+++ b/gcc/genextract.cc
@@ -38,7 +38,7 @@ along with GCC; see the file COPYING3. If not see
the same assumption (and uses the same representation) and it is currently
true. */
-typedef char *locstr;
+typedef unsigned char *locstr;
struct extraction
{
@@ -76,27 +76,29 @@ public:
auto_vec<locstr> oplocs;
auto_vec<locstr> duplocs;
auto_vec<int> dupnums;
- auto_vec<char> pathstr;
+ auto_vec<unsigned char> pathstr;
};
/* Forward declarations. */
static void walk_rtx (md_rtx_info *, rtx, class accum_extract *);
-#define UPPER_OFFSET ('A' - ('z' - 'a' + 1))
-
-/* Convert integer OPERAND into a character - either into [a-zA-Z] for vector
- operands or [0-9] for integer operands - and push onto the end of the path
- in ACC. */
+/* A path is a sequence of steps down a pattern, one byte each. A step
+ down XEXP (x, INDEX) is 2 * INDEX + 1 and a step down XVECEXP (x, 0,
+ INDEX) is 2 * INDEX + 2, which leaves zero free to terminate a path and
+ MISSING_OPERAND_STEP free to mark an operand number that the pattern
+ does not use. */
+#define ENCODE_PATH_STEP(INDEX, IS_VECTOR) (2 * (INDEX) + (IS_VECTOR) + 1)
+#define MISSING_OPERAND_STEP 255
+#define MAX_PATH_INDEX ((MISSING_OPERAND_STEP - 2) / 2)
+
+/* Encode the step to OPERAND, a vector element if IS_VECTOR, and push it
+ onto the end of the path in ACC. */
static void
push_pathstr_operand (int operand, bool is_vector,
class accum_extract *acc)
{
- if (is_vector && 'a' + operand > 'z')
- acc->pathstr.safe_push (operand + UPPER_OFFSET);
- else if (is_vector)
- acc->pathstr.safe_push (operand + 'a');
- else
- acc->pathstr.safe_push (operand + '0');
+ gcc_assert (IN_RANGE (operand, 0, MAX_PATH_INDEX));
+ acc->pathstr.safe_push (ENCODE_PATH_STEP (operand, is_vector));
}
static void
@@ -138,9 +140,10 @@ gen_insn (md_rtx_info *info)
for (j = 0; j < op_count; j++)
{
- char *a = p->oplocs[j];
- char *b = acc.oplocs[j];
- if (a != b && (!a || !b || strcmp (a, b)))
+ locstr a = p->oplocs[j];
+ locstr b = acc.oplocs[j];
+ if (a != b
+ && (!a || !b || strcmp ((const char *) a, (const char *) b)))
break;
}
@@ -149,7 +152,8 @@ gen_insn (md_rtx_info *info)
for (j = 0; j < dup_count; j++)
if (p->dupnums[j] != acc.dupnums[j]
- || strcmp (p->duplocs[j], acc.duplocs[j]))
+ || strcmp ((const char *) p->duplocs[j],
+ (const char *) acc.duplocs[j]))
break;
if (j != dup_count)
@@ -175,7 +179,7 @@ gen_insn (md_rtx_info *info)
p->insns = link;
link->next = 0;
- p->oplocs = (char **)((char *)p + sizeof (struct extraction));
+ p->oplocs = (locstr *)((char *)p + sizeof (struct extraction));
p->duplocs = p->oplocs + op_count;
p->dupnums = (int *)(p->duplocs + dup_count);
@@ -191,7 +195,7 @@ gen_insn (md_rtx_info *info)
containing define_* expression. */
static void
VEC_safe_set_locstr (md_rtx_info *info, vec<locstr> *vp,
- unsigned int ix, char *str)
+ unsigned int ix, locstr str)
{
if (ix < (*vp).length ())
{
@@ -211,15 +215,16 @@ VEC_safe_set_locstr (md_rtx_info *info, vec<locstr> *vp,
}
}
-/* Another helper subroutine of walk_rtx: given a vec<char>, convert it
- to a NUL-terminated string in malloc memory. */
-static char *
-VEC_char_to_string (const vec<char> &v)
+/* Another helper subroutine of walk_rtx: given a vec of path steps,
+ convert it to a zero-terminated path in malloc memory. No step is
+ zero, so the result can be handled as a string. */
+static unsigned char *
+VEC_char_to_string (const vec<unsigned char> &v)
{
size_t n = v.length ();
- char *s = XNEWVEC (char, n + 1);
+ unsigned char *s = XNEWVEC (unsigned char, n + 1);
memcpy (s, v.address (), n);
- s[n] = '\0';
+ s[n] = 0;
return s;
}
@@ -304,11 +309,7 @@ walk_rtx (md_rtx_info *info, rtx x, class accum_extract
*acc)
}
}
-/* The character that marks an operand number that a pattern does not use.
- It cannot clash with a path step, which is always a digit or a letter. */
-#define MISSING_OPERAND_CHAR '!'
-
-/* The paths of all extraction methods, concatenated. Each path is NUL
+/* The paths of all extraction methods, concatenated. Each path is zero
terminated; the paths of one method are adjacent, operands first and
dups second. */
static struct obstack pathpool;
@@ -320,13 +321,13 @@ static vec<int> dupnums;
to the path pool. */
static void
-add_path (const char *path)
+add_path (const unsigned char *path)
{
if (path)
- obstack_grow (&pathpool, path, strlen (path));
+ obstack_grow (&pathpool, path, strlen ((const char *) path));
else
- obstack_1grow (&pathpool, MISSING_OPERAND_CHAR);
- obstack_1grow (&pathpool, '\0');
+ obstack_1grow (&pathpool, MISSING_OPERAND_STEP);
+ obstack_1grow (&pathpool, 0);
}
static void
@@ -355,27 +356,6 @@ print_header (void)
static rtx junk ATTRIBUTE_UNUSED;\n");
}
-/* Print STR as a C string literal, broken into chunks so that no output
- line gets excessively long. */
-
-static void
-print_string_literal (const char *str, unsigned int len)
-{
- printf (" \"");
- for (unsigned int i = 0; i < len; i++)
- {
- if (str[i] == '\0')
- /* Spell the terminator with all three octal digits: the next
- character may be a digit, which a shorter escape would absorb. */
- printf ("\\000");
- else
- putchar (str[i]);
- if ((i % 60) == 59 && i + 1 < len)
- printf ("\"\n \"");
- }
- printf ("\"");
-}
-
/* Print the tables that drive insn_extract, and insn_extract itself. */
static void
@@ -428,20 +408,20 @@ print_extractions (void)
path_start.safe_push (obstack_object_size (&pathpool));
unsigned int pool_len = obstack_object_size (&pathpool);
- const char *pool = XOBFINISH (&pathpool, const char *);
+ const unsigned char *pool = XOBFINISH (&pathpool, const unsigned char *);
printf ("/* The paths that locate the operands and the dups of each\n"
" extraction method. A path is a sequence of steps down the\n"
- " pattern: a digit D selects XEXP (x, D - '0'), a lower-case\n"
- " letter L selects XVECEXP (x, 0, L - 'a') and an upper-case\n"
- " letter U selects XVECEXP (x, 0, U - %d). An empty path denotes\n"
- " the pattern itself and '%c' an operand number that the pattern\n"
- " does not use. */\n", UPPER_OFFSET, MISSING_OPERAND_CHAR);
- printf ("#define UPPER_OFFSET %d\n", UPPER_OFFSET);
- printf ("#define MISSING_OPERAND_CHAR '%c'\n\n", MISSING_OPERAND_CHAR);
- printf ("static const char extract_paths[] =\n");
- print_string_literal (pool, pool_len);
- printf (";\n\n");
+ " pattern, one byte each: an even step S selects\n"
+ " XVECEXP (x, 0, S / 2 - 1) and an odd step S selects\n"
+ " XEXP (x, S / 2). A zero terminates a path, an empty path\n"
+ " denotes the pattern itself, and %d marks an operand number\n"
+ " that the pattern does not use. */\n", MISSING_OPERAND_STEP);
+ printf ("#define MISSING_OPERAND_STEP %d\n\n", MISSING_OPERAND_STEP);
+ printf ("static const unsigned char extract_paths[] = {");
+ for (i = 0; i < pool_len; i++)
+ printf ("%s%d,", (i % 20) == 0 ? "\n " : " ", pool[i]);
+ printf ("\n};\n\n");
printf ("static const unsigned char extract_dup_num[] = {");
for (i = 0; i < dupnums.length (); i++)
@@ -469,21 +449,22 @@ print_extractions (void)
printf ("\n};\n\n");
puts ("\
-/* Follow one NUL-terminated path in extract_paths from *PP, starting at\n\
+/* Follow one zero-terminated path in extract_paths from *PP, starting at\n\
the pattern *ROOT, and return the location it selects. *PP is left\n\
just after the path's terminator. */\n\
\n\
static inline rtx *\n\
-follow_extract_path (const char **pp, rtx *root)\n{\n\
- const char *p = *pp;\n\
+follow_extract_path (const unsigned char **pp, rtx *root)\n{\n\
+ const unsigned char *p = *pp;\n\
rtx *loc = root;\n\
for (; *p; p++)\n\
- if (ISDIGIT (*p))\n\
- loc = &XEXP (*loc, *p - '0');\n\
- else if (ISLOWER (*p))\n\
- loc = &XVECEXP (*loc, 0, *p - 'a');\n\
- else\n\
- loc = &XVECEXP (*loc, 0, *p - UPPER_OFFSET);\n\
+ {\n\
+ unsigned int step = *p - 1;\n\
+ if (step & 1)\n\
+ loc = &XVECEXP (*loc, 0, step >> 1);\n\
+ else\n\
+ loc = &XEXP (*loc, step >> 1);\n\
+ }\n\
*pp = p + 1;\n\
return loc;\n\
}\n");
@@ -526,9 +507,9 @@ insn_extract (rtx_insn *insn)\n{\n\
}\n\
\n\
const struct extract_method_d *m = &extract_methods[method];\n\
- const char *p = extract_paths + m->paths;\n\
+ const unsigned char *p = extract_paths + m->paths;\n\
for (unsigned int i = 0; i < m->n_operands; i++)\n\
- if (*p == MISSING_OPERAND_CHAR)\n\
+ if (*p == MISSING_OPERAND_STEP)\n\
{\n\
ro[i] = const0_rtx;\n\
ro_loc[i] = &junk;\n\
--
2.50.1 (Apple Git-155)