X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Frtl.c;h=c275091ad775df86f00209fa8f9ae78f442409b1;hp=deaf22c24cf39e266670fa0a044af0f3f4303f14;hb=c6934f8a4cb3f7e899efcd5a793a1f4632fce7b6;hpb=2a631e19bed8b13c3856eff9576b6b9bd1c576e7 diff --git a/gcc/rtl.c b/gcc/rtl.c index deaf22c24cf..c275091ad77 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -1,12 +1,12 @@ /* RTL utility routines. - Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001 - Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002, + 2003, 2004, 2005, 2006, 2007, 2008 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 the Free -Software Foundation; either version 2, or (at your option) any later +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 @@ -15,88 +15,36 @@ 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 GCC; 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 COPYING3. If not see +. */ +/* This file is compiled twice: once for the generator programs + once for the compiler. */ +#ifdef GENERATOR_FILE +#include "bconfig.h" +#else #include "config.h" +#endif + #include "system.h" +#include "coretypes.h" +#include "tm.h" #include "rtl.h" #include "real.h" #include "ggc.h" -#include "errors.h" - - -/* 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" +#ifdef GENERATOR_FILE +# include "errors.h" #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 +# include "toplev.h" #endif + /* Indexed by rtx code, gives number of operands for an rtx with that code. Does NOT include rtx header data (code and links). */ #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) sizeof FORMAT - 1 , -const int rtx_length[NUM_RTX_CODE + 1] = { +const unsigned char rtx_length[NUM_RTX_CODE] = { #include "rtl.def" }; @@ -106,115 +54,17 @@ const int rtx_length[NUM_RTX_CODE + 1] = { #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) NAME , -const char * const rtx_name[] = { +const char * const rtx_name[NUM_RTX_CODE] = { #include "rtl.def" /* rtl expressions are documented here */ }; #undef DEF_RTL_EXPR -/* 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, BITSIZE, SIZE, UNIT, WIDER) NAME, - -const char * const mode_name[] = { -#include "machmode.def" -}; - -#undef DEF_MACHMODE - -/* 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[] = { -#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, BITSIZE, SIZE, UNIT, WIDER) BITSIZE, - -const unsigned int mode_bitsize[] = { -#include "machmode.def" -}; - -#undef DEF_MACHMODE - -/* Indexed by machine mode, gives the length of the mode, in bytes. - GET_MODE_SIZE uses this. */ - -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) SIZE, - -const unsigned int mode_size[] = { -#include "machmode.def" -}; - -#undef DEF_MACHMODE - -/* Indexed by machine mode, gives the length of the mode's subunit. - GET_MODE_UNIT_SIZE uses this. */ - -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) UNIT, - -const unsigned int mode_unit_size[] = { -#include "machmode.def" /* machine modes are documented here */ -}; - -#undef DEF_MACHMODE - -/* Indexed by machine mode, gives next wider natural mode - (QI -> HI -> SI -> DI, etc.) Widening multiply instructions - use this. */ - -#define DEF_MACHMODE(SYM, NAME, CLASS, BITSIZE, SIZE, UNIT, WIDER) \ - (unsigned char) WIDER, - -const unsigned char mode_wider_mode[] = { -#include "machmode.def" /* machine modes are documented here */ -}; - -#undef DEF_MACHMODE - -#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. */ - -const unsigned HOST_WIDE_INT mode_mask_array[] = { -#include "machmode.def" -}; - -/* 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 -}; - - /* 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. */ -const char * const rtx_format[] = { +const char * const rtx_format[NUM_RTX_CODE] = { /* "*" undefined. can cause a warning message "0" field is unused (or used in a phase-dependent manner) @@ -239,6 +89,7 @@ const char * const rtx_format[] = { "u" a pointer to another insn prints the uid of the insn. "b" is a pointer to a bitmap header. + "B" is a basic block pointer. "t" is a tree pointer. */ #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT , @@ -249,89 +100,127 @@ const char * const 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. */ -const char rtx_class[] = { +const enum rtx_class rtx_class[NUM_RTX_CODE] = { #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) CLASS, #include "rtl.def" /* rtl expressions are defined here */ #undef DEF_RTL_EXPR }; +/* Indexed by rtx code, gives the size of the rtx in bytes. */ + +const unsigned char rtx_code_size[NUM_RTX_CODE] = { +#define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) \ + ((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE || (ENUM) == CONST_FIXED\ + ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT) \ + : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)), + +#include "rtl.def" +#undef DEF_RTL_EXPR +}; + /* Names for kinds of NOTEs and REG_NOTEs. */ -const char * const note_insn_name[NOTE_INSN_MAX - NOTE_INSN_BIAS] = +const char * const note_insn_name[NOTE_INSN_MAX] = { - "", "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_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" +#define DEF_INSN_NOTE(NAME) #NAME, +#include "insn-notes.def" +#undef DEF_INSN_NOTE }; -const char * const reg_note_name[] = +const char * const reg_note_name[REG_NOTE_MAX] = { - "", "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_SAVE_NOTE", "REG_MAYBE_DEAD", "REG_NORETURN", - "REG_NON_LOCAL_GOTO", "REG_SETJMP", "REG_ALWAYS_RETURN", - "REG_VTABLE_REF" +#define DEF_REG_NOTE(NAME) #NAME, +#include "reg-notes.def" +#undef DEF_REG_NOTE }; +#ifdef GATHER_STATISTICS +static int rtx_alloc_counts[(int) LAST_AND_UNUSED_RTX_CODE]; +static int rtx_alloc_sizes[(int) LAST_AND_UNUSED_RTX_CODE]; +static int rtvec_alloc_counts; +static int rtvec_alloc_sizes; +#endif + /* Allocate an rtx vector of N elements. Store the length, and initialize all elements to zero. */ rtvec -rtvec_alloc (n) - int n; +rtvec_alloc (int n) { rtvec rt; rt = ggc_alloc_rtvec (n); - /* clear out the vector */ + /* Clear out the vector. */ memset (&rt->elem[0], 0, n * sizeof (rtx)); PUT_NUM_ELEM (rt, n); + +#ifdef GATHER_STATISTICS + rtvec_alloc_counts++; + rtvec_alloc_sizes += n * sizeof (rtx); +#endif + return rt; } +/* Return the number of bytes occupied by rtx value X. */ + +unsigned int +rtx_size (const_rtx x) +{ + if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_HAS_BLOCK_INFO_P (x)) + return RTX_HDR_SIZE + sizeof (struct block_symbol); + return RTX_CODE_SIZE (GET_CODE (x)); +} + /* Allocate an rtx of code CODE. The CODE is stored in the rtx; all the rest is initialized to zero. */ rtx -rtx_alloc (code) - RTX_CODE code; +rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL) { rtx rt; - int n = GET_RTX_LENGTH (code); - rt = ggc_alloc_rtx (n); + rt = (rtx) ggc_alloc_zone_pass_stat (RTX_CODE_SIZE (code), &rtl_zone); /* 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)); + memset (rt, 0, RTX_HDR_SIZE); PUT_CODE (rt, code); + +#ifdef GATHER_STATISTICS + rtx_alloc_counts[code]++; + rtx_alloc_sizes[code] += RTX_CODE_SIZE (code); +#endif + return rt; } +/* Return true if ORIG is a sharable CONST. */ + +bool +shared_const_p (const_rtx orig) +{ + gcc_assert (GET_CODE (orig) == CONST); + + /* CONST can be shared if it contains a SYMBOL_REF. If it contains + a LABEL_REF, it isn't sharable. */ + return (GET_CODE (XEXP (orig, 0)) == PLUS + && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF + && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT); +} + + /* Create a new copy of an rtx. Recursively copies the operands of the rtx, except for those few rtx codes that are sharable. */ rtx -copy_rtx (orig) - rtx orig; +copy_rtx (rtx orig) { rtx copy; int i, j; @@ -343,24 +232,24 @@ copy_rtx (orig) switch (code) { case REG: - case QUEUED: case CONST_INT: case CONST_DOUBLE: + case CONST_FIXED: + case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: case PC: case CC0: case SCRATCH: /* SCRATCH must be shared because they represent distinct values. */ - case ADDRESSOF: return orig; + case CLOBBER: + if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER) + return orig; + break; case CONST: - /* CONST can be shared if it contains a SYMBOL_REF. If it contains - a LABEL_REF, it isn't sharable. */ - if (GET_CODE (XEXP (orig, 0)) == PLUS - && GET_CODE (XEXP (XEXP (orig, 0), 0)) == SYMBOL_REF - && GET_CODE (XEXP (XEXP (orig, 0), 1)) == CONST_INT) + if (shared_const_p (orig)) return orig; break; @@ -373,226 +262,100 @@ copy_rtx (orig) break; } - copy = rtx_alloc (code); - - /* Copy the various flags, and other information. We assume that - all fields need copying, and then clear the fields that should + /* Copy the various flags, fields, 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)); + copy = shallow_copy_rtx (orig); /* We do not copy the USED flag, which is used as a mark bit during walks over the RTL. */ - copy->used = 0; + RTX_FLAG (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; + if (INSN_P (orig)) + RTX_FLAG (copy, frame_related) = 0; + RTX_FLAG (copy, jump) = RTX_FLAG (orig, jump); + RTX_FLAG (copy, call) = RTX_FLAG (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': - if (XEXP (orig, i) != NULL) - XEXP (copy, i) = copy_rtx (XEXP (orig, i)); - break; - - case 'E': - case 'V': - if (XVEC (orig, i) != NULL) - { - XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); - for (j = 0; j < XVECLEN (copy, i); j++) - XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j)); - } - break; - - case 't': - case 'w': - case 'i': - case 's': - case 'S': - case 'T': - case 'u': - case '0': - /* These are left unchanged. */ - break; - - default: - abort (); - } - } - return copy; -} - -/* Similar to `copy_rtx' except that if MAY_SHARE is present, it is - placed in the result directly, rather than being copied. */ - -rtx -copy_most_rtx (orig, may_share) - rtx orig; - rtx may_share; -{ - rtx copy; - int i, j; - RTX_CODE code; - const char *format_ptr; - - if (orig == may_share) - return orig; - - code = GET_CODE (orig); - - switch (code) - { - case REG: - case QUEUED: - case CONST_INT: - case CONST_DOUBLE: - case SYMBOL_REF: - case CODE_LABEL: - case PC: - case CC0: - return orig; - default: - break; - } - - 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; - - format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); - - for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); i++) - { - switch (*format_ptr++) - { - case 'e': - XEXP (copy, i) = XEXP (orig, i); - if (XEXP (orig, i) != NULL && XEXP (orig, i) != may_share) - XEXP (copy, i) = copy_most_rtx (XEXP (orig, i), may_share); - break; - - 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)); - for (j = 0; j < XVECLEN (copy, i); j++) - XVECEXP (copy, i, j) - = copy_most_rtx (XVECEXP (orig, i, j), may_share); - } - break; - - case 'w': - XWINT (copy, i) = XWINT (orig, i); - break; - - case 'n': - case 'i': - 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 (); - } - } + switch (*format_ptr++) + { + case 'e': + if (XEXP (orig, i) != NULL) + XEXP (copy, i) = copy_rtx (XEXP (orig, i)); + break; + + case 'E': + case 'V': + if (XVEC (orig, i) != NULL) + { + XVEC (copy, i) = rtvec_alloc (XVECLEN (orig, i)); + for (j = 0; j < XVECLEN (copy, i); j++) + XVECEXP (copy, i, j) = copy_rtx (XVECEXP (orig, i, j)); + } + break; + + case 't': + case 'w': + case 'i': + case 's': + case 'S': + case 'T': + case 'u': + case 'B': + case '0': + /* These are left unchanged. */ + break; + + default: + gcc_unreachable (); + } return copy; } /* Create a new copy of an rtx. Only copy just one level. */ rtx -shallow_copy_rtx (orig) - rtx orig; -{ - int i; - RTX_CODE code = GET_CODE (orig); - 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; -} - -/* Return the alignment of MODE. This will be bounded by 1 and - BIGGEST_ALIGNMENT. */ - -unsigned int -get_mode_alignment (mode) - enum machine_mode mode; +shallow_copy_rtx_stat (const_rtx orig MEM_STAT_DECL) { - unsigned int alignment = GET_MODE_UNIT_SIZE (mode); - - /* Extract the LSB of the size. */ - alignment = alignment & -alignment; - alignment *= BITS_PER_UNIT; - - alignment = MIN (BIGGEST_ALIGNMENT, MAX (1, alignment)); - return alignment; + const unsigned int size = rtx_size (orig); + rtx const copy = (rtx) ggc_alloc_zone_pass_stat (size, &rtl_zone); + return (rtx) memcpy (copy, orig, size); } -/* 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; + +/* Nonzero when we are expanding trees to RTL. */ +int currently_expanding_to_rtl; + -/* Return 1 if X and Y are identical-looking rtx's. - This is the Lisp function EQUAL for rtx arguments. */ + +/* Same as rtx_equal_p, but call CB on each pair of rtx if CB is not NULL. + When the callback returns true, we continue with the new pair. */ int -rtx_equal_p (x, y) - rtx x, y; +rtx_equal_p_cb (const_rtx x, const_rtx y, rtx_equal_p_callback_function cb) { int i; int j; enum rtx_code code; const char *fmt; + rtx nx, ny; if (x == y) return 1; if (x == 0 || y == 0) return 0; + /* Invoke the callback first. */ + if (cb != NULL + && ((*cb) (&x, &y, &nx, &ny))) + return rtx_equal_p_cb (nx, ny, cb); + code = GET_CODE (x); /* Rtx's of different codes cannot be equal. */ if (code != GET_CODE (y)) @@ -608,14 +371,7 @@ rtx_equal_p (x, y) 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))); + return (REGNO (x) == REGNO (y)); case LABEL_REF: return XEXP (x, 0) == XEXP (y, 0); @@ -626,6 +382,7 @@ rtx_equal_p (x, y) case SCRATCH: case CONST_DOUBLE: case CONST_INT: + case CONST_FIXED: return 0; default: @@ -633,7 +390,7 @@ rtx_equal_p (x, y) } /* Compare the elements. If any pair of corresponding elements - fail to match, return 0 for the whole things. */ + fail to match, return 0 for the whole thing. */ fmt = GET_RTX_FORMAT (code); for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) @@ -659,18 +416,21 @@ rtx_equal_p (x, y) /* 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) + if (rtx_equal_p_cb (XVECEXP (x, i, j), + XVECEXP (y, i, j), cb) == 0) return 0; break; case 'e': - if (rtx_equal_p (XEXP (x, i), XEXP (y, i)) == 0) + if (rtx_equal_p_cb (XEXP (x, i), XEXP (y, i), cb) == 0) return 0; break; case 'S': case 's': - if (strcmp (XSTR (x, i), XSTR (y, i))) + if ((XSTR (x, i) || XSTR (y, i)) + && (! XSTR (x, i) || ! XSTR (y, i) + || strcmp (XSTR (x, i), XSTR (y, i)))) return 0; break; @@ -686,35 +446,66 @@ rtx_equal_p (x, y) contain anything but integers and other rtx's, except for within LABEL_REFs and SYMBOL_REFs. */ default: - abort (); + gcc_unreachable (); } } return 1; } + +/* Return 1 if X and Y are identical-looking rtx's. + This is the Lisp function EQUAL for rtx arguments. */ + +int +rtx_equal_p (const_rtx x, const_rtx y) +{ + return rtx_equal_p_cb (x, y, NULL); +} + +void +dump_rtx_statistics (void) +{ +#ifdef GATHER_STATISTICS + int i; + int total_counts = 0; + int total_sizes = 0; + fprintf (stderr, "\nRTX Kind Count Bytes\n"); + fprintf (stderr, "---------------------------------------\n"); + for (i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++) + if (rtx_alloc_counts[i]) + { + fprintf (stderr, "%-20s %7d %10d\n", GET_RTX_NAME (i), + rtx_alloc_counts[i], rtx_alloc_sizes[i]); + total_counts += rtx_alloc_counts[i]; + total_sizes += rtx_alloc_sizes[i]; + } + if (rtvec_alloc_counts) + { + fprintf (stderr, "%-20s %7d %10d\n", "rtvec", + rtvec_alloc_counts, rtvec_alloc_sizes); + total_counts += rtvec_alloc_counts; + total_sizes += rtvec_alloc_sizes; + } + fprintf (stderr, "---------------------------------------\n"); + fprintf (stderr, "%-20s %7d %10d\n", + "Total", total_counts, total_sizes); + fprintf (stderr, "---------------------------------------\n"); +#endif +} #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) void -rtl_check_failed_bounds (r, n, file, line, func) - rtx r; - int n; - const char *file; - int line; - const char *func; +rtl_check_failed_bounds (const_rtx r, int n, const char *file, int line, + const char *func) { internal_error - ("RTL check: access of elt %d of `%s' with last elt %d in %s, at %s:%d", + ("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); } 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; +rtl_check_failed_type1 (const_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", @@ -723,14 +514,8 @@ rtl_check_failed_type1 (r, n, c1, file, line, func) } 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; +rtl_check_failed_type2 (const_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", @@ -739,43 +524,68 @@ rtl_check_failed_type2 (r, n, c1, c2, file, line, func) } void -rtl_check_failed_code1 (r, code, file, line, func) - rtx r; - enum rtx_code code; - const char *file; - int line; - const char *func; +rtl_check_failed_code1 (const_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", + 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); } 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; +rtl_check_failed_code2 (const_rtx r, enum rtx_code code1, enum rtx_code 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", + ("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); } +void +rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, enum machine_mode mode, + bool not_mode, const char *file, int line, + const char *func) +{ + internal_error ((not_mode + ? ("RTL check: expected code '%s' and not mode '%s', " + "have code '%s' and mode '%s' in %s, at %s:%d") + : ("RTL check: expected code '%s' and mode '%s', " + "have code '%s' and mode '%s' in %s, at %s:%d")), + GET_RTX_NAME (code), GET_MODE_NAME (mode), + GET_RTX_NAME (GET_CODE (r)), GET_MODE_NAME (GET_MODE (r)), + func, trim_filename (file), line); +} + +/* Report that line LINE of FILE tried to access the block symbol fields + of a non-block symbol. FUNC is the function that contains the line. */ + +void +rtl_check_failed_block_symbol (const char *file, int line, const char *func) +{ + internal_error + ("RTL check: attempt to treat non-block symbol as a block symbol " + "in %s, at %s:%d", func, trim_filename (file), line); +} + /* 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; +rtvec_check_failed_bounds (const_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 */ + +#if defined ENABLE_RTL_FLAG_CHECKING +void +rtl_check_failed_flag (const char *name, const_rtx r, const char *file, + int line, const char *func) +{ + internal_error + ("RTL flag check: %s used with unexpected rtx code '%s' in %s, at %s:%d", + name, GET_RTX_NAME (GET_CODE (r)), func, trim_filename (file), line); +} +#endif /* ENABLE_RTL_FLAG_CHECKING */