RTL: Also support HOST_WIDE_INT with int iterators
authorMaciej W. Rozycki <macro@linux-mips.org>
Sat, 5 Dec 2020 18:26:24 +0000 (18:26 +0000)
committerMaciej W. Rozycki <macro@linux-mips.org>
Sat, 5 Dec 2020 18:26:24 +0000 (18:26 +0000)
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
gcc/read-rtl.c

index da8c9a283dd42e2b3078ed5f370a37180ee0b538..573a340c14b17fab2393d3ac2f2a6b7b9b681003 100644 (file)
@@ -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
index 3ec83a60baf4f61c5e9f149f368c0228b7aeaeb9..403f254f3cb6e56172c4c0a7a081621570d011a2 100644 (file)
@@ -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;
-
+\f
 /* The mode and code iterator structures.  */
 static struct iterator_group modes, codes, ints, substs;
 
@@ -152,9 +152,49 @@ static vec<iterator_use> iterator_uses;
 /* The list of all attribute uses in the current rtx.  */
 static vec<attribute_use> 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)
     }
 }
 \f
-/* 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
-\f
 
 #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.  */