X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Frtl.c;h=a812d3118204dfbe7789c8b8101eeaa49c69b258;hb=b48209d97d1a754d95c68970e95dde86ee7b5b7b;hp=edf393f29d2e661d8f6f96a2a1dbc28c2bac6944;hpb=e397ad8e71a8cf04fb36f26a47107ef2886d7354;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/rtl.c b/gcc/rtl.c index edf393f29d2..a812d311820 100644 --- a/gcc/rtl.c +++ b/gcc/rtl.c @@ -1,6 +1,7 @@ /* RTL utility routines. Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc. + 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 + Free Software Foundation, Inc. This file is part of GCC. @@ -30,12 +31,11 @@ along with GCC; see the file COPYING3. If not see #include "coretypes.h" #include "tm.h" #include "rtl.h" -#include "real.h" #include "ggc.h" #ifdef GENERATOR_FILE # include "errors.h" #else -# include "toplev.h" +# include "diagnostic-core.h" #endif @@ -150,7 +150,7 @@ rtvec_alloc (int n) { rtvec rt; - rt = ggc_alloc_rtvec (n); + rt = ggc_alloc_rtvec_sized (n); /* Clear out the vector. */ memset (&rt->elem[0], 0, n * sizeof (rtx)); @@ -164,6 +164,20 @@ 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 @@ -180,9 +194,8 @@ rtx_size (const_rtx x) rtx rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL) { - rtx rt; - - rt = (rtx) ggc_alloc_zone_pass_stat (RTX_CODE_SIZE (code), &rtl_zone); + rtx rt = ggc_alloc_zone_rtx_def_stat (&rtl_zone, RTX_CODE_SIZE (code) + PASS_MEM_STAT); /* 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 @@ -206,12 +219,12 @@ 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); + && CONST_INT_P(XEXP (XEXP (orig, 0), 1))); } @@ -232,6 +245,8 @@ copy_rtx (rtx orig) switch (code) { case REG: + case DEBUG_EXPR: + case VALUE: case CONST_INT: case CONST_DOUBLE: case CONST_FIXED: @@ -240,6 +255,8 @@ copy_rtx (rtx orig) case CODE_LABEL: case PC: case CC0: + case RETURN: + case SIMPLE_RETURN: case SCRATCH: /* SCRATCH must be shared because they represent distinct values. */ return orig; @@ -272,12 +289,6 @@ copy_rtx (rtx orig) walks over the RTL. */ RTX_FLAG (copy, used) = 0; - /* We do not copy FRAME_RELATED for INSNs. */ - 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++) @@ -322,8 +333,8 @@ 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 memcpy (copy, orig, size); + rtx const copy = ggc_alloc_zone_rtx_def_stat (&rtl_zone, size PASS_MEM_STAT); + return (rtx) memcpy (copy, orig, size); } /* Nonzero when we are generating CONCATs. */ @@ -333,8 +344,156 @@ int generating_concat_p; 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) + { + 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; + + case DEBUG_IMPLICIT_PTR: + return DEBUG_IMPLICIT_PTR_DECL (x) + == DEBUG_IMPLICIT_PTR_DECL (y); + + case DEBUG_PARAMETER_REF: + return DEBUG_PARAMETER_REF_DECL (x) + == DEBUG_PARAMETER_REF_DECL (x); + + case ENTRY_VALUE: + return rtx_equal_p_cb (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y), cb); + + 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 'w': + if (XWINT (x, i) != XWINT (y, i)) + return 0; + break; + + case 'n': + case 'i': + if (XINT (x, i) != XINT (y, i)) + { +#ifndef GENERATOR_FILE + if (((code == ASM_OPERANDS && i == 6) + || (code == ASM_INPUT && i == 1)) + && locator_eq (XINT (x, i), XINT (y, i))) + break; +#endif + 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_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 'S': + 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': + /* 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: + gcc_unreachable (); + } + } + return 1; +} + /* 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 (const_rtx x, const_rtx y) @@ -360,6 +519,10 @@ rtx_equal_p (const_rtx x, const_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) { @@ -372,12 +535,25 @@ rtx_equal_p (const_rtx x, const_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; + case DEBUG_IMPLICIT_PTR: + return DEBUG_IMPLICIT_PTR_DECL (x) + == DEBUG_IMPLICIT_PTR_DECL (y); + + case DEBUG_PARAMETER_REF: + return DEBUG_PARAMETER_REF_DECL (x) + == DEBUG_PARAMETER_REF_DECL (y); + + case ENTRY_VALUE: + return rtx_equal_p (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y)); + default: break; } @@ -398,7 +574,15 @@ rtx_equal_p (const_rtx x, const_rtx y) case 'n': case 'i': if (XINT (x, i) != XINT (y, i)) - return 0; + { +#ifndef GENERATOR_FILE + if (((code == ASM_OPERANDS && i == 6) + || (code == ASM_INPUT && i == 1)) + && locator_eq (XINT (x, i), XINT (y, i))) + break; +#endif + return 0; + } break; case 'V': @@ -409,7 +593,7 @@ rtx_equal_p (const_rtx x, const_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; @@ -444,6 +628,80 @@ rtx_equal_p (const_rtx x, const_rtx y) return 1; } +/* Iteratively hash rtx X. */ + +hashval_t +iterative_hash_rtx (const_rtx x, hashval_t hash) +{ + enum rtx_code code; + enum machine_mode mode; + int i, j; + const char *fmt; + + if (x == NULL_RTX) + return hash; + code = GET_CODE (x); + hash = iterative_hash_object (code, hash); + mode = GET_MODE (x); + hash = iterative_hash_object (mode, hash); + switch (code) + { + case REG: + i = REGNO (x); + return iterative_hash_object (i, hash); + case CONST_INT: + return iterative_hash_object (INTVAL (x), hash); + case SYMBOL_REF: + if (XSTR (x, 0)) + return iterative_hash (XSTR (x, 0), strlen (XSTR (x, 0)) + 1, + hash); + return hash; + case LABEL_REF: + case DEBUG_EXPR: + case VALUE: + case SCRATCH: + case CONST_DOUBLE: + case CONST_FIXED: + case DEBUG_IMPLICIT_PTR: + case DEBUG_PARAMETER_REF: + return hash; + default: + break; + } + + fmt = GET_RTX_FORMAT (code); + for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--) + switch (fmt[i]) + { + case 'w': + hash = iterative_hash_object (XWINT (x, i), hash); + break; + case 'n': + case 'i': + hash = iterative_hash_object (XINT (x, i), hash); + break; + case 'V': + case 'E': + j = XVECLEN (x, i); + hash = iterative_hash_object (j, hash); + for (j = 0; j < XVECLEN (x, i); j++) + hash = iterative_hash_rtx (XVECEXP (x, i, j), hash); + break; + case 'e': + hash = iterative_hash_rtx (XEXP (x, i), hash); + break; + case 'S': + case 's': + if (XSTR (x, i)) + hash = iterative_hash (XSTR (x, 0), strlen (XSTR (x, 0)) + 1, + hash); + break; + default: + break; + } + return hash; +} + void dump_rtx_statistics (void) { @@ -472,7 +730,7 @@ 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)