OSDN Git Service

* simplify-rtx.c (simplify_subreg): Fix verification of
[pf3gnuchains/gcc-fork.git] / gcc / rtl.c
index 322bdc9..0fad136 100644 (file)
--- a/gcc/rtl.c
+++ b/gcc/rtl.c
@@ -1,5 +1,6 @@
 /* Allocate and read RTL for GNU C Compiler.
-   Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998 Free Software Foundation, Inc.
+   Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000
+   Free Software Foundation, Inc.
 
 This file is part of GNU CC.
 
@@ -24,30 +25,95 @@ Boston, MA 02111-1307, USA.  */
 #include "rtl.h"
 #include "real.h"
 #include "bitmap.h"
-
+#include "ggc.h"
 #include "obstack.h"
+#include "toplev.h"
+#include "hashtab.h"
+
 #define        obstack_chunk_alloc     xmalloc
 #define        obstack_chunk_free      free
 
-/* Obstack used for allocating RTL objects.
-   Between functions, this is the permanent_obstack.
-   While parsing and expanding a function, this is maybepermanent_obstack
-   so we can save it if it is an inline function.
-   During optimization and output, this is function_obstack.  */
-
-extern struct obstack *rtl_obstack;
 \f
+/* Calculate the format for CONST_DOUBLE.  This depends on the relative
+   widths of HOST_WIDE_INT and REAL_VALUE_TYPE.
+
+   We need to go out to e0wwwww, since REAL_ARITHMETIC assumes 16-bits
+   per element in REAL_VALUE_TYPE.
+
+   This is duplicated in gengenrtl.c.
+
+   A number of places assume that there are always at least two 'w'
+   slots in a CONST_DOUBLE, so we provide them even if one would suffice.  */
+
+#ifdef REAL_ARITHMETIC
+# if MAX_LONG_DOUBLE_TYPE_SIZE == 96
+#  define REAL_WIDTH   \
+     (11*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
+# else
+#  if MAX_LONG_DOUBLE_TYPE_SIZE == 128
+#   define REAL_WIDTH  \
+      (19*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
+#  else
+#   if HOST_FLOAT_FORMAT != TARGET_FLOAT_FORMAT
+#    define REAL_WIDTH \
+       (7*8 + HOST_BITS_PER_WIDE_INT)/HOST_BITS_PER_WIDE_INT
+#   endif
+#  endif
+# endif
+#endif /* REAL_ARITHMETIC */
+
+#ifndef REAL_WIDTH
+# if HOST_BITS_PER_WIDE_INT*2 >= MAX_LONG_DOUBLE_TYPE_SIZE
+#  define REAL_WIDTH   2
+# else
+#  if HOST_BITS_PER_WIDE_INT*3 >= MAX_LONG_DOUBLE_TYPE_SIZE
+#   define REAL_WIDTH  3
+#  else
+#   if HOST_BITS_PER_WIDE_INT*4 >= MAX_LONG_DOUBLE_TYPE_SIZE
+#    define REAL_WIDTH 4
+#   endif
+#  endif
+# endif
+#endif /* REAL_WIDTH */
+
+#if REAL_WIDTH == 1
+# define CONST_DOUBLE_FORMAT   "e0ww"
+#else
+# if REAL_WIDTH == 2
+#  define CONST_DOUBLE_FORMAT  "e0ww"
+# else
+#  if REAL_WIDTH == 3
+#   define CONST_DOUBLE_FORMAT "e0www"
+#  else
+#   if REAL_WIDTH == 4
+#    define CONST_DOUBLE_FORMAT        "e0wwww"
+#   else
+#    if REAL_WIDTH == 5
+#     define CONST_DOUBLE_FORMAT       "e0wwwww"
+#    else
+#     define CONST_DOUBLE_FORMAT       /* nothing - will cause syntax error */
+#    endif
+#   endif
+#  endif
+# endif
+#endif
+
 /* Indexed by rtx code, gives number of operands for an rtx with that code.
-   Does NOT include rtx header data (code and links).
-   This array is initialized in init_rtl.  */
+   Does NOT include rtx header data (code and links).  */
+
+#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   sizeof FORMAT - 1 ,
 
-int rtx_length[NUM_RTX_CODE + 1];
+const int rtx_length[NUM_RTX_CODE + 1] = {
+#include "rtl.def"
+};
+
+#undef DEF_RTL_EXPR
 
 /* Indexed by rtx code, gives the name of that kind of rtx, as a C string.  */
 
 #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   NAME ,
 
-char *rtx_name[] = {
+const char * const rtx_name[] = {
 #include "rtl.def"             /* rtl expressions are documented here */
 };
 
@@ -56,14 +122,10 @@ char *rtx_name[] = {
 /* Indexed by machine mode, gives the name of that machine mode.
    This name does not include the letters "mode".  */
 
-#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  NAME,
+#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER)  NAME,
 
-char *mode_name[(int) MAX_MACHINE_MODE + 1] = {
+const char * const mode_name[(int) MAX_MACHINE_MODE + 1] = {
 #include "machmode.def"
-
-#ifdef EXTRA_CC_MODES
-  EXTRA_CC_NAMES,
-#endif
   /* Add an extra field to avoid a core dump if someone tries to convert
      MAX_MACHINE_MODE to a string.   */
   ""
@@ -71,12 +133,22 @@ char *mode_name[(int) MAX_MACHINE_MODE + 1] = {
 
 #undef DEF_MACHMODE
 
-/* Indexed by machine mode, gives the length of the mode, in bytes.
-   GET_MODE_CLASS uses this.  */
+/* Indexed by machine mode, gives the class mode for GET_MODE_CLASS.  */
+
+#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER)  CLASS,
+
+const enum mode_class mode_class[(int) MAX_MACHINE_MODE] = {
+#include "machmode.def"
+};
+
+#undef DEF_MACHMODE
+
+/* Indexed by machine mode, gives the length of the mode, in bits.
+   GET_MODE_BITSIZE uses this.  */
 
-#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  CLASS,
+#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER)  BITSIZE,
 
-enum mode_class mode_class[(int) MAX_MACHINE_MODE] = {
+const unsigned int mode_bitsize[(int) MAX_MACHINE_MODE] = {
 #include "machmode.def"
 };
 
@@ -85,9 +157,9 @@ enum mode_class mode_class[(int) MAX_MACHINE_MODE] = {
 /* Indexed by machine mode, gives the length of the mode, in bytes.
    GET_MODE_SIZE uses this.  */
 
-#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  SIZE,
+#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER)  SIZE,
 
-int mode_size[(int) MAX_MACHINE_MODE] = {
+const unsigned int mode_size[(int) MAX_MACHINE_MODE] = {
 #include "machmode.def"
 };
 
@@ -96,9 +168,9 @@ int mode_size[(int) MAX_MACHINE_MODE] = {
 /* Indexed by machine mode, gives the length of the mode's subunit.
    GET_MODE_UNIT_SIZE uses this.  */
 
-#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  UNIT,
+#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER)  UNIT,
 
-int mode_unit_size[(int) MAX_MACHINE_MODE] = {
+const unsigned int mode_unit_size[(int) MAX_MACHINE_MODE] = {
 #include "machmode.def"                /* machine modes are documented here */
 };
 
@@ -108,33 +180,51 @@ int mode_unit_size[(int) MAX_MACHINE_MODE] = {
    (QI -> HI -> SI -> DI, etc.)  Widening multiply instructions
    use this.  */
 
-#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
+#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER)  \
   (unsigned char) WIDER,
 
-unsigned char mode_wider_mode[(int) MAX_MACHINE_MODE] = {
+const unsigned char mode_wider_mode[(int) MAX_MACHINE_MODE] = {
 #include "machmode.def"                /* machine modes are documented here */
 };
 
 #undef DEF_MACHMODE
 
-#define DEF_MACHMODE(SYM, NAME, CLASS, SIZE, UNIT, WIDER)  \
-  ((SIZE) * BITS_PER_UNIT >= HOST_BITS_PER_WIDE_INT) ? ~(unsigned HOST_WIDE_INT)0 : ((unsigned HOST_WIDE_INT) 1 << (SIZE) * BITS_PER_UNIT) - 1,
+#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER)  \
+  ((BITSIZE) >= HOST_BITS_PER_WIDE_INT) ? ~(unsigned HOST_WIDE_INT)0 : ((unsigned HOST_WIDE_INT) 1 << (BITSIZE)) - 1,
 
 /* Indexed by machine mode, gives mask of significant bits in mode.  */
 
-unsigned HOST_WIDE_INT mode_mask_array[(int) MAX_MACHINE_MODE] = {
+const unsigned HOST_WIDE_INT mode_mask_array[(int) MAX_MACHINE_MODE] = {
 #include "machmode.def"
 };
 
-/* Indexed by mode class, gives the narrowest mode for each class.  */
+/* Indexed by mode class, gives the narrowest mode for each class.
+   The Q modes are always of width 1 (2 for complex) - it is impossible
+   for any mode to be narrower.
+
+   Note that we use QImode instead of BImode for MODE_INT, since
+   otherwise the middle end will try to use it for bitfields in
+   structures and the like, which we do not want.  Only the target
+   md file should generate BImode widgets.  */
+
+const enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS] = {
+    /* MODE_RANDOM */          VOIDmode,
+    /* MODE_INT */             QImode,
+    /* MODE_FLOAT */           QFmode,
+    /* MODE_PARTIAL_INT */     PQImode,
+    /* MODE_CC */              CCmode,
+    /* MODE_COMPLEX_INT */     CQImode,
+    /* MODE_COMPLEX_FLOAT */   QCmode,
+    /* MODE_VECTOR_INT */      V2QImode,
+    /* MODE_VECTOR_FLOAT */    V2SFmode
+};
 
-enum machine_mode class_narrowest_mode[(int) MAX_MODE_CLASS];
 
 /* Indexed by rtx code, gives a sequence of operand-types for
    rtx's of that code.  The sequence is a C string in which
    each character describes one operand.  */
 
-char *rtx_format[] = {
+const char * const rtx_format[] = {
   /* "*" undefined.
          can cause a warning message
      "0" field is unused (or used in a phase-dependent manner)
@@ -167,37 +257,52 @@ char *rtx_format[] = {
 /* Indexed by rtx code, gives a character representing the "class" of
    that rtx code.  See rtl.def for documentation on the defined classes.  */
 
-char rtx_class[] = {
-#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   CLASS, 
+const char rtx_class[] = {
+#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS)   CLASS,
 #include "rtl.def"             /* rtl expressions are defined here */
 #undef DEF_RTL_EXPR
 };
 
 /* Names for kinds of NOTEs and REG_NOTEs.  */
 
-char *note_insn_name[] = { 0                    , "NOTE_INSN_DELETED",
-                          "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
-                          "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
-                          "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
-                          "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
-                          "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
-                          "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
-                          "NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
-                          "NOTE_REPEATED_LINE_NUMBER", "NOTE_INSN_RANGE_START",
-                          "NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE" };
-
-char *reg_note_name[] = { "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_WAS_0",
-                         "REG_EQUAL", "REG_RETVAL", "REG_LIBCALL",
-                         "REG_NONNEG", "REG_NO_CONFLICT", "REG_UNUSED",
-                         "REG_CC_SETTER", "REG_CC_USER", "REG_LABEL",
-                         "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
-                         "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA",
-                         "REG_BR_PRED", "REG_EH_CONTEXT",
-                         "REG_FRAME_RELATED_EXPR", "REG_EH_REGION",
-                         "REG_EH_RETHROW" };
-
-static void dump_and_abort     PROTO((int, int, FILE *)) ATTRIBUTE_NORETURN;
-static void read_name          PROTO((char *, FILE *));
+const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS] =
+{
+  "", "NOTE_INSN_DELETED",
+  "NOTE_INSN_BLOCK_BEG", "NOTE_INSN_BLOCK_END",
+  "NOTE_INSN_LOOP_BEG", "NOTE_INSN_LOOP_END",
+  "NOTE_INSN_LOOP_CONT", "NOTE_INSN_LOOP_VTOP",
+  "NOTE_INSN_FUNCTION_END", "NOTE_INSN_SETJMP",
+  "NOTE_INSN_PROLOGUE_END", "NOTE_INSN_EPILOGUE_BEG",
+  "NOTE_INSN_DELETED_LABEL", "NOTE_INSN_FUNCTION_BEG",
+  "NOTE_INSN_EH_REGION_BEG", "NOTE_INSN_EH_REGION_END",
+  "NOTE_INSN_REPEATED_LINE_NUMBER", "NOTE_INSN_RANGE_BEG",
+  "NOTE_INSN_RANGE_END", "NOTE_INSN_LIVE",
+  "NOTE_INSN_BASIC_BLOCK", "NOTE_INSN_EXPECTED_VALUE"
+};
+
+const char * const reg_note_name[] =
+{
+  "", "REG_DEAD", "REG_INC", "REG_EQUIV", "REG_EQUAL",
+  "REG_WAS_0", "REG_RETVAL", "REG_LIBCALL", "REG_NONNEG",
+  "REG_NO_CONFLICT", "REG_UNUSED", "REG_CC_SETTER", "REG_CC_USER",
+  "REG_LABEL", "REG_DEP_ANTI", "REG_DEP_OUTPUT", "REG_BR_PROB",
+  "REG_EXEC_COUNT", "REG_NOALIAS", "REG_SAVE_AREA", "REG_BR_PRED",
+  "REG_FRAME_RELATED_EXPR", "REG_EH_CONTEXT", "REG_EH_REGION",
+  "REG_EH_RETHROW", "REG_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN",
+  "REG_NON_LOCAL_GOTO"
+};
+
+static htab_t md_constants;
+
+static void fatal_with_file_and_line PARAMS ((FILE *, const char *, ...))
+  ATTRIBUTE_PRINTF_2 ATTRIBUTE_NORETURN;
+static void fatal_expected_char PARAMS ((FILE *, int, int)) ATTRIBUTE_NORETURN;
+static void read_name          PARAMS ((char *, FILE *));
+static char *read_string       PARAMS ((struct obstack *, FILE *));
+static unsigned def_hash PARAMS ((const void *));
+static int def_name_eq_p PARAMS ((const void *, const void *));
+static void read_constants PARAMS ((FILE *infile, char *tmp_char));
+
 \f
 /* Allocate an rtx vector of N elements.
    Store the length, and initialize all elements to zero.  */
@@ -207,18 +312,12 @@ rtvec_alloc (n)
      int n;
 {
   rtvec rt;
-  int i;
-
-  rt = (rtvec) obstack_alloc (rtl_obstack,
-                             sizeof (struct rtvec_def)
-                             + (( n - 1) * sizeof (rtunion)));
 
+  rt = ggc_alloc_rtvec (n);
   /* clear out the vector */
-  PUT_NUM_ELEM (rt, n);
-
-  for (i = 0; i < n; i++)
-    rt->elem[i].rtwint = 0;
+  memset (&rt->elem[0], 0, n * sizeof (rtx));
 
+  PUT_NUM_ELEM (rt, n);
   return rt;
 }
 
@@ -230,47 +329,19 @@ rtx_alloc (code)
   RTX_CODE code;
 {
   rtx rt;
-  register struct obstack *ob = rtl_obstack;
-  register int nelts = GET_RTX_LENGTH (code);
-  register int length = sizeof (struct rtx_def)
-    + (nelts - 1) * sizeof (rtunion);
-
-  /* This function is called more than any other in GCC,
-     so we manipulate the obstack directly.
-
-     Even though rtx objects are word aligned, we may be sharing an obstack
-     with tree nodes, which may have to be double-word aligned.  So align
-     our length to the alignment mask in the obstack.  */
+  int n = GET_RTX_LENGTH (code);
 
-  length = (length + ob->alignment_mask) & ~ ob->alignment_mask;
+  rt = ggc_alloc_rtx (n);
 
-  if (ob->chunk_limit - ob->next_free < length)
-    _obstack_newchunk (ob, length);
-  rt = (rtx)ob->object_base;
-  ob->next_free += length;
-  ob->object_base = ob->next_free;
-
-  /* We want to clear everything up to the FLD array.  Normally, this is
-     one int, but we don't want to assume that and it isn't very portable
-     anyway; this is.  */
-
-  length = (sizeof (struct rtx_def) - sizeof (rtunion) - 1) / sizeof (int);
-  for (; length >= 0; length--)
-    ((int *) rt)[length] = 0;
+  /* We want to clear everything up to the FLD array.  Normally, this
+     is one int, but we don't want to assume that and it isn't very
+     portable anyway; this is.  */
 
+  memset (rt, 0, sizeof (struct rtx_def) - sizeof (rtunion));
   PUT_CODE (rt, code);
-
   return rt;
 }
 
-/* Free the rtx X and all RTL allocated since X.  */
-
-void
-rtx_free (x)
-     rtx x;
-{
-  obstack_free (rtl_obstack, x);
-}
 \f
 /* Create a new copy of an rtx.
    Recursively copies the operands of the rtx,
@@ -283,7 +354,7 @@ copy_rtx (orig)
   register rtx copy;
   register int i, j;
   register RTX_CODE code;
-  register char *format_ptr;
+  register const char *format_ptr;
 
   code = GET_CODE (orig);
 
@@ -321,32 +392,37 @@ copy_rtx (orig)
     }
 
   copy = rtx_alloc (code);
-  PUT_MODE (copy, GET_MODE (orig));
-  copy->in_struct = orig->in_struct;
-  copy->volatil = orig->volatil;
-  copy->unchanging = orig->unchanging;
-  copy->integrated = orig->integrated;
-  
+
+  /* Copy the various flags, and other information.  We assume that
+     all fields need copying, and then clear the fields that should
+     not be copied.  That is the sensible default behavior, and forces
+     us to explicitly document why we are *not* copying a flag.  */
+  memcpy (copy, orig, sizeof (struct rtx_def) - sizeof (rtunion));
+
+  /* We do not copy the USED flag, which is used as a mark bit during
+     walks over the RTL.  */
+  copy->used = 0;
+
+  /* We do not copy FRAME_RELATED for INSNs.  */
+  if (GET_RTX_CLASS (code) == 'i')
+    copy->frame_related = 0;
+  copy->jump = orig->jump;
+  copy->call = orig->call;
+
   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
 
   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
     {
+      copy->fld[i] = orig->fld[i];
       switch (*format_ptr++)
        {
        case 'e':
-         XEXP (copy, i) = XEXP (orig, i);
          if (XEXP (orig, i) != NULL)
            XEXP (copy, i) = copy_rtx (XEXP (orig, i));
          break;
 
-       case '0':
-       case 'u':
-         XEXP (copy, i) = XEXP (orig, i);
-         break;
-
        case 'E':
        case 'V':
-         XVEC (copy, i) = XVEC (orig, i);
          if (XVEC (orig, i) != NULL)
            {
              XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i));
@@ -355,29 +431,14 @@ copy_rtx (orig)
            }
          break;
 
-       case 'b':
-         {
-           bitmap new_bits = BITMAP_OBSTACK_ALLOC (rtl_obstack);
-           bitmap_copy (new_bits, XBITMAP (orig, i));
-           XBITMAP (copy, i) = new_bits;
-           break;
-         }
-
        case 't':
-         XTREE (copy, i) = XTREE (orig, i);
-         break;
-
        case 'w':
-         XWINT (copy, i) = XWINT (orig, i);
-         break;
-
        case 'i':
-         XINT (copy, i) = XINT (orig, i);
-         break;
-
        case 's':
        case 'S':
-         XSTR (copy, i) = XSTR (orig, i);
+       case 'u':
+       case '0':
+         /* These are left unchanged.  */
          break;
 
        default:
@@ -398,7 +459,7 @@ copy_most_rtx (orig, may_share)
   register rtx copy;
   register int i, j;
   register RTX_CODE code;
-  register char *format_ptr;
+  register const char *format_ptr;
 
   if (orig == may_share)
     return orig;
@@ -426,7 +487,8 @@ copy_most_rtx (orig, may_share)
   copy->volatil = orig->volatil;
   copy->unchanging = orig->unchanging;
   copy->integrated = orig->integrated;
-  
+  copy->frame_related = orig->frame_related;
+
   format_ptr = GET_RTX_FORMAT (GET_CODE (copy));
 
   for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++)
@@ -439,7 +501,6 @@ copy_most_rtx (orig, may_share)
            XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share);
          break;
 
-       case '0':
        case 'u':
          XEXP (copy, i) = XEXP (orig, i);
          break;
@@ -465,44 +526,230 @@ copy_most_rtx (orig, may_share)
          XINT (copy, i) = XINT (orig, i);
          break;
 
+       case 't':
+         XTREE (copy, i) = XTREE (orig, i);
+         break;
+
        case 's':
        case 'S':
          XSTR (copy, i) = XSTR (orig, i);
          break;
 
+       case '0':
+         /* Copy this through the wide int field; that's safest. */
+         X0WINT (copy, i) = X0WINT (orig, i);
+         break;
+
        default:
          abort ();
        }
     }
   return copy;
 }
+
+/* Create a new copy of an rtx.  Only copy just one level.  */
+rtx
+shallow_copy_rtx (orig)
+     rtx orig;
+{
+  register int i;
+  register RTX_CODE code = GET_CODE (orig);
+  register rtx copy = rtx_alloc (code);
+
+  PUT_MODE (copy, GET_MODE (orig));
+  copy->in_struct = orig->in_struct;
+  copy->volatil = orig->volatil;
+  copy->unchanging = orig->unchanging;
+  copy->integrated = orig->integrated;
+  copy->frame_related = orig->frame_related;
+
+  for (i = 0; i < GET_RTX_LENGTH (code); i++)
+    copy->fld[i] = orig->fld[i];
+
+  return copy;
+}
+\f
+/* This is 1 until after the rtl generation pass.  */
+int rtx_equal_function_value_matters;
+
+/* Nonzero when we are generating CONCATs.  */
+int generating_concat_p;
+\f
+/* Return 1 if X and Y are identical-looking rtx's.
+   This is the Lisp function EQUAL for rtx arguments.  */
+
+int
+rtx_equal_p (x, y)
+     rtx x, y;
+{
+  register int i;
+  register int j;
+  register enum rtx_code code;
+  register const char *fmt;
+
+  if (x == y)
+    return 1;
+  if (x == 0 || y == 0)
+    return 0;
+
+  code = GET_CODE (x);
+  /* Rtx's of different codes cannot be equal.  */
+  if (code != GET_CODE (y))
+    return 0;
+
+  /* (MULT:SI x y) and (MULT:HI x y) are NOT equivalent.
+     (REG:SI x) and (REG:HI x) are NOT equivalent.  */
+
+  if (GET_MODE (x) != GET_MODE (y))
+    return 0;
+
+  /* Some RTL can be compared nonrecursively.  */
+  switch (code)
+    {
+    case REG:
+      /* Until rtl generation is complete, don't consider a reference to the
+        return register of the current function the same as the return from a
+        called function.  This eases the job of function integration.  Once the
+        distinction is no longer needed, they can be considered equivalent.  */
+      return (REGNO (x) == REGNO (y)
+             && (! rtx_equal_function_value_matters
+                 || REG_FUNCTION_VALUE_P (x) == REG_FUNCTION_VALUE_P (y)));
+
+    case LABEL_REF:
+      return XEXP (x, 0) == XEXP (y, 0);
+
+    case SYMBOL_REF:
+      return XSTR (x, 0) == XSTR (y, 0);
+
+    case SCRATCH:
+    case CONST_DOUBLE:
+    case CONST_INT:
+      return 0;
+
+    default:
+      break;
+    }
+
+  /* Compare the elements.  If any pair of corresponding elements
+     fail to match, return 0 for the whole things.  */
+
+  fmt = GET_RTX_FORMAT (code);
+  for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
+    {
+      switch (fmt[i])
+       {
+       case 'w':
+         if (XWINT (x, i) != XWINT (y, i))
+           return 0;
+         break;
+
+       case 'n':
+       case 'i':
+         if (XINT (x, i) != XINT (y, i))
+           return 0;
+         break;
+
+       case 'V':
+       case 'E':
+         /* Two vectors must have the same length.  */
+         if (XVECLEN (x, i) != XVECLEN (y, i))
+           return 0;
+
+         /* And the corresponding elements must match.  */
+         for (j = 0; j < XVECLEN (x, i); j++)
+           if (rtx_equal_p (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0)
+             return 0;
+         break;
+
+       case 'e':
+         if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0)
+           return 0;
+         break;
+
+       case 'S':
+       case 's':
+         if (strcmp (XSTR (x, i), XSTR (y, i)))
+           return 0;
+         break;
+
+       case 'u':
+         /* These are just backpointers, so they don't matter.  */
+         break;
+
+       case '0':
+       case 't':
+         break;
+
+         /* It is believed that rtx's at this level will never
+            contain anything but integers and other rtx's,
+            except for within LABEL_REFs and SYMBOL_REFs.  */
+       default:
+         abort ();
+       }
+    }
+  return 1;
+}
 \f
 /* Subroutines of read_rtx.  */
 
-/* Dump code after printing a message.  Used when read_rtx finds
-   invalid data.  */
+/* The current line number for the file.  */
+int read_rtx_lineno = 1;
+
+/* The filename for aborting with file and line.  */
+const char *read_rtx_filename = "<unknown>";
 
 static void
-dump_and_abort (expected_c, actual_c, infile)
-     int expected_c, actual_c;
-     FILE *infile;
+fatal_with_file_and_line VPARAMS ((FILE *infile, const char *msg, ...))
 {
-  int c, i;
-
-  if (expected_c >= 0)
-    fprintf (stderr,
-            "Expected character %c.  Found character %c.",
-            expected_c, actual_c);
-  fprintf (stderr, "  At file position: %ld\n", ftell (infile));
-  fprintf (stderr, "Following characters are:\n\t");
-  for (i = 0; i < 200; i++)
+#ifndef ANSI_PROTOTYPES
+  FILE *infile;
+  const char *msg;
+#endif
+  va_list ap;
+  char context[64];
+  size_t i;
+  int c;
+
+  VA_START (ap, msg);
+
+#ifndef ANSI_PROTOTYPES
+  infile = va_arg (ap, FILE *);
+  msg = va_arg (ap, const char *);
+#endif
+
+  fprintf (stderr, "%s:%d: ", read_rtx_filename, read_rtx_lineno);
+  vfprintf (stderr, msg, ap);
+  putc ('\n', stderr);
+
+  /* Gather some following context.  */
+  for (i = 0; i < sizeof(context)-1; ++i)
     {
       c = getc (infile);
-      if (EOF == c) break;
-      putc (c, stderr);
+      if (c == EOF)
+       break;
+      if (c == '\r' || c == '\n')
+       break;
+      context[i] = c;
     }
-  fprintf (stderr, "Aborting.\n");
-  abort ();
+  context[i] = '\0';
+
+  fprintf (stderr, "%s:%d: following context is `%s'\n",
+          read_rtx_filename, read_rtx_lineno, context);
+
+  va_end (ap);
+  exit (1);
+}
+
+/* Dump code after printing a message.  Used when read_rtx finds
+   invalid data.  */
+
+static void
+fatal_expected_char (infile, expected_c, actual_c)
+     FILE *infile;
+     int expected_c, actual_c;
+{
+  fatal_with_file_and_line (infile, "expected character `%c', found `%c'",
+                           expected_c, actual_c);
 }
 
 /* Read chars from INFILE until a non-whitespace char
@@ -515,33 +762,48 @@ read_skip_spaces (infile)
      FILE *infile;
 {
   register int c;
-  while ((c = getc (infile)))
+  while (1)
     {
-      if (c == ' ' || c == '\n' || c == '\t' || c == '\f')
-       ;
-      else if (c == ';')
-       {
-         while ((c = getc (infile)) && c != '\n' && c != EOF)
-           ;
-       }
-      else if (c == '/')
+      c = getc (infile);
+      switch (c)
        {
-         register int prevc;
-         c = getc (infile);
-         if (c != '*')
-           dump_and_abort ('*', c, infile);
-         
-         prevc = 0;
-         while ((c = getc (infile)) && c != EOF)
-           {
-             if (prevc == '*' && c == '/')
-               break;
-             prevc = c;
-           }
+       case '\n':
+         read_rtx_lineno++;
+         break;
+
+       case ' ': case '\t': case '\f': case '\r':
+         break;
+
+       case ';':
+         do
+           c = getc (infile);
+         while (c != '\n' && c != EOF);
+         read_rtx_lineno++;
+         break;
+
+       case '/':
+         {
+           register int prevc;
+           c = getc (infile);
+           if (c != '*')
+             fatal_expected_char (infile, '*', c);
+
+           prevc = 0;
+           while ((c = getc (infile)) && c != EOF)
+             {
+               if (c == '\n')
+                  read_rtx_lineno++;
+               else if (prevc == '*' && c == '/')
+                 break;
+               prevc = c;
+             }
+         }
+         break;
+
+       default:
+         return c;
        }
-      else break;
     }
-  return c;
 }
 
 /* Read an rtx code name into the buffer STR[].
@@ -572,12 +834,87 @@ read_name (str, infile)
       c = getc (infile);
     }
   if (p == str)
+    fatal_with_file_and_line (infile, "missing name or number");
+  if (c == '\n')
+    read_rtx_lineno++;
+
+  *p = 0;
+
+  if (md_constants)
+    {
+      /* Do constant expansion.  */
+      struct md_constant *def;
+
+      p = str;
+      do
+       {
+         struct md_constant tmp_def;
+
+         tmp_def.name = p;
+         def = htab_find (md_constants, &tmp_def);
+         if (def)
+           p = def->value;
+       } while (def);
+      if (p != str)
+       strcpy (str, p);
+    }
+}
+
+/* Read a double-quoted string onto the obstack.  */
+
+static char *
+read_string (ob, infile)
+     struct obstack *ob;
+     FILE *infile;
+{
+  char *stringbuf;
+  int saw_paren = 0;
+  int c;
+
+  c = read_skip_spaces (infile);
+  if (c == '(')
     {
-      fprintf (stderr, "missing name or number");
-      dump_and_abort (-1, -1, infile);
+      saw_paren = 1;
+      c = read_skip_spaces (infile);
     }
+  if (c != '"')
+    fatal_expected_char (infile, '"', c);
 
-  *p = 0;
+  while (1)
+    {
+      c = getc (infile); /* Read the string  */
+      if (c == '\n')
+       read_rtx_lineno++;
+      else if (c == '\\')
+       {
+         c = getc (infile);    /* Read the string  */
+         /* \; makes stuff for a C string constant containing
+            newline and tab.  */
+         if (c == ';')
+           {
+             obstack_grow (ob, "\\n\\t", 4);
+             continue;
+           }
+         if (c == '\n')
+           read_rtx_lineno++;
+       }
+      else if (c == '"')
+       break;
+
+      obstack_1grow (ob, c);
+    }
+
+  obstack_1grow (ob, 0);
+  stringbuf = (char *) obstack_finish (ob);
+
+  if (saw_paren)
+    {
+      c = read_skip_spaces (infile);
+      if (c != ')')
+       fatal_expected_char (infile, ')', c);
+    }
+
+  return stringbuf;
 }
 \f
 /* Provide a version of a function to read a long long if the system does
@@ -617,6 +954,98 @@ atoll(p)
 }
 #endif
 
+/* Given a constant definition, return a hash code for its name.  */
+static unsigned
+def_hash (def)
+     const void *def;
+{
+  unsigned result, i;
+  const char *string = ((const struct md_constant *)def)->name;
+
+  for (result = i = 0;*string++ != '\0'; i++)
+    result += ((unsigned char) *string << (i % CHAR_BIT));
+  return result;
+}
+
+/* Given two constant definitions, return true if they have the same name.  */
+static int
+def_name_eq_p (def1, def2)
+     const void *def1, *def2;
+{
+  return ! strcmp (((const struct md_constant *)def1)->name,
+                  ((const struct md_constant *)def2)->name);
+}
+
+/* INFILE is a FILE pointer to read text from.  TMP_CHAR is a buffer suitable
+   to read a name or number into.  Process a define_constants directive,
+   starting with the optional space after the "define_constants".  */
+static void
+read_constants (infile, tmp_char)
+     FILE *infile;
+     char *tmp_char;
+{
+  int c;
+  htab_t defs;
+
+  c = read_skip_spaces (infile);
+  if (c != '[')
+    fatal_expected_char (infile, '[', c);
+  defs = md_constants;
+  if (! defs)
+    defs = htab_create (32, def_hash, def_name_eq_p, (htab_del) 0);
+  /* Disable constant expansion during definition processing.  */
+  md_constants = 0;
+  while ( (c = read_skip_spaces (infile)) != ']')
+    {
+      struct md_constant *def;
+      void **entry_ptr;
+
+      if (c != '(')
+       fatal_expected_char (infile, '(', c);
+      def = xmalloc (sizeof (struct md_constant));
+      def->name = tmp_char;
+      read_name (tmp_char, infile);
+      entry_ptr = htab_find_slot (defs, def, TRUE);
+      if (! *entry_ptr)
+       def->name = xstrdup (tmp_char);
+      c = read_skip_spaces (infile);
+      ungetc (c, infile);
+      read_name (tmp_char, infile);
+      if (! *entry_ptr)
+       {
+         def->value = xstrdup (tmp_char);
+         *entry_ptr = def;
+       }
+      else
+       {
+         def = *entry_ptr;
+         if (strcmp (def->value, tmp_char))
+           fatal_with_file_and_line (infile,
+                                     "redefinition of %s, was %s, now %s",
+                                     def->name, def->value, tmp_char);
+       }
+      c = read_skip_spaces (infile);
+      if (c != ')')
+       fatal_expected_char (infile, ')', c);
+    }
+  md_constants = defs;
+  c = read_skip_spaces (infile);
+  if (c != ')')
+    fatal_expected_char (infile, ')', c);
+}
+
+/* For every constant definition, call CALLBACK with two arguments:
+   a pointer a pointer to the constant definition and INFO.
+   Stops when CALLBACK returns zero.  */
+void
+traverse_md_constants (callback, info)
+     htab_trav callback;
+     void *info;
+{
+  if (md_constants)
+    htab_traverse (md_constants, callback, info);
+}
+
 /* Read an rtx in printed representation from INFILE
    and return an actual rtx in core constructed accordingly.
    read_rtx is not used in the compiler proper, but rather in
@@ -626,9 +1055,9 @@ rtx
 read_rtx (infile)
      FILE *infile;
 {
-  register int i, j, list_counter;
+  register int i, j;
   RTX_CODE tmp_code;
-  register char *format_ptr;
+  register const char *format_ptr;
   /* tmp_char is a buffer used for reading decimal integers
      and names of rtx types and machine modes.
      Therefore, 256 must be enough.  */
@@ -638,45 +1067,60 @@ read_rtx (infile)
   int tmp_int;
   HOST_WIDE_INT tmp_wide;
 
+  /* Obstack used for allocating RTL objects.  */
+  static struct obstack rtl_obstack;
+  static int initialized;
+
   /* Linked list structure for making RTXs: */
   struct rtx_list
     {
       struct rtx_list *next;
-      rtx value;               /* Value of this node...                */
+      rtx value;               /* Value of this node.  */
     };
 
+  if (!initialized) {
+    _obstack_begin (&rtl_obstack,0, 0,
+                   (void *(*) PARAMS ((long))) xmalloc,
+                   (void (*) PARAMS ((void *))) free);
+    initialized = 1;
+  }
+
+again:
   c = read_skip_spaces (infile); /* Should be open paren.  */
   if (c != '(')
-    dump_and_abort ('(', c, infile);
+    fatal_expected_char (infile, '(', c);
 
   read_name (tmp_char, infile);
 
   tmp_code = UNKNOWN;
 
-  for (i=0; i < NUM_RTX_CODE; i++) /* @@ might speed this search up */
+  if (! strcmp (tmp_char, "define_constants"))
     {
-      if (!(strcmp (tmp_char, GET_RTX_NAME (i))))
-       {
-         tmp_code = (RTX_CODE) i;      /* get value for name */
-         break;
-       }
+      read_constants (infile, tmp_char);
+      goto again;
     }
+  for (i = 0; i < NUM_RTX_CODE; i++)
+    if (! strcmp (tmp_char, GET_RTX_NAME (i)))
+      {
+       tmp_code = (RTX_CODE) i;        /* get value for name */
+       break;
+      }
+
   if (tmp_code == UNKNOWN)
-    {
-      fprintf (stderr,
-              "Unknown rtx read in rtl.read_rtx(). Code name was %s .",
-              tmp_char);
-    }
+    fatal_with_file_and_line (infile, "unknown rtx code `%s'", tmp_char);
+
   /* (NIL) stands for an expression that isn't there.  */
   if (tmp_code == NIL)
     {
       /* Discard the closeparen.  */
-      while ((c = getc (infile)) && c != ')');
+      while ((c = getc (infile)) && c != ')')
+       ;
+
       return 0;
     }
 
-  return_rtx = rtx_alloc (tmp_code); /* if we end up with an insn expression
-                                      then we free this space below.  */
+  /* If we end up with an insn expression then we free this space below.  */
+  return_rtx = rtx_alloc (tmp_code);
   format_ptr = GET_RTX_FORMAT (GET_CODE (return_rtx));
 
   /* If what follows is `: mode ', read it and
@@ -685,13 +1129,15 @@ read_rtx (infile)
   i = read_skip_spaces (infile);
   if (i == ':')
     {
-      register int k;
       read_name (tmp_char, infile);
-      for (k = 0; k < NUM_MACHINE_MODES; k++)
-       if (!strcmp (GET_MODE_NAME (k), tmp_char))
+      for (j = 0; j < NUM_MACHINE_MODES; j++)
+       if (! strcmp (GET_MODE_NAME (j), tmp_char))
          break;
 
-      PUT_MODE (return_rtx, (enum machine_mode) k );
+      if (j == MAX_MACHINE_MODE)
+       fatal_with_file_and_line (infile, "unknown mode `%s'", tmp_char);
+
+      PUT_MODE (return_rtx, (enum machine_mode) j);
     }
   else
     ungetc (i, infile);
@@ -720,43 +1166,34 @@ read_rtx (infile)
            break;
          }
        /* Now process the vector.  */
-  
+
       case 'E':
        {
-         register struct rtx_list *next_rtx, *rtx_list_link;
-         struct rtx_list *list_rtx = NULL;
+         /* Obstack to store scratch vector in.  */
+         struct obstack vector_stack;
+         int list_counter = 0;
+         rtvec return_vec = NULL_RTVEC;
 
          c = read_skip_spaces (infile);
          if (c != '[')
-           dump_and_abort ('[', c, infile);
+           fatal_expected_char (infile, '[', c);
 
          /* add expressions to a list, while keeping a count */
-         next_rtx = NULL;
-         list_counter = 0;
+         obstack_init (&vector_stack);
          while ((c = read_skip_spaces (infile)) && c != ']')
            {
              ungetc (c, infile);
              list_counter++;
-             rtx_list_link = (struct rtx_list *)
-               alloca (sizeof (struct rtx_list));
-             rtx_list_link->value = read_rtx (infile);
-             if (next_rtx == 0)
-               list_rtx = rtx_list_link;
-             else
-               next_rtx->next = rtx_list_link;
-             next_rtx = rtx_list_link;
-             rtx_list_link->next = 0;
+             obstack_ptr_grow (&vector_stack, (PTR) read_rtx (infile));
            }
-         /* get vector length and allocate it */
-         XVEC (return_rtx, i) = (list_counter
-                                 ? rtvec_alloc (list_counter) : NULL_RTVEC);
          if (list_counter > 0)
            {
-             next_rtx = list_rtx;
-             for (j = 0; j < list_counter; j++,
-                  next_rtx = next_rtx->next)
-               XVECEXP (return_rtx, i, j) = next_rtx->value;
+             return_vec = rtvec_alloc (list_counter);
+             memcpy (&return_vec->elem[0], obstack_finish (&vector_stack),
+                     list_counter * sizeof (rtx));
            }
+         XVEC (return_rtx, i) = return_vec;
+         obstack_free (&vector_stack, NULL);
          /* close bracket gotten */
        }
        break;
@@ -774,47 +1211,32 @@ read_rtx (infile)
 
       case 's':
        {
-         int saw_paren = 0;
-         register char *stringbuf;
-
-         c = read_skip_spaces (infile);
-         if (c == '(')
+         char *stringbuf;
+
+         stringbuf = read_string (&rtl_obstack, infile);
+
+         /* For insn patterns, we want to provide a default name
+            based on the file and line, like "*foo.md:12", if the
+            given name is blank.  These are only for define_insn and
+            define_insn_and_split, to aid debugging.  */
+         if (*stringbuf == '\0'
+             && i == 0
+             && (GET_CODE (return_rtx) == DEFINE_INSN
+                 || GET_CODE (return_rtx) == DEFINE_INSN_AND_SPLIT))
            {
-             saw_paren = 1;
-             c = read_skip_spaces (infile);
+             char line_name[20];
+             const char *fn = (read_rtx_filename ? read_rtx_filename : "rtx");
+             const char *slash;
+             for (slash = fn; *slash; slash ++)
+               if (*slash == '/' || *slash == '\\' || *slash == ':')
+                 fn = slash + 1;
+             obstack_1grow (&rtl_obstack, '*');
+             obstack_grow (&rtl_obstack, fn, strlen (fn));
+             sprintf (line_name, ":%d", read_rtx_lineno);
+             obstack_grow (&rtl_obstack, line_name, strlen (line_name)+1);
+             stringbuf = (char *) obstack_finish (&rtl_obstack);
            }
-         if (c != '"')
-           dump_and_abort ('"', c, infile);
 
-         while (1)
-           {
-             c = getc (infile); /* Read the string  */
-             if (c == '\\')
-               {
-                 c = getc (infile);    /* Read the string  */
-                 /* \; makes stuff for a C string constant containing
-                    newline and tab.  */
-                 if (c == ';')
-                   {
-                     obstack_grow (rtl_obstack, "\\n\\t", 4);
-                     continue;
-                   }
-               }
-             else if (c == '"')
-               break;
-
-             obstack_1grow (rtl_obstack, c);
-           }
-
-         obstack_1grow (rtl_obstack, 0);
-         stringbuf = (char *) obstack_finish (rtl_obstack);
-
-         if (saw_paren)
-           {
-             c = read_skip_spaces (infile);
-             if (c != ')')
-               dump_and_abort (')', c, infile);
-           }
          XSTR (return_rtx, i) = stringbuf;
        }
        break;
@@ -827,7 +1249,7 @@ read_rtx (infile)
 #if HOST_BITS_PER_WIDE_INT == HOST_BITS_PER_LONG
        tmp_wide = atol (tmp_char);
 #else
-       /* Prefer atoll over atoq, since the former is in the ISO C9X draft. 
+       /* Prefer atoll over atoq, since the former is in the ISO C99 standard.
           But prefer not to use our hand-rolled function above either.  */
 #if defined(HAVE_ATOLL) || !defined(HAVE_ATOQ)
        tmp_wide = atoll (tmp_char);
@@ -856,72 +1278,95 @@ read_rtx (infile)
 
   c = read_skip_spaces (infile);
   if (c != ')')
-    dump_and_abort (')', c, infile);
+    fatal_expected_char (infile, ')', c);
 
   return return_rtx;
 }
-\f
-/* This is called once per compilation, before any rtx's are constructed.
-   It initializes the vector `rtx_length', the extra CC modes, if any,
-   and computes certain commonly-used modes.  */
 
+#if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007)
 void
-init_rtl ()
+rtl_check_failed_bounds (r, n, file, line, func)
+    rtx r;
+    int n;
+    const char *file;
+    int line;
+    const char *func;
 {
-  int min_class_size[(int) MAX_MODE_CLASS];
-  enum machine_mode mode;
-  int i;
+  internal_error
+    ("RTL check: access of elt %d of `%s' with last elt %d in %s, at %s:%d",
+     n, GET_RTX_NAME (GET_CODE (r)), GET_RTX_LENGTH (GET_CODE (r)) - 1,
+     func, trim_filename (file), line);
+}
 
-  for (i = 0; i < NUM_RTX_CODE; i++)
-    rtx_length[i] = strlen (rtx_format[i]);
-
-  /* Make CONST_DOUBLE bigger, if real values are bigger than
-     it normally expects to have room for.
-     Note that REAL_VALUE_TYPE is not defined by default,
-     since tree.h is not included.  But the default dfn as `double'
-     would do no harm.  */
-#ifdef REAL_VALUE_TYPE
-  i = sizeof (REAL_VALUE_TYPE) / sizeof (rtunion) + 2;
-  if (rtx_length[(int) CONST_DOUBLE] < i)
-    {
-      char *s = (char *) xmalloc (i + 1);
-      rtx_length[(int) CONST_DOUBLE] = i;
-      rtx_format[(int) CONST_DOUBLE] = s;
-      *s++ = 'e';
-      *s++ = '0';
-      /* Set the GET_RTX_FORMAT of CONST_DOUBLE to a string
-        of as many `w's as we now have elements.  Subtract two from
-        the size to account for the 'e' and the '0'.  */
-      for (i = 2; i < rtx_length[(int) CONST_DOUBLE]; i++)
-       *s++ = 'w';
-      *s++ = 0;
-    }
-#endif
+void
+rtl_check_failed_type1 (r, n, c1, file, line, func)
+    rtx r;
+    int n;
+    int c1;
+    const char *file;
+    int line;
+    const char *func;
+{
+  internal_error
+    ("RTL check: expected elt %d type '%c', have '%c' (rtx %s) in %s, at %s:%d",
+     n, c1, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)),
+     func, trim_filename (file), line);
+}
 
-#ifdef EXTRA_CC_MODES
-  for (i = (int) CCmode + 1; i < (int) MAX_MACHINE_MODE; i++)
-    {
-      mode_class[i] = MODE_CC;
-      mode_mask_array[i] = mode_mask_array[(int) CCmode];
-      mode_size[i] = mode_size[(int) CCmode];
-      mode_unit_size[i] = mode_unit_size[(int) CCmode];
-      mode_wider_mode[i - 1] = i;
-      mode_wider_mode[i] = (unsigned char)VOIDmode;
-    }
-#endif
+void
+rtl_check_failed_type2 (r, n, c1, c2, file, line, func)
+    rtx r;
+    int n;
+    int c1;
+    int c2;
+    const char *file;
+    int line;
+    const char *func;
+{
+  internal_error
+    ("RTL check: expected elt %d type '%c' or '%c', have '%c' (rtx %s) in %s, at %s:%d",
+     n, c1, c2, GET_RTX_FORMAT (GET_CODE (r))[n], GET_RTX_NAME (GET_CODE (r)),
+     func, trim_filename (file), line);
+}
 
-  /* Find the narrowest mode for each class.  */
+void
+rtl_check_failed_code1 (r, code, file, line, func)
+    rtx r;
+    enum rtx_code code;
+    const char *file;
+    int line;
+    const char *func;
+{
+  internal_error ("RTL check: expected code `%s', have `%s' in %s, at %s:%d",
+                 GET_RTX_NAME (code), GET_RTX_NAME (GET_CODE (r)), func,
+                 trim_filename (file), line);
+}
 
-  for (i = 0; i < (int) MAX_MODE_CLASS; i++)
-    min_class_size[i] = 1000;
+void
+rtl_check_failed_code2 (r, code1, code2, file, line, func)
+    rtx r;
+    enum rtx_code code1, code2;
+    const char *file;
+    int line;
+    const char *func;
+{
+  internal_error
+    ("RTL check: expected code `%s' or `%s', have `%s' in %s, at %s:%d",
+     GET_RTX_NAME (code1), GET_RTX_NAME (code2), GET_RTX_NAME (GET_CODE (r)),
+     func, trim_filename (file), line);
+}
 
-  for (mode = VOIDmode; (int) mode < (int) MAX_MACHINE_MODE;
-       mode = (enum machine_mode) ((int) mode + 1))
-    {
-      if (GET_MODE_SIZE (mode) < min_class_size[(int) GET_MODE_CLASS (mode)])
-       {
-         class_narrowest_mode[(int) GET_MODE_CLASS (mode)] = mode;
-         min_class_size[(int) GET_MODE_CLASS (mode)] = GET_MODE_SIZE (mode);
-       }
-    }
+/* XXX Maybe print the vector?  */
+void
+rtvec_check_failed_bounds (r, n, file, line, func)
+    rtvec r;
+    int n;
+    const char *file;
+    int line;
+    const char *func;
+{
+  internal_error
+    ("RTL check: access of elt %d of vector with last elt %d in %s, at %s:%d",
+     n, GET_NUM_ELEM (r) - 1, func, trim_filename (file), line);
 }
+#endif /* ENABLE_RTL_CHECKING */