summaryrefslogtreecommitdiff
path: root/gcc/lra-constraints.c
diff options
context:
space:
mode:
authorbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2013-02-18 20:01:31 +0000
committerbstarynk <bstarynk@138bc75d-0d04-0410-961f-82ee72b054a4>2013-02-18 20:01:31 +0000
commit49e6b159a6b2225a0198f8e261c6b6f3772fba3f (patch)
tree7474601b4ae09317bf0a9ed2647974807abfc493 /gcc/lra-constraints.c
parent2fffb07a72d0755a559b08cfa30eb12d277daec1 (diff)
downloadgcc-49e6b159a6b2225a0198f8e261c6b6f3772fba3f.tar.gz
2013-02-18 Basile Starynkevitch <basile@starynkevitch.net>
MELT branch merged with trunk rev 196123 using svnmerge.py git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/melt-branch@196126 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r--gcc/lra-constraints.c112
1 files changed, 73 insertions, 39 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index af68c3aee4c..d3f4420b6a0 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -421,8 +421,20 @@ get_reload_reg (enum op_type type, enum machine_mode mode, rtx original,
if (rtx_equal_p (curr_insn_input_reloads[i].input, original)
&& in_class_p (curr_insn_input_reloads[i].reg, rclass, &new_class))
{
- *result_reg = curr_insn_input_reloads[i].reg;
- regno = REGNO (*result_reg);
+ rtx reg = curr_insn_input_reloads[i].reg;
+ regno = REGNO (reg);
+ /* If input is equal to original and both are VOIDmode,
+ GET_MODE (reg) might be still different from mode.
+ Ensure we don't return *result_reg with wrong mode. */
+ if (GET_MODE (reg) != mode)
+ {
+ if (GET_MODE_SIZE (GET_MODE (reg)) < GET_MODE_SIZE (mode))
+ continue;
+ reg = lowpart_subreg (mode, reg, GET_MODE (reg));
+ if (reg == NULL_RTX || GET_CODE (reg) != SUBREG)
+ continue;
+ }
+ *result_reg = reg;
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file, " Reuse r%d for reload ", regno);
@@ -1201,24 +1213,26 @@ simplify_operand_subreg (int nop, enum machine_mode reg_mode)
enum reg_class rclass
= (enum reg_class) targetm.preferred_reload_class (reg, ALL_REGS);
- new_reg = lra_create_new_reg_with_unique_value (reg_mode, reg, rclass,
- "subreg reg");
- bitmap_set_bit (&lra_optional_reload_pseudos, REGNO (new_reg));
- if (type != OP_OUT
- || GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode))
- {
- push_to_sequence (before);
- lra_emit_move (new_reg, reg);
- before = get_insns ();
- end_sequence ();
- }
- if (type != OP_IN)
+ if (get_reload_reg (curr_static_id->operand[nop].type, reg_mode, reg,
+ rclass, "subreg reg", &new_reg))
{
- start_sequence ();
- lra_emit_move (reg, new_reg);
- emit_insn (after);
- after = get_insns ();
- end_sequence ();
+ bitmap_set_bit (&lra_optional_reload_pseudos, REGNO (new_reg));
+ if (type != OP_OUT
+ || GET_MODE_SIZE (GET_MODE (reg)) > GET_MODE_SIZE (mode))
+ {
+ push_to_sequence (before);
+ lra_emit_move (new_reg, reg);
+ before = get_insns ();
+ end_sequence ();
+ }
+ if (type != OP_IN)
+ {
+ start_sequence ();
+ lra_emit_move (reg, new_reg);
+ emit_insn (after);
+ after = get_insns ();
+ end_sequence ();
+ }
}
SUBREG_REG (operand) = new_reg;
lra_process_new_insns (curr_insn, before, after,
@@ -1519,8 +1533,8 @@ process_alt_operands (int only_alternative)
if (! curr_static_id->operand[m].early_clobber
|| operand_reg[nop] == NULL_RTX
|| (find_regno_note (curr_insn, REG_DEAD,
- REGNO (operand_reg[nop]))
- != NULL_RTX))
+ REGNO (op))
+ || REGNO (op) == REGNO (operand_reg[m])))
match_p = true;
}
if (match_p)
@@ -2045,6 +2059,7 @@ process_alt_operands (int only_alternative)
if ((! curr_alt_win[i] && ! curr_alt_match_win[i])
|| hard_regno[i] < 0)
continue;
+ lra_assert (operand_reg[i] != NULL_RTX);
clobbered_hard_regno = hard_regno[i];
CLEAR_HARD_REG_SET (temp_set);
add_to_hard_reg_set (&temp_set, biggest_mode[i], clobbered_hard_regno);
@@ -2059,30 +2074,49 @@ process_alt_operands (int only_alternative)
else if ((curr_alt_matches[j] == i && curr_alt_match_win[j])
|| (curr_alt_matches[i] == j && curr_alt_match_win[i]))
continue;
- else if (uses_hard_regs_p (*curr_id->operand_loc[j], temp_set))
+ /* If we don't reload j-th operand, check conflicts. */
+ else if ((curr_alt_win[j] || curr_alt_match_win[j])
+ && uses_hard_regs_p (*curr_id->operand_loc[j], temp_set))
break;
if (j >= n_operands)
continue;
- /* We need to reload early clobbered register. */
- for (j = 0; j < n_operands; j++)
- if (curr_alt_matches[j] == i)
- {
- curr_alt_match_win[j] = false;
- losers++;
- overall += LRA_LOSER_COST_FACTOR;
- }
- if (! curr_alt_match_win[i])
- curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = i;
+ /* If earlyclobber operand conflicts with another
+ non-matching operand which is actually the same register
+ as the earlyclobber operand, it is better to reload the
+ another operand as an operand matching the earlyclobber
+ operand can be also the same. */
+ if (operand_reg[j] != NULL_RTX && ! curr_alt_match_win[j]
+ && REGNO (operand_reg[i]) == REGNO (operand_reg[j]))
+ {
+ curr_alt_win[j] = false;
+ curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = j;
+ losers++;
+ overall += LRA_LOSER_COST_FACTOR;
+ }
else
{
- /* Remember pseudos used for match reloads are never
- inherited. */
- lra_assert (curr_alt_matches[i] >= 0);
- curr_alt_win[curr_alt_matches[i]] = false;
+ /* We need to reload early clobbered register and the
+ matched registers. */
+ for (j = 0; j < n_operands; j++)
+ if (curr_alt_matches[j] == i)
+ {
+ curr_alt_match_win[j] = false;
+ losers++;
+ overall += LRA_LOSER_COST_FACTOR;
+ }
+ if (! curr_alt_match_win[i])
+ curr_alt_dont_inherit_ops[curr_alt_dont_inherit_ops_num++] = i;
+ else
+ {
+ /* Remember pseudos used for match reloads are never
+ inherited. */
+ lra_assert (curr_alt_matches[i] >= 0);
+ curr_alt_win[curr_alt_matches[i]] = false;
+ }
+ curr_alt_win[i] = curr_alt_match_win[i] = false;
+ losers++;
+ overall += LRA_LOSER_COST_FACTOR;
}
- curr_alt_win[i] = curr_alt_match_win[i] = false;
- losers++;
- overall += LRA_LOSER_COST_FACTOR;
}
small_class_operands_num = 0;
for (nop = 0; nop < n_operands; nop++)