]> gcc.gnu.org Git - gcc.git/blobdiff - gcc/gensupport.c
tree-optimization/93868 copy SLP tree before re-arranging stmts
[gcc.git] / gcc / gensupport.c
index 596b88564c7dbeab151005e75c4439044a729377..f2ad54f0c5555b531782d79ed42903d00bc28c6f 100644 (file)
@@ -1,5 +1,5 @@
 /* Support routines for the various generation passes.
-   Copyright (C) 2000-2016 Free Software Foundation, Inc.
+   Copyright (C) 2000-2020 Free Software Foundation, Inc.
 
    This file is part of GCC.
 
@@ -65,59 +65,60 @@ static htab_t condition_table;
    define_cond_exec and define_subst patterns, then return
    them one at a time.  */
 
-struct queue_elem
+class queue_elem
 {
+public:
   rtx data;
   file_location loc;
-  struct queue_elem *next;
-  /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT, SPLIT
-     points to the generated DEFINE_SPLIT.  */
-  struct queue_elem *split;
+  class queue_elem *next;
+  /* In a DEFINE_INSN that came from a DEFINE_INSN_AND_SPLIT or
+     DEFINE_INSN_AND_REWRITE, SPLIT points to the generated DEFINE_SPLIT.  */
+  class queue_elem *split;
 };
 
 #define MNEMONIC_ATTR_NAME "mnemonic"
 #define MNEMONIC_HTAB_SIZE 1024
 
-static struct queue_elem *define_attr_queue;
-static struct queue_elem **define_attr_tail = &define_attr_queue;
-static struct queue_elem *define_pred_queue;
-static struct queue_elem **define_pred_tail = &define_pred_queue;
-static struct queue_elem *define_insn_queue;
-static struct queue_elem **define_insn_tail = &define_insn_queue;
-static struct queue_elem *define_cond_exec_queue;
-static struct queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
-static struct queue_elem *define_subst_queue;
-static struct queue_elem **define_subst_tail = &define_subst_queue;
-static struct queue_elem *other_queue;
-static struct queue_elem **other_tail = &other_queue;
-static struct queue_elem *define_subst_attr_queue;
-static struct queue_elem **define_subst_attr_tail = &define_subst_attr_queue;
+static class queue_elem *define_attr_queue;
+static class queue_elem **define_attr_tail = &define_attr_queue;
+static class queue_elem *define_pred_queue;
+static class queue_elem **define_pred_tail = &define_pred_queue;
+static class queue_elem *define_insn_queue;
+static class queue_elem **define_insn_tail = &define_insn_queue;
+static class queue_elem *define_cond_exec_queue;
+static class queue_elem **define_cond_exec_tail = &define_cond_exec_queue;
+static class queue_elem *define_subst_queue;
+static class queue_elem **define_subst_tail = &define_subst_queue;
+static class queue_elem *other_queue;
+static class queue_elem **other_tail = &other_queue;
+static class queue_elem *define_subst_attr_queue;
+static class queue_elem **define_subst_attr_tail = &define_subst_attr_queue;
 
 /* Mapping from DEFINE_* rtxes to their location in the source file.  */
 static hash_map <rtx, file_location> *rtx_locs;
 
 static void remove_constraints (rtx);
 
-static int is_predicable (struct queue_elem *);
+static int is_predicable (class queue_elem *);
 static void identify_predicable_attribute (void);
 static int n_alternatives (const char *);
 static void collect_insn_data (rtx, int *, int *);
-static const char *alter_test_for_insn (struct queue_elem *,
-                                       struct queue_elem *);
+static const char *alter_test_for_insn (class queue_elem *,
+                                       class queue_elem *);
 static char *shift_output_template (char *, const char *, int);
-static const char *alter_output_for_insn (struct queue_elem *,
-                                         struct queue_elem *,
+static const char *alter_output_for_insn (class queue_elem *,
+                                         class queue_elem *,
                                          int, int);
-static void process_one_cond_exec (struct queue_elem *);
+static void process_one_cond_exec (class queue_elem *);
 static void process_define_cond_exec (void);
 static void init_predicate_table (void);
 static void record_insn_name (int, const char *);
 
-static bool has_subst_attribute (struct queue_elem *, struct queue_elem *);
+static bool has_subst_attribute (class queue_elem *, class queue_elem *);
 static const char * alter_output_for_subst_insn (rtx, int);
-static void alter_attrs_for_subst_insn (struct queue_elem *, int);
-static void process_substs_on_one_elem (struct queue_elem *,
-                                       struct queue_elem *);
+static void alter_attrs_for_subst_insn (class queue_elem *, int);
+static void process_substs_on_one_elem (class queue_elem *,
+                                       class queue_elem *);
 static rtx subst_dup (rtx, int, int);
 static void process_define_subst (void);
 
@@ -399,11 +400,11 @@ process_define_predicate (rtx desc, file_location loc)
 /* Queue PATTERN on LIST_TAIL.  Return the address of the new queue
    element.  */
 
-static struct queue_elem *
-queue_pattern (rtx pattern, struct queue_elem ***list_tail,
+static class queue_elem *
+queue_pattern (rtx pattern, class queue_elem ***list_tail,
               file_location loc)
 {
-  struct queue_elem *e = XNEW (struct queue_elem);
+  class queue_elem *e = XNEW (class queue_elem);
   e->data = pattern;
   e->loc = loc;
   e->next = NULL;
@@ -415,9 +416,9 @@ queue_pattern (rtx pattern, struct queue_elem ***list_tail,
 
 /* Remove element ELEM from QUEUE.  */
 static void
-remove_from_queue (struct queue_elem *elem, struct queue_elem **queue)
+remove_from_queue (class queue_elem *elem, class queue_elem **queue)
 {
-  struct queue_elem *prev, *e;
+  class queue_elem *prev, *e;
   prev = NULL;
   for (e = *queue; e ; e = e->next)
     {
@@ -439,14 +440,14 @@ remove_from_queue (struct queue_elem *elem, struct queue_elem **queue)
 static void
 add_define_attr (const char *name)
 {
-  struct queue_elem *e = XNEW (struct queue_elem);
+  class queue_elem *e = XNEW (class queue_elem);
   rtx t1 = rtx_alloc (DEFINE_ATTR);
   XSTR (t1, 0) = name;
   XSTR (t1, 1) = "no,yes";
   XEXP (t1, 2) = rtx_alloc (CONST_STRING);
   XSTR (XEXP (t1, 2), 0) = "yes";
   e->data = t1;
-  e->loc = file_location ("built-in", -1);
+  e->loc = file_location ("built-in", -1, -1);
   e->next = define_attr_queue;
   define_attr_queue = e;
 
@@ -485,6 +486,65 @@ remove_constraints (rtx part)
       }
 }
 
+/* Recursively replace MATCH_OPERANDs with MATCH_DUPs and MATCH_OPERATORs
+   with MATCH_OP_DUPs in X.  */
+
+static rtx
+replace_operands_with_dups (rtx x)
+{
+  if (x == 0)
+    return x;
+
+  rtx newx;
+  if (GET_CODE (x) == MATCH_OPERAND)
+    {
+      newx = rtx_alloc (MATCH_DUP);
+      XINT (newx, 0) = XINT (x, 0);
+      x = newx;
+    }
+  else if (GET_CODE (x) == MATCH_OPERATOR)
+    {
+      newx = rtx_alloc (MATCH_OP_DUP);
+      XINT (newx, 0) = XINT (x, 0);
+      XVEC (newx, 1) = XVEC (x, 2);
+      x = newx;
+    }
+  else
+    newx = shallow_copy_rtx (x);
+
+  const char *format_ptr = GET_RTX_FORMAT (GET_CODE (x));
+  for (int i = 0; i < GET_RTX_LENGTH (GET_CODE (x)); i++)
+    switch (*format_ptr++)
+      {
+      case 'e':
+      case 'u':
+       XEXP (newx, i) = replace_operands_with_dups (XEXP (x, i));
+       break;
+      case 'E':
+       if (XVEC (x, i) != NULL)
+         {
+           XVEC (newx, i) = rtvec_alloc (XVECLEN (x, i));
+           for (int j = 0; j < XVECLEN (x, i); j++)
+             XVECEXP (newx, i, j)
+               = replace_operands_with_dups (XVECEXP (x, i, j));
+         }
+       break;
+      }
+  return newx;
+}
+
+/* Convert matching pattern VEC from a DEFINE_INSN_AND_REWRITE into
+   a sequence that should be generated by the splitter.  */
+
+static rtvec
+gen_rewrite_sequence (rtvec vec)
+{
+  rtvec new_vec = rtvec_alloc (1);
+  rtx x = add_implicit_parallel (vec);
+  RTVEC_ELT (new_vec, 0) = replace_operands_with_dups (x);
+  return new_vec;
+}
+
 /* Process a top level rtx in some way, queuing as appropriate.  */
 
 static void
@@ -521,18 +581,21 @@ process_rtx (rtx desc, file_location loc)
     case DEFINE_CONSTRAINT:
     case DEFINE_REGISTER_CONSTRAINT:
     case DEFINE_MEMORY_CONSTRAINT:
+    case DEFINE_SPECIAL_MEMORY_CONSTRAINT:
     case DEFINE_ADDRESS_CONSTRAINT:
       queue_pattern (desc, &define_pred_tail, loc);
       break;
 
     case DEFINE_INSN_AND_SPLIT:
+    case DEFINE_INSN_AND_REWRITE:
       {
        const char *split_cond;
        rtx split;
        rtvec attr;
        int i;
-       struct queue_elem *insn_elem;
-       struct queue_elem *split_elem;
+       class queue_elem *insn_elem;
+       class queue_elem *split_elem;
+       int split_code = (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE ? 5 : 6);
 
        /* Create a split with values from the insn_and_split.  */
        split = rtx_alloc (DEFINE_SPLIT);
@@ -550,15 +613,21 @@ process_rtx (rtx desc, file_location loc)
        split_cond = XSTR (desc, 4);
        if (split_cond[0] == '&' && split_cond[1] == '&')
          {
-           copy_md_ptr_loc (split_cond + 2, split_cond);
-           split_cond = join_c_conditions (XSTR (desc, 2), split_cond + 2);
+           rtx_reader_ptr->copy_md_ptr_loc (split_cond + 2, split_cond);
+           split_cond = rtx_reader_ptr->join_c_conditions (XSTR (desc, 2),
+                                                           split_cond + 2);
          }
+       else if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
+         error_at (loc, "the rewrite condition must start with `&&'");
        XSTR (split, 1) = split_cond;
-       XVEC (split, 2) = XVEC (desc, 5);
-       XSTR (split, 3) = XSTR (desc, 6);
+       if (GET_CODE (desc) == DEFINE_INSN_AND_REWRITE)
+         XVEC (split, 2) = gen_rewrite_sequence (XVEC (desc, 1));
+       else
+         XVEC (split, 2) = XVEC (desc, 5);
+       XSTR (split, 3) = XSTR (desc, split_code);
 
        /* Fix up the DEFINE_INSN.  */
-       attr = XVEC (desc, 7);
+       attr = XVEC (desc, split_code + 1);
        PUT_CODE (desc, DEFINE_INSN);
        XVEC (desc, 4) = attr;
 
@@ -579,7 +648,7 @@ process_rtx (rtx desc, file_location loc)
    a DEFINE_INSN.  */
 
 static int
-is_predicable (struct queue_elem *elem)
+is_predicable (class queue_elem *elem)
 {
   rtvec vec = XVEC (elem->data, 4);
   const char *value;
@@ -649,8 +718,8 @@ is_predicable (struct queue_elem *elem)
 
 /* Find attribute SUBST in ELEM and assign NEW_VALUE to it.  */
 static void
-change_subst_attribute (struct queue_elem *elem,
-                       struct queue_elem *subst_elem,
+change_subst_attribute (class queue_elem *elem,
+                       class queue_elem *subst_elem,
                        const char *new_value)
 {
   rtvec attrs_vec = XVEC (elem->data, 4);
@@ -677,9 +746,9 @@ change_subst_attribute (struct queue_elem *elem,
    represented by SUBST_ELEM and this attribute has value SUBST_TRUE.
    DEFINE_SUBST isn't applied to patterns without such attribute.  In other
    words, we suppose the default value of the attribute to be 'no' since it is
-   always generated automaticaly in read-rtl.c.  */
+   always generated automatically in read-rtl.c.  */
 static bool
-has_subst_attribute (struct queue_elem *elem, struct queue_elem *subst_elem)
+has_subst_attribute (class queue_elem *elem, class queue_elem *subst_elem)
 {
   rtvec attrs_vec = XVEC (elem->data, 4);
   const char *value, *subst_name = XSTR (subst_elem->data, 0);
@@ -719,9 +788,10 @@ has_subst_attribute (struct queue_elem *elem, struct queue_elem *subst_elem)
          return false;
 
        case SET_ATTR_ALTERNATIVE:
-         error_at (elem->loc,
-                   "%s: `set_attr_alternative' is unsupported by "
-                   "`define_subst'", XSTR (elem->data, 0));
+         if (strcmp (XSTR (cur_attr, 0), subst_name) == 0)
+           error_at (elem->loc,
+                     "%s: `set_attr_alternative' is unsupported by "
+                     "`define_subst'", XSTR (elem->data, 0));
          return false;
 
 
@@ -881,7 +951,7 @@ subst_pattern_match (rtx x, rtx pt, file_location loc)
 
       switch (fmt[i])
        {
-       case 'i': case 'r': case 'w': case 's':
+       case 'r': case 'p': case 'i': case 'w': case 's':
          continue;
 
        case 'e': case 'u':
@@ -912,7 +982,7 @@ subst_pattern_match (rtx x, rtx pt, file_location loc)
 static void
 identify_predicable_attribute (void)
 {
-  struct queue_elem *elem;
+  class queue_elem *elem;
   char *p_true, *p_false;
   const char *value;
 
@@ -1037,6 +1107,7 @@ get_alternatives_number (rtx pattern, int *n_alt, file_location loc)
        case 'V':
          if (XVEC (pattern, i) == NULL)
            break;
+         /* FALLTHRU */
 
        case 'E':
          for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
@@ -1044,7 +1115,8 @@ get_alternatives_number (rtx pattern, int *n_alt, file_location loc)
              return 0;
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
+       case 'r': case 'p': case 'i': case 'w':
+       case '0': case 's': case 'S': case 'T':
          break;
 
        default:
@@ -1103,7 +1175,8 @@ collect_insn_data (rtx pattern, int *palt, int *pmax)
            collect_insn_data (XVECEXP (pattern, i, j), palt, pmax);
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
+       case 'r': case 'p': case 'i': case 'w':
+       case '0': case 's': case 'S': case 'T':
          break;
 
        default:
@@ -1187,7 +1260,7 @@ alter_predicate_for_insn (rtx pattern, int alt, int max_op,
            }
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's':
+       case 'r': case 'p': case 'i': case 'w': case '0': case 's':
          break;
 
        default:
@@ -1245,7 +1318,7 @@ alter_constraints (rtx pattern, int n_dup, constraints_handler_t alter)
            }
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's':
+       case 'r': case 'p': case 'i': case 'w': case '0': case 's':
          break;
 
        default:
@@ -1257,11 +1330,11 @@ alter_constraints (rtx pattern, int n_dup, constraints_handler_t alter)
 }
 
 static const char *
-alter_test_for_insn (struct queue_elem *ce_elem,
-                    struct queue_elem *insn_elem)
+alter_test_for_insn (class queue_elem *ce_elem,
+                    class queue_elem *insn_elem)
 {
-  return join_c_conditions (XSTR (ce_elem->data, 1),
-                           XSTR (insn_elem->data, 2));
+  return rtx_reader_ptr->join_c_conditions (XSTR (ce_elem->data, 1),
+                                           XSTR (insn_elem->data, 2));
 }
 
 /* Modify VAL, which is an attribute expression for the "enabled" attribute,
@@ -1369,7 +1442,7 @@ alter_attrs_for_insn (rtx insn)
 
   if (!global_changes_made)
     {
-      struct queue_elem *elem;
+      class queue_elem *elem;
 
       global_changes_made = true;
       add_define_attr ("ce_enabled");
@@ -1410,7 +1483,7 @@ alter_attrs_for_insn (rtx insn)
    ELEM is a queue element, containing our rtl-template,
    N_DUP - multiplication factor.  */
 static void
-alter_attrs_for_subst_insn (struct queue_elem * elem, int n_dup)
+alter_attrs_for_subst_insn (class queue_elem * elem, int n_dup)
 {
   rtvec vec = XVEC (elem->data, 4);
   int num_elem;
@@ -1473,8 +1546,8 @@ shift_output_template (char *dest, const char *src, int disp)
 }
 
 static const char *
-alter_output_for_insn (struct queue_elem *ce_elem,
-                      struct queue_elem *insn_elem,
+alter_output_for_insn (class queue_elem *ce_elem,
+                      class queue_elem *insn_elem,
                       int alt, int max_op)
 {
   const char *ce_out, *insn_out;
@@ -1630,33 +1703,30 @@ duplicate_each_alternative (const char * str, int n_dup)
 static const char *
 alter_output_for_subst_insn (rtx insn, int alt)
 {
-  const char *insn_out, *sp ;
-  char *old_out, *new_out, *cp;
-  int i, j, new_len;
+  const char *insn_out, *old_out;
+  char *new_out, *cp;
+  size_t old_len, new_len;
+  int j;
 
   insn_out = XTMPL (insn, 3);
 
-  if (alt < 2 || *insn_out == '*' || *insn_out != '@')
+  if (alt < 2 || *insn_out != '@')
     return insn_out;
 
-  old_out = XNEWVEC (char, strlen (insn_out)),
-  sp = insn_out;
+  old_out = insn_out + 1;
+  while (ISSPACE (*old_out))
+    old_out++;
+  old_len = strlen (old_out);
 
-  while (ISSPACE (*sp) || *sp == '@')
-    sp++;
-
-  for (i = 0; *sp;)
-    old_out[i++] = *sp++;
-
-  new_len = alt * (i + 1) + 1;
+  new_len = alt * (old_len + 1) + 1;
 
   new_out = XNEWVEC (char, new_len);
   new_out[0] = '@';
 
-  for (j = 0, cp = new_out + 1; j < alt; j++, cp += i + 1)
+  for (j = 0, cp = new_out + 1; j < alt; j++, cp += old_len + 1)
     {
-      memcpy (cp, old_out, i);
-      *(cp+i) = (j == alt - 1) ? '\0' : '\n';
+      memcpy (cp, old_out, old_len);
+      cp[old_len] = (j == alt - 1) ? '\0' : '\n';
     }
 
   return new_out;
@@ -1665,9 +1735,9 @@ alter_output_for_subst_insn (rtx insn, int alt)
 /* Replicate insns as appropriate for the given DEFINE_COND_EXEC.  */
 
 static void
-process_one_cond_exec (struct queue_elem *ce_elem)
+process_one_cond_exec (class queue_elem *ce_elem)
 {
-  struct queue_elem *insn_elem;
+  class queue_elem *insn_elem;
   for (insn_elem = define_insn_queue; insn_elem ; insn_elem = insn_elem->next)
     {
       int alternatives, max_operand;
@@ -1771,10 +1841,10 @@ process_one_cond_exec (struct queue_elem *ce_elem)
    was applied, ELEM would be deleted.  */
 
 static void
-process_substs_on_one_elem (struct queue_elem *elem,
-                           struct queue_elem *queue)
+process_substs_on_one_elem (class queue_elem *elem,
+                           class queue_elem *queue)
 {
-  struct queue_elem *subst_elem;
+  class queue_elem *subst_elem;
   int i, j, patterns_match;
 
   for (subst_elem = define_subst_queue;
@@ -1872,8 +1942,9 @@ process_substs_on_one_elem (struct queue_elem *elem,
 
       /* Recalculate condition, joining conditions from original and
         DEFINE_SUBST input patterns.  */
-      XSTR (elem->data, 2) = join_c_conditions (XSTR (subst_elem->data, 2),
-                                               XSTR (elem->data, 2));
+      XSTR (elem->data, 2)
+       = rtx_reader_ptr->join_c_conditions (XSTR (subst_elem->data, 2),
+                                            XSTR (elem->data, 2));
       /* Mark that subst was applied by changing attribute from "yes"
         to "no".  */
       change_subst_attribute (elem, subst_elem, subst_false);
@@ -2155,6 +2226,7 @@ subst_dup (rtx pattern, int n_alt, int n_subst_alt)
        case 'V':
          if (XVEC (pattern, i) == NULL)
            break;
+         /* FALLTHRU */
        case 'E':
          if (code != MATCH_DUP && code != MATCH_OP_DUP)
            for (j = XVECLEN (pattern, i) - 1; j >= 0; --j)
@@ -2162,7 +2234,8 @@ subst_dup (rtx pattern, int n_alt, int n_subst_alt)
                                                   n_alt, n_subst_alt);
          break;
 
-       case 'i': case 'r': case 'w': case '0': case 's': case 'S': case 'T':
+       case 'r': case 'p': case 'i': case 'w':
+       case '0': case 's': case 'S': case 'T':
          break;
 
        default:
@@ -2178,7 +2251,7 @@ subst_dup (rtx pattern, int n_alt, int n_subst_alt)
 static void
 process_define_cond_exec (void)
 {
-  struct queue_elem *elem;
+  class queue_elem *elem;
 
   identify_predicable_attribute ();
   if (have_error)
@@ -2194,7 +2267,7 @@ process_define_cond_exec (void)
 static void
 process_define_subst (void)
 {
-  struct queue_elem *elem, *elem_attr;
+  class queue_elem *elem, *elem_attr;
 
   /* Check if each define_subst has corresponding define_subst_attr.  */
   for (elem = define_subst_queue; elem ; elem = elem->next)
@@ -2225,10 +2298,18 @@ process_define_subst (void)
     }
 }
 \f
-/* A read_md_files callback for reading an rtx.  */
+/* A subclass of rtx_reader which reads .md files and calls process_rtx on
+   the top-level elements.  */
 
-static void
-rtx_handle_directive (file_location loc, const char *rtx_name)
+class gen_reader : public rtx_reader
+{
+ public:
+  gen_reader () : rtx_reader (false) {}
+  void handle_unknown_directive (file_location, const char *);
+};
+
+void
+gen_reader::handle_unknown_directive (file_location loc, const char *rtx_name)
 {
   auto_vec<rtx, 32> subrtxs;
   if (!read_rtx (rtx_name, &subrtxs))
@@ -2249,7 +2330,7 @@ htab_eq_string (const void *s1, const void *s2)
 }
 
 /* Add mnemonic STR with length LEN to the mnemonic hash table
-   MNEMONIC_HTAB.  A trailing zero end character is appendend to STR
+   MNEMONIC_HTAB.  A trailing zero end character is appended to STR
    and a permanent heap copy of STR is created.  */
 
 static void
@@ -2291,6 +2372,7 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
   rtx set_attr;
   char *attr_name;
   rtvec new_vec;
+  struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
 
   template_code = XTMPL (insn, 3);
 
@@ -2316,13 +2398,13 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
          sp = ep + 1;
 
       if (i > 0)
-       obstack_1grow (&string_obstack, ',');
+       obstack_1grow (string_obstack, ',');
 
       while (cp < sp && ((*cp >= '0' && *cp <= '9')
                         || (*cp >= 'a' && *cp <= 'z')))
 
        {
-         obstack_1grow (&string_obstack, *cp);
+         obstack_1grow (string_obstack, *cp);
          cp++;
          size++;
        }
@@ -2333,7 +2415,7 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
            {
              /* Don't set a value if there are more than one
                 instruction in the string.  */
-             obstack_blank_fast (&string_obstack, -size);
+             obstack_blank_fast (string_obstack, -size);
              size = 0;
 
              cp = sp;
@@ -2342,22 +2424,22 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
          cp++;
        }
       if (size == 0)
-       obstack_1grow (&string_obstack, '*');
+       obstack_1grow (string_obstack, '*');
       else
        add_mnemonic_string (mnemonic_htab,
-                            (char *) obstack_next_free (&string_obstack) - size,
+                            (char *) obstack_next_free (string_obstack) - size,
                             size);
       i++;
     }
 
   /* An insn definition might emit an empty string.  */
-  if (obstack_object_size (&string_obstack) == 0)
+  if (obstack_object_size (string_obstack) == 0)
     return;
 
-  obstack_1grow (&string_obstack, '\0');
+  obstack_1grow (string_obstack, '\0');
 
   set_attr = rtx_alloc (SET_ATTR);
-  XSTR (set_attr, 1) = XOBFINISH (&string_obstack, char *);
+  XSTR (set_attr, 1) = XOBFINISH (string_obstack, char *);
   attr_name = XNEWVAR (char, strlen (MNEMONIC_ATTR_NAME) + 1);
   strcpy (attr_name, MNEMONIC_ATTR_NAME);
   XSTR (set_attr, 0) = attr_name;
@@ -2380,8 +2462,10 @@ gen_mnemonic_setattr (htab_t mnemonic_htab, rtx insn)
 static int
 mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED)
 {
-  obstack_grow (&string_obstack, (char*)*slot, strlen ((char*)*slot));
-  obstack_1grow (&string_obstack, ',');
+  struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
+
+  obstack_grow (string_obstack, (char*) *slot, strlen ((char*) *slot));
+  obstack_1grow (string_obstack, ',');
   return 1;
 }
 
@@ -2394,11 +2478,12 @@ mnemonic_htab_callback (void **slot, void *info ATTRIBUTE_UNUSED)
 static void
 gen_mnemonic_attr (void)
 {
-  struct queue_elem *elem;
+  class queue_elem *elem;
   rtx mnemonic_attr = NULL;
   htab_t mnemonic_htab;
   const char *str, *p;
   int i;
+  struct obstack *string_obstack = rtx_reader_ptr->get_string_obstack ();
 
   if (have_error)
     return;
@@ -2462,15 +2547,15 @@ gen_mnemonic_attr (void)
   htab_traverse (mnemonic_htab, mnemonic_htab_callback, NULL);
 
   /* Replace the last ',' with the zero end character.  */
-  *((char *)obstack_next_free (&string_obstack) - 1) = '\0';
-  XSTR (mnemonic_attr, 1) = XOBFINISH (&string_obstack, char *);
+  *((char *) obstack_next_free (string_obstack) - 1) = '\0';
+  XSTR (mnemonic_attr, 1) = XOBFINISH (string_obstack, char *);
 }
 
 /* Check if there are DEFINE_ATTRs with the same name.  */
 static void
 check_define_attr_duplicates ()
 {
-  struct queue_elem *elem;
+  class queue_elem *elem;
   htab_t attr_htab;
   char * attr_name;
   void **slot;
@@ -2499,8 +2584,8 @@ check_define_attr_duplicates ()
 
 /* The entry point for initializing the reader.  */
 
-bool
-init_rtx_reader_args_cb (int argc, char **argv,
+rtx_reader *
+init_rtx_reader_args_cb (int argc, const char **argv,
                         bool (*parse_opt) (const char *))
 {
   /* Prepare to read input.  */
@@ -2515,7 +2600,8 @@ init_rtx_reader_args_cb (int argc, char **argv,
   split_sequence_num = 1;
   peephole2_sequence_num = 1;
 
-  read_md_files (argc, argv, parse_opt, rtx_handle_directive);
+  gen_reader *reader = new gen_reader ();
+  reader->read_md_files (argc, argv, parse_opt);
 
   if (define_attr_queue != NULL)
     check_define_attr_duplicates ();
@@ -2531,13 +2617,19 @@ init_rtx_reader_args_cb (int argc, char **argv,
   if (define_attr_queue != NULL)
     gen_mnemonic_attr ();
 
-  return !have_error;
+  if (have_error)
+    {
+      delete reader;
+      return NULL;
+    }
+
+  return reader;
 }
 
 /* Programs that don't have their own options can use this entry point
    instead.  */
-bool
-init_rtx_reader_args (int argc, char **argv)
+rtx_reader *
+init_rtx_reader_args (int argc, const char **argv)
 {
   return init_rtx_reader_args_cb (argc, argv, 0);
 }
@@ -2559,7 +2651,7 @@ read_md_rtx (md_rtx_info *info)
      to use elided pattern numbers for anything.  */
   do
     {
-      struct queue_elem **queue, *elem;
+      class queue_elem **queue, *elem;
 
       /* Read all patterns from a given queue before moving on to the next.  */
       if (define_attr_queue != NULL)
@@ -2803,6 +2895,7 @@ add_predicate_code (struct pred_data *pred, enum rtx_code code)
          && code != CONCAT
          && code != PARALLEL
          && code != STRICT_LOW_PART
+         && code != ZERO_EXTRACT
          && code != SCRATCH)
        pred->allows_non_lvalue = true;
 
@@ -2979,6 +3072,10 @@ get_pattern_stats_1 (struct pattern_stats *stats, rtx x)
       break;
 
     case MATCH_SCRATCH:
+      if (stats->min_scratch_opno == -1)
+       stats->min_scratch_opno = XINT (x, 0);
+      else
+       stats->min_scratch_opno = MIN (stats->min_scratch_opno, XINT (x, 0));
       stats->max_scratch_opno = MAX (stats->max_scratch_opno, XINT (x, 0));
       break;
 
@@ -3011,6 +3108,7 @@ get_pattern_stats (struct pattern_stats *stats, rtvec pattern)
 
   stats->max_opno = -1;
   stats->max_dup_opno = -1;
+  stats->min_scratch_opno = -1;
   stats->max_scratch_opno = -1;
   stats->num_dups = 0;
 
This page took 0.061052 seconds and 5 git commands to generate.