OSDN Git Service

* gfortran.dg/isnan_1.f90: Add -mieee for sh.
[pf3gnuchains/gcc-fork.git] / gcc / genrecog.c
index 097faef..8564b5c 100644 (file)
@@ -1,12 +1,13 @@
 /* Generate code from machine description to recognize rtl as insns.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1997, 1998,
-   1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007
+   Free Software Foundation, Inc.
 
    This file is part of GCC.
 
    GCC is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2, or (at your option)
+   the Free Software Foundation; either version 3, or (at your option)
    any later version.
 
    GCC is distributed in the hope that it will be useful, but WITHOUT
@@ -15,9 +16,8 @@
    License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GCC; see the file COPYING.  If not, write to the Free
-   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-   02111-1307, USA.  */
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
 
 
 /* This program is used to produce insn-recog.c, which contains a
 #define OUTPUT_LABEL(INDENT_STRING, LABEL_NUMBER) \
   printf("%sL%d: ATTRIBUTE_UNUSED_LABEL\n", (INDENT_STRING), (LABEL_NUMBER))
 
-/* Holds an array of names indexed by insn_code_number.  */
-static char **insn_name_ptr = 0;
-static int insn_name_ptr_size = 0;
-
 /* A listhead of decision trees.  The alternatives to a node are kept
    in a doubly-linked list so we can easily add nodes to the proper
    place when merging.  */
@@ -87,6 +83,7 @@ struct decision_test
   /* These types are roughly in the order in which we'd like to test them.  */
   enum decision_type
     {
+      DT_num_insns,
       DT_mode, DT_code, DT_veclen,
       DT_elt_zero_int, DT_elt_one_int, DT_elt_zero_wide, DT_elt_zero_wide_safe,
       DT_const_int,
@@ -96,6 +93,7 @@ struct decision_test
 
   union
   {
+    int num_insns;             /* Number if insn in a define_peephole2.  */
     enum machine_mode mode;    /* Machine mode of node.  */
     RTX_CODE code;             /* Code to test.  */
 
@@ -173,7 +171,7 @@ static int pattern_lineno;
 /* Count of errors.  */
 static int error_count;
 \f
-/* Predicate handling. 
+/* Predicate handling.
 
    We construct from the machine description a table mapping each
    predicate to a list of the rtl codes it can possibly match.  The
@@ -226,6 +224,9 @@ static int error_count;
 #define TRISTATE_NOT(a)                                \
   ((a) == I ? I : !(a))
 
+/* 0 means no warning about that code yet, 1 means warned.  */
+static char did_you_mean_codes[NUM_RTX_CODE];
+
 /* Recursively calculate the set of rtx codes accepted by the
    predicate expression EXP, writing the result to CODES.  */
 static void
@@ -254,11 +255,11 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
     case NOT:
       compute_predicate_codes (XEXP (exp, 0), op0_codes);
       for (i = 0; i < NUM_RTX_CODE; i++)
-       codes[i] = TRISTATE_NOT (codes[i]);
+       codes[i] = TRISTATE_NOT (op0_codes[i]);
       break;
 
     case IF_THEN_ELSE:
-      /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */ 
+      /* a ? b : c  accepts the same codes as (a & b) | (!a & c).  */
       compute_predicate_codes (XEXP (exp, 0), op0_codes);
       compute_predicate_codes (XEXP (exp, 1), op1_codes);
       compute_predicate_codes (XEXP (exp, 2), op2_codes);
@@ -269,7 +270,15 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
       break;
 
     case MATCH_CODE:
-      /* MATCH_CODE allows a specified list of codes.  */
+      /* MATCH_CODE allows a specified list of codes.  However, if it
+        does not apply to the top level of the expression, it does not
+        constrain the set of codes for the top level.  */
+      if (XSTR (exp, 1)[0] != '\0')
+       {
+         memset (codes, Y, NUM_RTX_CODE);
+         break;
+       }
+
       memset (codes, N, NUM_RTX_CODE);
       {
        const char *next_code = XSTR (exp, 0);
@@ -285,14 +294,31 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
        while ((code = scan_comma_elt (&next_code)) != 0)
          {
            size_t n = next_code - code;
-           
+           int found_it = 0;
+
            for (i = 0; i < NUM_RTX_CODE; i++)
              if (!strncmp (code, GET_RTX_NAME (i), n)
                  && GET_RTX_NAME (i)[n] == '\0')
                {
                  codes[i] = Y;
+                 found_it = 1;
                  break;
                }
+           if (!found_it)
+             {
+               message_with_line (pattern_lineno, "match_code \"%.*s\" matches nothing",
+                                  (int) n, code);
+               error_count ++;
+               for (i = 0; i < NUM_RTX_CODE; i++)
+                 if (!strncasecmp (code, GET_RTX_NAME (i), n)
+                     && GET_RTX_NAME (i)[n] == '\0'
+                     && !did_you_mean_codes[i])
+                   {
+                     did_you_mean_codes[i] = 1;
+                     message_with_line (pattern_lineno, "(did you mean \"%s\"?)", GET_RTX_NAME (i));
+                   }
+             }
+
          }
       }
       break;
@@ -419,7 +445,7 @@ static void find_afterward
   (struct decision_head *, struct decision *);
 
 static void change_state
-  (const char *, const char *, struct decision *, const char *);
+  (const char *, const char *, const char *);
 static void print_code
   (enum rtx_code);
 static void write_afterward
@@ -451,9 +477,6 @@ static struct decision_head make_insn_sequence
 static void process_tree
   (struct decision_head *, enum routine_type);
 
-static void record_insn_name
-  (int, const char *);
-
 static void debug_decision_0
   (struct decision *, int, int);
 static void debug_decision_1
@@ -488,7 +511,7 @@ new_decision_test (enum decision_type type, struct decision_test ***pplace)
   struct decision_test **place = *pplace;
   struct decision_test *test;
 
-  test = xmalloc (sizeof (*test));
+  test = XNEW (struct decision_test);
   test->next = *place;
   test->type = type;
   *place = test;
@@ -547,7 +570,7 @@ find_operand (rtx pattern, int n, rtx stop)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -598,7 +621,7 @@ find_matching_operand (rtx pattern, int n)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -851,7 +874,7 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 }
@@ -903,8 +926,22 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
       /* Toplevel peephole pattern.  */
       if (insn_type == PEEPHOLE2 && top)
        {
-         /* We don't need the node we just created -- unlink it.  */
-         last->first = last->last = NULL;
+         int num_insns;
+
+         /* Check we have sufficient insns.  This avoids complications
+            because we then know peep2_next_insn never fails.  */
+         num_insns = XVECLEN (pattern, 0);
+         if (num_insns > 1)
+           {
+             test = new_decision_test (DT_num_insns, &place);
+             test->u.num_insns = num_insns;
+             last = &sub->success;
+           }
+         else
+           {
+             /* We don't need the node we just created -- unlink it.  */
+             last->first = last->last = NULL;
+           }
 
          for (i = 0; i < (size_t) XVECLEN (pattern, 0); i++)
            {
@@ -992,7 +1029,7 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
        if (allows_const_int)
          mode = VOIDmode;
 
-       /* Accept the operand, ie. record it in `operands'.  */
+       /* Accept the operand, i.e. record it in `operands'.  */
        test = new_decision_test (DT_accept_op, &place);
        test->u.opno = XINT (pattern, 0);
 
@@ -1050,18 +1087,18 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
     {
       if (fmt[i] == 'i')
        {
-         if (i == 0)
+         gcc_assert (i < 2);
+
+         if (!i)
            {
              test = new_decision_test (DT_elt_zero_int, &place);
              test->u.intval = XINT (pattern, i);
            }
-         else if (i == 1)
+         else
            {
              test = new_decision_test (DT_elt_one_int, &place);
              test->u.intval = XINT (pattern, i);
            }
-         else
-           abort ();
        }
       else if (fmt[i] == 'w')
        {
@@ -1071,16 +1108,14 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
            = ((int) XWINT (pattern, i) == XWINT (pattern, i))
              ? DT_elt_zero_wide_safe : DT_elt_zero_wide;
 
-         if (i != 0)
-           abort ();
+         gcc_assert (!i);
 
          test = new_decision_test (type, &place);
          test->u.intval = XWINT (pattern, i);
        }
       else if (fmt[i] == 'E')
        {
-         if (i != 0)
-           abort ();
+         gcc_assert (!i);
 
          test = new_decision_test (DT_veclen, &place);
          test->u.veclen = XVECLEN (pattern, i);
@@ -1117,7 +1152,7 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -1139,8 +1174,7 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
     }
 
   /* If we didn't insert any tests or accept nodes, hork.  */
-  if (this->tests == NULL)
-    abort ();
+  gcc_assert (this->tests);
 
  ret:
   free (subpos);
@@ -1157,6 +1191,12 @@ maybe_both_true_2 (struct decision_test *d1, struct decision_test *d2)
     {
       switch (d1->type)
        {
+       case DT_num_insns:
+         if (d1->u.num_insns == d2->u.num_insns)
+           return 1;
+         else
+           return -1;
+
        case DT_mode:
          return d1->u.mode == d2->u.mode;
 
@@ -1311,8 +1351,7 @@ maybe_both_true (struct decision *d1, struct decision *d2,
   cmp = strcmp (d1->position, d2->position);
   if (cmp != 0)
     {
-      if (toplevel)
-       abort ();
+      gcc_assert (!toplevel);
 
       /* If the d2->position was lexically lower, swap.  */
       if (cmp > 0)
@@ -1356,6 +1395,9 @@ nodes_identical_1 (struct decision_test *d1, struct decision_test *d2)
 {
   switch (d1->type)
     {
+    case DT_num_insns:
+      return d1->u.num_insns == d2->u.num_insns;
+
     case DT_mode:
       return d1->u.mode == d2->u.mode;
 
@@ -1390,7 +1432,7 @@ nodes_identical_1 (struct decision_test *d1, struct decision_test *d2)
       return 1;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -1492,8 +1534,7 @@ merge_trees (struct decision_head *oldh, struct decision_head *addh)
     }
 
   /* Trying to merge bits at different positions isn't possible.  */
-  if (strcmp (oldh->first->position, addh->first->position))
-    abort ();
+  gcc_assert (!strcmp (oldh->first->position, addh->first->position));
 
   for (add = addh->first; add ; add = next)
     {
@@ -1752,8 +1793,7 @@ find_afterward (struct decision_head *head, struct decision *real_afterward)
    match multiple insns and we try to step past the end of the stream.  */
 
 static void
-change_state (const char *oldpos, const char *newpos,
-             struct decision *afterward, const char *indent)
+change_state (const char *oldpos, const char *newpos, const char *indent)
 {
   int odepth = strlen (oldpos);
   int ndepth = strlen (newpos);
@@ -1778,22 +1818,8 @@ change_state (const char *oldpos, const char *newpos,
       /* It's a different insn from the first one.  */
       if (ISUPPER (newpos[depth]))
        {
-         /* We can only fail if we're moving down the tree.  */
-         if (old_has_insn >= 0 && oldpos[old_has_insn] >= newpos[depth])
-           {
-             printf ("%stem = peep2_next_insn (%d);\n",
-                     indent, newpos[depth] - 'A');
-           }
-         else
-           {
-             printf ("%stem = peep2_next_insn (%d);\n",
-                     indent, newpos[depth] - 'A');
-             printf ("%sif (tem == NULL_RTX)\n", indent);
-             if (afterward)
-               printf ("%s  goto L%d;\n", indent, afterward->number);
-             else
-               printf ("%s  goto ret0;\n", indent);
-           }
+         printf ("%stem = peep2_next_insn (%d);\n",
+                 indent, newpos[depth] - 'A');
          printf ("%sx%d = PATTERN (tem);\n", indent, depth + 1);
        }
       else if (ISLOWER (newpos[depth]))
@@ -1827,7 +1853,7 @@ write_afterward (struct decision *start, struct decision *afterward,
     printf("%sgoto ret0;\n", indent);
   else
     {
-      change_state (start->position, afterward->position, NULL, indent);
+      change_state (start->position, afterward->position, indent);
       printf ("%sgoto L%d;\n", indent, afterward->number);
     }
 }
@@ -1989,7 +2015,7 @@ write_switch (struct decision *start, int depth)
          printf ("(int) XWINT (x%d, 0)", depth);
          break;
        default:
-         abort ();
+         gcc_unreachable ();
        }
       printf (")\n%s    {\n", indent);
 
@@ -2022,7 +2048,7 @@ write_switch (struct decision *start, int depth)
              print_host_wide_int (p->tests->u.intval);
              break;
            default:
-             abort ();
+             gcc_unreachable ();
            }
          printf (":\n%s      goto L%d;\n", indent, p->success.first->number);
          p->success.first->need_label = 1;
@@ -2052,6 +2078,10 @@ write_cond (struct decision_test *p, int depth,
 {
   switch (p->type)
     {
+    case DT_num_insns:
+      printf ("peep2_current_count >= %d", p->u.num_insns);
+      break;
+
     case DT_mode:
       printf ("GET_MODE (x%d) == %smode", depth, GET_MODE_NAME (p->u.mode));
       break;
@@ -2098,25 +2128,17 @@ write_cond (struct decision_test *p, int depth,
       break;
 
     case DT_c_test:
-      printf ("(%s)", p->u.c_test);
+      print_c_condition (p->u.c_test);
       break;
 
     case DT_accept_insn:
-      switch (subroutine_type)
-       {
-       case RECOG:
-         if (p->u.insn.num_clobbers_to_add == 0)
-           abort ();
-         printf ("pnum_clobbers != NULL");
-         break;
-
-       default:
-         abort ();
-       }
+      gcc_assert (subroutine_type == RECOG);
+      gcc_assert (p->u.insn.num_clobbers_to_add);
+      printf ("pnum_clobbers != NULL");
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }
 
@@ -2151,14 +2173,12 @@ write_action (struct decision *p, struct decision_test *test,
       if (test->next)
        {
          test = test->next;
-         if (test->type != DT_accept_insn)
-           abort ();
+         gcc_assert (test->type == DT_accept_insn);
        }
     }
 
   /* Sanity check that we're now at the end of the list of tests.  */
-  if (test->next)
-    abort ();
+  gcc_assert (!test->next);
 
   if (test->type == DT_accept_insn)
     {
@@ -2170,7 +2190,7 @@ write_action (struct decision *p, struct decision_test *test,
                    indent, test->u.insn.num_clobbers_to_add);
          printf ("%sreturn %d;  /* %s */\n", indent,
                  test->u.insn.code_number,
-                 insn_name_ptr[test->u.insn.code_number]);
+                 get_insn_name (test->u.insn.code_number));
          break;
 
        case SPLIT:
@@ -2196,7 +2216,7 @@ write_action (struct decision *p, struct decision_test *test,
          break;
 
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
   else
@@ -2231,7 +2251,7 @@ is_unconditional (struct decision_test *t, enum routine_type subroutine_type)
        case PEEPHOLE2:
          return -1;
        default:
-         abort ();
+         gcc_unreachable ();
        }
     }
 
@@ -2358,7 +2378,7 @@ write_tree (struct decision_head *head, const char *prevpos,
          else
            printf ("  if (tem >= 0)\n    return tem;\n");
 
-         change_state (p->position, p->afterward->position, NULL, "  ");
+         change_state (p->position, p->afterward->position, "  ");
          printf ("  goto L%d;\n", p->afterward->number);
        }
       else
@@ -2371,7 +2391,7 @@ write_tree (struct decision_head *head, const char *prevpos,
     {
       int depth = strlen (p->position);
 
-      change_state (prevpos, p->position, head->last->afterward, "  ");
+      change_state (prevpos, p->position, "  ");
       write_tree_1 (head, depth, type);
 
       for (p = head->first; p; p = p->next)
@@ -2476,6 +2496,8 @@ write_header (void)
 #include \"resource.h\"\n\
 #include \"toplev.h\"\n\
 #include \"reload.h\"\n\
+#include \"regs.h\"\n\
+#include \"tm-constrs.h\"\n\
 \n");
 
   puts ("\n\
@@ -2527,10 +2549,7 @@ make_insn_sequence (rtx insn, enum routine_type type)
   char c_test_pos[2];
 
   /* We should never see an insn whose C test is false at compile time.  */
-  if (truth == 0)
-    abort ();
-
-  record_insn_name (next_insn_code, (type == RECOG ? XSTR (insn, 0) : NULL));
+  gcc_assert (truth);
 
   c_test_pos[0] = '\0';
   if (type == PEEPHOLE2)
@@ -2780,52 +2799,14 @@ main (int argc, char **argv)
   return (ferror (stdout) != 0 ? FATAL_EXIT_CODE : SUCCESS_EXIT_CODE);
 }
 \f
-/* Define this so we can link with print-rtl.o to get debug_rtx function.  */
-const char *
-get_insn_name (int code)
-{
-  if (code < insn_name_ptr_size)
-    return insn_name_ptr[code];
-  else
-    return NULL;
-}
-
-static void
-record_insn_name (int code, const char *name)
-{
-  static const char *last_real_name = "insn";
-  static int last_real_code = 0;
-  char *new;
-
-  if (insn_name_ptr_size <= code)
-    {
-      int new_size;
-      new_size = (insn_name_ptr_size ? insn_name_ptr_size * 2 : 512);
-      insn_name_ptr = xrealloc (insn_name_ptr, sizeof(char *) * new_size);
-      memset (insn_name_ptr + insn_name_ptr_size, 0,
-             sizeof(char *) * (new_size - insn_name_ptr_size));
-      insn_name_ptr_size = new_size;
-    }
-
-  if (!name || name[0] == '\0')
-    {
-      new = xmalloc (strlen (last_real_name) + 10);
-      sprintf (new, "%s+%d", last_real_name, code - last_real_code);
-    }
-  else
-    {
-      last_real_name = new = xstrdup (name);
-      last_real_code = code;
-    }
-
-  insn_name_ptr[code] = new;
-}
-\f
 static void
 debug_decision_2 (struct decision_test *test)
 {
   switch (test->type)
     {
+    case DT_num_insns:
+      fprintf (stderr, "num_insns=%d", test->u.num_insns);
+      break;
     case DT_mode:
       fprintf (stderr, "mode=%s", GET_MODE_NAME (test->u.mode));
       break;
@@ -2874,7 +2855,7 @@ debug_decision_2 (struct decision_test *test)
       break;
 
     default:
-      abort ();
+      gcc_unreachable ();
     }
 }