OSDN Git Service

(c_sizeof, build_c_cast): Set TREE_OVERFLOW in addition
[pf3gnuchains/gcc-fork.git] / gcc / genrecog.c
index 984cc8b..2480ea9 100644 (file)
@@ -46,7 +46,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
    it returns the split rtl in a SEQUENCE.  */
 
 #include <stdio.h>
-#include "config.h"
+#include "hconfig.h"
 #include "rtl.h"
 #include "obstack.h"
 
@@ -57,6 +57,7 @@ struct obstack *rtl_obstack = &obstack;
 #define obstack_chunk_free free
 
 extern void free ();
+extern rtx read_rtx ();
 
 /* Data structure for a listhead of decision trees.  The alternatives
    to a node are kept in a doublely-linked list so we can easily add nodes
@@ -82,6 +83,8 @@ struct decision
   int elt_zero_int;            /* Required value for XINT (rtl, 0) */
   int test_elt_one_int;                /* Nonzero if should test XINT (rtl, 1) */
   int elt_one_int;             /* Required value for XINT (rtl, 1) */
+  int test_elt_zero_wide;      /* Nonzero if should test XWINT (rtl, 0) */
+  HOST_WIDE_INT elt_zero_wide; /* Required value for XWINT (rtl, 0) */
   char *tests;                 /* If nonzero predicate to call */
   int pred;                    /* `preds' index of predicate or -1 */
   char *c_test;                        /* Additional test to perform */
@@ -161,26 +164,37 @@ static struct pred_table
 
 #define NUM_KNOWN_PREDS (sizeof preds / sizeof preds[0])
 
-static int try_merge_1 ();
-static int no_same_mode ();
-static int same_codes ();
-static int same_modes ();
-char *xmalloc ();
-static struct decision *add_to_sequence ();
-static struct decision_head merge_trees ();
-static struct decision *try_merge_2 ();
-static void write_subroutine ();
-static void print_code ();
-static void clear_codes ();
-static void clear_modes ();
-static void change_state ();
-static void write_tree ();
-static char *copystr ();
-static char *concat ();
-static void fatal ();
-void fancy_abort ();
-static void mybzero ();
-static void mybcopy ();
+static struct decision_head make_insn_sequence PROTO((rtx, enum routine_type));
+static struct decision *add_to_sequence PROTO((rtx, struct decision_head *,
+                                              char *));
+static int not_both_true       PROTO((struct decision *, struct decision *,
+                                      int));
+static int position_merit      PROTO((struct decision *, enum machine_mode,
+                                      enum rtx_code));
+static struct decision_head merge_trees PROTO((struct decision_head,
+                                              struct decision_head));
+static int break_out_subroutines PROTO((struct decision_head,
+                                       enum routine_type, int));
+static void write_subroutine   PROTO((struct decision *, enum routine_type));
+static void write_tree_1       PROTO((struct decision *, char *,
+                                      struct decision *, enum routine_type));
+static void print_code         PROTO((enum rtx_code));
+static int same_codes          PROTO((struct decision *, enum rtx_code));
+static void clear_codes                PROTO((struct decision *));
+static int same_modes          PROTO((struct decision *, enum machine_mode));
+static void clear_modes                PROTO((struct decision *));
+static void write_tree         PROTO((struct decision *, char *,
+                                      struct decision *, int,
+                                      enum routine_type));
+static void change_state       PROTO((char *, char *, int));
+static char *copystr           PROTO((char *));
+static void mybzero            PROTO((char *, unsigned));
+static void mybcopy            PROTO((char *, char *, unsigned));
+static char *concat            PROTO((char *, char *));
+static void fatal              PROTO((char *));
+char *xrealloc                 PROTO((char *, unsigned));
+char *xmalloc                  PROTO((unsigned));
+void fancy_abort               PROTO((void));
 \f
 /* Construct and return a sequence of decisions
    that will recognize INSN.
@@ -302,8 +316,10 @@ add_to_sequence (pattern, last, position)
   new->veclen = 0;
   new->test_elt_zero_int = 0;
   new->test_elt_one_int = 0;
+  new->test_elt_zero_wide = 0;
   new->elt_zero_int = 0;
   new->elt_one_int = 0;
+  new->elt_zero_wide = 0;
   new->tests = 0;
   new->pred = -1;
   new->c_test = 0;
@@ -395,8 +411,6 @@ add_to_sequence (pattern, last, position)
              new = add_to_sequence (XVECEXP (pattern, 2, i),
                                     &new->success, newpos);
            }
-
-         this->success.first->enforce_mode = 0;
        }
 
       return new;
@@ -412,10 +426,10 @@ add_to_sequence (pattern, last, position)
          new = add_to_sequence (XVECEXP (pattern, 1, i),
                                 &new->success, newpos);
        }
-      this->success.first->enforce_mode = 0;
       return new;
 
     case MATCH_DUP:
+    case MATCH_PAR_DUP:
       new->dupno = XINT (pattern, 0);
       new->code = UNKNOWN;
       new->enforce_mode = 0;
@@ -502,6 +516,11 @@ add_to_sequence (pattern, last, position)
          this->test_elt_one_int = 1;
          this->elt_one_int = XINT (pattern, i);
        }
+      else if (fmt[i] == 'w' && i == 0)
+       {
+         this->test_elt_zero_wide = 1;
+         this->elt_zero_wide = XWINT (pattern, i);
+       }
       else if (fmt[i] == 'E')
        {
          register int j;
@@ -551,6 +570,8 @@ not_both_true (d1, d2, toplevel)
          && d1->elt_zero_int != d2->elt_zero_int)
       || (d1->test_elt_one_int && d2->test_elt_one_int
          && d1->elt_one_int != d2->elt_one_int)
+      || (d1->test_elt_zero_wide && d2->test_elt_zero_wide
+         && d1->elt_zero_wide != d2->elt_zero_wide)
       || (d1->veclen && d2->veclen && d1->veclen != d2->veclen))
     return 1;
 
@@ -578,7 +599,7 @@ not_both_true (d1, d2, toplevel)
         for D1's predicate.  */
       if (d2->code != UNKNOWN)
        {
-         for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i]; i++)
+         for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i] != 0; i++)
            if (preds[d1->pred].codes[i] == d2->code)
              break;
 
@@ -590,7 +611,7 @@ not_both_true (d1, d2, toplevel)
 
       else if (d2->pred >= 0)
        {
-         for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i]; i++)
+         for (i = 0; i < NUM_RTX_CODE && preds[d1->pred].codes[i] != 0; i++)
            {
              for (j = 0; j < NUM_RTX_CODE; j++)
                if (preds[d2->pred].codes[j] == 0
@@ -632,7 +653,7 @@ not_both_true (d1, d2, toplevel)
 
    We would like to list nodes testing for specific codes before those
    that test predicates to avoid unnecessary function calls.  Similarly,
-   tests for specific modes should preceed nodes that allow any mode.
+   tests for specific modes should precede nodes that allow any mode.
 
    This function returns the merit (with 0 being the best) of inserting
    a test involving the specified MODE and CODE after node P.  If P is
@@ -643,7 +664,7 @@ static int
 position_merit (p, mode, code)
      struct decision *p;
      enum machine_mode mode;
-     RTX_CODE code;
+     enum rtx_code code;
 {
   enum machine_mode p_mode;
 
@@ -744,6 +765,7 @@ merge_trees (oldh, addh)
             would cause an infinite recursion.  */
          if (old->tests == 0 && old->test_elt_zero_int == 0
              && old->test_elt_one_int == 0 && old->veclen == 0
+             && old->test_elt_zero_wide == 0
              && old->dupno == -1 && old->mode == VOIDmode
              && old->code == UNKNOWN
              && (old->c_test != 0 || add->c_test != 0))
@@ -753,16 +775,18 @@ merge_trees (oldh, addh)
                    || (old->pred >= 0 && old->pred == add->pred)
                    || (old->tests && add->tests
                        && !strcmp (old->tests, add->tests)))
-             && old->test_elt_zero_int == add->test_elt_zero_int
-             && old->elt_zero_int == add->elt_zero_int
-             && old->test_elt_one_int == add->test_elt_one_int
-             && old->elt_one_int == add->elt_one_int
-             && old->veclen == add->veclen
-             && old->dupno == add->dupno
-             && old->opno == add->opno
-             && old->code == add->code
-             && old->enforce_mode == add->enforce_mode
-             && old->mode == add->mode)
+                  && old->test_elt_zero_int == add->test_elt_zero_int
+                  && old->elt_zero_int == add->elt_zero_int
+                  && old->test_elt_one_int == add->test_elt_one_int
+                  && old->elt_one_int == add->elt_one_int
+                  && old->test_elt_zero_wide == add->test_elt_zero_wide
+                  && old->elt_zero_wide == add->elt_zero_wide
+                  && old->veclen == add->veclen
+                  && old->dupno == add->dupno
+                  && old->opno == add->opno
+                  && old->code == add->code
+                  && old->enforce_mode == add->enforce_mode
+                  && old->mode == add->mode)
            {
              /* If the additional test is not the same, split both nodes
                 into nodes that just contain all things tested before the
@@ -780,7 +804,8 @@ merge_trees (oldh, addh)
                      struct decision *split
                        = (struct decision *) xmalloc (sizeof (struct decision));
 
-                     mybcopy (old, split, sizeof (struct decision));
+                     mybcopy ((char *) old, (char *) split,
+                              sizeof (struct decision));
 
                      old->success.first = old->success.last = split;
                      old->c_test = 0;
@@ -795,8 +820,10 @@ merge_trees (oldh, addh)
                      split->veclen = 0;
                      split->test_elt_zero_int = 0;
                      split->test_elt_one_int = 0;
+                     split->test_elt_zero_wide = 0;
                      split->tests = 0;
                      split->pred = -1;
+                     split->dupno = -1;
                    }
 
                  if (add->insn_code_number >= 0 || add->opno >= 0)
@@ -804,7 +831,8 @@ merge_trees (oldh, addh)
                      struct decision *split
                        = (struct decision *) xmalloc (sizeof (struct decision));
 
-                     mybcopy (add, split, sizeof (struct decision));
+                     mybcopy ((char *) add, (char *) split,
+                              sizeof (struct decision));
 
                      add->success.first = add->success.last = split;
                      add->c_test = 0;
@@ -819,8 +847,10 @@ merge_trees (oldh, addh)
                      split->veclen = 0;
                      split->test_elt_zero_int = 0;
                      split->test_elt_one_int = 0;
+                     split->test_elt_zero_wide = 0;
                      split->tests = 0;
                      split->pred = -1;
+                     split->dupno = -1;
                    }
                }
 
@@ -875,7 +905,8 @@ merge_trees (oldh, addh)
       if (best_position == 0)
        abort ();
 
-      if (old == 0 && position_merit (0, add_mode, add->code) < best_merit)
+      if (old == 0
+         && position_merit (NULL_PTR, add_mode, add->code) < best_merit)
        {
          add->prev = 0;
          add->next = oldh.first;
@@ -966,7 +997,7 @@ write_subroutine (tree, type)
 
   printf ("x%d;\n", max_depth);
   printf ("  %s tem;\n", type == SPLIT ? "rtx" : "int");
-  write_tree (tree, "", 0, 1, type);
+  write_tree (tree, "", NULL_PTR, 1, type);
   printf (" ret0: return %d;\n}\n\n", type == SPLIT ? 0 : -1);
 }
 \f
@@ -990,7 +1021,7 @@ static char *indents[]
    of the same mode, we also group tests with the same code, followed by a
    group that does not test a code.
 
-   Occasionally, we cannot arbitarily reorder the tests so that multiple
+   Occasionally, we cannot arbitrarily reorder the tests so that multiple
    sequence of groups as described above are present.
 
    We generate two nested switch statements, the outer statement for
@@ -1000,7 +1031,7 @@ static char *indents[]
    resulting function.   We do check for when every test is the same mode
    or code.  */
 
-void
+static void
 write_tree_1 (tree, prevpos, afterward, type)
      struct decision *tree;
      char *prevpos;
@@ -1101,7 +1132,7 @@ write_tree_1 (tree, prevpos, afterward, type)
 
          if (p->pred >= 0)
            {
-             for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i]; i++)
+             for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++)
                if (codemap[(int) preds[p->pred].codes[i]])
                  break;
 
@@ -1124,7 +1155,7 @@ write_tree_1 (tree, prevpos, afterward, type)
 
              if (code == MATCH_OPERAND)
                {
-                 for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i]; i++)
+                 for (i = 0; i < NUM_RTX_CODE && preds[p->pred].codes[i] != 0; i++)
                    {
                      printf ("%scase ", indents[indent - 2]);
                      print_code (preds[p->pred].codes[i]);
@@ -1280,7 +1311,8 @@ write_tree_1 (tree, prevpos, afterward, type)
 
       if ((mode != switch_mode && ! p->ignore_mode)
          || (p->code != switch_code && p->code != UNKNOWN && ! p->ignore_code)
-         || p->test_elt_zero_int || p->test_elt_one_int || p->veclen
+         || p->test_elt_zero_int || p->test_elt_one_int
+         || p->test_elt_zero_wide || p->veclen
          || p->dupno >= 0 || p->tests || p->num_clobbers_to_add)
        {
          printf ("%sif (", indents[indent]);
@@ -1299,6 +1331,14 @@ write_tree_1 (tree, prevpos, afterward, type)
            printf ("XINT (x%d, 0) == %d && ", depth, p->elt_zero_int);
          if (p->test_elt_one_int)
            printf ("XINT (x%d, 1) == %d && ", depth, p->elt_one_int);
+         if (p->test_elt_zero_wide)
+           printf (
+#if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_INT
+                   "XWINT (x%d, 0) == %d && ",
+#else
+                   "XWINT (x%d, 0) == %ld && ",
+#endif
+                   depth, p->elt_zero_wide);
          if (p->veclen)
            printf ("XVECLEN (x%d, 0) == %d && ", depth, p->veclen);
          if (p->dupno >= 0)
@@ -1414,7 +1454,7 @@ write_tree_1 (tree, prevpos, afterward, type)
 
 static void
 print_code (code)
-     RTX_CODE code;
+     enum rtx_code code;
 {
   register char *p1;
   for (p1 = GET_RTX_NAME (code); *p1; p1++)
@@ -1429,7 +1469,7 @@ print_code (code)
 static int
 same_codes (p, code)
      register struct decision *p;
-     register RTX_CODE code;
+     register enum rtx_code code;
 {
   for (; p; p = p->next)
     if (p->code != code)
@@ -1494,7 +1534,10 @@ write_tree (tree, prevpos, afterward, initial, type)
        {
          printf ("  tem = %s_%d (x0, insn%s);\n",
                  name_prefix, tree->subroutine_number, call_suffix);
-         printf ("  if (tem >= 0) return tem;\n");
+         if (type == SPLIT)
+           printf ("  if (tem != 0) return tem;\n");
+         else
+           printf ("  if (tem >= 0) return tem;\n");
          change_state (tree->position, afterward->position, 2);
          printf ("  goto L%d;\n", afterward->number);
        }
@@ -1622,11 +1665,11 @@ xmalloc (size)
 }
 
 static void
-fatal (s, a1, a2)
+fatal (s)
      char *s;
 {
   fprintf (stderr, "genrecog: ");
-  fprintf (stderr, s, a1, a2);
+  fprintf (stderr, s);
   fprintf (stderr, "\n");
   fprintf (stderr, "after %d definitions\n", next_index);
   exit (FATAL_EXIT_CODE);
@@ -1650,7 +1693,6 @@ main (argc, argv)
   struct decision_head recog_tree;
   struct decision_head split_tree;
   FILE *infile;
-  extern rtx read_rtx ();
   register int c;
 
   obstack_init (rtl_obstack);