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 813875b973b..762a6cf050e 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -11201,11 +11201,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