ira: Add ira_subloop_allocnos_can_differ_p

color_pass has two instances of the same code for propagating non-cap
assignments from parent loops to subloops.  This patch adds a helper
function for testing when such propagations are required for correctness
and uses it to remove the duplicated code.

A later patch will use this in ira-build.c too, which is why the
function is exported to ira-int.h.

No functional change intended.

gcc/
	PR rtl-optimization/98782
	* ira-int.h (ira_subloop_allocnos_can_differ_p): New function,
	extracted from...
	* ira-color.c (color_pass): ...here.
This commit is contained in:
Richard Sandiford 2022-01-10 14:47:07 +00:00
parent 909a4b4764
commit d54565d87f
2 changed files with 29 additions and 20 deletions

View file

@ -3446,26 +3446,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node)
if ((flag_ira_region == IRA_REGION_MIXED
&& (loop_tree_node->reg_pressure[pclass]
<= ira_class_hard_regs_num[pclass]))
|| (pic_offset_table_rtx != NULL
&& regno == (int) REGNO (pic_offset_table_rtx))
/* Avoid overlapped multi-registers. Moves between them
might result in wrong code generation. */
|| (hard_regno >= 0
&& ira_reg_class_max_nregs[pclass][mode] > 1))
{
if (! ALLOCNO_ASSIGNED_P (subloop_allocno))
{
ALLOCNO_HARD_REGNO (subloop_allocno) = hard_regno;
ALLOCNO_ASSIGNED_P (subloop_allocno) = true;
if (hard_regno >= 0)
update_costs_from_copies (subloop_allocno, true, true);
/* We don't need updated costs anymore. */
ira_free_allocno_updated_costs (subloop_allocno);
}
continue;
}
ira_assert (regno < ira_reg_equiv_len);
if (ira_equiv_no_lvalue_p (regno))
|| !ira_subloop_allocnos_can_differ_p (a, hard_regno >= 0))
{
if (! ALLOCNO_ASSIGNED_P (subloop_allocno))
{

View file

@ -1595,4 +1595,32 @@ ira_loop_border_costs::move_between_loops_cost () const
return move_cost * (m_entry_freq + m_exit_freq);
}
/* Return true if subloops that contain allocnos for A's register can
use a different assignment from A. ALLOCATED_P is true for the case
in which allocation succeeded for A. */
inline bool
ira_subloop_allocnos_can_differ_p (ira_allocno_t a, bool allocated_p = true)
{
auto regno = ALLOCNO_REGNO (a);
if (pic_offset_table_rtx != NULL
&& regno == (int) REGNO (pic_offset_table_rtx))
return false;
ira_assert (regno < ira_reg_equiv_len);
if (ira_equiv_no_lvalue_p (regno))
return false;
/* Avoid overlapping multi-registers. Moves between them might result
in wrong code generation. */
if (allocated_p)
{
auto pclass = ira_pressure_class_translate[ALLOCNO_CLASS (a)];
if (ira_reg_class_max_nregs[pclass][ALLOCNO_MODE (a)] > 1)
return false;
}
return true;
}
#endif /* GCC_IRA_INT_H */