summaryrefslogtreecommitdiff
path: root/gcc/lra-constraints.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/lra-constraints.c')
-rw-r--r--gcc/lra-constraints.c319
1 files changed, 177 insertions, 142 deletions
diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c
index 038acd72148..4ac20fd9553 100644
--- a/gcc/lra-constraints.c
+++ b/gcc/lra-constraints.c
@@ -859,10 +859,20 @@ emit_spill_move (bool to_p, rtx mem_pseudo, rtx val)
{
if (GET_MODE (mem_pseudo) != GET_MODE (val))
{
- val = gen_rtx_SUBREG (GET_MODE (mem_pseudo),
- GET_CODE (val) == SUBREG ? SUBREG_REG (val) : val,
- 0);
- LRA_SUBREG_P (val) = 1;
+ lra_assert (GET_MODE_SIZE (GET_MODE (mem_pseudo))
+ >= GET_MODE_SIZE (GET_MODE (val)));
+ if (! MEM_P (val))
+ {
+ val = gen_rtx_SUBREG (GET_MODE (mem_pseudo),
+ GET_CODE (val) == SUBREG ? SUBREG_REG (val) : val,
+ 0);
+ LRA_SUBREG_P (val) = 1;
+ }
+ else
+ {
+ mem_pseudo = gen_lowpart_SUBREG (GET_MODE (val), mem_pseudo);
+ LRA_SUBREG_P (mem_pseudo) = 1;
+ }
}
return (to_p
? gen_move_insn (mem_pseudo, val)
@@ -890,7 +900,7 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
dreg = SUBREG_REG (dest);
if (GET_CODE (src) == SUBREG)
sreg = SUBREG_REG (src);
- if (! REG_P (dreg) || ! REG_P (sreg))
+ if (! (REG_P (dreg) || MEM_P (dreg)) || ! (REG_P (sreg) || MEM_P (sreg)))
return false;
sclass = dclass = NO_REGS;
if (REG_P (dreg))
@@ -911,14 +921,22 @@ check_and_process_move (bool *change_p, bool *sec_mem_p ATTRIBUTE_UNUSED)
if (sclass == ALL_REGS)
/* See comments above. */
return false;
+ if (sclass == NO_REGS && dclass == NO_REGS)
+ return false;
#ifdef SECONDARY_MEMORY_NEEDED
- if (dclass != NO_REGS && sclass != NO_REGS
- && SECONDARY_MEMORY_NEEDED (sclass, dclass, GET_MODE (src)))
+ if (SECONDARY_MEMORY_NEEDED (sclass, dclass, GET_MODE (src))
+#ifdef SECONDARY_MEMORY_NEEDED_MODE
+ && ((sclass != NO_REGS && dclass != NO_REGS)
+ || GET_MODE (src) != SECONDARY_MEMORY_NEEDED_MODE (GET_MODE (src)))
+#endif
+ )
{
*sec_mem_p = true;
return false;
}
#endif
+ if (! REG_P (dreg) || ! REG_P (sreg))
+ return false;
sri.prev_sri = NULL;
sri.icode = CODE_FOR_nothing;
sri.extra_cost = 0;
@@ -1979,15 +1997,8 @@ process_alt_operands (int only_alternative)
(op, this_alternative) == NO_REGS))))
reject += LRA_MAX_REJECT;
- if (MEM_P (op) && offmemok)
- {
- /* If we know offset and this non-offsetable memory,
- something wrong with this memory and it is better
- to try other memory possibilities. */
- if (MEM_OFFSET_KNOWN_P (op))
- reject += LRA_MAX_REJECT;
- }
- else if (! (const_to_mem && constmemok))
+ if (! (MEM_P (op) && offmemok)
+ && ! (const_to_mem && constmemok))
{
/* We prefer to reload pseudos over reloading other
things, since such reloads may be able to be
@@ -3006,16 +3017,22 @@ curr_insn_transform (void)
/* If the target says specifically to use another mode for
secondary memory moves we can not reuse the original
insn. */
- after = emit_spill_move (false, new_reg, dest);
- lra_process_new_insns (curr_insn, NULL_RTX, after,
- "Inserting the sec. move");
- before = emit_spill_move (true, new_reg, src);
- lra_process_new_insns (curr_insn, before, NULL_RTX, "Changing on");
- lra_set_insn_deleted (curr_insn);
- }
+ after = emit_spill_move (false, new_reg, dest);
+ lra_process_new_insns (curr_insn, NULL_RTX, after,
+ "Inserting the sec. move");
+ /* We may have non null BEFORE here (e.g. after address
+ processing. */
+ push_to_sequence (before);
+ before = emit_spill_move (true, new_reg, src);
+ emit_insn (before);
+ before = get_insns ();
+ end_sequence ();
+ lra_process_new_insns (curr_insn, before, NULL_RTX, "Changing on");
+ lra_set_insn_deleted (curr_insn);
+ }
else if (dest == rld)
- {
- *curr_id->operand_loc[0] = new_reg;
+ {
+ *curr_id->operand_loc[0] = new_reg;
after = emit_spill_move (false, new_reg, dest);
lra_process_new_insns (curr_insn, NULL_RTX, after,
"Inserting the sec. move");
@@ -3023,7 +3040,12 @@ curr_insn_transform (void)
else
{
*curr_id->operand_loc[1] = new_reg;
+ /* See comments above. */
+ push_to_sequence (before);
before = emit_spill_move (true, new_reg, src);
+ emit_insn (before);
+ before = get_insns ();
+ end_sequence ();
lra_process_new_insns (curr_insn, before, NULL_RTX,
"Inserting the sec. move");
}
@@ -3823,7 +3845,9 @@ struct usage_insns
{
/* If the value is equal to CURR_USAGE_INSNS_CHECK, then the member
value INSNS is valid. The insns is chain of optional debug insns
- and a finishing non-debug insn using the corresponding reg. */
+ and a finishing non-debug insn using the corresponding reg. The
+ value is also used to mark the registers which are set up in the
+ current insn. The negated insn uid is used for this. */
int check;
/* Value of global reloads_num at the last insn in INSNS. */
int reloads_num;
@@ -4514,7 +4538,7 @@ update_ebb_live_info (rtx head, rtx tail)
bitmap_clear_bit (&live_regs, reg->regno);
/* Mark each used value as live. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next)
- if (reg->type == OP_IN
+ if (reg->type != OP_OUT
&& bitmap_bit_p (&check_only_regs, reg->regno))
bitmap_set_bit (&live_regs, reg->regno);
/* It is quite important to remove dead move insns because it
@@ -4738,75 +4762,81 @@ inherit_in_ebb (rtx head, rtx tail)
}
else if (INSN_P (curr_insn))
{
+ int iter;
int max_uid = get_max_uid ();
curr_id = lra_get_insn_recog_data (curr_insn);
+ curr_static_id = curr_id->insn_static_data;
to_inherit_num = 0;
/* Process insn definitions. */
- for (reg = curr_id->regs; reg != NULL; reg = reg->next)
- if (reg->type != OP_IN
- && (dst_regno = reg->regno) < lra_constraint_new_regno_start)
- {
- if (dst_regno >= FIRST_PSEUDO_REGISTER && reg->type == OP_OUT
- && reg_renumber[dst_regno] < 0 && ! reg->subreg_p
- && usage_insns[dst_regno].check == curr_usage_insns_check
- && (next_usage_insns
- = usage_insns[dst_regno].insns) != NULL_RTX)
- {
- struct lra_insn_reg *r;
-
- for (r = curr_id->regs; r != NULL; r = r->next)
- if (r->type != OP_OUT && r->regno == dst_regno)
- break;
- /* Don't do inheritance if the pseudo is also
- used in the insn. */
- if (r == NULL)
- /* We can not do inheritance right now
- because the current insn reg info (chain
- regs) can change after that. */
- add_to_inherit (dst_regno, next_usage_insns);
- }
- /* We can not process one reg twice here because of
- usage_insns invalidation. */
- if ((dst_regno < FIRST_PSEUDO_REGISTER
- || reg_renumber[dst_regno] >= 0)
- && ! reg->subreg_p && reg->type == OP_OUT)
- {
- HARD_REG_SET s;
-
- if (split_if_necessary (dst_regno, reg->biggest_mode,
- potential_reload_hard_regs,
- false, curr_insn, max_uid))
- change_p = true;
- CLEAR_HARD_REG_SET (s);
- if (dst_regno < FIRST_PSEUDO_REGISTER)
- add_to_hard_reg_set (&s, reg->biggest_mode, dst_regno);
- else
- add_to_hard_reg_set (&s, PSEUDO_REGNO_MODE (dst_regno),
- reg_renumber[dst_regno]);
- AND_COMPL_HARD_REG_SET (live_hard_regs, s);
- }
- /* We should invalidate potential inheritance or
- splitting for the current insn usages to the next
- usage insns (see code below) as the output pseudo
- prevents this. */
- if ((dst_regno >= FIRST_PSEUDO_REGISTER
- && reg_renumber[dst_regno] < 0)
- || (reg->type == OP_OUT && ! reg->subreg_p
- && (dst_regno < FIRST_PSEUDO_REGISTER
- || reg_renumber[dst_regno] >= 0)))
- {
- /* Invalidate. */
- if (dst_regno >= FIRST_PSEUDO_REGISTER)
- usage_insns[dst_regno].check = 0;
- else
- {
- nregs = hard_regno_nregs[dst_regno][reg->biggest_mode];
- for (i = 0; i < nregs; i++)
- usage_insns[dst_regno + i].check = 0;
- }
- }
- }
+ for (iter = 0; iter < 2; iter++)
+ for (reg = iter == 0 ? curr_id->regs : curr_static_id->hard_regs;
+ reg != NULL;
+ reg = reg->next)
+ if (reg->type != OP_IN
+ && (dst_regno = reg->regno) < lra_constraint_new_regno_start)
+ {
+ if (dst_regno >= FIRST_PSEUDO_REGISTER && reg->type == OP_OUT
+ && reg_renumber[dst_regno] < 0 && ! reg->subreg_p
+ && usage_insns[dst_regno].check == curr_usage_insns_check
+ && (next_usage_insns
+ = usage_insns[dst_regno].insns) != NULL_RTX)
+ {
+ struct lra_insn_reg *r;
+
+ for (r = curr_id->regs; r != NULL; r = r->next)
+ if (r->type != OP_OUT && r->regno == dst_regno)
+ break;
+ /* Don't do inheritance if the pseudo is also
+ used in the insn. */
+ if (r == NULL)
+ /* We can not do inheritance right now
+ because the current insn reg info (chain
+ regs) can change after that. */
+ add_to_inherit (dst_regno, next_usage_insns);
+ }
+ /* We can not process one reg twice here because of
+ usage_insns invalidation. */
+ if ((dst_regno < FIRST_PSEUDO_REGISTER
+ || reg_renumber[dst_regno] >= 0)
+ && ! reg->subreg_p && reg->type != OP_IN)
+ {
+ HARD_REG_SET s;
+
+ if (split_if_necessary (dst_regno, reg->biggest_mode,
+ potential_reload_hard_regs,
+ false, curr_insn, max_uid))
+ change_p = true;
+ CLEAR_HARD_REG_SET (s);
+ if (dst_regno < FIRST_PSEUDO_REGISTER)
+ add_to_hard_reg_set (&s, reg->biggest_mode, dst_regno);
+ else
+ add_to_hard_reg_set (&s, PSEUDO_REGNO_MODE (dst_regno),
+ reg_renumber[dst_regno]);
+ AND_COMPL_HARD_REG_SET (live_hard_regs, s);
+ }
+ /* We should invalidate potential inheritance or
+ splitting for the current insn usages to the next
+ usage insns (see code below) as the output pseudo
+ prevents this. */
+ if ((dst_regno >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[dst_regno] < 0)
+ || (reg->type == OP_OUT && ! reg->subreg_p
+ && (dst_regno < FIRST_PSEUDO_REGISTER
+ || reg_renumber[dst_regno] >= 0)))
+ {
+ /* Invalidate and mark definitions. */
+ if (dst_regno >= FIRST_PSEUDO_REGISTER)
+ usage_insns[dst_regno].check = -(int) INSN_UID (curr_insn);
+ else
+ {
+ nregs = hard_regno_nregs[dst_regno][reg->biggest_mode];
+ for (i = 0; i < nregs; i++)
+ usage_insns[dst_regno + i].check
+ = -(int) INSN_UID (curr_insn);
+ }
+ }
+ }
if (! JUMP_P (curr_insn))
for (i = 0; i < to_inherit_num; i++)
if (inherit_reload_reg (true, to_inherit[i].regno,
@@ -4851,57 +4881,62 @@ inherit_in_ebb (rtx head, rtx tail)
}
to_inherit_num = 0;
/* Process insn usages. */
- for (reg = curr_id->regs; reg != NULL; reg = reg->next)
- if ((reg->type != OP_OUT
- || (reg->type == OP_OUT && reg->subreg_p))
- && (src_regno = reg->regno) < lra_constraint_new_regno_start)
- {
- if (src_regno >= FIRST_PSEUDO_REGISTER
- && reg_renumber[src_regno] < 0 && reg->type == OP_IN)
- {
- if (usage_insns[src_regno].check == curr_usage_insns_check
- && (next_usage_insns
- = usage_insns[src_regno].insns) != NULL_RTX
- && NONDEBUG_INSN_P (curr_insn))
- add_to_inherit (src_regno, next_usage_insns);
- else
- /* Add usages. */
- add_next_usage_insn (src_regno, curr_insn, reloads_num);
- }
- else if (src_regno < FIRST_PSEUDO_REGISTER
- || reg_renumber[src_regno] >= 0)
- {
- bool before_p;
- rtx use_insn = curr_insn;
-
- before_p = (JUMP_P (curr_insn)
- || (CALL_P (curr_insn) && reg->type == OP_IN));
- if (NONDEBUG_INSN_P (curr_insn)
- && split_if_necessary (src_regno, reg->biggest_mode,
- potential_reload_hard_regs,
- before_p, curr_insn, max_uid))
- {
- if (reg->subreg_p)
- lra_risky_transformations_p = true;
- change_p = true;
- /* Invalidate. */
- usage_insns[src_regno].check = 0;
- if (before_p)
- use_insn = PREV_INSN (curr_insn);
- }
- if (NONDEBUG_INSN_P (curr_insn))
- {
- if (src_regno < FIRST_PSEUDO_REGISTER)
- add_to_hard_reg_set (&live_hard_regs,
- reg->biggest_mode, src_regno);
- else
- add_to_hard_reg_set (&live_hard_regs,
- PSEUDO_REGNO_MODE (src_regno),
- reg_renumber[src_regno]);
- }
- add_next_usage_insn (src_regno, use_insn, reloads_num);
- }
- }
+ for (iter = 0; iter < 2; iter++)
+ for (reg = iter == 0 ? curr_id->regs : curr_static_id->hard_regs;
+ reg != NULL;
+ reg = reg->next)
+ if ((reg->type != OP_OUT
+ || (reg->type == OP_OUT && reg->subreg_p))
+ && (src_regno = reg->regno) < lra_constraint_new_regno_start)
+ {
+ if (src_regno >= FIRST_PSEUDO_REGISTER
+ && reg_renumber[src_regno] < 0 && reg->type == OP_IN)
+ {
+ if (usage_insns[src_regno].check == curr_usage_insns_check
+ && (next_usage_insns
+ = usage_insns[src_regno].insns) != NULL_RTX
+ && NONDEBUG_INSN_P (curr_insn))
+ add_to_inherit (src_regno, next_usage_insns);
+ else if (usage_insns[src_regno].check
+ != -(int) INSN_UID (curr_insn))
+ /* Add usages but only if the reg is not set up
+ in the same insn. */
+ add_next_usage_insn (src_regno, curr_insn, reloads_num);
+ }
+ else if (src_regno < FIRST_PSEUDO_REGISTER
+ || reg_renumber[src_regno] >= 0)
+ {
+ bool before_p;
+ rtx use_insn = curr_insn;
+
+ before_p = (JUMP_P (curr_insn)
+ || (CALL_P (curr_insn) && reg->type == OP_IN));
+ if (NONDEBUG_INSN_P (curr_insn)
+ && split_if_necessary (src_regno, reg->biggest_mode,
+ potential_reload_hard_regs,
+ before_p, curr_insn, max_uid))
+ {
+ if (reg->subreg_p)
+ lra_risky_transformations_p = true;
+ change_p = true;
+ /* Invalidate. */
+ usage_insns[src_regno].check = 0;
+ if (before_p)
+ use_insn = PREV_INSN (curr_insn);
+ }
+ if (NONDEBUG_INSN_P (curr_insn))
+ {
+ if (src_regno < FIRST_PSEUDO_REGISTER)
+ add_to_hard_reg_set (&live_hard_regs,
+ reg->biggest_mode, src_regno);
+ else
+ add_to_hard_reg_set (&live_hard_regs,
+ PSEUDO_REGNO_MODE (src_regno),
+ reg_renumber[src_regno]);
+ }
+ add_next_usage_insn (src_regno, use_insn, reloads_num);
+ }
+ }
for (i = 0; i < to_inherit_num; i++)
{
src_regno = to_inherit[i].regno;