OSDN Git Service

2009-08-04 Tobias Burnus <burnus@net-b.de>
[pf3gnuchains/gcc-fork.git] / gcc / genrecog.c
index cb86849..6e82584 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,
 /* 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, 2005 Free Software Foundation, Inc.
+   1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009
+   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
 
    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
    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
    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, 51 Franklin Street, Fifth Floor, Boston, MA
-   02110-1301, 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
 
 
 /* This program is used to produce insn-recog.c, which contains a
@@ -71,6 +71,17 @@ struct decision_head
   struct decision *last;
 };
 
   struct decision *last;
 };
 
+/* 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,
+  DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
+  DT_accept_op, DT_accept_insn
+};
+
 /* A single test.  The two accept types aren't tests per-se, but
    their equality (or lack thereof) does affect tree merging so
    it is convenient to keep them here.  */
 /* A single test.  The two accept types aren't tests per-se, but
    their equality (or lack thereof) does affect tree merging so
    it is convenient to keep them here.  */
@@ -80,16 +91,7 @@ struct decision_test
   /* A linked list through the tests attached to a node.  */
   struct decision_test *next;
 
   /* A linked list through the tests attached to a node.  */
   struct decision_test *next;
 
-  /* 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,
-      DT_veclen_ge, DT_dup, DT_pred, DT_c_test,
-      DT_accept_op, DT_accept_insn
-    } type;
+  enum decision_type type;
 
   union
   {
 
   union
   {
@@ -171,7 +173,7 @@ static int pattern_lineno;
 /* Count of errors.  */
 static int error_count;
 \f
 /* 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
 
    We construct from the machine description a table mapping each
    predicate to a list of the rtl codes it can possibly match.  The
@@ -259,7 +261,7 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
       break;
 
     case IF_THEN_ELSE:
       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);
       compute_predicate_codes (XEXP (exp, 0), op0_codes);
       compute_predicate_codes (XEXP (exp, 1), op1_codes);
       compute_predicate_codes (XEXP (exp, 2), op2_codes);
@@ -270,7 +272,15 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
       break;
 
     case MATCH_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);
       memset (codes, N, NUM_RTX_CODE);
       {
        const char *next_code = XSTR (exp, 0);
@@ -287,7 +297,7 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
          {
            size_t n = next_code - code;
            int found_it = 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')
            for (i = 0; i < NUM_RTX_CODE; i++)
              if (!strncmp (code, GET_RTX_NAME (i), n)
                  && GET_RTX_NAME (i)[n] == '\0')
@@ -358,9 +368,8 @@ compute_predicate_codes (rtx exp, char codes[NUM_RTX_CODE])
 static void
 process_define_predicate (rtx desc)
 {
 static void
 process_define_predicate (rtx desc)
 {
-  struct pred_data *pred = xcalloc (sizeof (struct pred_data), 1);
+  struct pred_data *pred = XCNEW (struct pred_data);
   char codes[NUM_RTX_CODE];
   char codes[NUM_RTX_CODE];
-  bool seen_one = false;
   int i;
 
   pred->name = XSTR (desc, 0);
   int i;
 
   pred->name = XSTR (desc, 0);
@@ -371,26 +380,8 @@ process_define_predicate (rtx desc)
 
   for (i = 0; i < NUM_RTX_CODE; i++)
     if (codes[i] != N)
 
   for (i = 0; i < NUM_RTX_CODE; i++)
     if (codes[i] != N)
-      {
-       pred->codes[i] = true;
-       if (GET_RTX_CLASS (i) != RTX_CONST_OBJ)
-         pred->allows_non_const = true;
-       if (i != REG
-           && i != SUBREG
-           && i != MEM
-           && i != CONCAT
-           && i != PARALLEL
-           && i != STRICT_LOW_PART)
-         pred->allows_non_lvalue = true;
-
-       if (seen_one)
-         pred->singleton = UNKNOWN;
-       else
-         {
-           pred->singleton = i;
-           seen_one = true;
-         }
-      }
+      add_predicate_code (pred, (enum rtx_code) i);
+
   add_predicate (pred);
 }
 #undef I
   add_predicate (pred);
 }
 #undef I
@@ -485,14 +476,14 @@ extern void debug_decision_list
 static struct decision *
 new_decision (const char *position, struct decision_head *last)
 {
 static struct decision *
 new_decision (const char *position, struct decision_head *last)
 {
-  struct decision *new = xcalloc (1, sizeof (struct decision));
+  struct decision *new_decision = XCNEW (struct decision);
 
 
-  new->success = *last;
-  new->position = xstrdup (position);
-  new->number = next_number++;
+  new_decision->success = *last;
+  new_decision->position = xstrdup (position);
+  new_decision->number = next_number++;
 
 
-  last->first = last->last = new;
-  return new;
+  last->first = last->last = new_decision;
+  return new_decision;
 }
 
 /* Create a new test and link it in at PLACE.  */
 }
 
 /* Create a new test and link it in at PLACE.  */
@@ -503,7 +494,7 @@ new_decision_test (enum decision_type type, struct decision_test ***pplace)
   struct decision_test **place = *pplace;
   struct decision_test *test;
 
   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;
   test->next = *place;
   test->type = type;
   *place = test;
@@ -804,7 +795,8 @@ validate_pattern (rtx pattern, rtx insn, rtx set, int set_code)
                 && GET_CODE (dest) != CC0
                 && GET_CODE (src) != PC
                 && GET_CODE (src) != CC0
                 && GET_CODE (dest) != CC0
                 && GET_CODE (src) != PC
                 && GET_CODE (src) != CC0
-                && GET_CODE (src) != CONST_INT)
+                && !CONST_INT_P (src)
+                && GET_CODE (src) != CALL)
          {
            const char *which;
            which = (dmode == VOIDmode ? "destination" : "source");
          {
            const char *which;
            which = (dmode == VOIDmode ? "destination" : "source");
@@ -888,7 +880,7 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
                 enum routine_type insn_type, int top)
 {
   RTX_CODE code;
                 enum routine_type insn_type, int top)
 {
   RTX_CODE code;
-  struct decision *this, *sub;
+  struct decision *this_decision, *sub;
   struct decision_test *test;
   struct decision_test **place;
   char *subpos;
   struct decision_test *test;
   struct decision_test **place;
   char *subpos;
@@ -901,12 +893,12 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
   if (depth > max_depth)
     max_depth = depth;
 
   if (depth > max_depth)
     max_depth = depth;
 
-  subpos = xmalloc (depth + 2);
+  subpos = XNEWVAR (char, depth + 2);
   strcpy (subpos, position);
   subpos[depth + 1] = 0;
 
   strcpy (subpos, position);
   subpos[depth + 1] = 0;
 
-  sub = this = new_decision (position, last);
-  place = &this->tests;
+  sub = this_decision = new_decision (position, last);
+  place = &this_decision->tests;
 
  restart:
   mode = GET_MODE (pattern);
 
  restart:
   mode = GET_MODE (pattern);
@@ -1080,7 +1072,7 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
       if (fmt[i] == 'i')
        {
          gcc_assert (i < 2);
       if (fmt[i] == 'i')
        {
          gcc_assert (i < 2);
-         
+
          if (!i)
            {
              test = new_decision_test (DT_elt_zero_int, &place);
          if (!i)
            {
              test = new_decision_test (DT_elt_zero_int, &place);
@@ -1153,20 +1145,20 @@ add_to_sequence (rtx pattern, struct decision_head *last, const char *position,
      before any of the nodes we may have added above.  */
   if (code != UNKNOWN)
     {
      before any of the nodes we may have added above.  */
   if (code != UNKNOWN)
     {
-      place = &this->tests;
+      place = &this_decision->tests;
       test = new_decision_test (DT_code, &place);
       test->u.code = code;
     }
 
   if (mode != VOIDmode)
     {
       test = new_decision_test (DT_code, &place);
       test->u.code = code;
     }
 
   if (mode != VOIDmode)
     {
-      place = &this->tests;
+      place = &this_decision->tests;
       test = new_decision_test (DT_mode, &place);
       test->u.mode = mode;
     }
 
   /* If we didn't insert any tests or accept nodes, hork.  */
       test = new_decision_test (DT_mode, &place);
       test->u.mode = mode;
     }
 
   /* If we didn't insert any tests or accept nodes, hork.  */
-  gcc_assert (this->tests);
+  gcc_assert (this_decision->tests);
 
  ret:
   free (subpos);
 
  ret:
   free (subpos);
@@ -1254,7 +1246,7 @@ maybe_both_true_2 (struct decision_test *d1, struct decision_test *d2)
          else if (d2->type == DT_pred && d2->u.pred.data)
            {
              bool common = false;
          else if (d2->type == DT_pred && d2->u.pred.data)
            {
              bool common = false;
-             enum rtx_code c;
+             int c;
 
              for (c = 0; c < NUM_RTX_CODE; c++)
                if (d1->u.pred.data->codes[c] && d2->u.pred.data->codes[c])
 
              for (c = 0; c < NUM_RTX_CODE; c++)
                if (d1->u.pred.data->codes[c] && d2->u.pred.data->codes[c])
@@ -1603,7 +1595,7 @@ factor_tests (struct decision_head *head)
   for (first = head->first; first && first->next; first = next)
     {
       enum decision_type type;
   for (first = head->first; first && first->next; first = next)
     {
       enum decision_type type;
-      struct decision *new, *old_last;
+      struct decision *new_dec, *old_last;
 
       type = first->tests->type;
       next = first->next;
 
       type = first->tests->type;
       next = first->next;
@@ -1626,8 +1618,8 @@ factor_tests (struct decision_head *head)
          below our first test.  */
       if (first->tests->next != NULL)
        {
          below our first test.  */
       if (first->tests->next != NULL)
        {
-         new = new_decision (first->position, &first->success);
-         new->tests = first->tests->next;
+         new_dec = new_decision (first->position, &first->success);
+         new_dec->tests = first->tests->next;
          first->tests->next = NULL;
        }
 
          first->tests->next = NULL;
        }
 
@@ -1644,14 +1636,14 @@ factor_tests (struct decision_head *head)
 
          if (next->tests->next != NULL)
            {
 
          if (next->tests->next != NULL)
            {
-             new = new_decision (next->position, &next->success);
-             new->tests = next->tests->next;
+             new_dec = new_decision (next->position, &next->success);
+             new_dec->tests = next->tests->next;
              next->tests->next = NULL;
            }
              next->tests->next = NULL;
            }
-         new = next;
+         new_dec = next;
          next = next->next;
          next = next->next;
-         new->next = NULL;
-         h.first = h.last = new;
+         new_dec->next = NULL;
+         h.first = h.last = new_dec;
 
          merge_trees (head, &h);
        }
 
          merge_trees (head, &h);
        }
@@ -1932,7 +1924,8 @@ write_switch (struct decision *start, int depth)
       while (p && p->tests->type == DT_pred && p->tests->u.pred.data)
        {
          const struct pred_data *data = p->tests->u.pred.data;
       while (p && p->tests->type == DT_pred && p->tests->u.pred.data)
        {
          const struct pred_data *data = p->tests->u.pred.data;
-         RTX_CODE c;
+         int c;
+
          for (c = 0; c < NUM_RTX_CODE; c++)
            if (codemap[c] && data->codes[c])
              goto pred_done;
          for (c = 0; c < NUM_RTX_CODE; c++)
            if (codemap[c] && data->codes[c])
              goto pred_done;
@@ -1941,7 +1934,7 @@ write_switch (struct decision *start, int depth)
            if (data->codes[c])
              {
                fputs ("    case ", stdout);
            if (data->codes[c])
              {
                fputs ("    case ", stdout);
-               print_code (c);
+               print_code ((enum rtx_code) c);
                fputs (":\n", stdout);
                codemap[c] = 1;
              }
                fputs (":\n", stdout);
                codemap[c] = 1;
              }
@@ -2488,6 +2481,8 @@ write_header (void)
 #include \"resource.h\"\n\
 #include \"toplev.h\"\n\
 #include \"reload.h\"\n\
 #include \"resource.h\"\n\
 #include \"toplev.h\"\n\
 #include \"reload.h\"\n\
+#include \"regs.h\"\n\
+#include \"tm-constrs.h\"\n\
 \n");
 
   puts ("\n\
 \n");
 
   puts ("\n\
@@ -2627,25 +2622,25 @@ make_insn_sequence (rtx insn, enum routine_type type)
 
          if (i != XVECLEN (x, 0))
            {
 
          if (i != XVECLEN (x, 0))
            {
-             rtx new;
+             rtx new_rtx;
              struct decision_head clobber_head;
 
              /* Build a similar insn without the clobbers.  */
              if (i == 1)
              struct decision_head clobber_head;
 
              /* Build a similar insn without the clobbers.  */
              if (i == 1)
-               new = XVECEXP (x, 0, 0);
+               new_rtx = XVECEXP (x, 0, 0);
              else
                {
                  int j;
 
              else
                {
                  int j;
 
-                 new = rtx_alloc (PARALLEL);
-                 XVEC (new, 0) = rtvec_alloc (i);
+                 new_rtx = rtx_alloc (PARALLEL);
+                 XVEC (new_rtx, 0) = rtvec_alloc (i);
                  for (j = i - 1; j >= 0; j--)
                  for (j = i - 1; j >= 0; j--)
-                   XVECEXP (new, 0, j) = XVECEXP (x, 0, j);
+                   XVECEXP (new_rtx, 0, j) = XVECEXP (x, 0, j);
                }
 
              /* Recognize it.  */
              memset (&clobber_head, 0, sizeof(clobber_head));
                }
 
              /* Recognize it.  */
              memset (&clobber_head, 0, sizeof(clobber_head));
-             last = add_to_sequence (new, &clobber_head, "", type, 1);
+             last = add_to_sequence (new_rtx, &clobber_head, "", type, 1);
 
              /* Find the end of the test chain on the last node.  */
              for (test = last->tests; test->next; test = test->next)
 
              /* Find the end of the test chain on the last node.  */
              for (test = last->tests; test->next; test = test->next)