===================================================================
@@ -935,10 +935,10 @@ setup_live_pseudos_and_spill_after_risky
pseudos to the connected pseudos. We need this because inheritance
pseudos are allocated after reload pseudos in the thread and when
we assign a hard register to a reload pseudo we don't know yet that
- the connected inheritance pseudos can get the same hard
- register. */
+ the connected inheritance pseudos can get the same hard register.
+ Add pseudos with changed allocation to bitmap CHANGED_PSEUDOS. */
static void
-improve_inheritance (void)
+improve_inheritance (bitmap changed_pseudos)
{
unsigned int k;
int regno, another_regno, hard_regno, another_hard_regno, cost, i, n;
@@ -983,6 +983,7 @@ improve_inheritance (void)
assign_hard_regno (hard_regno, another_regno);
else
assign_hard_regno (another_hard_regno, another_regno);
+ bitmap_set_bit (changed_pseudos, another_regno);
}
}
}
@@ -1104,7 +1105,7 @@ assign_by_spills (void)
}
n = nfails;
}
- improve_inheritance ();
+ improve_inheritance (&changed_pseudo_bitmap);
bitmap_clear (&changed_insns);
/* We can not assign to inherited pseudos if any its inheritance
pseudo did not get hard register because undo inheritance pass
===================================================================
@@ -295,7 +295,9 @@ get_reload_reg (enum op_type type, enum
/* The page contains code to extract memory address parts. */
-/* Info about base and index regs of an address. */
+/* Info about base and index regs of an address. In some rare cases,
+ base/index register can be actually memory. In this case we will
+ reload it. */
struct address
{
rtx *base_reg_loc; /* NULL if there is no a base register. */
@@ -519,6 +521,13 @@ extract_loc_address_regs (bool top_p, en
SCRATCH, true, ad);
break;
+ /* We process memory as a register. That means we flatten
+ addresses. In other words, the final code will never
+ contains memory in an address even if the target supports
+ such addresses (it is too rare these days). Memory also can
+ occur in address as a result some previous transformations
+ like equivalence substitution. */
+ case MEM:
case REG:
if (context_p)
ad->index_reg_loc = loc;
@@ -1228,6 +1237,26 @@ process_addr_reg (rtx *loc, rtx *before,
enum machine_mode mode;
bool change_p = false;
+ mode = GET_MODE (reg);
+ if (MEM_P (reg))
+ {
+ /* Always reload memory in an address even if the target
+ supports such addresses. */
+ new_reg = lra_create_new_reg_with_unique_value (mode, reg, cl, "address");
+ push_to_sequence (*before);
+ lra_emit_move (new_reg, reg);
+ *before = get_insns ();
+ end_sequence ();
+ *loc = new_reg;
+ if (after != NULL)
+ {
+ push_to_sequence (*after);
+ lra_emit_move (reg, new_reg);
+ *after = get_insns ();
+ end_sequence ();
+ }
+ return true;
+ }
gcc_assert (REG_P (reg));
final_regno = regno = REGNO (reg);
if (regno < FIRST_PSEUDO_REGISTER)
@@ -1257,7 +1286,6 @@ process_addr_reg (rtx *loc, rtx *before,
}
if (*loc != reg || ! in_class_p (final_regno, cl, &new_class))
{
- mode = GET_MODE (reg);
reg = *loc;
if (get_reload_reg (OP_IN, mode, reg, cl, "address", &new_reg))
{
@@ -1564,7 +1592,7 @@ process_alt_operands (int only_alternati
}
op = no_subreg_operand[nop];
- mode = GET_MODE (*curr_id->operand_loc[nop]);
+ mode = get_op_mode (nop);
win = did_match = winreg = offmemok = constmemok = false;
badop = true;
@@ -2474,8 +2502,8 @@ process_address (int nop, rtx *before, r
{
if (process_addr_reg (ad.base_reg_loc, before,
(ad.base_modify_p
- && find_regno_note (curr_insn, REG_DEAD,
- REGNO (*ad.base_reg_loc)) == NULL
+ && find_reg_note (curr_insn, REG_DEAD,
+ *ad.base_reg_loc) == NULL
? after : NULL),
base_reg_class (mode, as, ad.base_outer_code,
ad.index_code)))
bash-4.1$ svn diff --diff-cmd diff -x -up lra*.[ch]
===================================================================
@@ -935,10 +935,10 @@ setup_live_pseudos_and_spill_after_risky
pseudos to the connected pseudos. We need this because inheritance
pseudos are allocated after reload pseudos in the thread and when
we assign a hard register to a reload pseudo we don't know yet that
- the connected inheritance pseudos can get the same hard
- register. */
+ the connected inheritance pseudos can get the same hard register.
+ Add pseudos with changed allocation to bitmap CHANGED_PSEUDOS. */
static void
-improve_inheritance (void)
+improve_inheritance (bitmap changed_pseudos)
{
unsigned int k;
int regno, another_regno, hard_regno, another_hard_regno, cost, i, n;
@@ -969,7 +969,11 @@ improve_inheritance (void)
}
else
gcc_unreachable ();
- if ((another_hard_regno = reg_renumber[another_regno]) >= 0
+ /* Don't change reload pseudo allocation. It might have
+ this allocation for a purpose (e.g. bound to another
+ pseudo) and changing it can result in LRA cycling. */
+ if (another_regno < lra_constraint_new_regno_start
+ && (another_hard_regno = reg_renumber[another_regno]) >= 0
&& another_hard_regno != hard_regno)
{
if (lra_dump_file != NULL)
@@ -983,6 +987,7 @@ improve_inheritance (void)
assign_hard_regno (hard_regno, another_regno);
else
assign_hard_regno (another_hard_regno, another_regno);
+ bitmap_set_bit (changed_pseudos, another_regno);
}
}
}
@@ -1104,7 +1109,7 @@ assign_by_spills (void)
}
n = nfails;
}
- improve_inheritance ();
+ improve_inheritance (&changed_pseudo_bitmap);
bitmap_clear (&changed_insns);
/* We can not assign to inherited pseudos if any its inheritance
pseudo did not get hard register because undo inheritance pass
===================================================================
@@ -295,7 +295,9 @@ get_reload_reg (enum op_type type, enum
/* The page contains code to extract memory address parts. */
-/* Info about base and index regs of an address. */
+/* Info about base and index regs of an address. In some rare cases,
+ base/index register can be actually memory. In this case we will
+ reload it. */
struct address
{
rtx *base_reg_loc; /* NULL if there is no a base register. */
@@ -519,6 +521,13 @@ extract_loc_address_regs (bool top_p, en
SCRATCH, true, ad);
break;
+ /* We process memory as a register. That means we flatten
+ addresses. In other words, the final code will never
+ contains memory in an address even if the target supports
+ such addresses (it is too rare these days). Memory also can
+ occur in address as a result some previous transformations
+ like equivalence substitution. */
+ case MEM:
case REG:
if (context_p)
ad->index_reg_loc = loc;
@@ -1228,6 +1237,26 @@ process_addr_reg (rtx *loc, rtx *before,
enum machine_mode mode;
bool change_p = false;
+ mode = GET_MODE (reg);
+ if (MEM_P (reg))
+ {
+ /* Always reload memory in an address even if the target
+ supports such addresses. */
+ new_reg = lra_create_new_reg_with_unique_value (mode, reg, cl, "address");
+ push_to_sequence (*before);
+ lra_emit_move (new_reg, reg);
+ *before = get_insns ();
+ end_sequence ();
+ *loc = new_reg;
+ if (after != NULL)
+ {
+ push_to_sequence (*after);
+ lra_emit_move (reg, new_reg);
+ *after = get_insns ();
+ end_sequence ();
+ }
+ return true;
+ }
gcc_assert (REG_P (reg));
final_regno = regno = REGNO (reg);
if (regno < FIRST_PSEUDO_REGISTER)
@@ -1257,7 +1286,6 @@ process_addr_reg (rtx *loc, rtx *before,
}
if (*loc != reg || ! in_class_p (final_regno, cl, &new_class))
{
- mode = GET_MODE (reg);
reg = *loc;
if (get_reload_reg (OP_IN, mode, reg, cl, "address", &new_reg))
{
@@ -1564,7 +1592,7 @@ process_alt_operands (int only_alternati
}
op = no_subreg_operand[nop];
- mode = GET_MODE (*curr_id->operand_loc[nop]);
+ mode = get_op_mode (nop);
win = did_match = winreg = offmemok = constmemok = false;
badop = true;
@@ -2474,8 +2502,8 @@ process_address (int nop, rtx *before, r
{
if (process_addr_reg (ad.base_reg_loc, before,
(ad.base_modify_p
- && find_regno_note (curr_insn, REG_DEAD,
- REGNO (*ad.base_reg_loc)) == NULL
+ && find_reg_note (curr_insn, REG_DEAD,
+ *ad.base_reg_loc) == NULL
? after : NULL),
base_reg_class (mode, as, ad.base_outer_code,
ad.index_code)))