/* 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
+ 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
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
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, 51 Franklin Street, Fifth Floor, Boston, MA
-02110-1301, USA. */
+along with GCC; see the file COPYING3. If not see
+<http://www.gnu.org/licenses/>. */
#include "config.h"
#include "system.h"
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. */
#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)
{
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
}
#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;
}
}
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));
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;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
{
- int class = (int) NO_REGS;
+ int rclass = (int) NO_REGS;
if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
continue;
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;
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)
+ && 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))))
+ || (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++;
- class = (int) NO_REGS;
+ rclass = (int) NO_REGS;
break;
}
p += CONSTRAINT_LEN (c, p);
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; };
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 ())
{
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;
{
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);
+ 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,
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;
static bool
gate_handle_postreload (void)
{
- return (optimize > 0);
+ return (optimize > 0 && reload_completed);
}
return 0;
}
-struct tree_opt_pass pass_postreload_cse =
+struct rtl_opt_pass pass_postreload_cse =
{
+ {
+ RTL_PASS,
"postreload", /* name */
gate_handle_postreload, /* gate */
rest_of_handle_postreload, /* execute */
0, /* properties_provided */
0, /* properties_destroyed */
0, /* todo_flags_start */
- TODO_df_finish |
- TODO_dump_func, /* todo_flags_finish */
- 'o' /* letter */
+ TODO_df_finish | TODO_verify_rtl_sharing |
+ TODO_dump_func /* todo_flags_finish */
+ }
};