X-Git-Url: http://git.sourceforge.jp/view?p=pf3gnuchains%2Fgcc-fork.git;a=blobdiff_plain;f=gcc%2Frtl.c;h=fe9c9514f1cd40624b9af8ab00ad8ebbc861b4bb;hp=6ec1d7e0f56093d9c07b0b6f5c02a9b9c886e5f5;hb=5dc5fe13a90f2df4a29038f17056adc410ec1efe;hpb=d2be3003b3851053ff0027bba6b307c1dc8dc2d5 diff --git a/gcc/rtl.c b/gcc/rtl.c index 6ec1d7e0f56..fe9c9514f1c 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, 2002, - 2003, 2004 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by 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,9 +15,8 @@ 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. */ @@ -33,7 +32,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "rtl.h" #include "real.h" #include "ggc.h" -#include "errors.h" +#ifdef GENERATOR_FILE +# include "errors.h" +#else +# include "toplev.h" +#endif /* Indexed by rtx code, gives number of operands for an rtx with that code. @@ -105,9 +108,9 @@ const enum rtx_class rtx_class[NUM_RTX_CODE] = { /* Indexed by rtx code, gives the size of the rtx in bytes. */ -const unsigned char rtx_size[NUM_RTX_CODE] = { +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_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)), @@ -115,15 +118,10 @@ const unsigned char rtx_size[NUM_RTX_CODE] = { #undef DEF_RTL_EXPR }; -/* Make sure all NOTE_INSN_* values are negative. */ -extern char NOTE_INSN_MAX_isnt_negative_adjust_NOTE_INSN_BIAS -[NOTE_INSN_MAX < 0 ? 1 : -1]; - /* 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] = { - "", #define DEF_INSN_NOTE(NAME) #NAME, #include "insn-notes.def" #undef DEF_INSN_NOTE @@ -166,6 +164,30 @@ rtvec_alloc (int n) return rt; } +/* Create a bitwise copy of VEC. */ + +rtvec +shallow_copy_rtvec (rtvec vec) +{ + rtvec newvec; + int n; + + n = GET_NUM_ELEM (vec); + newvec = rtvec_alloc (n); + memcpy (&newvec->elem[0], &vec->elem[0], sizeof (rtx) * n); + return newvec; +} + +/* 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. */ @@ -174,8 +196,7 @@ rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL) { rtx rt; - rt = (rtx) ggc_alloc_typed_stat (gt_ggc_e_7rtx_def, - RTX_SIZE (code) PASS_MEM_STAT); + 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 @@ -186,13 +207,28 @@ rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL) #ifdef GATHER_STATISTICS rtx_alloc_counts[code]++; - rtx_alloc_sizes[code] += RTX_SIZE (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 + && CONST_INT_P(XEXP (XEXP (orig, 0), 1))); +} + + /* Create a new copy of an rtx. Recursively copies the operands of the rtx, except for those few rtx codes that are sharable. */ @@ -210,8 +246,11 @@ copy_rtx (rtx orig) switch (code) { case REG: + case DEBUG_EXPR: + case VALUE: case CONST_INT: case CONST_DOUBLE: + case CONST_FIXED: case CONST_VECTOR: case SYMBOL_REF: case CODE_LABEL: @@ -226,11 +265,7 @@ copy_rtx (rtx 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; @@ -243,13 +278,11 @@ copy_rtx (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, RTX_HDR_SIZE); + copy = shallow_copy_rtx (orig); /* We do not copy the USED flag, which is used as a mark bit during walks over the RTL. */ @@ -264,69 +297,192 @@ copy_rtx (rtx orig) format_ptr = GET_RTX_FORMAT (GET_CODE (copy)); for (i = 0; i < GET_RTX_LENGTH (GET_CODE (copy)); 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 '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_stat (const_rtx orig MEM_STAT_DECL) +{ + 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); +} + +/* Nonzero when we are generating CONCATs. */ +int generating_concat_p; + +/* Nonzero when we are expanding trees to RTL. */ +int currently_expanding_to_rtl; + + + +/* 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. + Whenever changing this function check if rtx_equal_p below doesn't need + changing as well. */ + +int +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)) + 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; + + /* MEMs refering to different address space are not equivalent. */ + if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) + return 0; + + /* Some RTL can be compared nonrecursively. */ + switch (code) { - copy->u.fld[i] = orig->u.fld[i]; - switch (*format_ptr++) + case REG: + return (REGNO (x) == REGNO (y)); + + case LABEL_REF: + return XEXP (x, 0) == XEXP (y, 0); + + case SYMBOL_REF: + return XSTR (x, 0) == XSTR (y, 0); + + case DEBUG_EXPR: + case VALUE: + case SCRATCH: + case CONST_DOUBLE: + case CONST_INT: + case CONST_FIXED: + return 0; + + default: + break; + } + + /* Compare the elements. If any pair of corresponding elements + fail to match, return 0 for the whole thing. */ + + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + { + switch (fmt[i]) { - case 'e': - if (XEXP (orig, i) != NULL) - XEXP (copy, i) = copy_rtx (XEXP (orig, 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 '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)); - } + 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_cb (XVECEXP (x, i, j), + XVECEXP (y, i, j), cb) == 0) + return 0; + break; + + case 'e': + if (rtx_equal_p_cb (XEXP (x, i), XEXP (y, i), cb) == 0) + return 0; break; - case 't': - case 'w': - case 'i': - case 's': case 'S': - case 'T': + case 's': + if ((XSTR (x, i) || XSTR (y, i)) + && (! XSTR (x, i) || ! XSTR (y, i) + || strcmp (XSTR (x, i), XSTR (y, i)))) + return 0; + break; + case 'u': - case 'B': + /* These are just backpointers, so they don't matter. */ + break; + case '0': - /* These are left unchanged. */ + 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: gcc_unreachable (); } } - return copy; -} - -/* Create a new copy of an rtx. Only copy just one level. */ - -rtx -shallow_copy_rtx_stat (rtx orig MEM_STAT_DECL) -{ - rtx copy; - - copy = (rtx) ggc_alloc_typed_stat (gt_ggc_e_7rtx_def, - RTX_SIZE (GET_CODE (orig)) PASS_MEM_STAT); - memcpy (copy, orig, RTX_SIZE (GET_CODE (orig))); - return copy; + return 1; } - -/* 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. */ + This is the Lisp function EQUAL for rtx arguments. + Whenever changing this function check if rtx_equal_p_cb above doesn't need + changing as well. */ int -rtx_equal_p (rtx x, rtx y) +rtx_equal_p (const_rtx x, const_rtx y) { int i; int j; @@ -349,6 +505,10 @@ rtx_equal_p (rtx x, rtx y) if (GET_MODE (x) != GET_MODE (y)) return 0; + /* MEMs refering to different address space are not equivalent. */ + if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) + return 0; + /* Some RTL can be compared nonrecursively. */ switch (code) { @@ -361,9 +521,12 @@ rtx_equal_p (rtx x, rtx y) case SYMBOL_REF: return XSTR (x, 0) == XSTR (y, 0); + case DEBUG_EXPR: + case VALUE: case SCRATCH: case CONST_DOUBLE: case CONST_INT: + case CONST_FIXED: return 0; default: @@ -397,7 +560,7 @@ rtx_equal_p (rtx x, rtx 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 (XVECEXP (x, i, j), XVECEXP (y, i, j)) == 0) return 0; break; @@ -432,7 +595,8 @@ rtx_equal_p (rtx x, rtx y) return 1; } -void dump_rtx_statistics (void) +void +dump_rtx_statistics (void) { #ifdef GATHER_STATISTICS int i; @@ -459,12 +623,12 @@ void dump_rtx_statistics (void) fprintf (stderr, "%-20s %7d %10d\n", "Total", total_counts, total_sizes); fprintf (stderr, "---------------------------------------\n"); -#endif +#endif } #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) void -rtl_check_failed_bounds (rtx r, int n, const char *file, int line, +rtl_check_failed_bounds (const_rtx r, int n, const char *file, int line, const char *func) { internal_error @@ -474,7 +638,7 @@ rtl_check_failed_bounds (rtx r, int n, const char *file, int line, } void -rtl_check_failed_type1 (rtx r, int n, int c1, const char *file, int line, +rtl_check_failed_type1 (const_rtx r, int n, int c1, const char *file, int line, const char *func) { internal_error @@ -484,7 +648,7 @@ rtl_check_failed_type1 (rtx r, int n, int c1, const char *file, int line, } void -rtl_check_failed_type2 (rtx r, int n, int c1, int c2, const char *file, +rtl_check_failed_type2 (const_rtx r, int n, int c1, int c2, const char *file, int line, const char *func) { internal_error @@ -494,7 +658,7 @@ rtl_check_failed_type2 (rtx r, int n, int c1, int c2, const char *file, } void -rtl_check_failed_code1 (rtx r, enum rtx_code code, const char *file, +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", @@ -503,7 +667,7 @@ rtl_check_failed_code1 (rtx r, enum rtx_code code, const char *file, } void -rtl_check_failed_code2 (rtx r, enum rtx_code code1, enum rtx_code code2, +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 @@ -512,9 +676,35 @@ rtl_check_failed_code2 (rtx r, enum rtx_code code1, enum rtx_code code2, 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 (rtvec r, int n, const char *file, int line, +rtvec_check_failed_bounds (const_rtvec r, int n, const char *file, int line, const char *func) { internal_error @@ -525,7 +715,7 @@ rtvec_check_failed_bounds (rtvec r, int n, const char *file, int line, #if defined ENABLE_RTL_FLAG_CHECKING void -rtl_check_failed_flag (const char *name, rtx r, const char *file, +rtl_check_failed_flag (const char *name, const_rtx r, const char *file, int line, const char *func) { internal_error