Commit 8a8330b7 by Vladimir Makarov Committed by Vladimir Makarov

re PR rtl-optimization/69847 (Spec 2006 403.gcc slows down with -mlra vs. reload on PowerPC)

2016-08-02  Vladimir Makarov  <vmakarov@redhat.com>

	PR rtl-optimization/69847
	* lra-int.h (struct lra-reg): Use restore_rtx instead of
	restore_regno.
	(lra_rtx_hash): New.
	* lra.c (initialize_lra_reg_info_element): Use restore_rtx instead
	of restore_regno.
	(lra_rtx_hash): Rename and move lra-remat.c::rtx_hash.
	* lra-remat.c (rtx_hash): Rename and Move to lra.c.
	* lra-spills.c (lra_final_code_change): Don't delete insn when the
	next insn is USE with the same reg as the current insn source.
	* lra-constraints.c (curr_insn_transform): Use restore_rtx instead
	of restore_regno.
	(lra_constraints_init): Call initiate_invariants.
	(lra_constraints_finish): Call finish_invariants.
	(struct invariant, invariant_t, invariant_ptr_t): New.
	(const_invariant_ptr_t, invariants, invariants_pool): New.
	(invariant_table, invariant_hash, invariant_eq_p): New.
	(insert_invariant, initiate_invariants, finish_invariants): New.
	(clear_invariants, invalid_invariant_regs): New.
	(inherit_reload_reg, split_reg, fix_bb_live_info): Use restore_rtx
	instead of restore_regno.
	(invariant_p, process_invariant_for_inheritance): New.
	(inherit_in_ebb): Implement invariant inheritance.
	(lra_inheritance): Initialize and finalize invalid_invariant_regs.
	(remove_inheritance_pseudos): Implement undoing invariant
	inheritance.
	(undo_optional_reloads, lra_undo_inheritance): Use restore_rtx
	instead of restore_regno.
	* lra-assigns.c (regno_live_length): New.
	(reload_pseudo_compare_func): Use regno_live_length.
	(assign_by_spills): Use restore_rtx instead of restore_regno.
	(lra_assign): Ditto.  Initiate regno_live_length.

From-SVN: r238991
parent 354c5470
2016-08-02 Vladimir Makarov <vmakarov@redhat.com>
PR rtl-optimization/69847
* lra-int.h (struct lra-reg): Use restore_rtx instead of
restore_regno.
(lra_rtx_hash): New.
* lra.c (initialize_lra_reg_info_element): Use restore_rtx instead
of restore_regno.
(lra_rtx_hash): Rename and move lra-remat.c::rtx_hash.
* lra-remat.c (rtx_hash): Rename and Move to lra.c.
* lra-spills.c (lra_final_code_change): Don't delete insn when the
next insn is USE with the same reg as the current insn source.
* lra-constraints.c (curr_insn_transform): Use restore_rtx instead
of restore_regno.
(lra_constraints_init): Call initiate_invariants.
(lra_constraints_finish): Call finish_invariants.
(struct invariant, invariant_t, invariant_ptr_t): New.
(const_invariant_ptr_t, invariants, invariants_pool): New.
(invariant_table, invariant_hash, invariant_eq_p): New.
(insert_invariant, initiate_invariants, finish_invariants): New.
(clear_invariants, invalid_invariant_regs): New.
(inherit_reload_reg, split_reg, fix_bb_live_info): Use restore_rtx
instead of restore_regno.
(invariant_p, process_invariant_for_inheritance): New.
(inherit_in_ebb): Implement invariant inheritance.
(lra_inheritance): Initialize and finalize invalid_invariant_regs.
(remove_inheritance_pseudos): Implement undoing invariant
inheritance.
(undo_optional_reloads, lra_undo_inheritance): Use restore_rtx
instead of restore_regno.
* lra-assigns.c (regno_live_length): New.
(reload_pseudo_compare_func): Use regno_live_length.
(assign_by_spills): Use restore_rtx instead of restore_regno.
(lra_assign): Ditto. Initiate regno_live_length.
2016-02-08 James Greenhalgh <james.greenhalgh@arm.com> 2016-02-08 James Greenhalgh <james.greenhalgh@arm.com>
* config/aarch64/arm_neon.h (vminnm_f64): Add back missing 'f' from * config/aarch64/arm_neon.h (vminnm_f64): Add back missing 'f' from
......
...@@ -107,6 +107,10 @@ static bool former_reload_pseudo_spill_p; ...@@ -107,6 +107,10 @@ static bool former_reload_pseudo_spill_p;
lra_get_allocno_class. It is used to speed up the code. */ lra_get_allocno_class. It is used to speed up the code. */
static enum reg_class *regno_allocno_class_array; static enum reg_class *regno_allocno_class_array;
/* Array containing lengths of pseudo live ranges. It is used to
speed up the code. */
static int *regno_live_length;
/* Information about the thread to which a pseudo belongs. Threads are /* Information about the thread to which a pseudo belongs. Threads are
a set of connected reload and inheritance pseudos with the same set of a set of connected reload and inheritance pseudos with the same set of
available hard registers. Lone registers belong to their own threads. */ available hard registers. Lone registers belong to their own threads. */
...@@ -227,6 +231,11 @@ reload_pseudo_compare_func (const void *v1p, const void *v2p) ...@@ -227,6 +231,11 @@ reload_pseudo_compare_func (const void *v1p, const void *v2p)
/* Put pseudos from the thread nearby. */ /* Put pseudos from the thread nearby. */
if ((diff = regno_assign_info[r1].first - regno_assign_info[r2].first) != 0) if ((diff = regno_assign_info[r1].first - regno_assign_info[r2].first) != 0)
return diff; return diff;
/* Prefer pseudos with longer live ranges. It sets up better
prefered hard registers for the thread pseudos and decreases
register-register moves between the thread pseudos. */
if ((diff = regno_live_length[r2] - regno_live_length[r1]) != 0)
return diff;
/* If regs are equally good, sort by their numbers, so that the /* If regs are equally good, sort by their numbers, so that the
results of qsort leave nothing to chance. */ results of qsort leave nothing to chance. */
return r1 - r2; return r1 - r2;
...@@ -1300,7 +1309,8 @@ find_all_spills_for (int regno) ...@@ -1300,7 +1309,8 @@ find_all_spills_for (int regno)
static void static void
assign_by_spills (void) assign_by_spills (void)
{ {
int i, n, nfails, iter, regno, hard_regno, cost, restore_regno; int i, n, nfails, iter, regno, hard_regno, cost;
rtx restore_rtx;
rtx_insn *insn; rtx_insn *insn;
bitmap_head changed_insns, do_not_assign_nonreload_pseudos; bitmap_head changed_insns, do_not_assign_nonreload_pseudos;
unsigned int u, conflict_regno; unsigned int u, conflict_regno;
...@@ -1333,6 +1343,8 @@ assign_by_spills (void) ...@@ -1333,6 +1343,8 @@ assign_by_spills (void)
for (i = 0; i < n; i++) for (i = 0; i < n; i++)
{ {
regno = sorted_pseudos[i]; regno = sorted_pseudos[i];
if (reg_renumber[regno] >= 0)
continue;
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
fprintf (lra_dump_file, " Assigning to %d " fprintf (lra_dump_file, " Assigning to %d "
"(cl=%s, orig=%d, freq=%d, tfirst=%d, tfreq=%d)...\n", "(cl=%s, orig=%d, freq=%d, tfirst=%d, tfreq=%d)...\n",
...@@ -1471,21 +1483,25 @@ assign_by_spills (void) ...@@ -1471,21 +1483,25 @@ assign_by_spills (void)
such inheritance or split pseudos. */ such inheritance or split pseudos. */
bitmap_initialize (&do_not_assign_nonreload_pseudos, &reg_obstack); bitmap_initialize (&do_not_assign_nonreload_pseudos, &reg_obstack);
EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, u, bi) EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, u, bi)
if ((restore_regno = lra_reg_info[u].restore_regno) >= 0 if ((restore_rtx = lra_reg_info[u].restore_rtx) != NULL_RTX
&& REG_P (restore_rtx)
&& reg_renumber[u] < 0 && reg_renumber[u] < 0
&& bitmap_bit_p (&lra_inheritance_pseudos, u)) && bitmap_bit_p (&lra_inheritance_pseudos, u))
bitmap_set_bit (&do_not_assign_nonreload_pseudos, restore_regno); bitmap_set_bit (&do_not_assign_nonreload_pseudos, REGNO (restore_rtx));
EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, u, bi) EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, u, bi)
if ((restore_regno = lra_reg_info[u].restore_regno) >= 0 if ((restore_rtx = lra_reg_info[u].restore_rtx) != NULL_RTX
&& reg_renumber[u] >= 0) && reg_renumber[u] >= 0)
bitmap_set_bit (&do_not_assign_nonreload_pseudos, restore_regno); {
lra_assert (REG_P (restore_rtx));
bitmap_set_bit (&do_not_assign_nonreload_pseudos, REGNO (restore_rtx));
}
for (n = 0, i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) for (n = 0, i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
if (((i < lra_constraint_new_regno_start if (((i < lra_constraint_new_regno_start
&& ! bitmap_bit_p (&do_not_assign_nonreload_pseudos, i)) && ! bitmap_bit_p (&do_not_assign_nonreload_pseudos, i))
|| (bitmap_bit_p (&lra_inheritance_pseudos, i) || (bitmap_bit_p (&lra_inheritance_pseudos, i)
&& lra_reg_info[i].restore_regno >= 0) && lra_reg_info[i].restore_rtx != NULL_RTX)
|| (bitmap_bit_p (&lra_split_regs, i) || (bitmap_bit_p (&lra_split_regs, i)
&& lra_reg_info[i].restore_regno >= 0) && lra_reg_info[i].restore_rtx != NULL_RTX)
|| bitmap_bit_p (&lra_subreg_reload_pseudos, i) || bitmap_bit_p (&lra_subreg_reload_pseudos, i)
|| bitmap_bit_p (&lra_optional_reload_pseudos, i)) || bitmap_bit_p (&lra_optional_reload_pseudos, i))
&& reg_renumber[i] < 0 && lra_reg_info[i].nrefs != 0 && reg_renumber[i] < 0 && lra_reg_info[i].nrefs != 0
...@@ -1513,7 +1529,7 @@ assign_by_spills (void) ...@@ -1513,7 +1529,7 @@ assign_by_spills (void)
enum reg_class spill_class; enum reg_class spill_class;
if (targetm.spill_class == NULL if (targetm.spill_class == NULL
|| lra_reg_info[regno].restore_regno < 0 || lra_reg_info[regno].restore_rtx == NULL_RTX
|| ! bitmap_bit_p (&lra_inheritance_pseudos, regno) || ! bitmap_bit_p (&lra_inheritance_pseudos, regno)
|| (spill_class || (spill_class
= ((enum reg_class) = ((enum reg_class)
...@@ -1570,8 +1586,17 @@ lra_assign (void) ...@@ -1570,8 +1586,17 @@ lra_assign (void)
sorted_pseudos = XNEWVEC (int, max_regno); sorted_pseudos = XNEWVEC (int, max_regno);
sorted_reload_pseudos = XNEWVEC (int, max_regno); sorted_reload_pseudos = XNEWVEC (int, max_regno);
regno_allocno_class_array = XNEWVEC (enum reg_class, max_regno); regno_allocno_class_array = XNEWVEC (enum reg_class, max_regno);
regno_live_length = XNEWVEC (int, max_regno);
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
regno_allocno_class_array[i] = lra_get_allocno_class (i); {
int l;
lra_live_range_t r;
regno_allocno_class_array[i] = lra_get_allocno_class (i);
for (l = 0, r = lra_reg_info[i].live_ranges; r != NULL; r = r->next)
l += r->finish - r->start + 1;
regno_live_length[i] = l;
}
former_reload_pseudo_spill_p = false; former_reload_pseudo_spill_p = false;
init_regno_assign_info (); init_regno_assign_info ();
bitmap_initialize (&all_spilled_pseudos, &reg_obstack); bitmap_initialize (&all_spilled_pseudos, &reg_obstack);
...@@ -1594,7 +1619,7 @@ lra_assign (void) ...@@ -1594,7 +1619,7 @@ lra_assign (void)
EXECUTE_IF_SET_IN_BITMAP (&all_spilled_pseudos, 0, u, bi) EXECUTE_IF_SET_IN_BITMAP (&all_spilled_pseudos, 0, u, bi)
/* We ignore spilled pseudos created on last inheritance pass /* We ignore spilled pseudos created on last inheritance pass
because they will be removed. */ because they will be removed. */
if (lra_reg_info[u].restore_regno < 0) if (lra_reg_info[u].restore_rtx == NULL_RTX)
{ {
no_spills_p = false; no_spills_p = false;
break; break;
...@@ -1613,6 +1638,7 @@ lra_assign (void) ...@@ -1613,6 +1638,7 @@ lra_assign (void)
} }
bitmap_clear (&insns_to_process); bitmap_clear (&insns_to_process);
finish_regno_assign_info (); finish_regno_assign_info ();
free (regno_live_length);
free (regno_allocno_class_array); free (regno_allocno_class_array);
free (sorted_pseudos); free (sorted_pseudos);
free (sorted_reload_pseudos); free (sorted_reload_pseudos);
...@@ -1631,3 +1657,4 @@ lra_assign (void) ...@@ -1631,3 +1657,4 @@ lra_assign (void)
LRA_MAX_ASSIGNMENT_ITERATION_NUMBER); LRA_MAX_ASSIGNMENT_ITERATION_NUMBER);
return no_spills_p; return no_spills_p;
} }
...@@ -4105,14 +4105,16 @@ curr_insn_transform (bool check_only_p) ...@@ -4105,14 +4105,16 @@ curr_insn_transform (bool check_only_p)
if (optional_p) if (optional_p)
{ {
lra_assert (REG_P (op)); rtx reg = op;
regno = REGNO (op);
lra_assert (REG_P (reg));
regno = REGNO (reg);
op = *curr_id->operand_loc[i]; /* Substitution. */ op = *curr_id->operand_loc[i]; /* Substitution. */
if (GET_CODE (op) == SUBREG) if (GET_CODE (op) == SUBREG)
op = SUBREG_REG (op); op = SUBREG_REG (op);
gcc_assert (REG_P (op) && (int) REGNO (op) >= new_regno_start); gcc_assert (REG_P (op) && (int) REGNO (op) >= new_regno_start);
bitmap_set_bit (&lra_optional_reload_pseudos, REGNO (op)); bitmap_set_bit (&lra_optional_reload_pseudos, REGNO (op));
lra_reg_info[REGNO (op)].restore_regno = regno; lra_reg_info[REGNO (op)].restore_rtx = reg;
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
fprintf (lra_dump_file, fprintf (lra_dump_file,
" Making reload reg %d for reg %d optional\n", " Making reload reg %d for reg %d optional\n",
...@@ -4646,11 +4648,15 @@ lra_constraints (bool first_p) ...@@ -4646,11 +4648,15 @@ lra_constraints (bool first_p)
return changed_p; return changed_p;
} }
static void initiate_invariants (void);
static void finish_invariants (void);
/* Initiate the LRA constraint pass. It is done once per /* Initiate the LRA constraint pass. It is done once per
function. */ function. */
void void
lra_constraints_init (void) lra_constraints_init (void)
{ {
initiate_invariants ();
} }
/* Finalize the LRA constraint pass. It is done once per /* Finalize the LRA constraint pass. It is done once per
...@@ -4658,6 +4664,100 @@ lra_constraints_init (void) ...@@ -4658,6 +4664,100 @@ lra_constraints_init (void)
void void
lra_constraints_finish (void) lra_constraints_finish (void)
{ {
finish_invariants ();
}
/* Structure describes invariants for ineheritance. */
struct invariant
{
/* The order number of the invariant. */
int num;
/* The invariant RTX. */
rtx invariant_rtx;
/* The origin insn of the invariant. */
rtx_insn *insn;
};
typedef struct invariant invariant_t;
typedef invariant_t *invariant_ptr_t;
typedef const invariant_t *const_invariant_ptr_t;
/* Pointer to the inheritance invariants. */
static vec<invariant_ptr_t> invariants;
/* Allocation pool for the invariants. */
static object_allocator<struct invariant> *invariants_pool;
/* Hash table for the invariants. */
static htab_t invariant_table;
/* Hash function for INVARIANT. */
static hashval_t
invariant_hash (const void *invariant)
{
rtx inv = ((const_invariant_ptr_t) invariant)->invariant_rtx;
return lra_rtx_hash (inv);
}
/* Equal function for invariants INVARIANT1 and INVARIANT2. */
static int
invariant_eq_p (const void *invariant1, const void *invariant2)
{
rtx inv1 = ((const_invariant_ptr_t) invariant1)->invariant_rtx;
rtx inv2 = ((const_invariant_ptr_t) invariant2)->invariant_rtx;
return rtx_equal_p (inv1, inv2);
}
/* Insert INVARIANT_RTX into the table if it is not there yet. Return
invariant which is in the table. */
static invariant_ptr_t
insert_invariant (rtx invariant_rtx)
{
void **entry_ptr;
invariant_t invariant;
invariant_ptr_t invariant_ptr;
invariant.invariant_rtx = invariant_rtx;
entry_ptr = htab_find_slot (invariant_table, &invariant, INSERT);
if (*entry_ptr == NULL)
{
invariant_ptr = invariants_pool->allocate ();
invariant_ptr->invariant_rtx = invariant_rtx;
invariant_ptr->insn = NULL;
invariants.safe_push (invariant_ptr);
*entry_ptr = (void *) invariant_ptr;
}
return (invariant_ptr_t) *entry_ptr;
}
/* Initiate the invariant table. */
static void
initiate_invariants (void)
{
invariants.create (100);
invariants_pool = new object_allocator<struct invariant> ("Inheritance invariants");
invariant_table = htab_create (100, invariant_hash, invariant_eq_p, NULL);
}
/* Finish the invariant table. */
static void
finish_invariants (void)
{
htab_delete (invariant_table);
delete invariants_pool;
invariants.release ();
}
/* Make the invariant table empty. */
static void
clear_invariants (void)
{
htab_empty (invariant_table);
invariants_pool->release ();
invariants.truncate (0);
} }
...@@ -4789,6 +4889,10 @@ check_secondary_memory_needed_p (enum reg_class inher_cl ATTRIBUTE_UNUSED, ...@@ -4789,6 +4889,10 @@ check_secondary_memory_needed_p (enum reg_class inher_cl ATTRIBUTE_UNUSED,
(inheritance/split pseudos and original registers). */ (inheritance/split pseudos and original registers). */
static bitmap_head check_only_regs; static bitmap_head check_only_regs;
/* Reload pseudos can not be involded in invariant inheritance in the
current EBB. */
static bitmap_head invalid_invariant_regs;
/* Do inheritance transformations for insn INSN, which defines (if /* Do inheritance transformations for insn INSN, which defines (if
DEF_P) or uses ORIGINAL_REGNO. NEXT_USAGE_INSNS specifies which DEF_P) or uses ORIGINAL_REGNO. NEXT_USAGE_INSNS specifies which
instruction in the EBB next uses ORIGINAL_REGNO; it has the same instruction in the EBB next uses ORIGINAL_REGNO; it has the same
...@@ -4910,7 +5014,7 @@ inherit_reload_reg (bool def_p, int original_regno, ...@@ -4910,7 +5014,7 @@ inherit_reload_reg (bool def_p, int original_regno,
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
fprintf (lra_dump_file, " Original reg change %d->%d (bb%d):\n", fprintf (lra_dump_file, " Original reg change %d->%d (bb%d):\n",
original_regno, REGNO (new_reg), BLOCK_FOR_INSN (insn)->index); original_regno, REGNO (new_reg), BLOCK_FOR_INSN (insn)->index);
lra_reg_info[REGNO (new_reg)].restore_regno = original_regno; lra_reg_info[REGNO (new_reg)].restore_rtx = regno_reg_rtx[original_regno];
bitmap_set_bit (&check_only_regs, REGNO (new_reg)); bitmap_set_bit (&check_only_regs, REGNO (new_reg));
bitmap_set_bit (&check_only_regs, original_regno); bitmap_set_bit (&check_only_regs, original_regno);
bitmap_set_bit (&lra_inheritance_pseudos, REGNO (new_reg)); bitmap_set_bit (&lra_inheritance_pseudos, REGNO (new_reg));
...@@ -5194,7 +5298,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn, ...@@ -5194,7 +5298,7 @@ split_reg (bool before_p, int original_regno, rtx_insn *insn,
return false; return false;
} }
after_p = usage_insns[original_regno].after_p; after_p = usage_insns[original_regno].after_p;
lra_reg_info[REGNO (new_reg)].restore_regno = original_regno; lra_reg_info[REGNO (new_reg)].restore_rtx = regno_reg_rtx[original_regno];
bitmap_set_bit (&check_only_regs, REGNO (new_reg)); bitmap_set_bit (&check_only_regs, REGNO (new_reg));
bitmap_set_bit (&check_only_regs, original_regno); bitmap_set_bit (&check_only_regs, original_regno);
bitmap_set_bit (&lra_split_regs, REGNO (new_reg)); bitmap_set_bit (&lra_split_regs, REGNO (new_reg));
...@@ -5273,6 +5377,134 @@ split_if_necessary (int regno, machine_mode mode, ...@@ -5273,6 +5377,134 @@ split_if_necessary (int regno, machine_mode mode,
return res; return res;
} }
/* Return TRUE if rtx X is considered as an invariant for
inheritance. */
static bool
invariant_p (const_rtx x)
{
machine_mode mode;
const char *fmt;
enum rtx_code code;
int i, j;
code = GET_CODE (x);
mode = GET_MODE (x);
if (code == SUBREG)
{
x = SUBREG_REG (x);
code = GET_CODE (x);
if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (mode))
mode = GET_MODE (x);
}
if (MEM_P (x))
return false;
if (REG_P (x))
{
int i, nregs, regno = REGNO (x);
if (regno >= FIRST_PSEUDO_REGISTER || regno == STACK_POINTER_REGNUM
|| TEST_HARD_REG_BIT (eliminable_regset, regno)
|| GET_MODE_CLASS (GET_MODE (x)) == MODE_CC)
return false;
nregs = hard_regno_nregs[regno][mode];
for (i = 0; i < nregs; i++)
if (! fixed_regs[regno + i]
/* A hard register may be clobbered in the current insn
but we can ignore this case because if the hard
register is used it should be set somewhere after the
clobber. */
|| bitmap_bit_p (&invalid_invariant_regs, regno + i))
return false;
}
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
if (fmt[i] == 'e')
{
if (! invariant_p (XEXP (x, i)))
return false;
}
else if (fmt[i] == 'E')
{
for (j = XVECLEN (x, i) - 1; j >= 0; j--)
if (! invariant_p (XVECEXP (x, i, j)))
return false;
}
}
return true;
}
/* We have 'dest_reg <- invariant'. Let us try to make an invariant
inheritance transformation (using dest_reg instead invariant in a
subsequent insn). */
static bool
process_invariant_for_inheritance (rtx dst_reg, rtx invariant_rtx)
{
invariant_ptr_t invariant_ptr;
rtx_insn *insn, *new_insns;
rtx insn_set, insn_reg, new_reg;
int insn_regno;
bool succ_p = false;
int dst_regno = REGNO (dst_reg);
enum machine_mode dst_mode = GET_MODE (dst_reg);
enum reg_class cl = lra_get_allocno_class (dst_regno), insn_reg_cl;
invariant_ptr = insert_invariant (invariant_rtx);
if ((insn = invariant_ptr->insn) != NULL_RTX)
{
/* We have a subsequent insn using the invariant. */
insn_set = single_set (insn);
lra_assert (insn_set != NULL);
insn_reg = SET_DEST (insn_set);
lra_assert (REG_P (insn_reg));
insn_regno = REGNO (insn_reg);
insn_reg_cl = lra_get_allocno_class (insn_regno);
if (dst_mode == GET_MODE (insn_reg)
/* We should consider only result move reg insns which are
cheap. */
&& targetm.register_move_cost (dst_mode, cl, insn_reg_cl) == 2
&& targetm.register_move_cost (dst_mode, cl, cl) == 2)
{
if (lra_dump_file != NULL)
fprintf (lra_dump_file,
" [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[\n");
new_reg = lra_create_new_reg (dst_mode, dst_reg,
cl, "invariant inheritance");
bitmap_set_bit (&lra_inheritance_pseudos, REGNO (new_reg));
bitmap_set_bit (&check_only_regs, REGNO (new_reg));
lra_reg_info[REGNO (new_reg)].restore_rtx = invariant_rtx;
start_sequence ();
lra_emit_move (new_reg, dst_reg);
new_insns = get_insns ();
end_sequence ();
lra_process_new_insns (curr_insn, NULL, new_insns,
"Add invariant inheritance<-original");
start_sequence ();
lra_emit_move (SET_DEST (insn_set), new_reg);
new_insns = get_insns ();
end_sequence ();
lra_process_new_insns (insn, NULL, new_insns,
"Changing reload<-inheritance");
lra_set_insn_deleted (insn);
succ_p = true;
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file,
" Invariant inheritance reuse change %d (bb%d):\n",
REGNO (new_reg), BLOCK_FOR_INSN (insn)->index);
dump_insn_slim (lra_dump_file, insn);
fprintf (lra_dump_file,
" ]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]\n");
}
}
}
invariant_ptr->insn = curr_insn;
return succ_p;
}
/* Check only registers living at the current program point in the /* Check only registers living at the current program point in the
current EBB. */ current EBB. */
static bitmap_head live_regs; static bitmap_head live_regs;
...@@ -5495,7 +5727,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail) ...@@ -5495,7 +5727,7 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
int i, src_regno, dst_regno, nregs; int i, src_regno, dst_regno, nregs;
bool change_p, succ_p, update_reloads_num_p; bool change_p, succ_p, update_reloads_num_p;
rtx_insn *prev_insn, *last_insn; rtx_insn *prev_insn, *last_insn;
rtx next_usage_insns, set; rtx next_usage_insns, curr_set;
enum reg_class cl; enum reg_class cl;
struct lra_insn_reg *reg; struct lra_insn_reg *reg;
basic_block last_processed_bb, curr_bb = NULL; basic_block last_processed_bb, curr_bb = NULL;
...@@ -5507,8 +5739,10 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail) ...@@ -5507,8 +5739,10 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
change_p = false; change_p = false;
curr_usage_insns_check++; curr_usage_insns_check++;
clear_invariants ();
reloads_num = calls_num = 0; reloads_num = calls_num = 0;
bitmap_clear (&check_only_regs); bitmap_clear (&check_only_regs);
bitmap_clear (&invalid_invariant_regs);
last_processed_bb = NULL; last_processed_bb = NULL;
CLEAR_HARD_REG_SET (potential_reload_hard_regs); CLEAR_HARD_REG_SET (potential_reload_hard_regs);
COPY_HARD_REG_SET (live_hard_regs, eliminable_regset); COPY_HARD_REG_SET (live_hard_regs, eliminable_regset);
...@@ -5556,13 +5790,11 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail) ...@@ -5556,13 +5790,11 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
} }
} }
src_regno = dst_regno = -1; src_regno = dst_regno = -1;
if (NONDEBUG_INSN_P (curr_insn) curr_set = single_set (curr_insn);
&& (set = single_set (curr_insn)) != NULL_RTX if (curr_set != NULL_RTX && REG_P (SET_DEST (curr_set)))
&& REG_P (SET_DEST (set)) && REG_P (SET_SRC (set))) dst_regno = REGNO (SET_DEST (curr_set));
{ if (curr_set != NULL_RTX && REG_P (SET_SRC (curr_set)))
src_regno = REGNO (SET_SRC (set)); src_regno = REGNO (SET_SRC (curr_set));
dst_regno = REGNO (SET_DEST (set));
}
update_reloads_num_p = true; update_reloads_num_p = true;
if (src_regno < lra_constraint_new_regno_start if (src_regno < lra_constraint_new_regno_start
&& src_regno >= FIRST_PSEUDO_REGISTER && src_regno >= FIRST_PSEUDO_REGISTER
...@@ -5587,6 +5819,22 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail) ...@@ -5587,6 +5819,22 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
IOR_HARD_REG_SET (potential_reload_hard_regs, IOR_HARD_REG_SET (potential_reload_hard_regs,
reg_class_contents[cl]); reg_class_contents[cl]);
} }
else if (src_regno < 0
&& dst_regno >= lra_constraint_new_regno_start
&& invariant_p (SET_SRC (curr_set))
&& (cl = lra_get_allocno_class (dst_regno)) != NO_REGS
&& ! bitmap_bit_p (&invalid_invariant_regs, dst_regno))
{
/* 'reload_pseudo <- invariant'. */
if (ira_class_hard_regs_num[cl] <= max_small_class_regs_num)
reloads_num++;
update_reloads_num_p = false;
if (process_invariant_for_inheritance (SET_DEST (curr_set), SET_SRC (curr_set)))
change_p = true;
if (hard_reg_set_subset_p (reg_class_contents[cl], live_hard_regs))
IOR_HARD_REG_SET (potential_reload_hard_regs,
reg_class_contents[cl]);
}
else if (src_regno >= lra_constraint_new_regno_start else if (src_regno >= lra_constraint_new_regno_start
&& dst_regno < lra_constraint_new_regno_start && dst_regno < lra_constraint_new_regno_start
&& dst_regno >= FIRST_PSEUDO_REGISTER && dst_regno >= FIRST_PSEUDO_REGISTER
...@@ -5819,16 +6067,15 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail) ...@@ -5819,16 +6067,15 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
} }
} }
if (update_reloads_num_p if (update_reloads_num_p
&& NONDEBUG_INSN_P (curr_insn) && NONDEBUG_INSN_P (curr_insn) && curr_set != NULL_RTX)
&& (set = single_set (curr_insn)) != NULL_RTX)
{ {
int regno = -1; int regno = -1;
if ((REG_P (SET_DEST (set)) if ((REG_P (SET_DEST (curr_set))
&& (regno = REGNO (SET_DEST (set))) >= lra_constraint_new_regno_start && (regno = REGNO (SET_DEST (curr_set))) >= lra_constraint_new_regno_start
&& reg_renumber[regno] < 0 && reg_renumber[regno] < 0
&& (cl = lra_get_allocno_class (regno)) != NO_REGS) && (cl = lra_get_allocno_class (regno)) != NO_REGS)
|| (REG_P (SET_SRC (set)) || (REG_P (SET_SRC (curr_set))
&& (regno = REGNO (SET_SRC (set))) >= lra_constraint_new_regno_start && (regno = REGNO (SET_SRC (curr_set))) >= lra_constraint_new_regno_start
&& reg_renumber[regno] < 0 && reg_renumber[regno] < 0
&& (cl = lra_get_allocno_class (regno)) != NO_REGS)) && (cl = lra_get_allocno_class (regno)) != NO_REGS))
{ {
...@@ -5839,6 +6086,25 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail) ...@@ -5839,6 +6086,25 @@ inherit_in_ebb (rtx_insn *head, rtx_insn *tail)
reg_class_contents[cl]); reg_class_contents[cl]);
} }
} }
if (NONDEBUG_INSN_P (curr_insn))
{
int regno;
/* Invalidate invariants with changed regs. */
curr_id = lra_get_insn_recog_data (curr_insn);
for (reg = curr_id->regs; reg != NULL; reg = reg->next)
if (reg->type != OP_IN)
bitmap_set_bit (&invalid_invariant_regs, reg->regno);
curr_static_id = curr_id->insn_static_data;
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
if (reg->type != OP_IN)
bitmap_set_bit (&invalid_invariant_regs, reg->regno);
if (curr_id->arg_hard_regs != NULL)
for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++)
bitmap_set_bit (&invalid_invariant_regs,
regno >= FIRST_PSEUDO_REGISTER
? regno : regno - FIRST_PSEUDO_REGISTER);
}
/* We reached the start of the current basic block. */ /* We reached the start of the current basic block. */
if (prev_insn == NULL_RTX || prev_insn == PREV_INSN (head) if (prev_insn == NULL_RTX || prev_insn == PREV_INSN (head)
|| BLOCK_FOR_INSN (prev_insn) != curr_bb) || BLOCK_FOR_INSN (prev_insn) != curr_bb)
...@@ -5911,6 +6177,7 @@ lra_inheritance (void) ...@@ -5911,6 +6177,7 @@ lra_inheritance (void)
for (i = 0; i < lra_constraint_new_regno_start; i++) for (i = 0; i < lra_constraint_new_regno_start; i++)
usage_insns[i].check = 0; usage_insns[i].check = 0;
bitmap_initialize (&check_only_regs, &reg_obstack); bitmap_initialize (&check_only_regs, &reg_obstack);
bitmap_initialize (&invalid_invariant_regs, &reg_obstack);
bitmap_initialize (&live_regs, &reg_obstack); bitmap_initialize (&live_regs, &reg_obstack);
bitmap_initialize (&temp_bitmap, &reg_obstack); bitmap_initialize (&temp_bitmap, &reg_obstack);
bitmap_initialize (&ebb_global_regs, &reg_obstack); bitmap_initialize (&ebb_global_regs, &reg_obstack);
...@@ -5947,6 +6214,7 @@ lra_inheritance (void) ...@@ -5947,6 +6214,7 @@ lra_inheritance (void)
bitmap_clear (&ebb_global_regs); bitmap_clear (&ebb_global_regs);
bitmap_clear (&temp_bitmap); bitmap_clear (&temp_bitmap);
bitmap_clear (&live_regs); bitmap_clear (&live_regs);
bitmap_clear (&invalid_invariant_regs);
bitmap_clear (&check_only_regs); bitmap_clear (&check_only_regs);
free (usage_insns); free (usage_insns);
...@@ -5970,8 +6238,9 @@ fix_bb_live_info (bitmap live, bitmap removed_pseudos) ...@@ -5970,8 +6238,9 @@ fix_bb_live_info (bitmap live, bitmap removed_pseudos)
bitmap_iterator bi; bitmap_iterator bi;
EXECUTE_IF_SET_IN_BITMAP (removed_pseudos, 0, regno, bi) EXECUTE_IF_SET_IN_BITMAP (removed_pseudos, 0, regno, bi)
if (bitmap_clear_bit (live, regno)) if (bitmap_clear_bit (live, regno)
bitmap_set_bit (live, lra_reg_info[regno].restore_regno); && REG_P (lra_reg_info[regno].restore_rtx))
bitmap_set_bit (live, REGNO (lra_reg_info[regno].restore_rtx));
} }
/* Return regno of the (subreg of) REG. Otherwise, return a negative /* Return regno of the (subreg of) REG. Otherwise, return a negative
...@@ -6024,7 +6293,8 @@ static bool ...@@ -6024,7 +6293,8 @@ static bool
remove_inheritance_pseudos (bitmap remove_pseudos) remove_inheritance_pseudos (bitmap remove_pseudos)
{ {
basic_block bb; basic_block bb;
int regno, sregno, prev_sregno, dregno, restore_regno; int regno, sregno, prev_sregno, dregno;
rtx restore_rtx;
rtx set, prev_set; rtx set, prev_set;
rtx_insn *prev_insn; rtx_insn *prev_insn;
bool change_p, done_p; bool change_p, done_p;
...@@ -6053,13 +6323,42 @@ remove_inheritance_pseudos (bitmap remove_pseudos) ...@@ -6053,13 +6323,42 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
if (sregno >= 0 && dregno >= 0) if (sregno >= 0 && dregno >= 0)
{ {
if ((bitmap_bit_p (remove_pseudos, sregno) if (bitmap_bit_p (remove_pseudos, dregno)
&& (lra_reg_info[sregno].restore_regno == dregno && ! REG_P (lra_reg_info[dregno].restore_rtx))
{
/* invariant inheritance pseudo <- original pseudo */
if (lra_dump_file != NULL)
{
fprintf (lra_dump_file, " Removing invariant inheritance:\n");
dump_insn_slim (lra_dump_file, curr_insn);
fprintf (lra_dump_file, "\n");
}
delete_move_and_clobber (curr_insn, dregno);
done_p = true;
}
else if (bitmap_bit_p (remove_pseudos, sregno)
&& ! REG_P (lra_reg_info[sregno].restore_rtx))
{
/* reload pseudo <- invariant inheritance pseudo */
start_sequence ();
/* We can not just change the source. It might be
an insn different from the move. */
lra_emit_move (SET_DEST (set), lra_reg_info[sregno].restore_rtx);
rtx_insn *new_insns = get_insns ();
end_sequence ();
lra_process_new_insns (curr_insn, NULL, new_insns,
"Changing reload<-invariant inheritance");
delete_move_and_clobber (curr_insn, dregno);
done_p = true;
}
else if ((bitmap_bit_p (remove_pseudos, sregno)
&& (get_regno (lra_reg_info[sregno].restore_rtx) == dregno
|| (bitmap_bit_p (remove_pseudos, dregno)
&& get_regno (lra_reg_info[sregno].restore_rtx) >= 0
&& (get_regno (lra_reg_info[sregno].restore_rtx)
== get_regno (lra_reg_info[dregno].restore_rtx)))))
|| (bitmap_bit_p (remove_pseudos, dregno) || (bitmap_bit_p (remove_pseudos, dregno)
&& (lra_reg_info[sregno].restore_regno && get_regno (lra_reg_info[dregno].restore_rtx) == sregno))
== lra_reg_info[dregno].restore_regno))))
|| (bitmap_bit_p (remove_pseudos, dregno)
&& lra_reg_info[dregno].restore_regno == sregno))
/* One of the following cases: /* One of the following cases:
original <- removed inheritance pseudo original <- removed inheritance pseudo
removed inherit pseudo <- another removed inherit pseudo removed inherit pseudo <- another removed inherit pseudo
...@@ -6104,13 +6403,16 @@ remove_inheritance_pseudos (bitmap remove_pseudos) ...@@ -6104,13 +6403,16 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
&& (int) REGNO (SET_DEST (prev_set)) == sregno && (int) REGNO (SET_DEST (prev_set)) == sregno
&& ((prev_sregno = REGNO (SET_SRC (prev_set))) && ((prev_sregno = REGNO (SET_SRC (prev_set)))
>= FIRST_PSEUDO_REGISTER) >= FIRST_PSEUDO_REGISTER)
/* As we consider chain of inheritance or && (lra_reg_info[prev_sregno].restore_rtx == NULL_RTX
splitting described in above comment we should ||
check that sregno and prev_sregno were /* As we consider chain of inheritance or
inheritance/split pseudos created from the splitting described in above comment we should
same original regno. */ check that sregno and prev_sregno were
&& (lra_reg_info[sregno].restore_regno inheritance/split pseudos created from the
== lra_reg_info[prev_sregno].restore_regno) same original regno. */
(get_regno (lra_reg_info[sregno].restore_rtx) >= 0
&& (get_regno (lra_reg_info[sregno].restore_rtx)
== get_regno (lra_reg_info[prev_sregno].restore_rtx))))
&& ! bitmap_bit_p (remove_pseudos, prev_sregno)) && ! bitmap_bit_p (remove_pseudos, prev_sregno))
{ {
lra_assert (GET_MODE (SET_SRC (prev_set)) lra_assert (GET_MODE (SET_SRC (prev_set))
...@@ -6124,14 +6426,13 @@ remove_inheritance_pseudos (bitmap remove_pseudos) ...@@ -6124,14 +6426,13 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
inheritance pseudo for another pseudo. */ inheritance pseudo for another pseudo. */
if (bitmap_bit_p (remove_pseudos, dregno) if (bitmap_bit_p (remove_pseudos, dregno)
&& bitmap_bit_p (&lra_inheritance_pseudos, dregno) && bitmap_bit_p (&lra_inheritance_pseudos, dregno)
&& (restore_regno && (restore_rtx
= lra_reg_info[dregno].restore_regno) >= 0) = lra_reg_info[dregno].restore_rtx) != NULL_RTX)
{ {
if (GET_CODE (SET_DEST (set)) == SUBREG) if (GET_CODE (SET_DEST (set)) == SUBREG)
SUBREG_REG (SET_DEST (set)) SUBREG_REG (SET_DEST (set)) = restore_rtx;
= regno_reg_rtx[restore_regno];
else else
SET_DEST (set) = regno_reg_rtx[restore_regno]; SET_DEST (set) = restore_rtx;
} }
lra_push_insn_and_update_insn_regno_info (curr_insn); lra_push_insn_and_update_insn_regno_info (curr_insn);
lra_set_used_insn_alternative_by_uid lra_set_used_insn_alternative_by_uid
...@@ -6155,14 +6456,13 @@ remove_inheritance_pseudos (bitmap remove_pseudos) ...@@ -6155,14 +6456,13 @@ remove_inheritance_pseudos (bitmap remove_pseudos)
for (reg = curr_id->regs; reg != NULL; reg = reg->next) for (reg = curr_id->regs; reg != NULL; reg = reg->next)
{ {
regno = reg->regno; regno = reg->regno;
restore_regno = lra_reg_info[regno].restore_regno; restore_rtx = lra_reg_info[regno].restore_rtx;
if (restore_regno >= 0) if (restore_rtx != NULL_RTX)
{ {
if (change_p && bitmap_bit_p (remove_pseudos, regno)) if (change_p && bitmap_bit_p (remove_pseudos, regno))
{ {
lra_substitute_pseudo_within_insn lra_substitute_pseudo_within_insn
(curr_insn, regno, regno_reg_rtx[restore_regno], (curr_insn, regno, restore_rtx, false);
false);
restored_regs_p = true; restored_regs_p = true;
} }
else else
...@@ -6213,11 +6513,11 @@ undo_optional_reloads (void) ...@@ -6213,11 +6513,11 @@ undo_optional_reloads (void)
{ {
keep_p = false; keep_p = false;
/* Keep optional reloads from previous subpasses. */ /* Keep optional reloads from previous subpasses. */
if (lra_reg_info[regno].restore_regno < 0 if (lra_reg_info[regno].restore_rtx == NULL_RTX
/* If the original pseudo changed its allocation, just /* If the original pseudo changed its allocation, just
removing the optional pseudo is dangerous as the original removing the optional pseudo is dangerous as the original
pseudo will have longer live range. */ pseudo will have longer live range. */
|| reg_renumber[lra_reg_info[regno].restore_regno] >= 0) || reg_renumber[REGNO (lra_reg_info[regno].restore_rtx)] >= 0)
keep_p = true; keep_p = true;
else if (reg_renumber[regno] >= 0) else if (reg_renumber[regno] >= 0)
EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi2) EXECUTE_IF_SET_IN_BITMAP (&lra_reg_info[regno].insn_bitmap, 0, uid, bi2)
...@@ -6231,7 +6531,7 @@ undo_optional_reloads (void) ...@@ -6231,7 +6531,7 @@ undo_optional_reloads (void)
continue; continue;
if (REGNO (dest) == regno if (REGNO (dest) == regno
/* Ignore insn for optional reloads itself. */ /* Ignore insn for optional reloads itself. */
&& lra_reg_info[regno].restore_regno != (int) REGNO (src) && REGNO (lra_reg_info[regno].restore_rtx) != REGNO (src)
/* Check only inheritance on last inheritance pass. */ /* Check only inheritance on last inheritance pass. */
&& (int) REGNO (src) >= new_regno_start && (int) REGNO (src) >= new_regno_start
/* Check that the optional reload was inherited. */ /* Check that the optional reload was inherited. */
...@@ -6264,11 +6564,11 @@ undo_optional_reloads (void) ...@@ -6264,11 +6564,11 @@ undo_optional_reloads (void)
dest = SET_DEST (set); dest = SET_DEST (set);
if (REG_P (src) && REG_P (dest) if (REG_P (src) && REG_P (dest)
&& ((REGNO (src) == regno && ((REGNO (src) == regno
&& (lra_reg_info[regno].restore_regno && (REGNO (lra_reg_info[regno].restore_rtx)
== (int) REGNO (dest))) == REGNO (dest)))
|| (REGNO (dest) == regno || (REGNO (dest) == regno
&& (lra_reg_info[regno].restore_regno && (REGNO (lra_reg_info[regno].restore_rtx)
== (int) REGNO (src))))) == REGNO (src)))))
{ {
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
{ {
...@@ -6286,8 +6586,7 @@ undo_optional_reloads (void) ...@@ -6286,8 +6586,7 @@ undo_optional_reloads (void)
reload. */ reload. */
} }
lra_substitute_pseudo_within_insn lra_substitute_pseudo_within_insn
(insn, regno, regno_reg_rtx[lra_reg_info[regno].restore_regno], (insn, regno, lra_reg_info[regno].restore_rtx, false);
false);
lra_update_insn_regno_info (insn); lra_update_insn_regno_info (insn);
if (lra_dump_file != NULL) if (lra_dump_file != NULL)
{ {
...@@ -6299,7 +6598,7 @@ undo_optional_reloads (void) ...@@ -6299,7 +6598,7 @@ undo_optional_reloads (void)
} }
/* Clear restore_regnos. */ /* Clear restore_regnos. */
EXECUTE_IF_SET_IN_BITMAP (&lra_optional_reload_pseudos, 0, regno, bi) EXECUTE_IF_SET_IN_BITMAP (&lra_optional_reload_pseudos, 0, regno, bi)
lra_reg_info[regno].restore_regno = -1; lra_reg_info[regno].restore_rtx = NULL_RTX;
bitmap_clear (&insn_bitmap); bitmap_clear (&insn_bitmap);
bitmap_clear (&removed_optional_reload_pseudos); bitmap_clear (&removed_optional_reload_pseudos);
return change_p; return change_p;
...@@ -6311,8 +6610,9 @@ bool ...@@ -6311,8 +6610,9 @@ bool
lra_undo_inheritance (void) lra_undo_inheritance (void)
{ {
unsigned int regno; unsigned int regno;
int restore_regno, hard_regno; int hard_regno;
int n_all_inherit, n_inherit, n_all_split, n_split; int n_all_inherit, n_inherit, n_all_split, n_split;
rtx restore_rtx;
bitmap_head remove_pseudos; bitmap_head remove_pseudos;
bitmap_iterator bi; bitmap_iterator bi;
bool change_p; bool change_p;
...@@ -6327,14 +6627,15 @@ lra_undo_inheritance (void) ...@@ -6327,14 +6627,15 @@ lra_undo_inheritance (void)
bitmap_initialize (&remove_pseudos, &reg_obstack); bitmap_initialize (&remove_pseudos, &reg_obstack);
n_inherit = n_all_inherit = 0; n_inherit = n_all_inherit = 0;
EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, regno, bi) EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, regno, bi)
if (lra_reg_info[regno].restore_regno >= 0) if (lra_reg_info[regno].restore_rtx != NULL_RTX)
{ {
n_all_inherit++; n_all_inherit++;
if (reg_renumber[regno] < 0 if (reg_renumber[regno] < 0
/* If the original pseudo changed its allocation, just /* If the original pseudo changed its allocation, just
removing inheritance is dangerous as for changing removing inheritance is dangerous as for changing
allocation we used shorter live-ranges. */ allocation we used shorter live-ranges. */
&& reg_renumber[lra_reg_info[regno].restore_regno] < 0) && (! REG_P (lra_reg_info[regno].restore_rtx)
|| reg_renumber[REGNO (lra_reg_info[regno].restore_rtx)] < 0))
bitmap_set_bit (&remove_pseudos, regno); bitmap_set_bit (&remove_pseudos, regno);
else else
n_inherit++; n_inherit++;
...@@ -6345,8 +6646,10 @@ lra_undo_inheritance (void) ...@@ -6345,8 +6646,10 @@ lra_undo_inheritance (void)
(double) n_inherit / n_all_inherit * 100); (double) n_inherit / n_all_inherit * 100);
n_split = n_all_split = 0; n_split = n_all_split = 0;
EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, regno, bi) EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, regno, bi)
if ((restore_regno = lra_reg_info[regno].restore_regno) >= 0) if ((restore_rtx = lra_reg_info[regno].restore_rtx) != NULL_RTX)
{ {
int restore_regno = REGNO (restore_rtx);
n_all_split++; n_all_split++;
hard_regno = (restore_regno >= FIRST_PSEUDO_REGISTER hard_regno = (restore_regno >= FIRST_PSEUDO_REGISTER
? reg_renumber[restore_regno] : restore_regno); ? reg_renumber[restore_regno] : restore_regno);
...@@ -6368,9 +6671,9 @@ lra_undo_inheritance (void) ...@@ -6368,9 +6671,9 @@ lra_undo_inheritance (void)
bitmap_clear (&remove_pseudos); bitmap_clear (&remove_pseudos);
/* Clear restore_regnos. */ /* Clear restore_regnos. */
EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, regno, bi) EXECUTE_IF_SET_IN_BITMAP (&lra_inheritance_pseudos, 0, regno, bi)
lra_reg_info[regno].restore_regno = -1; lra_reg_info[regno].restore_rtx = NULL_RTX;
EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, regno, bi) EXECUTE_IF_SET_IN_BITMAP (&lra_split_regs, 0, regno, bi)
lra_reg_info[regno].restore_regno = -1; lra_reg_info[regno].restore_rtx = NULL_RTX;
change_p = undo_optional_reloads () || change_p; change_p = undo_optional_reloads () || change_p;
return change_p; return change_p;
} }
...@@ -99,9 +99,9 @@ struct lra_reg ...@@ -99,9 +99,9 @@ struct lra_reg
*non-debug* insns. */ *non-debug* insns. */
int nrefs, freq; int nrefs, freq;
int last_reload; int last_reload;
/* Regno used to undo the inheritance. It can be non-zero only /* rtx used to undo the inheritance. It can be non-null only
between couple of inheritance and undo inheritance passes. */ between subsequent inheritance and undo inheritance passes. */
int restore_regno; rtx restore_rtx;
/* Value holding by register. If the pseudos have the same value /* Value holding by register. If the pseudos have the same value
they do not conflict. */ they do not conflict. */
int val; int val;
...@@ -285,6 +285,7 @@ extern lra_insn_recog_data_t *lra_insn_recog_data; ...@@ -285,6 +285,7 @@ extern lra_insn_recog_data_t *lra_insn_recog_data;
extern int lra_curr_reload_num; extern int lra_curr_reload_num;
extern void lra_dump_bitmap_with_title (const char *, bitmap, int); extern void lra_dump_bitmap_with_title (const char *, bitmap, int);
extern hashval_t lra_rtx_hash (rtx x);
extern void lra_push_insn (rtx_insn *); extern void lra_push_insn (rtx_insn *);
extern void lra_push_insn_by_uid (unsigned int); extern void lra_push_insn_by_uid (unsigned int);
extern void lra_push_insn_and_update_insn_regno_info (rtx_insn *); extern void lra_push_insn_and_update_insn_regno_info (rtx_insn *);
......
...@@ -167,92 +167,6 @@ get_remat_bb_data_by_index (int index) ...@@ -167,92 +167,6 @@ get_remat_bb_data_by_index (int index)
/* Recursive hash function for RTL X. */
static hashval_t
rtx_hash (rtx x)
{
int i, j;
enum rtx_code code;
const char *fmt;
hashval_t val = 0;
if (x == 0)
return val;
code = GET_CODE (x);
val += (int) code + 4095;
/* Some RTL can be compared nonrecursively. */
switch (code)
{
case REG:
return val + REGNO (x);
case LABEL_REF:
return iterative_hash_object (XEXP (x, 0), val);
case SYMBOL_REF:
return iterative_hash_object (XSTR (x, 0), val);
case SCRATCH:
case CONST_DOUBLE:
case CONST_INT:
case CONST_VECTOR:
return val;
default:
break;
}
/* Hash the elements. */
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
switch (fmt[i])
{
case 'w':
val += XWINT (x, i);
break;
case 'n':
case 'i':
val += XINT (x, i);
break;
case 'V':
case 'E':
val += XVECLEN (x, i);
for (j = 0; j < XVECLEN (x, i); j++)
val += rtx_hash (XVECEXP (x, i, j));
break;
case 'e':
val += rtx_hash (XEXP (x, i));
break;
case 'S':
case 's':
val += htab_hash_string (XSTR (x, i));
break;
case 'u':
case '0':
case 't':
break;
/* It is believed that rtx's at this level will never
contain anything but integers and other rtx's, except for
within LABEL_REFs and SYMBOL_REFs. */
default:
abort ();
}
}
return val;
}
/* Hash table for the candidates. Different insns (e.g. structurally /* Hash table for the candidates. Different insns (e.g. structurally
the same insns or even insns with different unused output regs) can the same insns or even insns with different unused output regs) can
be represented by the same candidate in the table. */ be represented by the same candidate in the table. */
......
...@@ -693,7 +693,7 @@ lra_final_code_change (void) ...@@ -693,7 +693,7 @@ lra_final_code_change (void)
{ {
int i, hard_regno; int i, hard_regno;
basic_block bb; basic_block bb;
rtx_insn *insn, *curr; rtx_insn *insn, *curr, *next_insn;
int max_regno = max_reg_num (); int max_regno = max_reg_num ();
for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++) for (i = FIRST_PSEUDO_REGISTER; i < max_regno; i++)
...@@ -727,7 +727,12 @@ lra_final_code_change (void) ...@@ -727,7 +727,12 @@ lra_final_code_change (void)
if (NONJUMP_INSN_P (insn) && GET_CODE (pat) == SET if (NONJUMP_INSN_P (insn) && GET_CODE (pat) == SET
&& REG_P (SET_SRC (pat)) && REG_P (SET_DEST (pat)) && REG_P (SET_SRC (pat)) && REG_P (SET_DEST (pat))
&& REGNO (SET_SRC (pat)) == REGNO (SET_DEST (pat)) && REGNO (SET_SRC (pat)) == REGNO (SET_DEST (pat))
&& ! return_regno_p (REGNO (SET_SRC (pat)))) && (! return_regno_p (REGNO (SET_SRC (pat)))
|| (next_insn = next_nondebug_insn (insn)) == NULL_RTX
|| ! INSN_P (next_insn)
|| GET_CODE (PATTERN (next_insn)) != USE
|| ! REG_P (XEXP (PATTERN (next_insn), 0))
|| REGNO (SET_SRC (pat)) != REGNO (XEXP (PATTERN (next_insn), 0))))
{ {
lra_invalidate_insn_data (insn); lra_invalidate_insn_data (insn);
delete_insn (insn); delete_insn (insn);
......
...@@ -1286,7 +1286,7 @@ initialize_lra_reg_info_element (int i) ...@@ -1286,7 +1286,7 @@ initialize_lra_reg_info_element (int i)
lra_reg_info[i].live_ranges = NULL; lra_reg_info[i].live_ranges = NULL;
lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0; lra_reg_info[i].nrefs = lra_reg_info[i].freq = 0;
lra_reg_info[i].last_reload = 0; lra_reg_info[i].last_reload = 0;
lra_reg_info[i].restore_regno = -1; lra_reg_info[i].restore_rtx = NULL_RTX;
lra_reg_info[i].val = get_new_reg_value (); lra_reg_info[i].val = get_new_reg_value ();
lra_reg_info[i].offset = 0; lra_reg_info[i].offset = 0;
lra_reg_info[i].copies = NULL; lra_reg_info[i].copies = NULL;
...@@ -1621,6 +1621,92 @@ lra_get_insn_regs (int uid) ...@@ -1621,6 +1621,92 @@ lra_get_insn_regs (int uid)
/* Recursive hash function for RTL X. */
hashval_t
lra_rtx_hash (rtx x)
{
int i, j;
enum rtx_code code;
const char *fmt;
hashval_t val = 0;
if (x == 0)
return val;
code = GET_CODE (x);
val += (int) code + 4095;
/* Some RTL can be compared nonrecursively. */
switch (code)
{
case REG:
return val + REGNO (x);
case LABEL_REF:
return iterative_hash_object (XEXP (x, 0), val);
case SYMBOL_REF:
return iterative_hash_object (XSTR (x, 0), val);
case SCRATCH:
case CONST_DOUBLE:
case CONST_INT:
case CONST_VECTOR:
return val;
default:
break;
}
/* Hash the elements. */
fmt = GET_RTX_FORMAT (code);
for (i = GET_RTX_LENGTH (code) - 1; i >= 0; i--)
{
switch (fmt[i])
{
case 'w':
val += XWINT (x, i);
break;
case 'n':
case 'i':
val += XINT (x, i);
break;
case 'V':
case 'E':
val += XVECLEN (x, i);
for (j = 0; j < XVECLEN (x, i); j++)
val += lra_rtx_hash (XVECEXP (x, i, j));
break;
case 'e':
val += lra_rtx_hash (XEXP (x, i));
break;
case 'S':
case 's':
val += htab_hash_string (XSTR (x, i));
break;
case 'u':
case '0':
case 't':
break;
/* It is believed that rtx's at this level will never
contain anything but integers and other rtx's, except for
within LABEL_REFs and SYMBOL_REFs. */
default:
abort ();
}
}
return val;
}
/* This page contains code dealing with stack of the insns which /* This page contains code dealing with stack of the insns which
should be processed by the next constraint pass. */ should be processed by the next constraint pass. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment