OSDN Git Service

* Makefile.in: Remove pointless setting of CXXFLAGS for dejagnu
[pf3gnuchains/gcc-fork.git] / gcc / genrecog.c
index e721e41..baf8c7f 100644 (file)
@@ -1,6 +1,6 @@
 /* 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 GCC.
 
 
    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
@@ -187,22 +189,23 @@ static const struct pred_table
   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,7 +214,7 @@ static const 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)
@@ -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
@@ -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)
@@ -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
@@ -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)
@@ -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.  */
@@ -1910,9 +1889,6 @@ write_switch (start, depth)
           || type == DT_elt_zero_wide_safe)
     {
       const char *indent = "";
-      /* Pmode may not be a compile-time constant.  */
-      if (type == DT_mode && p->tests->u.mode == Pmode)
-       return p;
 
       /* We cast switch parameter to integer, so we must ensure that the value
         fits.  */
@@ -1956,10 +1932,6 @@ 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;
 
@@ -1976,7 +1948,7 @@ 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 ();
@@ -1996,7 +1968,7 @@ write_switch (start, depth)
     }
   else
     {
-      /* None of the other tests are ameanable.  */
+      /* None of the other tests are amenable.  */
       return p;
     }
 }
@@ -2035,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:
@@ -2426,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\
@@ -2463,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");
 }
@@ -2484,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';
@@ -2536,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)
@@ -2609,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;
@@ -2687,7 +2669,7 @@ 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_args (argc, argv) != SUCCESS_EXIT_CODE)
     return (FATAL_EXIT_CODE);