mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
620e594be5
commit
874e50cbd5
|
|
@ -1,3 +1,30 @@
|
||||||
|
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".
|
||||||
|
|
|
||||||
327
gcc/lra-lives.c
327
gcc/lra-lives.c
|
|
@ -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;
|
||||||
/* 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)
|
||||||
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;
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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,
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
/* 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)
|
||||||
}
|
}
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
|
|
||||||
/* 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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);
|
||||||
|
|
||||||
|
/* 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);
|
||||||
|
}
|
||||||
|
|
||||||
sparseset_clear (start_living);
|
sparseset_clear (start_living);
|
||||||
|
|
||||||
need_curr_point_incr = false;
|
|
||||||
|
|
||||||
/* 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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
}
|
}
|
||||||
/* 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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue