OSDN Git Service

* Makefile.in: Remove pointless setting of CXXFLAGS for dejagnu
[pf3gnuchains/gcc-fork.git] / gcc / genrecog.c
index 0a02977..baf8c7f 100644 (file)
@@ -1,23 +1,23 @@
 /* Generate code from machine description to recognize rtl as insns.
    Copyright (C) 1987, 1988, 1992, 1993, 1994, 1995, 1997, 1998,
-   1999, 2000, 2001 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002 Free Software Foundation, Inc.
 
-   This file is part of GNU CC.
+   This file is part of GCC.
 
-   GNU CC is free software; you can redistribute it and/or modify
-   it under the terms of the GNU General Public License as published by
+   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)
    any later version.
 
-   GNU CC is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-   GNU General Public License for more details.
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
 
    You should have received a copy of the GNU General Public License
-   along with GNU CC; 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 COPYING.  If not, write to the Free
+   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+   02111-1307, USA.  */
 
 
 /* This program is used to produce insn-recog.c, which contains a
 
    This program also generates the function `split_insns', which
    returns 0 if the rtl could not be split, or it returns the split
-   rtl in a SEQUENCE.
+   rtl as an INSN list.
 
    This program also generates the function `peephole2_insns', which
    returns 0 if the rtl could not be matched.  If there was a match,
-   the new rtl is returned in a SEQUENCE, and LAST_INSN will point
+   the new rtl is returned in an INSN list, and LAST_INSN will point
    to the last recognized insn in the old sequence.  */
 
-#include "hconfig.h"
+#include "bconfig.h"
 #include "system.h"
+#include "coretypes.h"
+#include "tm.h"
 #include "rtl.h"
 #include "errors.h"
 #include "gensupport.h"
@@ -65,7 +67,7 @@ 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 doublely-linked list so we can easily add nodes to the proper
+   in a doubly-linked list so we can easily add nodes to the proper
    place when merging.  */
 
 struct decision_head
@@ -181,28 +183,29 @@ static int error_count;
    of tree nodes.  Also, if a predicate can match only one code, we can
    hardwire that code into the node testing the predicate.  */
 
-static struct pred_table
+static const struct pred_table
 {
-  const char *name;
-  RTX_CODE codes[NUM_RTX_CODE];
+  const char *const name;
+  const RTX_CODE codes[NUM_RTX_CODE];
 } preds[] = {
   {"general_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                      LABEL_REF, SUBREG, REG, MEM}},
+                      LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}},
 #ifdef PREDICATE_CODES
   PREDICATE_CODES
 #endif
   {"address_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                      LABEL_REF, SUBREG, REG, MEM, PLUS, MINUS, MULT}},
-  {"register_operand", {SUBREG, REG}},
-  {"pmode_register_operand", {SUBREG, REG}},
+                      LABEL_REF, SUBREG, REG, MEM, ADDRESSOF,
+                      PLUS, MINUS, MULT}},
+  {"register_operand", {SUBREG, REG, ADDRESSOF}},
+  {"pmode_register_operand", {SUBREG, REG, ADDRESSOF}},
   {"scratch_operand", {SCRATCH, REG}},
   {"immediate_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
                         LABEL_REF}},
   {"const_int_operand", {CONST_INT}},
   {"const_double_operand", {CONST_INT, CONST_DOUBLE}},
-  {"nonimmediate_operand", {SUBREG, REG, MEM}},
+  {"nonimmediate_operand", {SUBREG, REG, MEM, ADDRESSOF}},
   {"nonmemory_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                        LABEL_REF, SUBREG, REG}},
+                        LABEL_REF, SUBREG, REG, ADDRESSOF}},
   {"push_operand", {MEM}},
   {"pop_operand", {MEM}},
   {"memory_operand", {SUBREG, MEM}},
@@ -211,12 +214,12 @@ static struct pred_table
                           UNORDERED, ORDERED, UNEQ, UNGE, UNGT, UNLE,
                           UNLT, LTGT}},
   {"mode_independent_operand", {CONST_INT, CONST_DOUBLE, CONST, SYMBOL_REF,
-                               LABEL_REF, SUBREG, REG, MEM}}
+                               LABEL_REF, SUBREG, REG, MEM, ADDRESSOF}}
 };
 
 #define NUM_KNOWN_PREDS ARRAY_SIZE (preds)
 
-static const char * special_mode_pred_table[] = {
+static const char *const special_mode_pred_table[] = {
 #ifdef SPECIAL_MODE_PREDICATES
   SPECIAL_MODE_PREDICATES
 #endif
@@ -238,8 +241,6 @@ static void validate_pattern
 static struct decision *add_to_sequence
   PARAMS ((rtx, struct decision_head *, const char *, enum routine_type, int));
 
-static int maybe_both_true_mode
-  PARAMS ((enum machine_mode, enum machine_mode));
 static int maybe_both_true_2
   PARAMS ((struct decision_test *, struct decision_test *));
 static int maybe_both_true_1
@@ -319,7 +320,7 @@ new_decision (position, last)
      const char *position;
      struct decision_head *last;
 {
-  register struct decision *new
+  struct decision *new
     = (struct decision *) xmalloc (sizeof (struct decision));
 
   memset (new, 0, sizeof (*new));
@@ -522,6 +523,7 @@ validate_pattern (pattern, insn, set, set_code)
                    if (c != REG
                        && c != SUBREG
                        && c != MEM
+                       && c != ADDRESSOF
                        && c != CONCAT
                        && c != PARALLEL
                        && c != STRICT_LOW_PART)
@@ -777,8 +779,8 @@ add_to_sequence (pattern, last, position, insn_type, top)
   struct decision_test *test;
   struct decision_test **place;
   char *subpos;
-  register size_t i;
-  register const char *fmt;
+  size_t i;
+  const char *fmt;
   int depth = strlen (position);
   int len;
   enum machine_mode mode;
@@ -1009,7 +1011,7 @@ add_to_sequence (pattern, last, position, insn_type, top)
 
        case 'E':
          {
-           register int j;
+           int j;
            for (j = 0; j < XVECLEN (pattern, i); j++)
              {
                subpos[depth] = 'a' + j;
@@ -1056,29 +1058,6 @@ add_to_sequence (pattern, last, position, insn_type, top)
   return sub;
 }
 \f
-/* A subroutine of maybe_both_true; compares two modes.
-   Returns > 0 for "definitely both true" and < 0 for "maybe both true".  */
-
-static int
-maybe_both_true_mode (m1, m2)
-     enum machine_mode m1, m2;
-{
-  enum mode_class other_mode_class;
-
-  /* Pmode is not a distinct mode.  We do know that it is
-     either MODE_INT or MODE_PARTIAL_INT though.  */
-  if (m1 == Pmode)
-    other_mode_class = GET_MODE_CLASS (m2);
-  else if (m2 == Pmode)
-    other_mode_class = GET_MODE_CLASS (m1);
-  else
-    return m1 == m2;
-
-  return (other_mode_class == MODE_INT
-         || other_mode_class == MODE_PARTIAL_INT
-         ? -1 : 0);
-}
-
 /* A subroutine of maybe_both_true; examines only one test.
    Returns > 0 for "definitely both true" and < 0 for "maybe both true".  */
 
@@ -1091,7 +1070,7 @@ maybe_both_true_2 (d1, d2)
       switch (d1->type)
        {
        case DT_mode:
-         return maybe_both_true_mode (d1->u.mode, d2->u.mode);
+         return d1->u.mode == d2->u.mode;
 
        case DT_code:
          return d1->u.code == d2->u.code;
@@ -1127,7 +1106,7 @@ maybe_both_true_2 (d1, d2)
        {
          if (d2->type == DT_mode)
            {
-             if (maybe_both_true_mode (d1->u.pred.mode, d2->u.mode) == 0
+             if (d1->u.pred.mode != d2->u.mode
                  /* The mode of an address_operand predicate is the
                     mode of the memory, not the operand.  It can only
                     be used for testing the predicate, so we must
@@ -1200,7 +1179,7 @@ maybe_both_true_1 (d1, d2)
   struct decision_test *t1, *t2;
 
   /* A match_operand with no predicate can match anything.  Recognize
-     this by the existance of a lone DT_accept_op test.  */
+     this by the existence of a lone DT_accept_op test.  */
   if (d1->type == DT_accept_op || d2->type == DT_accept_op)
     return 1;
 
@@ -1225,7 +1204,7 @@ maybe_both_true_1 (d1, d2)
    D1 and D2.  Otherwise, return 1 (it may be that there is an RTL that
    can match both or just that we couldn't prove there wasn't such an RTL).
 
-   TOPLEVEL is non-zero if we are to only look at the top level and not
+   TOPLEVEL is nonzero if we are to only look at the top level and not
    recursively descend.  */
 
 static int
@@ -1258,7 +1237,7 @@ maybe_both_true (d1, d2, toplevel)
   if (cmp != 0)
     {
       if (toplevel)
-       abort();
+       abort ();
 
       /* If the d2->position was lexically lower, swap.  */
       if (cmp > 0)
@@ -1665,7 +1644,7 @@ find_afterward (head, real_afterward)
 {
   struct decision *p, *q, *afterward;
 
-  /* We can't propogate alternatives across subroutine boundaries.
+  /* We can't propagate alternatives across subroutine boundaries.
      This is not incorrect, merely a minor optimization loss.  */
 
   p = head->first;
@@ -1702,7 +1681,7 @@ find_afterward (head, real_afterward)
 \f
 /* Assuming that the state of argument is denoted by OLDPOS, take whatever
    actions are necessary to move to NEWPOS.  If we fail to move to the
-   new state, branch to node AFTERWARD if non-zero, otherwise return.
+   new state, branch to node AFTERWARD if nonzero, otherwise return.
 
    Failure to move to the new state can only occur if we are trying to
    match multiple insns and we try to step past the end of the stream.  */
@@ -1725,17 +1704,17 @@ change_state (oldpos, newpos, afterward, indent)
 
   /* Hunt for the last [A-Z] in both strings.  */
   for (old_has_insn = odepth - 1; old_has_insn >= 0; --old_has_insn)
-    if (oldpos[old_has_insn] >= 'A' && oldpos[old_has_insn] <= 'Z')
+    if (ISUPPER (oldpos[old_has_insn]))
       break;
   for (new_has_insn = ndepth - 1; new_has_insn >= 0; --new_has_insn)
-    if (newpos[new_has_insn] >= 'A' && newpos[new_has_insn] <= 'Z')
+    if (ISUPPER (newpos[new_has_insn]))
       break;
 
   /* Go down to desired level.  */
   while (depth < ndepth)
     {
       /* It's a different insn from the first one.  */
-      if (newpos[depth] >= 'A' && newpos[depth] <= 'Z')
+      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])
@@ -1755,7 +1734,7 @@ change_state (oldpos, newpos, afterward, indent)
            }
          printf ("%sx%d = PATTERN (tem);\n", indent, depth + 1);
        }
-      else if (newpos[depth] >= 'a' && newpos[depth] <= 'z')
+      else if (ISLOWER (newpos[depth]))
        printf ("%sx%d = XVECEXP (x%d, 0, %d);\n",
                indent, depth + 1, depth, newpos[depth] - 'a');
       else
@@ -1772,7 +1751,7 @@ static void
 print_code (code)
      enum rtx_code code;
 {
-  register const char *p;
+  const char *p;
   for (p = GET_RTX_NAME (code); *p; p++)
     putchar (TOUPPER (*p));
 }
@@ -1909,11 +1888,16 @@ write_switch (start, depth)
           || type == DT_elt_one_int
           || type == DT_elt_zero_wide_safe)
     {
-      /* Pmode may not be a compile-time constant.  */
-      if (type == DT_mode && p->tests->u.mode == Pmode)
-       return p;
+      const char *indent = "";
 
-      printf ("  switch (");
+      /* We cast switch parameter to integer, so we must ensure that the value
+        fits.  */
+      if (type == DT_elt_zero_wide_safe)
+       {
+         indent = "  ";
+         printf("  if ((int) XWINT (x%d, 0) == XWINT (x%d, 0))\n", depth, depth);
+       }
+      printf ("%s  switch (", indent);
       switch (type)
        {
        case DT_mode:
@@ -1936,7 +1920,7 @@ write_switch (start, depth)
        default:
          abort ();
        }
-      printf (")\n    {\n");
+      printf (")\n%s    {\n", indent);
 
       do
        {
@@ -1948,14 +1932,10 @@ write_switch (start, depth)
            if (nodes_identical_1 (p->tests, q->tests))
              goto case_done;
 
-         /* Pmode may not be a compile-time constant.  */
-         if (type == DT_mode && p->tests->u.mode == Pmode)
-           goto case_done;
-
          if (p != start && p->need_label && needs_label == NULL)
            needs_label = p;
 
-         printf ("    case ");
+         printf ("%s    case ", indent);
          switch (type)
            {
            case DT_mode:
@@ -1968,12 +1948,12 @@ write_switch (start, depth)
            case DT_elt_one_int:
            case DT_elt_zero_wide:
            case DT_elt_zero_wide_safe:
-             printf (HOST_WIDE_INT_PRINT_DEC, p->tests->u.intval);
+             printf (HOST_WIDE_INT_PRINT_DEC_C, p->tests->u.intval);
              break;
            default:
              abort ();
            }
-         printf (":\n      goto L%d;\n", p->success.first->number);
+         printf (":\n%s      goto L%d;\n", indent, p->success.first->number);
          p->success.first->need_label = 1;
 
          p = p->next;
@@ -1981,13 +1961,14 @@ write_switch (start, depth)
       while (p && p->tests->type == type && !p->tests->next);
 
     case_done:
-      printf ("    default:\n      break;\n    }\n");
+      printf ("%s    default:\n%s      break;\n%s    }\n",
+             indent, indent, indent);
 
       return needs_label != NULL ? needs_label : p;
     }
   else
     {
-      /* None of the other tests are ameanable.  */
+      /* None of the other tests are amenable.  */
       return p;
     }
 }
@@ -2026,7 +2007,7 @@ write_cond (p, depth, subroutine_type)
     case DT_elt_zero_wide:
     case DT_elt_zero_wide_safe:
       printf ("XWINT (x%d, 0) == ", depth);
-      printf (HOST_WIDE_INT_PRINT_DEC, p->u.intval);
+      printf (HOST_WIDE_INT_PRINT_DEC_C, p->u.intval);
       break;
 
     case DT_veclen_ge:
@@ -2129,7 +2110,7 @@ write_action (p, test, depth, uncond, success, subroutine_type)
            int match_len = 0, i;
 
            for (i = strlen (p->position) - 1; i >= 0; --i)
-             if (p->position[i] >= 'A' && p->position[i] <= 'Z')
+             if (ISUPPER (p->position[i]))
                {
                  match_len = p->position[i] - 'A';
                  break;
@@ -2271,7 +2252,7 @@ write_tree (head, prevpos, type, initial)
      enum routine_type type;
      int initial;
 {
-  register struct decision *p = head->first;
+  struct decision *p = head->first;
 
   putchar ('\n');
   if (p->need_label)
@@ -2349,7 +2330,7 @@ write_subroutine (head, type)
       printf ("%sint recog%s PARAMS ((rtx, rtx, int *));\n", s_or_e, extension);
       printf ("%sint\n\
 recog%s (x0, insn, pnum_clobbers)\n\
-     register rtx x0;\n\
+     rtx x0 ATTRIBUTE_UNUSED;\n\
      rtx insn ATTRIBUTE_UNUSED;\n\
      int *pnum_clobbers ATTRIBUTE_UNUSED;\n", s_or_e, extension);
       break;
@@ -2357,7 +2338,7 @@ recog%s (x0, insn, pnum_clobbers)\n\
       printf ("%srtx split%s PARAMS ((rtx, rtx));\n", s_or_e, extension);
       printf ("%srtx\n\
 split%s (x0, insn)\n\
-     register rtx x0;\n\
+     rtx x0 ATTRIBUTE_UNUSED;\n\
      rtx insn ATTRIBUTE_UNUSED;\n", s_or_e, extension);
       break;
     case PEEPHOLE2:
@@ -2365,15 +2346,15 @@ split%s (x0, insn)\n\
              s_or_e, extension);
       printf ("%srtx\n\
 peephole2%s (x0, insn, _pmatch_len)\n\
-     register rtx x0;\n\
+     rtx x0 ATTRIBUTE_UNUSED;\n\
      rtx insn ATTRIBUTE_UNUSED;\n\
      int *_pmatch_len ATTRIBUTE_UNUSED;\n", s_or_e, extension);
       break;
     }
 
-  printf ("{\n  register rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];\n");
+  printf ("{\n  rtx * const operands ATTRIBUTE_UNUSED = &recog_data.operand[0];\n");
   for (i = 1; i <= max_depth; i++)
-    printf ("  register rtx x%d ATTRIBUTE_UNUSED;\n", i);
+    printf ("  rtx x%d ATTRIBUTE_UNUSED;\n", i);
 
   printf ("  %s tem ATTRIBUTE_UNUSED;\n", IS_SPLIT (type) ? "rtx" : "int");
 
@@ -2417,6 +2398,8 @@ write_header ()
 \n\
 #include \"config.h\"\n\
 #include \"system.h\"\n\
+#include \"coretypes.h\"\n\
+#include \"tm.h\"\n\
 #include \"rtl.h\"\n\
 #include \"tm_p.h\"\n\
 #include \"function.h\"\n\
@@ -2454,10 +2437,10 @@ write_header ()
 
   puts ("\n\
    The function split_insns returns 0 if the rtl could not\n\
-   be split or the split rtl in a SEQUENCE if it can be.\n\
+   be split or the split rtl as an INSN list if it can be.\n\
 \n\
    The function peephole2_insns returns 0 if the rtl could not\n\
-   be matched. If there was a match, the new rtl is returned in a SEQUENCE,\n\
+   be matched. If there was a match, the new rtl is returned in an INSN list,\n\
    and LAST_INSN will point to the last recognized insn in the old sequence.\n\
 */\n\n");
 }
@@ -2475,11 +2458,16 @@ make_insn_sequence (insn, type)
 {
   rtx x;
   const char *c_test = XSTR (insn, type == RECOG ? 2 : 1);
+  int truth = maybe_eval_c_test (c_test);
   struct decision *last;
   struct decision_test *test, **place;
   struct decision_head head;
   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));
 
   c_test_pos[0] = '\0';
@@ -2527,7 +2515,8 @@ make_insn_sequence (insn, type)
     continue;
   place = &test->next;
 
-  if (c_test[0])
+  /* Skip the C test if it's known to be true at compile time.  */
+  if (truth == -1)
     {
       /* Need a new node if we have another test to add.  */
       if (test->type == DT_accept_op)
@@ -2600,7 +2589,9 @@ make_insn_sequence (insn, type)
                  place = &last->tests;
                }
 
-             if (c_test[0])
+             /* Skip the C test if it's known to be true at compile
+                 time.  */
+             if (truth == -1)
                {
                  test = new_decision_test (DT_c_test, &place);
                  test->u.c_test = c_test;
@@ -2678,9 +2669,9 @@ main (argc, argv)
   memset (&peephole2_tree, 0, sizeof peephole2_tree);
 
   if (argc <= 1)
-    fatal ("No input file name.");
+    fatal ("no input file name");
 
-  if (init_md_reader (argv[1]) != SUCCESS_EXIT_CODE)
+  if (init_md_reader_args (argc, argv) != SUCCESS_EXIT_CODE)
     return (FATAL_EXIT_CODE);
 
   next_insn_code = 0;