Mercurial > hg > CbC > CbC_gcc
diff gcc/rtl.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/gcc/rtl.c Sun Aug 21 07:07:55 2011 +0900 +++ b/gcc/rtl.c Fri Oct 27 22:46:09 2017 +0900 @@ -1,7 +1,5 @@ /* RTL utility routines. - Copyright (C) 1987, 1988, 1991, 1994, 1997, 1998, 1999, 2000, 2001, 2002, - 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 - Free Software Foundation, Inc. + Copyright (C) 1987-2017 Free Software Foundation, Inc. This file is part of GCC. @@ -31,10 +29,10 @@ #include "coretypes.h" #include "tm.h" #include "rtl.h" -#include "ggc.h" #ifdef GENERATOR_FILE # include "errors.h" #else +# include "rtlhash.h" # include "diagnostic-core.h" #endif @@ -90,7 +88,8 @@ 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. */ + "t" is a tree pointer. + "r" a register. */ #define DEF_RTL_EXPR(ENUM, NAME, FORMAT, CLASS) FORMAT , #include "rtl.def" /* rtl expressions are defined here */ @@ -110,8 +109,11 @@ 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\ + (((ENUM) == CONST_INT || (ENUM) == CONST_DOUBLE \ + || (ENUM) == CONST_FIXED || (ENUM) == CONST_WIDE_INT) \ ? RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (HOST_WIDE_INT) \ + : (ENUM) == REG \ + ? RTX_HDR_SIZE + sizeof (reg_info) \ : RTX_HDR_SIZE + (sizeof FORMAT - 1) * sizeof (rtunion)), #include "rtl.def" @@ -134,12 +136,10 @@ #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. @@ -156,10 +156,11 @@ PUT_NUM_ELEM (rt, n); -#ifdef GATHER_STATISTICS - rtvec_alloc_counts++; - rtvec_alloc_sizes += n * sizeof (rtx); -#endif + if (GATHER_STATISTICS) + { + rtvec_alloc_counts++; + rtvec_alloc_sizes += n * sizeof (rtx); + } return rt; } @@ -183,19 +184,24 @@ unsigned int rtx_size (const_rtx x) { + if (CONST_WIDE_INT_P (x)) + return (RTX_HDR_SIZE + + sizeof (struct hwivec_def) + + ((CONST_WIDE_INT_NUNITS (x) - 1) + * sizeof (HOST_WIDE_INT))); 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. */ +/* Allocate an rtx of code CODE with EXTRA bytes in it. The CODE is + stored in the rtx; all the rest is initialized to zero. */ rtx -rtx_alloc_stat (RTX_CODE code MEM_STAT_DECL) +rtx_alloc_stat_v (RTX_CODE code MEM_STAT_DECL, int extra) { - rtx rt = ggc_alloc_zone_rtx_def_stat (&rtl_zone, RTX_CODE_SIZE (code) - PASS_MEM_STAT); + rtx rt = ggc_alloc_rtx_def_stat (RTX_CODE_SIZE (code) + extra + 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 @@ -204,14 +210,40 @@ 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 + if (GATHER_STATISTICS) + { + rtx_alloc_counts[code]++; + rtx_alloc_sizes[code] += RTX_CODE_SIZE (code); + } return rt; } +/* Allocate an rtx of code CODE. The CODE is stored in the rtx; + all the rest is initialized to zero. */ + +rtx +rtx_alloc (RTX_CODE code MEM_STAT_DECL) +{ + return rtx_alloc_stat_v (code PASS_MEM_STAT, 0); +} + +/* Write the wide constant X to OUTFILE. */ + +void +cwi_output_hex (FILE *outfile, const_rtx x) +{ + int i = CWI_GET_NUM_ELEM (x); + gcc_assert (i > 0); + if (CWI_ELT (x, i - 1) == 0) + /* The HOST_WIDE_INT_PRINT_HEX prepends a 0x only if the val is + non zero. We want all numbers to have a 0x prefix. */ + fprintf (outfile, "0x"); + fprintf (outfile, HOST_WIDE_INT_PRINT_HEX, CWI_ELT (x, --i)); + while (--i >= 0) + fprintf (outfile, HOST_WIDE_INT_PRINT_PADDED_HEX, CWI_ELT (x, i)); +} + /* Return true if ORIG is a sharable CONST. */ @@ -224,7 +256,7 @@ 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))); + && CONST_INT_P (XEXP (XEXP (orig, 0), 1))); } @@ -247,19 +279,22 @@ case REG: case DEBUG_EXPR: case VALUE: - case CONST_INT: - case CONST_DOUBLE: - case CONST_FIXED: - case CONST_VECTOR: + CASE_CONST_ANY: case SYMBOL_REF: 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; case CLOBBER: - if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER) + /* Share clobbers of hard registers (like cc0), but do not share pseudo reg + clobbers or clobbers of hard registers that originated as pseudos. + This is needed to allow safe register renaming. */ + if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER + && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0))) return orig; break; @@ -283,16 +318,6 @@ us to explicitly document why we are *not* copying a flag. */ copy = shallow_copy_rtx (orig); - /* We do not copy the USED flag, which is used as a mark bit during - 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++) @@ -334,11 +359,33 @@ /* Create a new copy of an rtx. Only copy just one level. */ rtx -shallow_copy_rtx_stat (const_rtx orig MEM_STAT_DECL) +shallow_copy_rtx (const_rtx orig MEM_STAT_DECL) { const unsigned int size = rtx_size (orig); - rtx const copy = ggc_alloc_zone_rtx_def_stat (&rtl_zone, size PASS_MEM_STAT); - return (rtx) memcpy (copy, orig, size); + rtx const copy = ggc_alloc_rtx_def_stat (size PASS_MEM_STAT); + memcpy (copy, orig, size); + switch (GET_CODE (orig)) + { + /* RTX codes copy_rtx_if_shared_1 considers are shareable, + the used flag is often used for other purposes. */ + case REG: + case DEBUG_EXPR: + case VALUE: + CASE_CONST_ANY: + case SYMBOL_REF: + case CODE_LABEL: + case PC: + case CC0: + case RETURN: + case SIMPLE_RETURN: + case SCRATCH: + break; + default: + /* For all other RTXes clear the used flag on the copy. */ + RTX_FLAG (copy, used) = 0; + break; + } + return copy; } /* Nonzero when we are generating CONCATs. */ @@ -384,7 +431,7 @@ if (GET_MODE (x) != GET_MODE (y)) return 0; - /* MEMs refering to different address space are not equivalent. */ + /* MEMs referring to different address space are not equivalent. */ if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) return 0; @@ -395,7 +442,7 @@ return (REGNO (x) == REGNO (y)); case LABEL_REF: - return XEXP (x, 0) == XEXP (y, 0); + return label_ref_label (x) == label_ref_label (y); case SYMBOL_REF: return XSTR (x, 0) == XSTR (y, 0); @@ -403,15 +450,20 @@ case DEBUG_EXPR: case VALUE: case SCRATCH: - case CONST_DOUBLE: - case CONST_INT: - case CONST_FIXED: + CASE_CONST_UNIQUE: 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_cb (ENTRY_VALUE_EXP (x), ENTRY_VALUE_EXP (y), cb); + default: break; } @@ -436,7 +488,7 @@ #ifndef GENERATOR_FILE if (((code == ASM_OPERANDS && i == 6) || (code == ASM_INPUT && i == 1)) - && locator_eq (XINT (x, i), XINT (y, i))) + && XINT (x, i) == XINT (y, i)) break; #endif return 0; @@ -516,7 +568,7 @@ if (GET_MODE (x) != GET_MODE (y)) return 0; - /* MEMs refering to different address space are not equivalent. */ + /* MEMs referring to different address space are not equivalent. */ if (code == MEM && MEM_ADDR_SPACE (x) != MEM_ADDR_SPACE (y)) return 0; @@ -527,7 +579,7 @@ return (REGNO (x) == REGNO (y)); case LABEL_REF: - return XEXP (x, 0) == XEXP (y, 0); + return label_ref_label (x) == label_ref_label (y); case SYMBOL_REF: return XSTR (x, 0) == XSTR (y, 0); @@ -535,15 +587,20 @@ case DEBUG_EXPR: case VALUE: case SCRATCH: - case CONST_DOUBLE: - case CONST_INT: - case CONST_FIXED: + CASE_CONST_UNIQUE: 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; } @@ -568,7 +625,7 @@ #ifndef GENERATOR_FILE if (((code == ASM_OPERANDS && i == 6) || (code == ASM_INPUT && i == 1)) - && locator_eq (XINT (x, i), XINT (y, i))) + && XINT (x, i) == XINT (y, i)) break; #endif return 0; @@ -618,86 +675,97 @@ return 1; } -/* Iteratively hash rtx X. */ +/* Return true if all elements of VEC are equal. */ -hashval_t -iterative_hash_rtx (const_rtx x, hashval_t hash) +bool +rtvec_all_equal_p (const_rtvec vec) { - 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) + const_rtx first = RTVEC_ELT (vec, 0); + /* Optimize the important special case of a vector of constants. + The main use of this function is to detect whether every element + of CONST_VECTOR is the same. */ + switch (GET_CODE (first)) { - 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: - return hash; + CASE_CONST_UNIQUE: + for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i) + if (first != RTVEC_ELT (vec, i)) + return false; + return true; + default: - break; + for (int i = 1, n = GET_NUM_ELEM (vec); i < n; ++i) + if (!rtx_equal_p (first, RTVEC_ELT (vec, i))) + return false; + return true; } +} + +/* Return an indication of which type of insn should have X as a body. + In generator files, this can be UNKNOWN if the answer is only known + at (GCC) runtime. Otherwise the value is CODE_LABEL, INSN, CALL_INSN + or JUMP_INSN. */ - 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; +enum rtx_code +classify_insn (rtx x) +{ + if (LABEL_P (x)) + return CODE_LABEL; + if (GET_CODE (x) == CALL) + return CALL_INSN; + if (ANY_RETURN_P (x)) + return JUMP_INSN; + if (GET_CODE (x) == SET) + { + if (GET_CODE (SET_DEST (x)) == PC) + return JUMP_INSN; + else if (GET_CODE (SET_SRC (x)) == CALL) + return CALL_INSN; + else + return INSN; + } + if (GET_CODE (x) == PARALLEL) + { + int j; + bool has_return_p = false; + for (j = XVECLEN (x, 0) - 1; j >= 0; j--) + if (GET_CODE (XVECEXP (x, 0, j)) == CALL) + return CALL_INSN; + else if (ANY_RETURN_P (XVECEXP (x, 0, j))) + has_return_p = true; + else if (GET_CODE (XVECEXP (x, 0, j)) == SET + && GET_CODE (SET_DEST (XVECEXP (x, 0, j))) == PC) + return JUMP_INSN; + else if (GET_CODE (XVECEXP (x, 0, j)) == SET + && GET_CODE (SET_SRC (XVECEXP (x, 0, j))) == CALL) + return CALL_INSN; + if (has_return_p) + return JUMP_INSN; + } +#ifdef GENERATOR_FILE + if (GET_CODE (x) == MATCH_OPERAND + || GET_CODE (x) == MATCH_OPERATOR + || GET_CODE (x) == MATCH_PARALLEL + || GET_CODE (x) == MATCH_OP_DUP + || GET_CODE (x) == MATCH_DUP + || GET_CODE (x) == PARALLEL) + return UNKNOWN; +#endif + return INSN; } void dump_rtx_statistics (void) { -#ifdef GATHER_STATISTICS int i; int total_counts = 0; int total_sizes = 0; + + if (! GATHER_STATISTICS) + { + fprintf (stderr, "No RTX statistics\n"); + return; + } + fprintf (stderr, "\nRTX Kind Count Bytes\n"); fprintf (stderr, "---------------------------------------\n"); for (i = 0; i < LAST_AND_UNUSED_RTX_CODE; i++) @@ -719,7 +787,6 @@ fprintf (stderr, "%-20s %7d %10d\n", "Total", total_counts, total_sizes); fprintf (stderr, "---------------------------------------\n"); -#endif } #if defined ENABLE_RTL_CHECKING && (GCC_VERSION >= 2007) @@ -773,7 +840,7 @@ } void -rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, enum machine_mode mode, +rtl_check_failed_code_mode (const_rtx r, enum rtx_code code, machine_mode mode, bool not_mode, const char *file, int line, const char *func) { @@ -800,6 +867,16 @@ /* XXX Maybe print the vector? */ void +cwi_check_failed_bounds (const_rtx x, int n, const char *file, int line, + const char *func) +{ + internal_error + ("RTL check: access of hwi elt %d of vector with last elt %d in %s, at %s:%d", + n, CWI_GET_NUM_ELEM (x) - 1, func, trim_filename (file), line); +} + +/* XXX Maybe print the vector? */ +void rtvec_check_failed_bounds (const_rtvec r, int n, const char *file, int line, const char *func) {