From da749b98cf9d87ebed92de08ff45f8a0d7fc9d1a Mon Sep 17 00:00:00 2001 From: "Maciej W. Rozycki" Date: Sat, 5 Dec 2020 18:26:24 +0000 Subject: [PATCH] RTL: Also support HOST_WIDE_INT with int iterators Add wide integer aka 'w' rtx format support to int iterators so that machine description can iterate over `const_int' expressions. This is made by expanding standard integer aka 'i' format support, observing that any standard integer already present in any of our existing RTL code will also fit into HOST_WIDE_INT, so there is no need for a separate handler. Any truncation of the number parsed is made by the caller. An assumption is made however that no place relies on capping out of range values to INT_MAX. Now the 'p' format is handled explicitly rather than being implied by rtx being a SUBREG, so actually assert that it is, just to play safe. gcc/ * read-rtl.c: Add a page-feed separator at the start of iterator code. (struct iterator_group): Change the return type to HOST_WIDE_INT for the `find_builtin' member. Likewise the second parameter type for the `apply_iterator' member. (atoll) [!HAVE_ATOQ]: Reorder. (find_mode, find_code): Change the return type to HOST_WIDE_INT. (apply_mode_iterator, apply_code_iterator) (apply_subst_iterator): Change the second parameter type to HOST_WIDE_INT. (find_int): Handle input suitable for HOST_WIDE_INT output. (apply_int_iterator): Rewrite in terms of explicit format interpretation. (rtx_reader::read_rtx_operand) <'w'>: Fold into... <'i', 'n', 'p'>: ... this. * doc/md.texi (Int Iterators): Document 'w' rtx format support. --- gcc/doc/md.texi | 10 +-- gcc/read-rtl.c | 165 ++++++++++++++++++++++++++---------------------- 2 files changed, 93 insertions(+), 82 deletions(-) diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index da8c9a283dd..573a340c14b 100644 --- a/gcc/doc/md.texi +++ b/gcc/doc/md.texi @@ -11223,11 +11223,11 @@ The construct: @end smallexample defines a pseudo integer constant @var{name} that can be instantiated as -@var{inti} if condition @var{condi} is true. Each @var{int} -must have the same rtx format. @xref{RTL Classes}. Int iterators can appear -in only those rtx fields that have 'i' as the specifier. This means that -each @var{int} has to be a constant defined using define_constant or -define_c_enum. +@var{inti} if condition @var{condi} is true. Each @var{int} must have the +same rtx format. @xref{RTL Classes}. Int iterators can appear in only +those rtx fields that have 'i', 'n', 'w', or 'p' as the specifier. This +means that each @var{int} has to be a constant defined using define_constant +or define_c_enum. As with mode and code iterators, each pattern that uses @var{name} will be expanded @var{n} times, once with all uses of @var{name} replaced by diff --git a/gcc/read-rtl.c b/gcc/read-rtl.c index 3ec83a60baf..403f254f3cb 100644 --- a/gcc/read-rtl.c +++ b/gcc/read-rtl.c @@ -77,12 +77,12 @@ struct iterator_group { /* Treat the given string as the name of a standard mode, etc., and return its integer value. */ - int (*find_builtin) (const char *); + HOST_WIDE_INT (*find_builtin) (const char *); /* Make the given rtx use the iterator value given by the third argument. If the iterator applies to operands, the second argument gives the operand index, otherwise it is ignored. */ - void (*apply_iterator) (rtx, unsigned int, int); + void (*apply_iterator) (rtx, unsigned int, HOST_WIDE_INT); /* Return the C token for the given standard mode, code, etc. */ const char *(*get_c_token) (int); @@ -139,7 +139,7 @@ static void one_time_initialization (void); /* Global singleton. */ rtx_reader *rtx_reader_ptr = NULL; - + /* The mode and code iterator structures. */ static struct iterator_group modes, codes, ints, substs; @@ -152,9 +152,49 @@ static vec iterator_uses; /* The list of all attribute uses in the current rtx. */ static vec attribute_uses; +/* Provide a version of a function to read a long long if the system does + not provide one. */ +#if (HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG \ + && !HAVE_DECL_ATOLL \ + && !defined (HAVE_ATOQ)) +HOST_WIDE_INT atoll (const char *); + +HOST_WIDE_INT +atoll (const char *p) +{ + int neg = 0; + HOST_WIDE_INT tmp_wide; + + while (ISSPACE (*p)) + p++; + if (*p == '-') + neg = 1, p++; + else if (*p == '+') + p++; + + tmp_wide = 0; + while (ISDIGIT (*p)) + { + HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0'); + if (new_wide < tmp_wide) + { + /* Return INT_MAX equiv on overflow. */ + tmp_wide = HOST_WIDE_INT_M1U >> 1; + break; + } + tmp_wide = new_wide; + p++; + } + + if (neg) + tmp_wide = -tmp_wide; + return tmp_wide; +} +#endif + /* Implementations of the iterator_group callbacks for modes. */ -static int +static HOST_WIDE_INT find_mode (const char *name) { int i; @@ -167,7 +207,7 @@ find_mode (const char *name) } static void -apply_mode_iterator (rtx x, unsigned int, int mode) +apply_mode_iterator (rtx x, unsigned int, HOST_WIDE_INT mode) { PUT_MODE (x, (machine_mode) mode); } @@ -215,7 +255,7 @@ maybe_find_code (const char *name) /* Implementations of the iterator_group callbacks for codes. */ -static int +static HOST_WIDE_INT find_code (const char *name) { rtx_code code = maybe_find_code (name); @@ -225,7 +265,7 @@ find_code (const char *name) } static void -apply_code_iterator (rtx x, unsigned int, int code) +apply_code_iterator (rtx x, unsigned int, HOST_WIDE_INT code) { PUT_CODE (x, (enum rtx_code) code); } @@ -245,20 +285,52 @@ get_code_token (int code) we have to accept any int as valid. No cross-checking can be done. */ -static int +static HOST_WIDE_INT find_int (const char *name) { + HOST_WIDE_INT tmp; + validate_const_int (name); - return atoi (name); +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT + tmp = atoi (name); +#else +#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG + tmp = atol (name); +#else + /* Prefer atoll over atoq, since the former is in the ISO C99 standard. + But prefer not to use our hand-rolled function above either. */ +#if HAVE_DECL_ATOLL || !defined(HAVE_ATOQ) + tmp = atoll (name); +#else + tmp = atoq (name); +#endif +#endif +#endif + return tmp; } static void -apply_int_iterator (rtx x, unsigned int index, int value) +apply_int_iterator (rtx x, unsigned int index, HOST_WIDE_INT value) { - if (GET_CODE (x) == SUBREG) - SUBREG_BYTE (x) = value; - else - XINT (x, index) = value; + RTX_CODE code = GET_CODE (x); + const char *format_ptr = GET_RTX_FORMAT (code); + + switch (format_ptr[index]) + { + case 'i': + case 'n': + XINT (x, index) = value; + break; + case 'w': + XWINT (x, index) = value; + break; + case 'p': + gcc_assert (code == SUBREG); + SUBREG_BYTE (x) = value; + break; + default: + gcc_unreachable (); + } } static const char * @@ -279,7 +351,7 @@ get_int_token (int value) applied. If such attribute has already been added, then no the routine has no effect. */ static void -apply_subst_iterator (rtx rt, unsigned int, int value) +apply_subst_iterator (rtx rt, unsigned int, HOST_WIDE_INT value) { rtx new_attr; rtvec attrs_vec, new_attrs_vec; @@ -1003,44 +1075,6 @@ initialize_iterators (void) } } -/* Provide a version of a function to read a long long if the system does - not provide one. */ -#if HOST_BITS_PER_WIDE_INT > HOST_BITS_PER_LONG && !HAVE_DECL_ATOLL && !defined(HAVE_ATOQ) -HOST_WIDE_INT atoll (const char *); - -HOST_WIDE_INT -atoll (const char *p) -{ - int neg = 0; - HOST_WIDE_INT tmp_wide; - - while (ISSPACE (*p)) - p++; - if (*p == '-') - neg = 1, p++; - else if (*p == '+') - p++; - - tmp_wide = 0; - while (ISDIGIT (*p)) - { - HOST_WIDE_INT new_wide = tmp_wide*10 + (*p - '0'); - if (new_wide < tmp_wide) - { - /* Return INT_MAX equiv on overflow. */ - tmp_wide = HOST_WIDE_INT_M1U >> 1; - break; - } - tmp_wide = new_wide; - p++; - } - - if (neg) - tmp_wide = -tmp_wide; - return tmp_wide; -} -#endif - #ifdef GENERATOR_FILE /* Process a define_conditions directive, starting with the optional @@ -1939,32 +1973,9 @@ rtx_reader::read_rtx_operand (rtx return_rtx, int idx) } break; - case 'w': - { - HOST_WIDE_INT tmp_wide; - read_name (&name); - validate_const_int (name.string); -#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT - tmp_wide = atoi (name.string); -#else -#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG - tmp_wide = atol (name.string); -#else - /* Prefer atoll over atoq, since the former is in the ISO C99 standard. - But prefer not to use our hand-rolled function above either. */ -#if HAVE_DECL_ATOLL || !defined(HAVE_ATOQ) - tmp_wide = atoll (name.string); -#else - tmp_wide = atoq (name.string); -#endif -#endif -#endif - XWINT (return_rtx, idx) = tmp_wide; - } - break; - case 'i': case 'n': + case 'w': case 'p': { /* Can be an iterator or an integer constant. */ -- 2.30.2