===================================================================
@@ -304,11 +304,14 @@ find_hard_regno_for (int regno, int *cos
int best_cost = INT_MAX, best_bank = INT_MAX, best_usage = INT_MAX;
lra_live_range_t r;
int p, i, j, rclass_size, best_hard_regno, bank, hard_regno;
+ int hr, conflict_hr, nregs;
+ enum machine_mode biggest_mode;
unsigned int k, conflict_regno;
int val;
enum reg_class rclass;
bitmap_iterator bi;
bool *rclass_intersect_p;
+ HARD_REG_SET impossible_start_hard_regs;
COPY_HARD_REG_SET (conflict_set, lra_no_alloc_regs);
rclass = regno_allocno_class_array[regno];
@@ -317,6 +320,7 @@ find_hard_regno_for (int regno, int *cos
sparseset_clear (conflict_reload_and_inheritance_pseudos);
sparseset_clear (live_range_hard_reg_pseudos);
IOR_HARD_REG_SET (conflict_set, lra_reg_info[regno].conflict_hard_regs);
+ biggest_mode = lra_reg_info[regno].biggest_mode;
for (r = lra_reg_info[regno].live_ranges; r != NULL; r = r->next)
{
EXECUTE_IF_SET_IN_BITMAP (&live_hard_reg_pseudos[r->start], 0, k, bi)
@@ -370,8 +374,26 @@ find_hard_regno_for (int regno, int *cos
#endif
sparseset_clear_bit (conflict_reload_and_inheritance_pseudos, regno);
val = lra_reg_info[regno].val;
+ CLEAR_HARD_REG_SET (impossible_start_hard_regs);
EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno)
- if (val != lra_reg_info[conflict_regno].val)
+ if (val == lra_reg_info[conflict_regno].val)
+ {
+ conflict_hr = live_pseudos_reg_renumber[conflict_regno];
+ nregs = (hard_regno_nregs[conflict_hr]
+ [lra_reg_info[conflict_regno].biggest_mode]);
+ /* Remember about multi-register pseudos. For example, 2 hard
+ register pseudos can start on the same hard register but can
+ not start on HR and HR+1/HR-1. */
+ for (hr = conflict_hr + 1;
+ hr < FIRST_PSEUDO_REGISTER && hr < conflict_hr + nregs;
+ hr++)
+ SET_HARD_REG_BIT (impossible_start_hard_regs, hr);
+ for (hr = conflict_hr - 1;
+ hr >= 0 && hr + hard_regno_nregs[hr][biggest_mode] > conflict_hr;
+ hr--)
+ SET_HARD_REG_BIT (impossible_start_hard_regs, hr);
+ }
+ else
{
lra_add_hard_reg_set (live_pseudos_reg_renumber[conflict_regno],
lra_reg_info[conflict_regno].biggest_mode,
@@ -424,7 +446,8 @@ find_hard_regno_for (int regno, int *cos
conflict_set)
/* We can not use prohibited_class_mode_regs because it is
defined not for all classes. */
- && HARD_REGNO_MODE_OK (hard_regno, PSEUDO_REGNO_MODE (regno)))
+ && HARD_REGNO_MODE_OK (hard_regno, PSEUDO_REGNO_MODE (regno))
+ && ! TEST_HARD_REG_BIT (impossible_start_hard_regs, hard_regno))
{
if (hard_regno_costs_check[hard_regno]
!= curr_hard_regno_costs_check)
@@ -881,9 +904,13 @@ setup_live_pseudos_and_spill_after_risky
}
}
COPY_HARD_REG_SET (conflict_set, lra_no_alloc_regs);
+ IOR_HARD_REG_SET (conflict_set, lra_reg_info[regno].conflict_hard_regs);
val = lra_reg_info[regno].val;
EXECUTE_IF_SET_IN_SPARSESET (live_range_hard_reg_pseudos, conflict_regno)
- if (val != lra_reg_info[conflict_regno].val)
+ if (val != lra_reg_info[conflict_regno].val
+ /* If it is multi-register pseudos they should start on
+ the same hard register. */
+ || hard_regno != reg_renumber[conflict_regno])
lra_add_hard_reg_set (reg_renumber[conflict_regno],
lra_reg_info[conflict_regno].biggest_mode,
&conflict_set);
@@ -893,7 +920,6 @@ setup_live_pseudos_and_spill_after_risky
continue;
}
bitmap_set_bit (spilled_pseudo_bitmap, regno);
- hard_regno = reg_renumber[regno];
for (j = 0;
j < hard_regno_nregs[hard_regno][PSEUDO_REGNO_MODE (regno)];
j++)
@@ -1154,6 +1180,15 @@ lra_assign (void)
init_regno_assign_info ();
bitmap_initialize (&all_spilled_pseudos, ®_obstack);
setup_live_pseudos_and_spill_after_risky_transforms (&all_spilled_pseudos);
+#ifdef ENABLE_CHECKING
+ for (i = FIRST_PSEUDO_REGISTER; i < max_reg_num (); i++)
+ if (lra_reg_info[i].nrefs != 0 && reg_renumber[i] >= 0
+ && lra_reg_info[i].call_p
+ && lra_hard_reg_set_intersection_p (reg_renumber[i],
+ PSEUDO_REGNO_MODE (i),
+ call_used_reg_set))
+ gcc_unreachable ();
+#endif
/* Setup insns to process. */
bitmap_initialize (&changed_pseudo_bitmap, ®_obstack);
init_live_reload_and_inheritance_pseudos ();
===================================================================
@@ -477,7 +477,7 @@ extract_loc_address_regs (bool top_p, en
{
extract_loc_address_regs (false, mode, arg0_loc, true, PLUS, code1,
modify_p, ad);
- if (code1 == MULT)
+ if (code0 == MULT)
ad->index_loc = arg0_loc;
extract_loc_address_regs (false, mode, arg1_loc, false, PLUS,
code0, modify_p, ad);
@@ -2363,6 +2363,18 @@ equiv_address_substitution (struct addre
return change_p;
}
+/* Exchange operands of plus X. */
+static void
+exchange_plus_ops (rtx x)
+{
+ rtx op0;
+
+ gcc_assert (GET_CODE (x) == PLUS);
+ op0 = XEXP (x, 0);
+ XEXP (x, 0) = XEXP (x, 1);
+ XEXP (x, 1) = op0;
+}
+
/* Major function to make reloads for address in operand NOP. Add to
reloads to the list *BEFORE and *AFTER. We might need to add
reloads to *AFTER because of inc/dec, {pre, post} modify in the
@@ -2489,6 +2501,14 @@ process_address (int nop, rtx *before, r
if (CONSTANT_P (XEXP (*addr_loc, 1)))
XEXP (*addr_loc, 1) = XEXP (*addr_loc, 0);
XEXP (*addr_loc, 0) = new_reg;
+ /* Some targets like ARM, accept address operands in
+ specific order -- try exchange them if necessary. */
+ if (! valid_address_p (mode, *addr_loc, as))
+ {
+ exchange_plus_ops (*addr_loc);
+ if (! valid_address_p (mode, *addr_loc, as))
+ exchange_plus_ops (*addr_loc);
+ }
}
}
else if (ad.index_reg_loc == NULL)
@@ -2505,6 +2525,14 @@ process_address (int nop, rtx *before, r
/* base + scale * index + disp => new base + scale * index */
new_reg = base_plus_disp_to_reg (mode, &ad);
*addr_loc = gen_rtx_PLUS (Pmode, new_reg, *ad.index_loc);
+ if (! valid_address_p (mode, *addr_loc, as))
+ {
+ /* Some targets like ARM, accept address operands in
+ specific order -- try exchange them if necessary. */
+ exchange_plus_ops (*addr_loc);
+ if (! valid_address_p (mode, *addr_loc, as))
+ exchange_plus_ops (*addr_loc);
+ }
}
*before = get_insns ();
end_sequence ();
@@ -3790,7 +3818,7 @@ choose_split_class (enum reg_class alloc
#endif
}
-/* Do split transformation for insn INSN defining (if DEF_P) or
+/* Do split transformation for insn INSN defining or
using ORIGINAL_REGNO where the subsequent insn(s) in EBB (remember
we traverse insns in the backward direction) for the original regno
is NEXT_USAGE_INSNS. The transformations look like
@@ -3808,10 +3836,10 @@ choose_split_class (enum reg_class alloc
<- ... p ... <- ... p ...
where p is an original pseudo got a hard register and s is a new
- split pseudo. Return true if we succeed in such
- transformation. */
+ split pseudo. The save is put before INSN if BEFORE_P is true.
+ Return true if we succeed in such transformation. */
static bool
-split_pseudo (bool def_p, int original_regno, rtx insn, rtx next_usage_insns)
+split_pseudo (bool before_p, int original_regno, rtx insn, rtx next_usage_insns)
{
enum reg_class rclass = lra_get_allocno_class (original_regno);
rtx original_reg = regno_reg_rtx[original_regno];
@@ -3855,6 +3883,7 @@ split_pseudo (bool def_p, int original_r
}
if (NEXT_INSN (save) != NULL_RTX)
{
+ gcc_assert (! call_save_p);
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file,
@@ -3877,6 +3906,7 @@ split_pseudo (bool def_p, int original_r
}
if (NEXT_INSN (restore) != NULL_RTX)
{
+ gcc_assert (! call_save_p);
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file,
@@ -3890,15 +3920,6 @@ split_pseudo (bool def_p, int original_r
return false;
}
after_p = usage_insns[original_regno].after_p;
- if (! def_p)
- {
- /* We now have a new usage insn for original regno. */
- usage_insns[original_regno].check = curr_usage_insns_check;
- usage_insns[original_regno].insns = save;
- usage_insns[original_regno].reloads_num = reloads_num;
- usage_insns[original_regno].calls_num = calls_num;
- usage_insns[original_regno].after_p = false;
- }
lra_reg_info[REGNO (new_reg)].restore_regno = original_regno;
bitmap_set_bit (&check_only_pseudos, REGNO (new_reg));
bitmap_set_bit (&check_only_pseudos, original_regno);
@@ -3923,14 +3944,14 @@ split_pseudo (bool def_p, int original_r
-1, 0);
}
}
- gcc_assert ((usage_insn != insn || (after_p && ! def_p))
- && NONDEBUG_INSN_P (usage_insn));
+ gcc_assert (NONDEBUG_INSN_P (usage_insn));
+ gcc_assert (usage_insn != insn || (after_p && before_p));
lra_process_new_insns (usage_insn, after_p ? NULL_RTX : restore,
after_p ? restore : NULL_RTX,
call_save_p
? "Add pseudo<-save" : "Add pseudo<-split");
- lra_process_new_insns (insn, def_p ? NULL_RTX : save,
- def_p ? save : NULL_RTX,
+ lra_process_new_insns (insn, before_p ? save : NULL_RTX,
+ before_p ? NULL_RTX : save,
call_save_p
? "Add save<-pseudo" : "Add split<-pseudo");
if (lra_dump_file != NULL)
@@ -4311,28 +4332,23 @@ inherit_in_ebb (rtx head, rtx tail)
}
/* We can not process one pseudo twice here
because of usage_insns invalidation. */
- if (reg_renumber[dst_regno] >= 0)
+ if (reg_renumber[dst_regno] >= 0 && ! reg->subreg_p
+ && reg->type == OP_OUT)
{
+ HARD_REG_SET s;
+
if (need_for_split_p (potential_reload_hard_regs,
dst_regno)
- && split_pseudo (true, dst_regno, curr_insn,
+ && split_pseudo (false, dst_regno, curr_insn,
next_usage_insns))
- {
- if (reg->subreg_p)
- lra_risky_transformations_p = true;
- change_p = true;
- }
- if (! reg->subreg_p)
- {
- HARD_REG_SET s;
-
- CLEAR_HARD_REG_SET (s);
- lra_add_hard_reg_set (reg_renumber[dst_regno],
- PSEUDO_REGNO_MODE (dst_regno),
- &s);
- AND_COMPL_HARD_REG_SET (live_hard_regs, s);
- }
+ change_p = true;
+ CLEAR_HARD_REG_SET (s);
+ lra_add_hard_reg_set (reg_renumber[dst_regno],
+ PSEUDO_REGNO_MODE (dst_regno), &s);
+ AND_COMPL_HARD_REG_SET (live_hard_regs, s);
}
+ if (reg_renumber[dst_regno] < 0
+ || (reg->type == OP_OUT && ! reg->subreg_p))
/* Invalidate. */
usage_insns[dst_regno].check = 0;
}
@@ -4357,18 +4373,17 @@ inherit_in_ebb (rtx head, rtx tail)
= usage_insns[src_regno].insns) != NULL_RTX
&& NONDEBUG_INSN_P (curr_insn))
add_to_inherit (src_regno, next_usage_insns);
- /* Add usages. */
else
+ /* Add usages. */
add_next_usage_insn (src_regno, curr_insn, reloads_num);
}
else if (reg_renumber[src_regno] >= 0)
{
- bool ok_p = false;
-
+ rtx use_insn = curr_insn;
+
if (usage_insns[src_regno].check == curr_usage_insns_check
&& (next_usage_insns
= usage_insns[src_regno].insns) != NULL_RTX
- && reg->type == OP_IN
/* To avoid processing the pseudo twice or
more. */
&& ((GET_CODE (next_usage_insns) != INSN_LIST
@@ -4379,19 +4394,23 @@ inherit_in_ebb (rtx head, rtx tail)
&& need_for_split_p (potential_reload_hard_regs,
src_regno)
&& NONDEBUG_INSN_P (curr_insn)
- && split_pseudo (false, src_regno, curr_insn,
+ && split_pseudo (CALL_P (curr_insn) && reg->type == OP_IN,
+ src_regno, curr_insn,
next_usage_insns))
{
if (reg->subreg_p)
lra_risky_transformations_p = true;
- ok_p = change_p = true;
+ change_p = true;
+ /* Invalidate. */
+ usage_insns[src_regno].check = 0;
+ if (CALL_P (curr_insn) && reg->type == OP_IN)
+ use_insn = PREV_INSN (curr_insn);
}
if (NONDEBUG_INSN_P (curr_insn))
lra_add_hard_reg_set (reg_renumber[src_regno],
PSEUDO_REGNO_MODE (src_regno),
&live_hard_regs);
- if (! ok_p)
- add_next_usage_insn (src_regno, curr_insn, reloads_num);
+ add_next_usage_insn (src_regno, use_insn, reloads_num);
}
}
for (i = 0; i < to_inherit_num; i++)
@@ -4442,7 +4461,8 @@ inherit_in_ebb (rtx head, rtx tail)
" ----------------------------------\n");
head_p = false;
}
- if (split_pseudo (false, j, first_insn, next_usage_insns))
+ if (split_pseudo (true, j, first_insn,
+ next_usage_insns))
change_p = true;
}
usage_insns[j].check = 0;
===================================================================
@@ -107,6 +107,12 @@ struct lra_reg
/* True if the pseudo should not be assigned to a stack register. */
bool no_stack_p;
#endif
+#ifdef ENABLE_CHECKING
+ /* True if the pseudo crosses a call. It is setup in lra-lives.c
+ and used to check that the pseudo crossing a call did not get a
+ call used hard register. */
+ bool call_p;
+#endif
/* Number of references and execution frequencies of the register in
*non-debug* insns. */
int nrefs, freq;
===================================================================
@@ -608,6 +608,9 @@ process_bb_lives (basic_block bb)
SET_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs);
IOR_HARD_REG_SET (lra_reg_info[i].conflict_hard_regs,
call_used_reg_set);
+#ifdef ENABLE_CHECKING
+ lra_reg_info[i].call_p = true;
+#endif
}
}
@@ -931,6 +934,9 @@ lra_create_live_ranges (bool all_p)
lra_reg_info[i].biggest_mode = GET_MODE (regno_reg_rtx[i]);
else
lra_reg_info[i].biggest_mode = VOIDmode;
+#ifdef ENABLE_CHECKING
+ lra_reg_info[i].call_p = false;
+#endif
if (i >= FIRST_PSEUDO_REGISTER
&& lra_reg_info[i].nrefs != 0 && (hard_regno = reg_renumber[i]) >= 0)
lra_hard_reg_usage[hard_regno] += lra_reg_info[i].freq;