Commit db1a8d98 by Vladimir Makarov Committed by Vladimir Makarov

re PR target/37488 (register allocation spills floats needlessly)

2009-07-22  Vladimir Makarov  <vmakarov@redhat.com>

	PR target/37488
	* ira-lives.c (bb_has_abnormal_call_pred): New function.
	(process_bb_node_lives): Use it.

	* ira.c (setup_cover_and_important_classes): Don't setup
	ira_important_class_nums.  Add cover classes to the end of
	important classes.
	(cover_class_order, comp_reg_classes_func,
	reorder_important_classes): New.
	(find_reg_class_closure): Use reorder_important_classes.

	* config/i386/i386.h (IRA_COVER_CLASSES): Remove.

	* config/i386/i386.c (i386_ira_cover_classes): New function.
	(TARGET_IRA_COVER_CLASSES): Redefine.

	* doc/tm.texi (TARGET_IRA_COVER_CLASSES): Add a comment about
	importance of order of cover classes in the array.

From-SVN: r149962
parent cae63f88
2009-07-22 Vladimir Makarov <vmakarov@redhat.com>
PR target/37488
* ira-lives.c (bb_has_abnormal_call_pred): New function.
(process_bb_node_lives): Use it.
* ira.c (setup_cover_and_important_classes): Don't setup
ira_important_class_nums. Add cover classes to the end of
important classes.
(cover_class_order, comp_reg_classes_func,
reorder_important_classes): New.
(find_reg_class_closure): Use reorder_important_classes.
* config/i386/i386.h (IRA_COVER_CLASSES): Remove.
* config/i386/i386.c (i386_ira_cover_classes): New function.
(TARGET_IRA_COVER_CLASSES): Redefine.
* doc/tm.texi (TARGET_IRA_COVER_CLASSES): Add a comment about
importance of order of cover classes in the array.
2009-07-22 Diego Novillo <dnovillo@google.com> 2009-07-22 Diego Novillo <dnovillo@google.com>
* tree-pass.h (TDF_EH): Define. * tree-pass.h (TDF_EH): Define.
......
...@@ -26132,6 +26132,22 @@ ix86_free_from_memory (enum machine_mode mode) ...@@ -26132,6 +26132,22 @@ ix86_free_from_memory (enum machine_mode mode)
} }
} }
/* Implement TARGET_IRA_COVER_CLASSES. If -mfpmath=sse, we prefer
SSE_REGS to FLOAT_REGS if their costs for a pseudo are the
same. */
static const enum reg_class *
i386_ira_cover_classes (void)
{
static const enum reg_class sse_fpmath_classes[] = {
GENERAL_REGS, SSE_REGS, MMX_REGS, FLOAT_REGS, LIM_REG_CLASSES
};
static const enum reg_class no_sse_fpmath_classes[] = {
GENERAL_REGS, FLOAT_REGS, MMX_REGS, SSE_REGS, LIM_REG_CLASSES
};
return TARGET_SSE_MATH ? sse_fpmath_classes : no_sse_fpmath_classes;
}
/* Put float CONST_DOUBLE in the constant pool instead of fp regs. /* Put float CONST_DOUBLE in the constant pool instead of fp regs.
QImode must go into class Q_REGS. QImode must go into class Q_REGS.
Narrow ALL_REGS to GENERAL_REGS. This supports allowing movsf and Narrow ALL_REGS to GENERAL_REGS. This supports allowing movsf and
...@@ -30652,6 +30668,9 @@ ix86_enum_va_list (int idx, const char **pname, tree *ptree) ...@@ -30652,6 +30668,9 @@ ix86_enum_va_list (int idx, const char **pname, tree *ptree)
#undef TARGET_LEGITIMATE_ADDRESS_P #undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P ix86_legitimate_address_p #define TARGET_LEGITIMATE_ADDRESS_P ix86_legitimate_address_p
#undef TARGET_IRA_COVER_CLASSES
#define TARGET_IRA_COVER_CLASSES i386_ira_cover_classes
#undef TARGET_FRAME_POINTER_REQUIRED #undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED ix86_frame_pointer_required #define TARGET_FRAME_POINTER_REQUIRED ix86_frame_pointer_required
......
...@@ -1288,19 +1288,6 @@ enum reg_class ...@@ -1288,19 +1288,6 @@ enum reg_class
{ 0xffffffff,0x1fffff } \ { 0xffffffff,0x1fffff } \
} }
/* The following macro defines cover classes for Integrated Register
Allocator. Cover classes is a set of non-intersected register
classes covering all hard registers used for register allocation
purpose. Any move between two registers of a cover class should be
cheaper than load or store of the registers. The macro value is
array of register classes with LIM_REG_CLASSES used as the end
marker. */
#define IRA_COVER_CLASSES \
{ \
GENERAL_REGS, FLOAT_REGS, MMX_REGS, SSE_REGS, LIM_REG_CLASSES \
}
/* The same information, inverted: /* The same information, inverted:
Return the class number of the smallest class containing Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression reg number REGNO. This could be a conditional expression
......
...@@ -2913,6 +2913,10 @@ purposes. If a move between two registers in the same cover class is ...@@ -2913,6 +2913,10 @@ purposes. If a move between two registers in the same cover class is
possible, it should be cheaper than a load or store of the registers. possible, it should be cheaper than a load or store of the registers.
The array is terminated by a @code{LIM_REG_CLASSES} element. The array is terminated by a @code{LIM_REG_CLASSES} element.
The order of cover classes in the array is important. If two classes
have the same cost of usage for a pseudo, the class occurred first in
the array is chosen for the pseudo.
This hook is called once at compiler startup, after the command-line This hook is called once at compiler startup, after the command-line
options have been processed. It is then re-examined by every call to options have been processed. It is then re-examined by every call to
@code{target_reinit}. @code{target_reinit}.
......
...@@ -814,6 +814,22 @@ process_single_reg_class_operands (bool in_p, int freq) ...@@ -814,6 +814,22 @@ process_single_reg_class_operands (bool in_p, int freq)
} }
} }
/* Return true when one of the predecessor edges of BB is marked with
EDGE_ABNORMAL_CALL or EDGE_EH. */
static bool
bb_has_abnormal_call_pred (basic_block bb)
{
edge e;
edge_iterator ei;
FOR_EACH_EDGE (e, ei, bb->preds)
{
if (e->flags & (EDGE_ABNORMAL_CALL | EDGE_EH))
return true;
}
return false;
}
/* Process insns of the basic block given by its LOOP_TREE_NODE to /* Process insns of the basic block given by its LOOP_TREE_NODE to
update allocno live ranges, allocno hard register conflicts, update allocno live ranges, allocno hard register conflicts,
intersected calls, and register pressure info for allocnos for the intersected calls, and register pressure info for allocnos for the
...@@ -1062,7 +1078,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) ...@@ -1062,7 +1078,7 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node)
/* No need to record conflicts for call clobbered regs if we /* No need to record conflicts for call clobbered regs if we
have nonlocal labels around, as we don't ever try to have nonlocal labels around, as we don't ever try to
allocate such regs in this case. */ allocate such regs in this case. */
if (!cfun->has_nonlocal_label) if (!cfun->has_nonlocal_label && bb_has_abnormal_call_pred (bb))
for (px = 0; px < FIRST_PSEUDO_REGISTER; px++) for (px = 0; px < FIRST_PSEUDO_REGISTER; px++)
if (call_used_regs[px]) if (call_used_regs[px])
make_regno_born (px); make_regno_born (px);
......
...@@ -729,7 +729,7 @@ static void ...@@ -729,7 +729,7 @@ static void
setup_cover_and_important_classes (void) setup_cover_and_important_classes (void)
{ {
int i, j, n, cl; int i, j, n, cl;
bool set_p, eq_p; bool set_p;
const enum reg_class *cover_classes; const enum reg_class *cover_classes;
HARD_REG_SET temp_hard_regset2; HARD_REG_SET temp_hard_regset2;
static enum reg_class classes[LIM_REG_CLASSES + 1]; static enum reg_class classes[LIM_REG_CLASSES + 1];
...@@ -802,7 +802,7 @@ setup_cover_and_important_classes (void) ...@@ -802,7 +802,7 @@ setup_cover_and_important_classes (void)
AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
if (! hard_reg_set_empty_p (temp_hard_regset)) if (! hard_reg_set_empty_p (temp_hard_regset))
{ {
set_p = eq_p = false; set_p = false;
for (j = 0; j < ira_reg_class_cover_size; j++) for (j = 0; j < ira_reg_class_cover_size; j++)
{ {
COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
...@@ -810,27 +810,22 @@ setup_cover_and_important_classes (void) ...@@ -810,27 +810,22 @@ setup_cover_and_important_classes (void)
COPY_HARD_REG_SET (temp_hard_regset2, COPY_HARD_REG_SET (temp_hard_regset2,
reg_class_contents[ira_reg_class_cover[j]]); reg_class_contents[ira_reg_class_cover[j]]);
AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs); AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
if ((enum reg_class) cl == ira_reg_class_cover[j]) if ((enum reg_class) cl == ira_reg_class_cover[j]
{ || hard_reg_set_equal_p (temp_hard_regset,
eq_p = false; temp_hard_regset2))
set_p = true; break;
break;
}
else if (hard_reg_set_equal_p (temp_hard_regset,
temp_hard_regset2))
eq_p = true;
else if (hard_reg_set_subset_p (temp_hard_regset, else if (hard_reg_set_subset_p (temp_hard_regset,
temp_hard_regset2)) temp_hard_regset2))
set_p = true; set_p = true;
} }
if (set_p && ! eq_p) if (set_p && j >= ira_reg_class_cover_size)
{ ira_important_classes[ira_important_classes_num++]
ira_important_class_nums[cl] = ira_important_classes_num; = (enum reg_class) cl;
ira_important_classes[ira_important_classes_num++] =
(enum reg_class) cl;
}
} }
} }
for (j = 0; j < ira_reg_class_cover_size; j++)
ira_important_classes[ira_important_classes_num++]
= ira_reg_class_cover[j];
} }
/* Map of all register classes to corresponding cover class containing /* Map of all register classes to corresponding cover class containing
...@@ -925,6 +920,43 @@ setup_class_translate (void) ...@@ -925,6 +920,43 @@ setup_class_translate (void)
} }
} }
/* Order numbers of cover classes in original target cover class
array, -1 for non-cover classes. */
static int cover_class_order[N_REG_CLASSES];
/* The function used to sort the important classes. */
static int
comp_reg_classes_func (const void *v1p, const void *v2p)
{
enum reg_class cl1 = *(const enum reg_class *) v1p;
enum reg_class cl2 = *(const enum reg_class *) v2p;
int diff;
cl1 = ira_class_translate[cl1];
cl2 = ira_class_translate[cl2];
if (cl1 != NO_REGS && cl2 != NO_REGS
&& (diff = cover_class_order[cl1] - cover_class_order[cl2]) != 0)
return diff;
return (int) cl1 - (int) cl2;
}
/* Reorder important classes according to the order of their cover
classes. Set up array ira_important_class_nums too. */
static void
reorder_important_classes (void)
{
int i;
for (i = 0; i < N_REG_CLASSES; i++)
cover_class_order[i] = -1;
for (i = 0; i < ira_reg_class_cover_size; i++)
cover_class_order[ira_reg_class_cover[i]] = i;
qsort (ira_important_classes, ira_important_classes_num,
sizeof (enum reg_class), comp_reg_classes_func);
for (i = 0; i < ira_important_classes_num; i++)
ira_important_class_nums[ira_important_classes[i]] = i;
}
/* The biggest important reg_class inside of intersection of the two /* The biggest important reg_class inside of intersection of the two
reg_classes (that is calculated taking only hard registers reg_classes (that is calculated taking only hard registers
available for allocation into account). If the both reg_classes available for allocation into account). If the both reg_classes
...@@ -1089,6 +1121,7 @@ find_reg_class_closure (void) ...@@ -1089,6 +1121,7 @@ find_reg_class_closure (void)
setup_reg_subclasses (); setup_reg_subclasses ();
setup_cover_and_important_classes (); setup_cover_and_important_classes ();
setup_class_translate (); setup_class_translate ();
reorder_important_classes ();
setup_reg_class_relations (); setup_reg_class_relations ();
} }
......
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