Commit 874e50cb by Peter Bergner Committed by Peter Bergner

re PR middle-end/87899 (r264897 cause mis-compiled native arm-linux-gnueabihf toolchain)

gcc/
	PR rtl-optimization/87899
	* lra-lives.c (start_living): Update white space in comment.
	(enum point_type): New.
	(sparseset_contains_pseudos_p): New function.
	(update_pseudo_point): Likewise.
	(make_hard_regno_live): Use HARD_REGISTER_NUM_P macro.
	(make_hard_regno_dead): Likewise.  Remove ignore_reg_for_conflicts
	handling.  Move early exit after adding conflicts.
	(mark_pseudo_live): Use HARD_REGISTER_NUM_P macro.  Add early exit
	if regno is already live.  Remove all handling of program points.
	(mark_pseudo_dead): Use HARD_REGISTER_NUM_P macro.  Add early exit
	after adding conflicts.  Remove all handling of program points and
	ignore_reg_for_conflicts.
	(mark_regno_live): Use HARD_REGISTER_NUM_P macro.  Remove return value
	and do not guard call to mark_pseudo_live.
	(mark_regno_dead): Use HARD_REGISTER_NUM_P macro.  Remove return value
	and do not guard call to mark_pseudo_dead.
	(check_pseudos_live_through_calls): Use HARD_REGISTER_NUM_P macro.
	(process_bb_lives): Use HARD_REGISTER_NUM_P and HARD_REGISTER_P macros.
	Use new function update_pseudo_point.  Handle register copies by
	removing the source register from the live set.  Handle INOUT operands.
	Update to the next program point using the unused_set, dead_set and
	start_dying sets.
	(lra_create_live_ranges_1): Use HARD_REGISTER_NUM_P macro.

From-SVN: r266086
parent 620e594b
2018-11-13 Peter Bergner <bergner@linux.ibm.com>
PR rtl-optimization/87899
* lra-lives.c (start_living): Update white space in comment.
(enum point_type): New.
(sparseset_contains_pseudos_p): New function.
(update_pseudo_point): Likewise.
(make_hard_regno_live): Use HARD_REGISTER_NUM_P macro.
(make_hard_regno_dead): Likewise. Remove ignore_reg_for_conflicts
handling. Move early exit after adding conflicts.
(mark_pseudo_live): Use HARD_REGISTER_NUM_P macro. Add early exit
if regno is already live. Remove all handling of program points.
(mark_pseudo_dead): Use HARD_REGISTER_NUM_P macro. Add early exit
after adding conflicts. Remove all handling of program points and
ignore_reg_for_conflicts.
(mark_regno_live): Use HARD_REGISTER_NUM_P macro. Remove return value
and do not guard call to mark_pseudo_live.
(mark_regno_dead): Use HARD_REGISTER_NUM_P macro. Remove return value
and do not guard call to mark_pseudo_dead.
(check_pseudos_live_through_calls): Use HARD_REGISTER_NUM_P macro.
(process_bb_lives): Use HARD_REGISTER_NUM_P and HARD_REGISTER_P macros.
Use new function update_pseudo_point. Handle register copies by
removing the source register from the live set. Handle INOUT operands.
Update to the next program point using the unused_set, dead_set and
start_dying sets.
(lra_create_live_ranges_1): Use HARD_REGISTER_NUM_P macro.
2018-11-13 David Malcolm <dmalcolm@redhat.com> 2018-11-13 David Malcolm <dmalcolm@redhat.com>
* builtins.c: Replace "source_location" with "location_t". * builtins.c: Replace "source_location" with "location_t".
...@@ -83,7 +83,7 @@ static HARD_REG_SET hard_regs_live; ...@@ -83,7 +83,7 @@ static HARD_REG_SET hard_regs_live;
/* Set of pseudos and hard registers start living/dying in the current /* Set of pseudos and hard registers start living/dying in the current
insn. These sets are used to update REG_DEAD and REG_UNUSED notes insn. These sets are used to update REG_DEAD and REG_UNUSED notes
in the insn. */ in the insn. */
static sparseset start_living, start_dying; static sparseset start_living, start_dying;
/* Set of pseudos and hard regs dead and unused in the current /* Set of pseudos and hard regs dead and unused in the current
...@@ -96,10 +96,6 @@ static bitmap_head temp_bitmap; ...@@ -96,10 +96,6 @@ static bitmap_head temp_bitmap;
/* Pool for pseudo live ranges. */ /* Pool for pseudo live ranges. */
static object_allocator<lra_live_range> lra_live_range_pool ("live ranges"); static object_allocator<lra_live_range> lra_live_range_pool ("live ranges");
/* If non-NULL, the source operand of a register to register copy for which
we should not add a conflict with the copy's destination operand. */
static rtx ignore_reg_for_conflicts;
/* Free live range list LR. */ /* Free live range list LR. */
static void static void
free_live_range_list (lra_live_range_t lr) free_live_range_list (lra_live_range_t lr)
...@@ -224,6 +220,57 @@ lra_intersected_live_ranges_p (lra_live_range_t r1, lra_live_range_t r2) ...@@ -224,6 +220,57 @@ lra_intersected_live_ranges_p (lra_live_range_t r1, lra_live_range_t r2)
return false; return false;
} }
enum point_type {
DEF_POINT,
USE_POINT
};
/* Return TRUE if set A contains a pseudo register, otherwise, return FALSE. */
static bool
sparseset_contains_pseudos_p (sparseset a)
{
int regno;
EXECUTE_IF_SET_IN_SPARSESET (a, regno)
if (!HARD_REGISTER_NUM_P (regno))
return true;
return false;
}
/* Mark pseudo REGNO as living or dying at program point POINT, depending on
whether TYPE is a definition or a use. If this is the first reference to
REGNO that we've encountered, then create a new live range for it. */
static void
update_pseudo_point (int regno, int point, enum point_type type)
{
lra_live_range_t p;
/* Don't compute points for hard registers. */
if (HARD_REGISTER_NUM_P (regno))
return;
if (complete_info_p || lra_get_regno_hard_regno (regno) < 0)
{
if (type == DEF_POINT)
{
if (sparseset_bit_p (pseudos_live, regno))
{
p = lra_reg_info[regno].live_ranges;
lra_assert (p != NULL);
p->finish = point;
}
}
else /* USE_POINT */
{
if (!sparseset_bit_p (pseudos_live, regno)
&& ((p = lra_reg_info[regno].live_ranges) == NULL
|| (p->finish != point && p->finish + 1 != point)))
lra_reg_info[regno].live_ranges
= create_live_range (regno, point, -1, p);
}
}
}
/* The corresponding bitmaps of BB currently being processed. */ /* The corresponding bitmaps of BB currently being processed. */
static bitmap bb_killed_pseudos, bb_gen_pseudos; static bitmap bb_killed_pseudos, bb_gen_pseudos;
...@@ -232,7 +279,7 @@ static bitmap bb_killed_pseudos, bb_gen_pseudos; ...@@ -232,7 +279,7 @@ static bitmap bb_killed_pseudos, bb_gen_pseudos;
static void static void
make_hard_regno_live (int regno) make_hard_regno_live (int regno)
{ {
lra_assert (regno < FIRST_PSEUDO_REGISTER); lra_assert (HARD_REGISTER_NUM_P (regno));
if (TEST_HARD_REG_BIT (hard_regs_live, regno)) if (TEST_HARD_REG_BIT (hard_regs_live, regno))
return; return;
SET_HARD_REG_BIT (hard_regs_live, regno); SET_HARD_REG_BIT (hard_regs_live, regno);
...@@ -247,19 +294,15 @@ make_hard_regno_live (int regno) ...@@ -247,19 +294,15 @@ make_hard_regno_live (int regno)
static void static void
make_hard_regno_dead (int regno) make_hard_regno_dead (int regno)
{ {
lra_assert (regno < FIRST_PSEUDO_REGISTER); lra_assert (HARD_REGISTER_NUM_P (regno));
if (! TEST_HARD_REG_BIT (hard_regs_live, regno))
return;
sparseset_set_bit (start_dying, regno);
unsigned int i; unsigned int i;
EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i) EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
{ SET_HARD_REG_BIT (lra_reg_info[i].conflict_hard_regs, regno);
if (ignore_reg_for_conflicts != NULL_RTX
&& REGNO (ignore_reg_for_conflicts) == i) if (! TEST_HARD_REG_BIT (hard_regs_live, regno))
continue; return;
SET_HARD_REG_BIT (lra_reg_info[i].conflict_hard_regs, regno);
}
CLEAR_HARD_REG_BIT (hard_regs_live, regno); CLEAR_HARD_REG_BIT (hard_regs_live, regno);
sparseset_set_bit (start_dying, regno);
if (fixed_regs[regno] || TEST_HARD_REG_BIT (hard_regs_spilled_into, regno)) if (fixed_regs[regno] || TEST_HARD_REG_BIT (hard_regs_spilled_into, regno))
{ {
bitmap_clear_bit (bb_gen_pseudos, regno); bitmap_clear_bit (bb_gen_pseudos, regno);
...@@ -267,130 +310,69 @@ make_hard_regno_dead (int regno) ...@@ -267,130 +310,69 @@ make_hard_regno_dead (int regno)
} }
} }
/* Mark pseudo REGNO as living at program point POINT, update START_LIVING /* Mark pseudo REGNO as now being live and update START_LIVING. */
and start a new live range for the pseudo corresponding to REGNO if it
is necessary. */
static void static void
mark_pseudo_live (int regno, int point) mark_pseudo_live (int regno)
{ {
lra_live_range_t p; lra_assert (!HARD_REGISTER_NUM_P (regno));
if (sparseset_bit_p (pseudos_live, regno))
return;
lra_assert (regno >= FIRST_PSEUDO_REGISTER);
lra_assert (! sparseset_bit_p (pseudos_live, regno));
sparseset_set_bit (pseudos_live, regno); sparseset_set_bit (pseudos_live, regno);
if ((complete_info_p || lra_get_regno_hard_regno (regno) < 0)
&& ((p = lra_reg_info[regno].live_ranges) == NULL
|| (p->finish != point && p->finish + 1 != point)))
lra_reg_info[regno].live_ranges
= create_live_range (regno, point, -1, p);
sparseset_set_bit (start_living, regno); sparseset_set_bit (start_living, regno);
} }
/* Mark pseudo REGNO as not living at program point POINT and update /* Mark pseudo REGNO as now being dead and update START_DYING. */
START_DYING.
This finishes the current live range for the pseudo corresponding
to REGNO. */
static void static void
mark_pseudo_dead (int regno, int point) mark_pseudo_dead (int regno)
{ {
lra_live_range_t p; lra_assert (!HARD_REGISTER_NUM_P (regno));
int ignore_regno = -1; IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs, hard_regs_live);
int end_regno = -1; if (!sparseset_bit_p (pseudos_live, regno))
return;
lra_assert (regno >= FIRST_PSEUDO_REGISTER);
lra_assert (sparseset_bit_p (pseudos_live, regno));
sparseset_clear_bit (pseudos_live, regno); sparseset_clear_bit (pseudos_live, regno);
sparseset_set_bit (start_dying, regno); sparseset_set_bit (start_dying, regno);
/* Check whether any part of IGNORE_REG_FOR_CONFLICTS already conflicts
with REGNO. */
if (ignore_reg_for_conflicts != NULL_RTX
&& REGNO (ignore_reg_for_conflicts) < FIRST_PSEUDO_REGISTER)
{
end_regno = END_REGNO (ignore_reg_for_conflicts);
int src_regno = ignore_regno = REGNO (ignore_reg_for_conflicts);
while (src_regno < end_regno)
{
if (TEST_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs,
src_regno))
{
ignore_regno = end_regno = -1;
break;
}
src_regno++;
}
}
IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs, hard_regs_live);
/* If IGNORE_REG_FOR_CONFLICTS did not already conflict with REGNO, make
sure it still doesn't. */
for (; ignore_regno < end_regno; ignore_regno++)
CLEAR_HARD_REG_BIT (lra_reg_info[regno].conflict_hard_regs, ignore_regno);
if (complete_info_p || lra_get_regno_hard_regno (regno) < 0)
{
p = lra_reg_info[regno].live_ranges;
lra_assert (p != NULL);
p->finish = point;
}
} }
/* Mark register REGNO (pseudo or hard register) in MODE as live at /* Mark register REGNO (pseudo or hard register) in MODE as being live
program point POINT. Update BB_GEN_PSEUDOS. and update BB_GEN_PSEUDOS. */
Return TRUE if the liveness tracking sets were modified, or FALSE static void
if nothing changed. */ mark_regno_live (int regno, machine_mode mode)
static bool
mark_regno_live (int regno, machine_mode mode, int point)
{ {
int last; int last;
bool changed = false;
if (regno < FIRST_PSEUDO_REGISTER) if (HARD_REGISTER_NUM_P (regno))
{ {
for (last = end_hard_regno (mode, regno); regno < last; regno++) for (last = end_hard_regno (mode, regno); regno < last; regno++)
make_hard_regno_live (regno); make_hard_regno_live (regno);
} }
else else
{ {
if (! sparseset_bit_p (pseudos_live, regno)) mark_pseudo_live (regno);
{
mark_pseudo_live (regno, point);
changed = true;
}
bitmap_set_bit (bb_gen_pseudos, regno); bitmap_set_bit (bb_gen_pseudos, regno);
} }
return changed;
} }
/* Mark register REGNO in MODE as dead at program point POINT. Update /* Mark register REGNO (pseudo or hard register) in MODE as being dead
BB_GEN_PSEUDOS and BB_KILLED_PSEUDOS. Return TRUE if the liveness and update BB_GEN_PSEUDOS and BB_KILLED_PSEUDOS. */
tracking sets were modified, or FALSE if nothing changed. */ static void
static bool mark_regno_dead (int regno, machine_mode mode)
mark_regno_dead (int regno, machine_mode mode, int point)
{ {
int last; int last;
bool changed = false;
if (regno < FIRST_PSEUDO_REGISTER) if (HARD_REGISTER_NUM_P (regno))
{ {
for (last = end_hard_regno (mode, regno); regno < last; regno++) for (last = end_hard_regno (mode, regno); regno < last; regno++)
make_hard_regno_dead (regno); make_hard_regno_dead (regno);
} }
else else
{ {
if (sparseset_bit_p (pseudos_live, regno)) mark_pseudo_dead (regno);
{
mark_pseudo_dead (regno, point);
changed = true;
}
bitmap_clear_bit (bb_gen_pseudos, regno); bitmap_clear_bit (bb_gen_pseudos, regno);
bitmap_set_bit (bb_killed_pseudos, regno); bitmap_set_bit (bb_killed_pseudos, regno);
} }
return changed;
} }
...@@ -607,7 +589,7 @@ check_pseudos_live_through_calls (int regno, ...@@ -607,7 +589,7 @@ check_pseudos_live_through_calls (int regno,
IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs, IOR_HARD_REG_SET (lra_reg_info[regno].conflict_hard_regs,
last_call_used_reg_set); last_call_used_reg_set);
for (hr = 0; hr < FIRST_PSEUDO_REGISTER; hr++) for (hr = 0; HARD_REGISTER_NUM_P (hr); hr++)
if (targetm.hard_regno_call_part_clobbered (hr, if (targetm.hard_regno_call_part_clobbered (hr,
PSEUDO_REGNO_MODE (regno))) PSEUDO_REGNO_MODE (regno)))
add_to_hard_reg_set (&lra_reg_info[regno].conflict_hard_regs, add_to_hard_reg_set (&lra_reg_info[regno].conflict_hard_regs,
...@@ -653,7 +635,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -653,7 +635,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
rtx link, *link_loc; rtx link, *link_loc;
bool need_curr_point_incr; bool need_curr_point_incr;
HARD_REG_SET last_call_used_reg_set; HARD_REG_SET last_call_used_reg_set;
reg_live_out = df_get_live_out (bb); reg_live_out = df_get_live_out (bb);
sparseset_clear (pseudos_live); sparseset_clear (pseudos_live);
sparseset_clear (pseudos_live_through_calls); sparseset_clear (pseudos_live_through_calls);
...@@ -662,7 +644,10 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -662,7 +644,10 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out); REG_SET_TO_HARD_REG_SET (hard_regs_live, reg_live_out);
AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset); AND_COMPL_HARD_REG_SET (hard_regs_live, eliminable_regset);
EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi) EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi)
mark_pseudo_live (j, curr_point); {
update_pseudo_point (j, curr_point, USE_POINT);
mark_pseudo_live (j);
}
bb_gen_pseudos = &get_bb_data (bb)->gen_pseudos; bb_gen_pseudos = &get_bb_data (bb)->gen_pseudos;
bb_killed_pseudos = &get_bb_data (bb)->killed_pseudos; bb_killed_pseudos = &get_bb_data (bb)->killed_pseudos;
...@@ -702,7 +687,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -702,7 +687,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
set = single_set (curr_insn); set = single_set (curr_insn);
if (dead_insn_p && set != NULL_RTX if (dead_insn_p && set != NULL_RTX
&& REG_P (SET_DEST (set)) && REGNO (SET_DEST (set)) >= FIRST_PSEUDO_REGISTER && REG_P (SET_DEST (set)) && !HARD_REGISTER_P (SET_DEST (set))
&& find_reg_note (curr_insn, REG_EH_REGION, NULL_RTX) == NULL_RTX && find_reg_note (curr_insn, REG_EH_REGION, NULL_RTX) == NULL_RTX
&& ! may_trap_p (PATTERN (curr_insn)) && ! may_trap_p (PATTERN (curr_insn))
/* Don't do premature remove of pic offset pseudo as we can /* Don't do premature remove of pic offset pseudo as we can
...@@ -759,7 +744,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -759,7 +744,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
if (partial_subreg_p (lra_reg_info[regno].biggest_mode, if (partial_subreg_p (lra_reg_info[regno].biggest_mode,
reg->biggest_mode)) reg->biggest_mode))
lra_reg_info[regno].biggest_mode = reg->biggest_mode; lra_reg_info[regno].biggest_mode = reg->biggest_mode;
if (regno < FIRST_PSEUDO_REGISTER) if (HARD_REGISTER_NUM_P (regno))
{ {
lra_hard_reg_usage[regno] += freq; lra_hard_reg_usage[regno] += freq;
/* A hard register explicitly can be used in small mode, /* A hard register explicitly can be used in small mode,
...@@ -775,7 +760,26 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -775,7 +760,26 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
} }
call_p = CALL_P (curr_insn); call_p = CALL_P (curr_insn);
ignore_reg_for_conflicts = non_conflicting_reg_copy_p (curr_insn);
/* If we have a simple register copy and the source reg is live after
this instruction, then remove the source reg from the live set so
that it will not conflict with the destination reg. */
rtx ignore_reg = non_conflicting_reg_copy_p (curr_insn);
if (ignore_reg != NULL_RTX)
{
int ignore_regno = REGNO (ignore_reg);
if (HARD_REGISTER_NUM_P (ignore_regno)
&& TEST_HARD_REG_BIT (hard_regs_live, ignore_regno))
CLEAR_HARD_REG_BIT (hard_regs_live, ignore_regno);
else if (!HARD_REGISTER_NUM_P (ignore_regno)
&& sparseset_bit_p (pseudos_live, ignore_regno))
sparseset_clear_bit (pseudos_live, ignore_regno);
else
/* We don't need any special handling of the source reg if
it is dead after this instruction. */
ignore_reg = NULL_RTX;
}
src_regno = (set != NULL_RTX && REG_P (SET_SRC (set)) src_regno = (set != NULL_RTX && REG_P (SET_SRC (set))
? REGNO (SET_SRC (set)) : -1); ? REGNO (SET_SRC (set)) : -1);
dst_regno = (set != NULL_RTX && REG_P (SET_DEST (set)) dst_regno = (set != NULL_RTX && REG_P (SET_DEST (set))
...@@ -785,13 +789,13 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -785,13 +789,13 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
/* Check that source regno does not conflict with /* Check that source regno does not conflict with
destination regno to exclude most impossible destination regno to exclude most impossible
preferences. */ preferences. */
&& (((src_regno >= FIRST_PSEUDO_REGISTER && (((!HARD_REGISTER_NUM_P (src_regno)
&& (! sparseset_bit_p (pseudos_live, src_regno) && (! sparseset_bit_p (pseudos_live, src_regno)
|| (dst_regno >= FIRST_PSEUDO_REGISTER || (!HARD_REGISTER_NUM_P (dst_regno)
&& lra_reg_val_equal_p (src_regno, && lra_reg_val_equal_p (src_regno,
lra_reg_info[dst_regno].val, lra_reg_info[dst_regno].val,
lra_reg_info[dst_regno].offset)))) lra_reg_info[dst_regno].offset))))
|| (src_regno < FIRST_PSEUDO_REGISTER || (HARD_REGISTER_NUM_P (src_regno)
&& ! TEST_HARD_REG_BIT (hard_regs_live, src_regno))) && ! TEST_HARD_REG_BIT (hard_regs_live, src_regno)))
/* It might be 'inheritance pseudo <- reload pseudo'. */ /* It might be 'inheritance pseudo <- reload pseudo'. */
|| (src_regno >= lra_constraint_new_regno_start || (src_regno >= lra_constraint_new_regno_start
...@@ -816,13 +820,13 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -816,13 +820,13 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
} }
else if (dst_regno >= lra_constraint_new_regno_start) else if (dst_regno >= lra_constraint_new_regno_start)
{ {
if ((hard_regno = src_regno) >= FIRST_PSEUDO_REGISTER) if (!HARD_REGISTER_NUM_P (hard_regno = src_regno))
hard_regno = reg_renumber[src_regno]; hard_regno = reg_renumber[src_regno];
regno = dst_regno; regno = dst_regno;
} }
else if (src_regno >= lra_constraint_new_regno_start) else if (src_regno >= lra_constraint_new_regno_start)
{ {
if ((hard_regno = dst_regno) >= FIRST_PSEUDO_REGISTER) if (!HARD_REGISTER_NUM_P (hard_regno = dst_regno))
hard_regno = reg_renumber[dst_regno]; hard_regno = reg_renumber[dst_regno];
regno = src_regno; regno = src_regno;
} }
...@@ -833,12 +837,6 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -833,12 +837,6 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
sparseset_clear (start_living); sparseset_clear (start_living);
/* Try to avoid unnecessary program point increments, this saves
a lot of time in remove_some_program_points_and_update_live_ranges.
We only need an increment if something becomes live or dies at this
program point. */
need_curr_point_incr = false;
/* Mark each defined value as live. We need to do this for /* Mark each defined value as live. We need to do this for
unused values because they still conflict with quantities unused values because they still conflict with quantities
that are live at the time of the definition. */ that are live at the time of the definition. */
...@@ -846,14 +844,13 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -846,14 +844,13 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
{ {
if (reg->type != OP_IN) if (reg->type != OP_IN)
{ {
need_curr_point_incr update_pseudo_point (reg->regno, curr_point, USE_POINT);
|= mark_regno_live (reg->regno, reg->biggest_mode, mark_regno_live (reg->regno, reg->biggest_mode);
curr_point);
check_pseudos_live_through_calls (reg->regno, check_pseudos_live_through_calls (reg->regno,
last_call_used_reg_set); last_call_used_reg_set);
} }
if (reg->regno >= FIRST_PSEUDO_REGISTER) if (!HARD_REGISTER_NUM_P (reg->regno))
for (hr = curr_static_id->hard_regs; hr != NULL; hr = hr->next) for (hr = curr_static_id->hard_regs; hr != NULL; hr = hr->next)
if (hr->clobber_high if (hr->clobber_high
&& maybe_gt (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno)), && maybe_gt (GET_MODE_SIZE (PSEUDO_REGNO_MODE (reg->regno)),
...@@ -868,7 +865,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -868,7 +865,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
if (curr_id->arg_hard_regs != NULL) if (curr_id->arg_hard_regs != NULL)
for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++) for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++)
if (regno >= FIRST_PSEUDO_REGISTER) if (!HARD_REGISTER_NUM_P (regno))
/* It is a clobber. */ /* It is a clobber. */
make_hard_regno_live (regno - FIRST_PSEUDO_REGISTER); make_hard_regno_live (regno - FIRST_PSEUDO_REGISTER);
...@@ -878,20 +875,22 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -878,20 +875,22 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
/* See which defined values die here. */ /* See which defined values die here. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next) for (reg = curr_id->regs; reg != NULL; reg = reg->next)
if (reg->type == OP_OUT if (reg->type != OP_IN
&& ! reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p) && ! reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p)
need_curr_point_incr {
|= mark_regno_dead (reg->regno, reg->biggest_mode, if (reg->type == OP_OUT)
curr_point); update_pseudo_point (reg->regno, curr_point, DEF_POINT);
mark_regno_dead (reg->regno, reg->biggest_mode);
}
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
if (reg->type == OP_OUT if (reg->type != OP_IN
&& ! reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p) && ! reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p)
make_hard_regno_dead (reg->regno); make_hard_regno_dead (reg->regno);
if (curr_id->arg_hard_regs != NULL) if (curr_id->arg_hard_regs != NULL)
for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++) for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++)
if (regno >= FIRST_PSEUDO_REGISTER) if (!HARD_REGISTER_NUM_P (regno))
/* It is a clobber. */ /* It is a clobber. */
make_hard_regno_dead (regno - FIRST_PSEUDO_REGISTER); make_hard_regno_dead (regno - FIRST_PSEUDO_REGISTER);
...@@ -931,50 +930,70 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -931,50 +930,70 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
} }
/* Increment the current program point if we must. */ /* Increment the current program point if we must. */
if (need_curr_point_incr) if (sparseset_contains_pseudos_p (unused_set)
|| sparseset_contains_pseudos_p (start_dying))
next_program_point (curr_point, freq); next_program_point (curr_point, freq);
sparseset_clear (start_living); /* If we removed the source reg from a simple register copy from the
live set above, then add it back now so we don't accidentally add
it to the start_living set below. */
if (ignore_reg != NULL_RTX)
{
int ignore_regno = REGNO (ignore_reg);
if (HARD_REGISTER_NUM_P (ignore_regno))
SET_HARD_REG_BIT (hard_regs_live, ignore_regno);
else
sparseset_set_bit (pseudos_live, ignore_regno);
}
need_curr_point_incr = false; sparseset_clear (start_living);
/* Mark each used value as live. */ /* Mark each used value as live. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next) for (reg = curr_id->regs; reg != NULL; reg = reg->next)
if (reg->type == OP_IN) if (reg->type != OP_OUT)
{ {
need_curr_point_incr if (reg->type == OP_IN)
|= mark_regno_live (reg->regno, reg->biggest_mode, update_pseudo_point (reg->regno, curr_point, USE_POINT);
curr_point); mark_regno_live (reg->regno, reg->biggest_mode);
check_pseudos_live_through_calls (reg->regno, check_pseudos_live_through_calls (reg->regno,
last_call_used_reg_set); last_call_used_reg_set);
} }
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
if (reg->type == OP_IN) if (reg->type != OP_OUT)
make_hard_regno_live (reg->regno); make_hard_regno_live (reg->regno);
if (curr_id->arg_hard_regs != NULL) if (curr_id->arg_hard_regs != NULL)
/* Make argument hard registers live. */ /* Make argument hard registers live. */
for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++) for (i = 0; (regno = curr_id->arg_hard_regs[i]) >= 0; i++)
if (regno < FIRST_PSEUDO_REGISTER) if (HARD_REGISTER_NUM_P (regno))
make_hard_regno_live (regno); make_hard_regno_live (regno);
sparseset_and_compl (dead_set, start_living, start_dying); sparseset_and_compl (dead_set, start_living, start_dying);
sparseset_clear (start_dying);
/* Mark early clobber outputs dead. */ /* Mark early clobber outputs dead. */
for (reg = curr_id->regs; reg != NULL; reg = reg->next) for (reg = curr_id->regs; reg != NULL; reg = reg->next)
if (reg->type == OP_OUT if (reg->type != OP_IN
&& reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p) && reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p)
need_curr_point_incr {
|= mark_regno_dead (reg->regno, reg->biggest_mode, if (reg->type == OP_OUT)
curr_point); update_pseudo_point (reg->regno, curr_point, DEF_POINT);
mark_regno_dead (reg->regno, reg->biggest_mode);
/* We're done processing inputs, so make sure early clobber
operands that are both inputs and outputs are still live. */
if (reg->type == OP_INOUT)
mark_regno_live (reg->regno, reg->biggest_mode);
}
for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next) for (reg = curr_static_id->hard_regs; reg != NULL; reg = reg->next)
if (reg->type == OP_OUT if (reg->type != OP_IN
&& reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p) && reg_early_clobber_p (reg, n_alt) && ! reg->subreg_p)
{ {
struct lra_insn_reg *reg2; struct lra_insn_reg *reg2;
/* We can have early clobbered non-operand hard reg and /* We can have early clobbered non-operand hard reg and
the same hard reg as an insn input. Don't make hard the same hard reg as an insn input. Don't make hard
reg dead before the insns. */ reg dead before the insns. */
...@@ -985,7 +1004,9 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -985,7 +1004,9 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
make_hard_regno_dead (reg->regno); make_hard_regno_dead (reg->regno);
} }
if (need_curr_point_incr) /* Increment the current program point if we must. */
if (sparseset_contains_pseudos_p (dead_set)
|| sparseset_contains_pseudos_p (start_dying))
next_program_point (curr_point, freq); next_program_point (curr_point, freq);
/* Update notes. */ /* Update notes. */
...@@ -1017,7 +1038,6 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -1017,7 +1038,6 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
EXECUTE_IF_SET_IN_SPARSESET (unused_set, j) EXECUTE_IF_SET_IN_SPARSESET (unused_set, j)
add_reg_note (curr_insn, REG_UNUSED, regno_reg_rtx[j]); add_reg_note (curr_insn, REG_UNUSED, regno_reg_rtx[j]);
} }
ignore_reg_for_conflicts = NULL_RTX;
if (bb_has_eh_pred (bb)) if (bb_has_eh_pred (bb))
for (j = 0; ; ++j) for (j = 0; ; ++j)
...@@ -1047,7 +1067,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -1047,7 +1067,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
allocate such regs in this case. */ allocate such regs in this case. */
if (!cfun->has_nonlocal_label if (!cfun->has_nonlocal_label
&& has_abnormal_call_or_eh_pred_edge_p (bb)) && has_abnormal_call_or_eh_pred_edge_p (bb))
for (px = 0; px < FIRST_PSEUDO_REGISTER; px++) for (px = 0; HARD_REGISTER_NUM_P (px); px++)
if (call_used_regs[px] if (call_used_regs[px]
#ifdef REAL_PIC_OFFSET_TABLE_REGNUM #ifdef REAL_PIC_OFFSET_TABLE_REGNUM
/* We should create a conflict of PIC pseudo with PIC /* We should create a conflict of PIC pseudo with PIC
...@@ -1057,7 +1077,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -1057,7 +1077,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
pseudo will also have a wrong value. */ pseudo will also have a wrong value. */
|| (px == REAL_PIC_OFFSET_TABLE_REGNUM || (px == REAL_PIC_OFFSET_TABLE_REGNUM
&& pic_offset_table_rtx != NULL_RTX && pic_offset_table_rtx != NULL_RTX
&& REGNO (pic_offset_table_rtx) >= FIRST_PSEUDO_REGISTER) && !HARD_REGISTER_P (pic_offset_table_rtx))
#endif #endif
) )
make_hard_regno_live (px); make_hard_regno_live (px);
...@@ -1095,7 +1115,10 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -1095,7 +1115,10 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
need_curr_point_incr = (sparseset_cardinality (pseudos_live) > 0); need_curr_point_incr = (sparseset_cardinality (pseudos_live) > 0);
EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i) EXECUTE_IF_SET_IN_SPARSESET (pseudos_live, i)
mark_pseudo_dead (i, curr_point); {
update_pseudo_point (i, curr_point, DEF_POINT);
mark_pseudo_dead (i);
}
EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), FIRST_PSEUDO_REGISTER, j, bi) EXECUTE_IF_SET_IN_BITMAP (df_get_live_in (bb), FIRST_PSEUDO_REGISTER, j, bi)
{ {
...@@ -1105,7 +1128,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p) ...@@ -1105,7 +1128,7 @@ process_bb_lives (basic_block bb, int &curr_point, bool dead_insn_p)
check_pseudos_live_through_calls (j, last_call_used_reg_set); check_pseudos_live_through_calls (j, last_call_used_reg_set);
} }
for (i = 0; i < FIRST_PSEUDO_REGISTER; ++i) for (i = 0; HARD_REGISTER_NUM_P (i); ++i)
{ {
if (!TEST_HARD_REG_BIT (hard_regs_live, i)) if (!TEST_HARD_REG_BIT (hard_regs_live, i))
continue; continue;
...@@ -1332,12 +1355,12 @@ lra_create_live_ranges_1 (bool all_p, bool dead_insn_p) ...@@ -1332,12 +1355,12 @@ lra_create_live_ranges_1 (bool all_p, bool dead_insn_p)
conservative because of recent transformation. Here in this conservative because of recent transformation. Here in this
file we recalculate it again as it costs practically file we recalculate it again as it costs practically
nothing. */ nothing. */
if (i >= FIRST_PSEUDO_REGISTER && regno_reg_rtx[i] != NULL_RTX) if (!HARD_REGISTER_NUM_P (i) && regno_reg_rtx[i] != NULL_RTX)
lra_reg_info[i].biggest_mode = GET_MODE (regno_reg_rtx[i]); lra_reg_info[i].biggest_mode = GET_MODE (regno_reg_rtx[i]);
else else
lra_reg_info[i].biggest_mode = VOIDmode; lra_reg_info[i].biggest_mode = VOIDmode;
lra_reg_info[i].call_p = false; lra_reg_info[i].call_p = false;
if (i >= FIRST_PSEUDO_REGISTER if (!HARD_REGISTER_NUM_P (i)
&& lra_reg_info[i].nrefs != 0) && lra_reg_info[i].nrefs != 0)
{ {
if ((hard_regno = reg_renumber[i]) >= 0) if ((hard_regno = reg_renumber[i]) >= 0)
...@@ -1394,7 +1417,7 @@ lra_create_live_ranges_1 (bool all_p, bool dead_insn_p) ...@@ -1394,7 +1417,7 @@ lra_create_live_ranges_1 (bool all_p, bool dead_insn_p)
} }
/* As we did not change CFG since LRA start we can use /* As we did not change CFG since LRA start we can use
DF-infrastructure solver to solve live data flow problem. */ DF-infrastructure solver to solve live data flow problem. */
for (int i = 0; i < FIRST_PSEUDO_REGISTER; ++i) for (int i = 0; HARD_REGISTER_NUM_P (i); ++i)
{ {
if (TEST_HARD_REG_BIT (hard_regs_spilled_into, i)) if (TEST_HARD_REG_BIT (hard_regs_spilled_into, i))
bitmap_clear_bit (&all_hard_regs_bitmap, i); bitmap_clear_bit (&all_hard_regs_bitmap, i);
......
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