/* Perform simple optimizations to clean up the result of reload.
- Copyright (C) 1987-2013 Free Software Foundation, Inc.
+ Copyright (C) 1987-2015 Free Software Foundation, Inc.
This file is part of GCC.
#include "config.h"
#include "system.h"
#include "coretypes.h"
-#include "tm.h"
-
-#include "machmode.h"
-#include "hard-reg-set.h"
+#include "backend.h"
+#include "predict.h"
+#include "tree.h"
#include "rtl.h"
+#include "df.h"
+
#include "tm_p.h"
-#include "obstack.h"
#include "insn-config.h"
#include "flags.h"
-#include "function.h"
+#include "alias.h"
+#include "expmed.h"
+#include "dojump.h"
+#include "explow.h"
+#include "calls.h"
+#include "emit-rtl.h"
+#include "varasm.h"
+#include "stmt.h"
#include "expr.h"
+#include "insn-codes.h"
#include "optabs.h"
#include "regs.h"
-#include "basic-block.h"
+#include "cfgrtl.h"
+#include "cfgbuild.h"
+#include "cfgcleanup.h"
#include "reload.h"
#include "recog.h"
+#include "alloc-pool.h"
#include "cselib.h"
#include "diagnostic-core.h"
#include "except.h"
-#include "tree.h"
#include "target.h"
#include "tree-pass.h"
-#include "df.h"
#include "dbgcnt.h"
+#ifndef LOAD_EXTEND_OP
+#define LOAD_EXTEND_OP(M) UNKNOWN
+#endif
+
static int reload_cse_noop_set_p (rtx);
-static bool reload_cse_simplify (rtx, rtx);
+static bool reload_cse_simplify (rtx_insn *, rtx);
static void reload_cse_regs_1 (void);
-static int reload_cse_simplify_set (rtx, rtx);
-static int reload_cse_simplify_operands (rtx, rtx);
+static int reload_cse_simplify_set (rtx, rtx_insn *);
+static int reload_cse_simplify_operands (rtx_insn *, rtx);
static void reload_combine (void);
-static void reload_combine_note_use (rtx *, rtx, int, rtx);
+static void reload_combine_note_use (rtx *, rtx_insn *, int, rtx);
static void reload_combine_note_store (rtx, const_rtx, void *);
-static bool reload_cse_move2add (rtx);
+static bool reload_cse_move2add (rtx_insn *);
static void move2add_note_store (rtx, const_rtx, void *);
/* Call cse / combine like post-reload optimization phases.
FIRST is the first instruction. */
static void
-reload_cse_regs (rtx first ATTRIBUTE_UNUSED)
+reload_cse_regs (rtx_insn *first ATTRIBUTE_UNUSED)
{
bool moves_converted;
reload_cse_regs_1 ();
/* Try to simplify INSN. Return true if the CFG may have changed. */
static bool
-reload_cse_simplify (rtx insn, rtx testreg)
+reload_cse_simplify (rtx_insn *insn, rtx testreg)
{
rtx body = PATTERN (insn);
basic_block insn_bb = BLOCK_FOR_INSN (insn);
{
bool cfg_changed = false;
basic_block bb;
- rtx insn;
- rtx testreg = gen_rtx_REG (VOIDmode, -1);
+ rtx_insn *insn;
+ rtx testreg = gen_rtx_REG (word_mode, LAST_VIRTUAL_REGISTER + 1);
cselib_init (CSELIB_RECORD_MEMORY);
init_alias_analysis ();
and change the set into a register copy. */
static int
-reload_cse_simplify_set (rtx set, rtx insn)
+reload_cse_simplify_set (rtx set, rtx_insn *insn)
{
int did_change = 0;
int dreg;
int old_cost;
cselib_val *val;
struct elt_loc_list *l;
-#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));
dclass = REGNO_REG_CLASS (dreg);
-#ifdef LOAD_EXTEND_OP
/* When replacing a memory with a register, we need to honor assumptions
that combine made wrt the contents of sign bits. We'll do this by
generating an extend instruction instead of a reg->reg copy. Thus
&& (extend_op = LOAD_EXTEND_OP (GET_MODE (src))) != UNKNOWN
&& !REG_P (SET_DEST (set)))
return 0;
-#endif
val = cselib_lookup (src, GET_MODE (SET_DEST (set)), 0, VOIDmode);
if (! val)
old_cost = register_move_cost (GET_MODE (src),
REGNO_REG_CLASS (REGNO (src)), dclass);
else
- old_cost = set_src_cost (src, speed);
+ old_cost = set_src_cost (src, GET_MODE (SET_DEST (set)), speed);
for (l = val->locs; l; l = l->next)
{
if (CONSTANT_P (this_rtx) && ! references_value_p (this_rtx, 0))
{
-#ifdef LOAD_EXTEND_OP
if (extend_op != UNKNOWN)
{
- HOST_WIDE_INT this_val;
+ wide_int result;
- /* ??? I'm lazy and don't wish to handle CONST_DOUBLE. Other
- constants, such as SYMBOL_REF, cannot be extended. */
- if (!CONST_INT_P (this_rtx))
+ if (!CONST_SCALAR_INT_P (this_rtx))
continue;
- this_val = INTVAL (this_rtx);
switch (extend_op)
{
case ZERO_EXTEND:
- this_val &= GET_MODE_MASK (GET_MODE (src));
+ result = wide_int::from (std::make_pair (this_rtx,
+ GET_MODE (src)),
+ BITS_PER_WORD, UNSIGNED);
break;
case SIGN_EXTEND:
- /* ??? In theory we're already extended. */
- if (this_val == trunc_int_for_mode (this_val, GET_MODE (src)))
- break;
+ result = wide_int::from (std::make_pair (this_rtx,
+ GET_MODE (src)),
+ BITS_PER_WORD, SIGNED);
+ break;
default:
gcc_unreachable ();
}
- this_rtx = GEN_INT (this_val);
+ this_rtx = immed_wide_int_const (result, word_mode);
}
-#endif
- this_cost = set_src_cost (this_rtx, speed);
+
+ this_cost = set_src_cost (this_rtx, GET_MODE (SET_DEST (set)), speed);
}
else if (REG_P (this_rtx))
{
-#ifdef LOAD_EXTEND_OP
if (extend_op != UNKNOWN)
{
this_rtx = gen_rtx_fmt_e (extend_op, word_mode, this_rtx);
- this_cost = set_src_cost (this_rtx, speed);
+ this_cost = set_src_cost (this_rtx, word_mode, speed);
}
else
-#endif
this_cost = register_move_cost (GET_MODE (this_rtx),
REGNO_REG_CLASS (REGNO (this_rtx)),
dclass);
&& REG_P (this_rtx)
&& !REG_P (SET_SRC (set))))
{
-#ifdef LOAD_EXTEND_OP
if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (set))) < BITS_PER_WORD
&& extend_op != UNKNOWN
#ifdef CANNOT_CHANGE_MODE_CLASS
ORIGINAL_REGNO (wide_dest) = ORIGINAL_REGNO (SET_DEST (set));
validate_change (insn, &SET_DEST (set), wide_dest, 1);
}
-#endif
validate_unshare_change (insn, &SET_SRC (set), this_rtx, 1);
old_cost = this_cost, did_change = 1;
hard registers. */
static int
-reload_cse_simplify_operands (rtx insn, rtx testreg)
+reload_cse_simplify_operands (rtx_insn *insn, rtx testreg)
{
int i, j;
/* Array of alternatives, sorted in order of decreasing desirability. */
int *alternative_order;
- extract_insn (insn);
+ extract_constrain_insn (insn);
if (recog_data.n_alternatives == 0 || recog_data.n_operands == 0)
return 0;
- /* Figure out which alternative currently matches. */
- if (! constrain_operands (1))
- fatal_insn_not_found (insn);
-
alternative_reject = XALLOCAVEC (int, recog_data.n_alternatives);
alternative_nregs = XALLOCAVEC (int, recog_data.n_alternatives);
alternative_order = XALLOCAVEC (int, recog_data.n_alternatives);
continue;
op = recog_data.operand[i];
-#ifdef LOAD_EXTEND_OP
if (MEM_P (op)
&& GET_MODE_BITSIZE (GET_MODE (op)) < BITS_PER_WORD
&& LOAD_EXTEND_OP (GET_MODE (op)) != UNKNOWN)
safe to optimize, but is it worth the trouble? */
continue;
}
-#endif /* LOAD_EXTEND_OP */
+
if (side_effects_p (op))
continue;
v = cselib_lookup (op, recog_data.operand_mode[i], 0, VOIDmode);
SET_HARD_REG_BIT (equiv_regs[i], REGNO (l->loc));
}
+ alternative_mask preferred = get_preferred_alternatives (insn);
for (i = 0; i < recog_data.n_operands; i++)
{
- enum machine_mode mode;
+ machine_mode mode;
int regno;
const char *p;
if (! TEST_HARD_REG_BIT (equiv_regs[i], regno))
continue;
- SET_REGNO_RAW (testreg, regno);
- PUT_MODE (testreg, mode);
+ set_mode_and_regno (testreg, mode, regno);
/* We found a register equal to this operand. Now look for all
alternatives that can accept this register and have not been
switch (c)
{
- case '=': case '+': case '?':
- case '#': case '&': case '!':
- case '*': case '%':
- case '0': case '1': case '2': case '3': case '4':
- case '5': case '6': case '7': case '8': case '9':
- 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 TARGET_MEM_CONSTRAINT:
- /* These don't say anything we care about. */
- break;
-
- case 'g': case 'r':
- rclass = reg_class_subunion[(int) rclass][(int) GENERAL_REGS];
+ case 'g':
+ rclass = reg_class_subunion[rclass][GENERAL_REGS];
break;
default:
rclass
= (reg_class_subunion
- [(int) rclass]
- [(int) REG_CLASS_FROM_CONSTRAINT ((unsigned char) c, p)]);
+ [rclass]
+ [reg_class_for_constraint (lookup_constraint (p))]);
break;
case ',': case '\0':
alternative yet and the operand being replaced is not
a cheap CONST_INT. */
if (op_alt_regno[i][j] == -1
- && recog_data.alternative_enabled_p[j]
+ && TEST_BIT (preferred, j)
&& reg_fits_class_p (testreg, rclass, 0, mode)
&& (!CONST_INT_P (recog_data.operand[i])
- || (set_src_cost (recog_data.operand[i],
+ || (set_src_cost (recog_data.operand[i], mode,
optimize_bb_for_speed_p
(BLOCK_FOR_INSN (insn)))
- > set_src_cost (testreg,
+ > set_src_cost (testreg, mode,
optimize_bb_for_speed_p
(BLOCK_FOR_INSN (insn))))))
{
int best = i;
int best_reject = alternative_reject[alternative_order[i]];
int best_nregs = alternative_nregs[alternative_order[i]];
- int tmp;
for (j = i + 1; j < recog_data.n_alternatives; j++)
{
}
}
- tmp = alternative_order[best];
- alternative_order[best] = alternative_order[i];
- alternative_order[i] = tmp;
+ std::swap (alternative_order[best], alternative_order[i]);
}
/* Substitute the operands as determined by op_alt_regno for the best
for (i = 0; i < recog_data.n_operands; i++)
{
- enum machine_mode mode = recog_data.operand_mode[i];
+ machine_mode mode = recog_data.operand_mode[i];
if (op_alt_regno[i][j] == -1)
continue;
for (i = recog_data.n_dups - 1; i >= 0; i--)
{
int op = recog_data.dup_num[i];
- enum machine_mode mode = recog_data.operand_mode[op];
+ machine_mode mode = recog_data.operand_mode[op];
if (op_alt_regno[op][j] == -1)
continue;
struct reg_use
{
/* The insn where a register has been used. */
- rtx insn;
+ rtx_insn *insn;
/* Points to the memory reference enclosing the use, if any, NULL_RTX
otherwise. */
rtx containing_mem;
information about uses in that particular insn. */
static void
-reload_combine_purge_insn_uses (rtx insn)
+reload_combine_purge_insn_uses (rtx_insn *insn)
{
unsigned i;
should make this change on debug insns. */
static void
-fixup_debug_insns (rtx reg, rtx replacement, rtx from, rtx to)
+fixup_debug_insns (rtx reg, rtx replacement, rtx_insn *from, rtx_insn *to)
{
- rtx insn;
+ rtx_insn *insn;
for (insn = from; insn != to; insn = NEXT_INSN (insn))
{
rtx t;
static bool
try_replace_in_use (struct reg_use *use, rtx reg, rtx src)
{
- rtx use_insn = use->insn;
+ rtx_insn *use_insn = use->insn;
rtx mem = use->containing_mem;
bool speed = optimize_bb_for_speed_p (BLOCK_FOR_INSN (use_insn));
&& CONSTANT_P (XEXP (SET_SRC (new_set), 1)))
{
rtx new_src;
- int old_cost = set_src_cost (SET_SRC (new_set), speed);
+ machine_mode mode = GET_MODE (SET_DEST (new_set));
+ int old_cost = set_src_cost (SET_SRC (new_set), mode, speed);
gcc_assert (rtx_equal_p (XEXP (SET_SRC (new_set), 0), reg));
new_src = simplify_replace_rtx (SET_SRC (new_set), reg, src);
- if (set_src_cost (new_src, speed) <= old_cost
+ if (set_src_cost (new_src, mode, speed) <= old_cost
&& validate_change (use_insn, &SET_SRC (new_set),
new_src, 0))
return true;
recognized and should be handled normally. */
static bool
-reload_combine_recognize_const_pattern (rtx insn)
+reload_combine_recognize_const_pattern (rtx_insn *insn)
{
int from_ruid = reload_combine_ruid;
rtx set, pat, reg, src, addreg;
unsigned int regno;
struct reg_use *use;
bool must_move_add;
- rtx add_moved_after_insn = NULL_RTX;
+ rtx_insn *add_moved_after_insn = NULL;
int add_moved_after_ruid = 0;
int clobbered_regno = -1;
reg = SET_DEST (set);
src = SET_SRC (set);
if (!REG_P (reg)
- || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1
+ || REG_NREGS (reg) != 1
|| GET_MODE (reg) != Pmode
|| reg == stack_pointer_rtx)
return false;
if (use && GET_MODE (*use->usep) == Pmode)
{
bool delete_add = false;
- rtx use_insn = use->insn;
+ rtx_insn *use_insn = use->insn;
int use_ruid = use->ruid;
/* Avoid moving the add insn past a jump. */
&& reg_state[clobbered_regno].real_store_ruid >= use_ruid)
break;
-#ifdef HAVE_cc0
/* Do not separate cc0 setter and cc0 user on HAVE_cc0 targets. */
- if (must_move_add && sets_cc0_p (PATTERN (use_insn)))
+ if (HAVE_cc0 && must_move_add && sets_cc0_p (PATTERN (use_insn)))
break;
-#endif
gcc_assert (reg_state[regno].store_ruid <= use_ruid);
/* Avoid moving a use of ADDREG past a point where it is stored. */
INSN; false if it wasn't recognized and should be handled normally. */
static bool
-reload_combine_recognize_pattern (rtx insn)
+reload_combine_recognize_pattern (rtx_insn *insn)
{
rtx set, reg, src;
unsigned int regno;
reg = SET_DEST (set);
src = SET_SRC (set);
- if (!REG_P (reg)
- || hard_regno_nregs[REGNO (reg)][GET_MODE (reg)] != 1)
+ if (!REG_P (reg) || REG_NREGS (reg) != 1)
return false;
regno = REGNO (reg);
&& last_label_ruid < reg_state[regno].use_ruid)
{
rtx base = XEXP (src, 1);
- rtx prev = prev_nonnote_nondebug_insn (insn);
+ rtx_insn *prev = prev_nonnote_nondebug_insn (insn);
rtx prev_set = prev ? single_set (prev) : NULL_RTX;
rtx index_reg = NULL_RTX;
rtx reg_sum = NULL_RTX;
static void
reload_combine (void)
{
- rtx insn, prev;
+ rtx_insn *insn, *prev;
basic_block bb;
unsigned int r;
int min_labelno, n_labels;
if (CALL_P (insn))
{
rtx link;
+ HARD_REG_SET used_regs;
+
+ get_call_reg_set_usage (insn, &used_regs, call_used_reg_set);
for (r = 0; r < FIRST_PSEUDO_REGISTER; r++)
- if (call_used_regs[r])
+ if (TEST_HARD_REG_BIT (used_regs, r))
{
reg_state[r].use_index = RELOAD_COMBINE_MAX_USES;
reg_state[r].store_ruid = reload_combine_ruid;
if ((GET_CODE (setuse) == USE || GET_CODE (setuse) == CLOBBER)
&& REG_P (usage_rtx))
{
- unsigned int i;
- unsigned int start_reg = REGNO (usage_rtx);
- unsigned int num_regs
- = hard_regno_nregs[start_reg][GET_MODE (usage_rtx)];
- unsigned int end_reg = start_reg + num_regs - 1;
- for (i = start_reg; i <= end_reg; i++)
+ unsigned int end_regno = END_REGNO (usage_rtx);
+ for (unsigned int i = REGNO (usage_rtx); i < end_regno; ++i)
if (GET_CODE (XEXP (link, 0)) == CLOBBER)
{
reg_state[i].use_index = RELOAD_COMBINE_MAX_USES;
{
int regno = 0;
int i;
- enum machine_mode mode = GET_MODE (dst);
+ machine_mode mode = GET_MODE (dst);
if (GET_CODE (dst) == SUBREG)
{
|| GET_CODE (dst) == PRE_DEC || GET_CODE (dst) == POST_DEC
|| GET_CODE (dst) == PRE_MODIFY || GET_CODE (dst) == POST_MODIFY)
{
- regno = REGNO (XEXP (dst, 0));
- mode = GET_MODE (XEXP (dst, 0));
- for (i = hard_regno_nregs[regno][mode] - 1 + regno; i >= regno; i--)
+ unsigned int end_regno = END_REGNO (XEXP (dst, 0));
+ for (unsigned int i = REGNO (XEXP (dst, 0)); i < end_regno; ++i)
{
/* We could probably do better, but for now mark the register
as used in an unknown fashion and set/clobbered at this
*XP is the pattern of INSN, or a part of it.
Called from reload_combine, and recursively by itself. */
static void
-reload_combine_note_use (rtx *xp, rtx insn, int ruid, rtx containing_mem)
+reload_combine_note_use (rtx *xp, rtx_insn *insn, int ruid, rtx containing_mem)
{
rtx x = *xp;
enum rtx_code code = x->code;
/* If this is the USE of a return value, we can't change it. */
if (REG_P (XEXP (x, 0)) && REG_FUNCTION_VALUE_P (XEXP (x, 0)))
{
- /* Mark the return register as used in an unknown fashion. */
+ /* Mark the return register as used in an unknown fashion. */
rtx reg = XEXP (x, 0);
- int regno = REGNO (reg);
- int nregs = hard_regno_nregs[regno][GET_MODE (reg)];
-
- while (--nregs >= 0)
- reg_state[regno + nregs].use_index = -1;
+ unsigned int end_regno = END_REGNO (reg);
+ for (unsigned int regno = REGNO (reg); regno < end_regno; ++regno)
+ reg_state[regno].use_index = -1;
return;
}
break;
/* No spurious USEs of pseudo registers may remain. */
gcc_assert (regno < FIRST_PSEUDO_REGISTER);
- nregs = hard_regno_nregs[regno][GET_MODE (x)];
+ nregs = REG_NREGS (x);
/* We can't substitute into multi-hard-reg uses. */
if (nregs > 1)
static HOST_WIDE_INT reg_offset[FIRST_PSEUDO_REGISTER];
static int reg_base_reg[FIRST_PSEUDO_REGISTER];
static rtx reg_symbol_ref[FIRST_PSEUDO_REGISTER];
-static enum machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
+static machine_mode reg_mode[FIRST_PSEUDO_REGISTER];
/* move2add_luid is linearly increased while scanning the instructions
from first to last. It is used to set reg_set_luid in
move2add_record_mode (rtx reg)
{
int regno, nregs;
- enum machine_mode mode = GET_MODE (reg);
+ machine_mode mode = GET_MODE (reg);
if (GET_CODE (reg) == SUBREG)
{
else if (REG_P (reg))
{
regno = REGNO (reg);
- nregs = hard_regno_nregs[regno][mode];
+ nregs = REG_NREGS (reg);
}
else
gcc_unreachable ();
/* Check if REGNO contains a valid value in MODE. */
static bool
-move2add_valid_value_p (int regno, enum machine_mode mode)
+move2add_valid_value_p (int regno, machine_mode mode)
{
if (reg_set_luid[regno] <= move2add_last_label_luid)
return false;
Return true if we made a change. */
static bool
-move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx insn)
+move2add_use_add2_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
{
rtx pat = PATTERN (insn);
rtx src = SET_SRC (pat);
changed = validate_change (insn, &SET_SRC (pat), tem, 0);
else if (sym == NULL_RTX && GET_MODE (reg) != BImode)
{
- enum machine_mode narrow_mode;
+ machine_mode narrow_mode;
for (narrow_mode = GET_CLASS_NARROWEST_MODE (MODE_INT);
narrow_mode != VOIDmode
&& narrow_mode != GET_MODE (reg);
rtx narrow_src = gen_int_mode (INTVAL (off),
narrow_mode);
rtx new_set
- = gen_rtx_SET (VOIDmode,
- gen_rtx_STRICT_LOW_PART (VOIDmode,
+ = gen_rtx_SET (gen_rtx_STRICT_LOW_PART (VOIDmode,
narrow_reg),
narrow_src);
- changed = validate_change (insn, &PATTERN (insn),
- new_set, 0);
- if (changed)
- break;
+ get_full_set_rtx_cost (new_set, &newcst);
+ if (costs_lt_p (&newcst, &oldcst, speed))
+ {
+ changed = validate_change (insn, &PATTERN (insn),
+ new_set, 0);
+ if (changed)
+ break;
+ }
}
}
}
Return true iff we made a change. */
static bool
-move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx insn)
+move2add_use_add3_insn (rtx reg, rtx sym, rtx off, rtx_insn *insn)
{
rtx pat = PATTERN (insn);
rtx src = SET_SRC (pat);
/* Convert move insns with constant inputs to additions if they are cheaper.
Return true if any changes were made. */
static bool
-reload_cse_move2add (rtx first)
+reload_cse_move2add (rtx_insn *first)
{
int i;
- rtx insn;
+ rtx_insn *insn;
bool changed = false;
for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
&& reg_base_reg[regno] == reg_base_reg[REGNO (src)]
&& move2add_valid_value_p (REGNO (src), GET_MODE (reg)))
{
- rtx next = next_nonnote_nondebug_insn (insn);
+ rtx_insn *next = next_nonnote_nondebug_insn (insn);
rtx set = NULL_RTX;
if (next)
set = single_set (next);
get_full_set_rtx_cost (set, &oldcst);
SET_SRC (set) = tem;
- get_full_set_src_cost (tem, &newcst);
+ get_full_set_src_cost (tem, GET_MODE (reg), &newcst);
SET_SRC (set) = old_src;
costs_add_n_insns (&oldcst, 1);
if (costs_lt_p (&newcst, &oldcst, speed)
&& have_add2_insn (reg, new_src))
{
- rtx newpat = gen_rtx_SET (VOIDmode, reg, tem);
+ rtx newpat = gen_rtx_SET (reg, tem);
success
= validate_change (next, &PATTERN (next),
newpat, 0);
number of calls to gen_rtx_SET to avoid memory
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
+ && REG_NREGS (XEXP (cnd, 0)) == 1
&& CONST_INT_P (XEXP (cnd, 1)))
{
rtx implicit_set =
- gen_rtx_SET (VOIDmode, XEXP (cnd, 0), XEXP (cnd, 1));
+ gen_rtx_SET (XEXP (cnd, 0), XEXP (cnd, 1));
move2add_note_store (SET_DEST (implicit_set), implicit_set, insn);
}
}
unknown values. */
if (CALL_P (insn))
{
+ rtx link;
+
for (i = FIRST_PSEUDO_REGISTER - 1; i >= 0; i--)
{
if (call_used_regs[i])
/* Reset the information about this register. */
reg_mode[i] = VOIDmode;
}
+
+ for (link = CALL_INSN_FUNCTION_USAGE (insn); link;
+ link = XEXP (link, 1))
+ {
+ rtx setuse = XEXP (link, 0);
+ rtx usage_rtx = XEXP (setuse, 0);
+ if (GET_CODE (setuse) == CLOBBER
+ && REG_P (usage_rtx))
+ {
+ unsigned int end_regno = END_REGNO (usage_rtx);
+ for (unsigned int r = REGNO (usage_rtx); r < end_regno; ++r)
+ /* Reset the information about this register. */
+ reg_mode[r] = VOIDmode;
+ }
+ }
}
}
return changed;
static void
move2add_note_store (rtx dst, const_rtx set, void *data)
{
- rtx insn = (rtx) data;
+ rtx_insn *insn = (rtx_insn *) data;
unsigned int regno = 0;
- enum machine_mode mode = GET_MODE (dst);
+ machine_mode mode = GET_MODE (dst);
/* Some targets do argument pushes without adding REG_INC notes. */
}
}
\f
-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 (cfun->can_throw_non_call_exceptions
- && purge_all_dead_edges ())
- cleanup_cfg (0);
-
- return 0;
-}
-
namespace {
const pass_data pass_data_postreload_cse =
RTL_PASS, /* type */
"postreload", /* name */
OPTGROUP_NONE, /* optinfo_flags */
- true, /* has_gate */
- true, /* has_execute */
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 | 0 ), /* todo_flags_finish */
+ TODO_df_finish, /* todo_flags_finish */
};
class pass_postreload_cse : public rtl_opt_pass
{}
/* opt_pass methods: */
- bool gate () { return gate_handle_postreload (); }
- unsigned int execute () { return rest_of_handle_postreload (); }
+ virtual bool gate (function *) { return (optimize > 0 && reload_completed); }
+
+ virtual unsigned int execute (function *);
}; // class pass_postreload_cse
+unsigned int
+pass_postreload_cse::execute (function *fun)
+{
+ 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 (fun->can_throw_non_call_exceptions
+ && purge_all_dead_edges ())
+ cleanup_cfg (0);
+
+ return 0;
+}
+
} // anon namespace
rtl_opt_pass *