/* 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, 2005, 2006, 2007, 2008
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
#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)
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)
{
/* ??? 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);
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))
{
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
cselib_val *v;
struct elt_loc_list *l;
rtx op;
- enum machine_mode mode;
CLEAR_HARD_REG_SET (equiv_regs[i]);
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);
&& 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],
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
{
- int rclass = (int) NO_REGS;
+ enum reg_class rclass = NO_REGS;
if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
continue;
a cheap CONST_INT. */
if (op_alt_regno[i][j] == -1
&& reg_fits_class_p (testreg, rclass, 0, mode)
- && (GET_CODE (recog_data.operand[i]) != CONST_INT
- || (rtx_cost (recog_data.operand[i], SET)
- > rtx_cost (testreg, SET))))
+ && (!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 = (int) NO_REGS;
+ rclass = NO_REGS;
break;
}
p += CONSTRAINT_LEN (c, p);
... (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);
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
&& 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;
}
/* 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),
if (apply_change_group ())
{
+ /* 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);
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;
}
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);
(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_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
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);
&& 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);
+ base_offset
- regno_offset,
GET_MODE (reg));
- int success = 0;
+ 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,
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));
{
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))]
TODO_dump_func /* todo_flags_finish */
}
};
-