X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fpostreload.c;h=8b622a7365a38740263cd1f7c30eaf31404bad3f;hb=e1ae8bc6e582ca614f0270a5ccaa8bbf6e14f349;hp=20d4a4f543e2b320b354b5af83209fd40ab05eb4;hpb=2045cdd44d272c6b5330210e6a60aa16f769b850;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/postreload.c b/gcc/postreload.c index 20d4a4f543e..8b622a7365a 100644 --- a/gcc/postreload.c +++ b/gcc/postreload.c @@ -1,12 +1,13 @@ /* Perform simple optimizations to clean up the result of reload. - Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, 1998, - 1999, 2000, 2001, 2002, 2003, 2004 Free Software Foundation, Inc. + Copyright (C) 1987, 1988, 1989, 1992, 1993, 1994, 1995, 1996, 1997, + 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, + 2010 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 +16,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 +. */ #include "config.h" #include "system.h" @@ -44,6 +44,10 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA #include "toplev.h" #include "except.h" #include "tree.h" +#include "timevar.h" +#include "tree-pass.h" +#include "df.h" +#include "dbgcnt.h" static int reload_cse_noop_set_p (rtx); static void reload_cse_simplify (rtx, rtx); @@ -53,10 +57,10 @@ static int reload_cse_simplify_operands (rtx, rtx); static void reload_combine (void); static void reload_combine_note_use (rtx *, rtx); -static void reload_combine_note_store (rtx, rtx, void *); +static void reload_combine_note_store (rtx, const_rtx, void *); static void reload_cse_move2add (rtx); -static void move2add_note_store (rtx, rtx, void *); +static void move2add_note_store (rtx, const_rtx, void *); /* Call cse / combine like post-reload optimization phases. FIRST is the first instruction. */ @@ -118,6 +122,19 @@ reload_cse_simplify (rtx insn, rtx testreg) int count = 0; rtx value = NULL_RTX; + /* Registers mentioned in the clobber list for an asm cannot be reused + within the body of the asm. Invalidate those registers now so that + we don't try to substitute values for them. */ + if (asm_noperands (body) >= 0) + { + for (i = XVECLEN (body, 0) - 1; i >= 0; --i) + { + rtx part = XVECEXP (body, 0, i); + if (GET_CODE (part) == CLOBBER && REG_P (XEXP (part, 0))) + cselib_invalidate_rtx (XEXP (part, 0)); + } + } + /* If every action in a PARALLEL is a noop, we can delete the entire PARALLEL. */ for (i = XVECLEN (body, 0) - 1; i >= 0; --i) @@ -181,7 +198,7 @@ reload_cse_regs_1 (rtx first) rtx insn; rtx testreg = gen_rtx_REG (VOIDmode, -1); - cselib_init (true); + cselib_init (CSELIB_RECORD_MEMORY); init_alias_analysis (); for (insn = first; insn; insn = NEXT_INSN (insn)) @@ -216,6 +233,7 @@ reload_cse_simplify_set (rtx set, rtx insn) #ifdef LOAD_EXTEND_OP enum rtx_code extend_op = UNKNOWN; #endif + bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); dreg = true_regnum (SET_DEST (set)); if (dreg < 0) @@ -250,7 +268,7 @@ reload_cse_simplify_set (rtx set, rtx insn) old_cost = REGISTER_MOVE_COST (GET_MODE (src), REGNO_REG_CLASS (REGNO (src)), dclass); else - old_cost = rtx_cost (src, SET); + old_cost = rtx_cost (src, SET, speed); for (l = val->locs; l; l = l->next) { @@ -266,7 +284,7 @@ reload_cse_simplify_set (rtx set, rtx insn) /* ??? I'm lazy and don't wish to handle CONST_DOUBLE. Other constants, such as SYMBOL_REF, cannot be extended. */ - if (GET_CODE (this_rtx) != CONST_INT) + if (!CONST_INT_P (this_rtx)) continue; this_val = INTVAL (this_rtx); @@ -280,12 +298,12 @@ reload_cse_simplify_set (rtx set, rtx insn) if (this_val == trunc_int_for_mode (this_val, GET_MODE (src))) break; default: - abort (); + gcc_unreachable (); } this_rtx = GEN_INT (this_val); } #endif - this_cost = rtx_cost (this_rtx, SET); + this_cost = rtx_cost (this_rtx, SET, speed); } else if (REG_P (this_rtx)) { @@ -293,7 +311,7 @@ reload_cse_simplify_set (rtx set, rtx insn) if (extend_op != UNKNOWN) { this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx); - this_cost = rtx_cost (this_rtx, SET); + this_cost = rtx_cost (this_rtx, SET, speed); } else #endif @@ -327,7 +345,7 @@ reload_cse_simplify_set (rtx set, rtx insn) } #endif - validate_change (insn, &SET_SRC (set), copy_rtx (this_rtx), 1); + validate_unshare_change (insn, &SET_SRC (set), this_rtx, 1); old_cost = this_cost, did_change = 1; } } @@ -377,9 +395,9 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) if (! constrain_operands (1)) fatal_insn_not_found (insn); - alternative_reject = alloca (recog_data.n_alternatives * sizeof (int)); - alternative_nregs = alloca (recog_data.n_alternatives * sizeof (int)); - alternative_order = alloca (recog_data.n_alternatives * sizeof (int)); + alternative_reject = XALLOCAVEC (int, recog_data.n_alternatives); + alternative_nregs = XALLOCAVEC (int, recog_data.n_alternatives); + alternative_order = XALLOCAVEC (int, recog_data.n_alternatives); memset (alternative_reject, 0, recog_data.n_alternatives * sizeof (int)); memset (alternative_nregs, 0, recog_data.n_alternatives * sizeof (int)); @@ -389,7 +407,6 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) cselib_val *v; struct elt_loc_list *l; rtx op; - enum machine_mode mode; CLEAR_HARD_REG_SET (equiv_regs[i]); @@ -402,11 +419,10 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) continue; op = recog_data.operand[i]; - mode = GET_MODE (op); #ifdef LOAD_EXTEND_OP if (MEM_P (op) - && GET_MODE_BITSIZE (mode) < BITS_PER_WORD - && LOAD_EXTEND_OP (mode) != UNKNOWN) + && GET_MODE_BITSIZE (GET_MODE (op)) < BITS_PER_WORD + && LOAD_EXTEND_OP (GET_MODE (op)) != UNKNOWN) { rtx set = single_set (insn); @@ -414,7 +430,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) extension. Punt on this for now. */ if (! set) continue; - /* If the destination is a also MEM or a STRICT_LOW_PART, no + /* If the destination is also a MEM or a STRICT_LOW_PART, no extension applies. Also, if there is an explicit extension, we don't have to worry about an implicit one. */ @@ -439,7 +455,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) && SET_DEST (set) == recog_data.operand[1-i]) { validate_change (insn, recog_data.operand_loc[i], - gen_rtx_fmt_e (LOAD_EXTEND_OP (mode), + gen_rtx_fmt_e (LOAD_EXTEND_OP (GET_MODE (op)), word_mode, op), 1); validate_change (insn, recog_data.operand_loc[1-i], @@ -470,7 +486,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) int regno; const char *p; - op_alt_regno[i] = alloca (recog_data.n_alternatives * sizeof (int)); + op_alt_regno[i] = XALLOCAVEC (int, recog_data.n_alternatives); for (j = 0; j < recog_data.n_alternatives; j++) op_alt_regno[i][j] = -1; @@ -501,12 +517,12 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) { - int class = (int) NO_REGS; + enum reg_class rclass = NO_REGS; if (! TEST_HARD_REG_BIT (equiv_regs[i], regno)) continue; - REGNO (testreg) = regno; + SET_REGNO (testreg, regno); PUT_MODE (testreg, mode); /* We found a register equal to this operand. Now look for all @@ -525,23 +541,23 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) case '*': case '%': case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - case 'm': case '<': case '>': case 'V': case 'o': + case '<': case '>': case 'V': case 'o': case 'E': case 'F': case 'G': case 'H': case 's': case 'i': case 'n': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N': case 'O': case 'P': - case 'p': case 'X': + case 'p': case 'X': case TARGET_MEM_CONSTRAINT: /* These don't say anything we care about. */ break; case 'g': case 'r': - class = reg_class_subunion[(int) class][(int) GENERAL_REGS]; + rclass = reg_class_subunion[(int) rclass][(int) GENERAL_REGS]; break; default: - class + rclass = (reg_class_subunion - [(int) class] + [(int) rclass] [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]); break; @@ -551,15 +567,18 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) alternative yet and the operand being replaced is not a cheap CONST_INT. */ if (op_alt_regno[i][j] == -1 - && reg_fits_class_p (testreg, class, 0, mode) - && (GET_CODE (recog_data.operand[i]) != CONST_INT - || (rtx_cost (recog_data.operand[i], SET) - > rtx_cost (testreg, SET)))) + && reg_fits_class_p (testreg, rclass, 0, mode) + && (!CONST_INT_P (recog_data.operand[i]) + || (rtx_cost (recog_data.operand[i], SET, + optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn))) + > rtx_cost (testreg, SET, + optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)))))) { alternative_nregs[j]++; op_alt_regno[i][j] = regno; } j++; + rclass = NO_REGS; break; } p += CONSTRAINT_LEN (c, p); @@ -592,7 +611,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) int this_nregs = alternative_nregs[alternative_order[j]]; if (this_reject < best_reject - || (this_reject == best_reject && this_nregs < best_nregs)) + || (this_reject == best_reject && this_nregs > best_nregs)) { best = j; best_reject = this_reject; @@ -643,7 +662,7 @@ reload_cse_simplify_operands (rtx insn, rtx testreg) replace them with reg+reg addressing. */ #define RELOAD_COMBINE_MAX_USES 6 -/* INSN is the insn where a register has ben used, and USEP points to the +/* INSN is the insn where a register has been used, and USEP points to the location of the register within the rtl. */ struct reg_use { rtx insn, *usep; }; @@ -715,7 +734,7 @@ reload_combine (void) destination. */ min_labelno = get_first_label_num (); n_labels = max_label_num () - min_labelno; - label_live = xmalloc (n_labels * sizeof (HARD_REG_SET)); + label_live = XNEWVEC (HARD_REG_SET, n_labels); CLEAR_HARD_REG_SET (ever_live_at_start); FOR_EACH_BB_REVERSE (bb) @@ -724,11 +743,10 @@ reload_combine (void) if (LABEL_P (insn)) { HARD_REG_SET live; + bitmap live_in = df_get_live_in (bb); - REG_SET_TO_HARD_REG_SET (live, - bb->global_live_at_start); - compute_use_by_pseudos (&live, - bb->global_live_at_start); + REG_SET_TO_HARD_REG_SET (live, live_in); + compute_use_by_pseudos (&live, live_in); COPY_HARD_REG_SET (LABEL_LIVE (insn), live); IOR_HARD_REG_SET (ever_live_at_start, live); } @@ -774,7 +792,7 @@ reload_combine (void) ... (MEM (PLUS (REGZ) (REGY)))... . First, check that we have (set (REGX) (PLUS (REGX) (REGY))) - and that we know all uses of REGX before it dies. + and that we know all uses of REGX before it dies. Also, explicitly check that REGX != REGY; our life information does not yet show whether REGY changes in this insn. */ set = single_set (insn); @@ -795,22 +813,19 @@ reload_combine (void) rtx prev = prev_nonnote_insn (insn); rtx prev_set = prev ? single_set (prev) : NULL_RTX; unsigned int regno = REGNO (reg); - rtx const_reg = NULL_RTX; + rtx index_reg = NULL_RTX; rtx reg_sum = NULL_RTX; - /* Now, we need an index register. - We'll set index_reg to this index register, const_reg to the - register that is to be loaded with the constant - (denoted as REGZ in the substitution illustration above), - and reg_sum to the register-register that we want to use to - substitute uses of REG (typically in MEMs) with. - First check REG and BASE for being index registers; - we can use them even if they are not dead. */ + /* Now we need to set INDEX_REG to an index register (denoted as + REGZ in the illustration above) and REG_SUM to the expression + register+register that we want to use to substitute uses of REG + (typically in MEMs) with. First check REG and BASE for being + index registers; we can use them even if they are not dead. */ if (TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], regno) || TEST_HARD_REG_BIT (reg_class_contents[INDEX_REG_CLASS], REGNO (base))) { - const_reg = reg; + index_reg = reg; reg_sum = plus; } else @@ -827,9 +842,7 @@ reload_combine (void) && reg_state[i].store_ruid <= reg_state[regno].use_ruid && hard_regno_nregs[i][GET_MODE (reg)] == 1) { - rtx index_reg = gen_rtx_REG (GET_MODE (reg), i); - - const_reg = index_reg; + index_reg = gen_rtx_REG (GET_MODE (reg), i); reg_sum = gen_rtx_PLUS (GET_MODE (reg), index_reg, base); break; } @@ -839,19 +852,19 @@ reload_combine (void) /* Check that PREV_SET is indeed (set (REGX) (CONST_INT)) and that (REGY), i.e. BASE, is not clobbered before the last use we'll create. */ - if (prev_set != 0 - && GET_CODE (SET_SRC (prev_set)) == CONST_INT + if (reg_sum + && prev_set + && CONST_INT_P (SET_SRC (prev_set)) && rtx_equal_p (SET_DEST (prev_set), reg) && reg_state[regno].use_index >= 0 && (reg_state[REGNO (base)].store_ruid - <= reg_state[regno].use_ruid) - && reg_sum != 0) + <= reg_state[regno].use_ruid)) { int i; - /* Change destination register and, if necessary, the - constant value in PREV, the constant loading instruction. */ - validate_change (prev, &SET_DEST (prev_set), const_reg, 1); + /* Change destination register and, if necessary, the constant + value in PREV, the constant loading instruction. */ + validate_change (prev, &SET_DEST (prev_set), index_reg, 1); if (reg_state[regno].offset != const0_rtx) validate_change (prev, &SET_SRC (prev_set), @@ -863,15 +876,26 @@ reload_combine (void) with REG_SUM. */ for (i = reg_state[regno].use_index; i < RELOAD_COMBINE_MAX_USES; i++) - validate_change (reg_state[regno].reg_use[i].insn, - reg_state[regno].reg_use[i].usep, - /* Each change must have its own - replacement. */ - copy_rtx (reg_sum), 1); + validate_unshare_change (reg_state[regno].reg_use[i].insn, + reg_state[regno].reg_use[i].usep, + /* Each change must have its own + replacement. */ + reg_sum, 1); if (apply_change_group ()) { - rtx *np; + /* For every new use of REG_SUM, we have to record the use + of BASE therein, i.e. operand 1. */ + for (i = reg_state[regno].use_index; + i < RELOAD_COMBINE_MAX_USES; i++) + reload_combine_note_use + (&XEXP (*reg_state[regno].reg_use[i].usep, 1), + reg_state[regno].reg_use[i].insn); + + if (reg_state[REGNO (base)].use_ruid + > reg_state[regno].use_ruid) + reg_state[REGNO (base)].use_ruid + = reg_state[regno].use_ruid; /* Delete the reg-reg addition. */ delete_insn (insn); @@ -879,17 +903,10 @@ reload_combine (void) if (reg_state[regno].offset != const0_rtx) /* Previous REG_EQUIV / REG_EQUAL notes for PREV are now invalid. */ - for (np = ®_NOTES (prev); *np;) - { - if (REG_NOTE_KIND (*np) == REG_EQUAL - || REG_NOTE_KIND (*np) == REG_EQUIV) - *np = XEXP (*np, 1); - else - np = &XEXP (*np, 1); - } + remove_reg_equal_equiv_notes (prev); reg_state[regno].use_index = RELOAD_COMBINE_MAX_USES; - reg_state[REGNO (const_reg)].store_ruid + reg_state[REGNO (index_reg)].store_ruid = reload_combine_ruid; continue; } @@ -972,7 +989,7 @@ reload_combine (void) accordingly. Called via note_stores from reload_combine. */ static void -reload_combine_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) +reload_combine_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED) { int regno = 0; int i; @@ -992,11 +1009,9 @@ reload_combine_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) /* note_stores might have stripped a STRICT_LOW_PART, so we have to be careful with registers / register parts that are not full words. - - Similarly for ZERO_EXTRACT and SIGN_EXTRACT. */ + Similarly for ZERO_EXTRACT. */ if (GET_CODE (set) != SET || GET_CODE (SET_DEST (set)) == ZERO_EXTRACT - || GET_CODE (SET_DEST (set)) == SIGN_EXTRACT || GET_CODE (SET_DEST (set)) == STRICT_LOW_PART) { for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--) @@ -1057,8 +1072,7 @@ reload_combine_note_use (rtx *xp, rtx insn) if (REG_P (SET_DEST (x))) { /* No spurious CLOBBERs of pseudo registers may remain. */ - if (REGNO (SET_DEST (x)) >= FIRST_PSEUDO_REGISTER) - abort (); + gcc_assert (REGNO (SET_DEST (x)) < FIRST_PSEUDO_REGISTER); return; } break; @@ -1066,7 +1080,7 @@ reload_combine_note_use (rtx *xp, rtx insn) case PLUS: /* We are interested in (plus (reg) (const_int)) . */ if (!REG_P (XEXP (x, 0)) - || GET_CODE (XEXP (x, 1)) != CONST_INT) + || !CONST_INT_P (XEXP (x, 1))) break; offset = XEXP (x, 1); x = XEXP (x, 0); @@ -1078,8 +1092,7 @@ reload_combine_note_use (rtx *xp, rtx insn) int nregs; /* No spurious USEs of pseudo registers may remain. */ - if (regno >= FIRST_PSEUDO_REGISTER) - abort (); + gcc_assert (regno < FIRST_PSEUDO_REGISTER); nregs = hard_regno_nregs[regno][GET_MODE (x)]; @@ -1216,7 +1229,8 @@ reload_cse_move2add (rtx first) /* Check if we have valid information on the contents of this register in the mode of REG. */ if (reg_set_luid[regno] > move2add_last_label_luid - && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno])) + && MODES_OK_FOR_MOVE2ADD (GET_MODE (reg), reg_mode[regno]) + && dbg_cnt (cse2_move2add)) { /* Try to transform (set (REGX) (CONST_INT A)) ... @@ -1231,12 +1245,12 @@ reload_cse_move2add (rtx first) (set (STRICT_LOW_PART (REGX)) (CONST_INT B)) */ - if (GET_CODE (src) == CONST_INT && reg_base_reg[regno] < 0) + if (CONST_INT_P (src) && reg_base_reg[regno] < 0) { - rtx new_src = - GEN_INT (trunc_int_for_mode (INTVAL (src) - - reg_offset[regno], - GET_MODE (reg))); + rtx new_src = gen_int_mode (INTVAL (src) - reg_offset[regno], + GET_MODE (reg)); + bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); + /* (set (reg) (plus (reg) (const_int 0))) is not canonical; use (set (reg) (reg)) instead. We don't delete this insn, nor do we convert it into a @@ -1252,17 +1266,18 @@ reload_cse_move2add (rtx first) if (INTVAL (src) == reg_offset [regno]) validate_change (insn, &SET_SRC (pat), reg, 0); } - else if (rtx_cost (new_src, PLUS) < rtx_cost (src, SET) + else if (rtx_cost (new_src, PLUS, speed) < rtx_cost (src, SET, speed) && have_add2_insn (reg, new_src)) { rtx tem = gen_rtx_PLUS (GET_MODE (reg), reg, new_src); validate_change (insn, &SET_SRC (pat), tem, 0); } - else + else if (GET_MODE (reg) != BImode) { enum machine_mode narrow_mode; for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT); - narrow_mode != GET_MODE (reg); + narrow_mode != VOIDmode + && narrow_mode != GET_MODE (reg); narrow_mode = GET_MODE_WIDER_MODE (narrow_mode)) { if (have_insn_for (STRICT_LOW_PART, narrow_mode) @@ -1273,9 +1288,8 @@ reload_cse_move2add (rtx first) { rtx narrow_reg = gen_rtx_REG (narrow_mode, REGNO (reg)); - rtx narrow_src = - GEN_INT (trunc_int_for_mode (INTVAL (src), - narrow_mode)); + rtx narrow_src = gen_int_mode (INTVAL (src), + narrow_mode); rtx new_set = gen_rtx_SET (VOIDmode, gen_rtx_STRICT_LOW_PART (VOIDmode, @@ -1317,25 +1331,26 @@ reload_cse_move2add (rtx first) && SET_DEST (set) == reg && GET_CODE (SET_SRC (set)) == PLUS && XEXP (SET_SRC (set), 0) == reg - && GET_CODE (XEXP (SET_SRC (set), 1)) == CONST_INT) + && CONST_INT_P (XEXP (SET_SRC (set), 1))) { rtx src3 = XEXP (SET_SRC (set), 1); HOST_WIDE_INT added_offset = INTVAL (src3); HOST_WIDE_INT base_offset = reg_offset[REGNO (src)]; HOST_WIDE_INT regno_offset = reg_offset[regno]; rtx new_src = - GEN_INT (trunc_int_for_mode (added_offset - + base_offset - - regno_offset, - GET_MODE (reg))); - int success = 0; + gen_int_mode (added_offset + + base_offset + - regno_offset, + GET_MODE (reg)); + bool success = false; + bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (insn)); if (new_src == const0_rtx) /* See above why we create (set (reg) (reg)) here. */ success = validate_change (next, &SET_SRC (set), reg, 0); - else if ((rtx_cost (new_src, PLUS) - < COSTS_N_INSNS (1) + rtx_cost (src3, SET)) + else if ((rtx_cost (new_src, PLUS, speed) + < COSTS_N_INSNS (1) + rtx_cost (src3, SET, speed)) && have_add2_insn (reg, new_src)) { rtx newpat = gen_rtx_SET (VOIDmode, @@ -1389,7 +1404,7 @@ reload_cse_move2add (rtx first) allocation if possible. */ && SCALAR_INT_MODE_P (GET_MODE (XEXP (cnd, 0))) && hard_regno_nregs[REGNO (XEXP (cnd, 0))][GET_MODE (XEXP (cnd, 0))] == 1 - && GET_CODE (XEXP (cnd, 1)) == CONST_INT) + && CONST_INT_P (XEXP (cnd, 1))) { rtx implicit_set = gen_rtx_SET (VOIDmode, XEXP (cnd, 0), XEXP (cnd, 1)); @@ -1416,9 +1431,10 @@ reload_cse_move2add (rtx first) Called from reload_cse_move2add via note_stores. */ static void -move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) +move2add_note_store (rtx dst, const_rtx set, void *data ATTRIBUTE_UNUSED) { unsigned int regno = 0; + unsigned int nregs = 0; unsigned int i; enum machine_mode mode = GET_MODE (dst); @@ -1428,6 +1444,7 @@ move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) GET_MODE (SUBREG_REG (dst)), SUBREG_BYTE (dst), GET_MODE (dst)); + nregs = subreg_nregs (dst); dst = SUBREG_REG (dst); } @@ -1445,11 +1462,12 @@ move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) return; regno += REGNO (dst); + if (!nregs) + nregs = hard_regno_nregs[regno][mode]; - if (SCALAR_INT_MODE_P (mode) - && hard_regno_nregs[regno][mode] == 1 && GET_CODE (set) == SET + if (SCALAR_INT_MODE_P (GET_MODE (dst)) + && nregs == 1 && GET_CODE (set) == SET && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT - && GET_CODE (SET_DEST (set)) != SIGN_EXTRACT && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART) { rtx src = SET_SRC (set); @@ -1467,7 +1485,7 @@ move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) { base_reg = XEXP (src, 0); - if (GET_CODE (XEXP (src, 1)) == CONST_INT) + if (CONST_INT_P (XEXP (src, 1))) offset = INTVAL (XEXP (src, 1)); else if (REG_P (XEXP (src, 1)) && (reg_set_luid[REGNO (XEXP (src, 1))] @@ -1548,10 +1566,53 @@ move2add_note_store (rtx dst, rtx set, void *data ATTRIBUTE_UNUSED) } else { - unsigned int endregno = regno + hard_regno_nregs[regno][mode]; + unsigned int endregno = regno + nregs; for (i = regno; i < endregno; i++) /* Reset the information about this register. */ reg_set_luid[i] = 0; } } + +static bool +gate_handle_postreload (void) +{ + return (optimize > 0 && reload_completed); +} + + +static unsigned int +rest_of_handle_postreload (void) +{ + if (!dbg_cnt (postreload_cse)) + return 0; + + /* Do a very simple CSE pass over just the hard registers. */ + reload_cse_regs (get_insns ()); + /* Reload_cse_regs can eliminate potentially-trapping MEMs. + Remove any EH edges associated with them. */ + if (flag_non_call_exceptions) + purge_all_dead_edges (); + + return 0; +} + +struct rtl_opt_pass pass_postreload_cse = +{ + { + RTL_PASS, + "postreload", /* name */ + gate_handle_postreload, /* gate */ + rest_of_handle_postreload, /* execute */ + NULL, /* sub */ + NULL, /* next */ + 0, /* static_pass_number */ + TV_RELOAD_CSE_REGS, /* tv_id */ + 0, /* properties_required */ + 0, /* properties_provided */ + 0, /* properties_destroyed */ + 0, /* todo_flags_start */ + TODO_df_finish | TODO_verify_rtl_sharing | + TODO_dump_func /* todo_flags_finish */ + } +};