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
This commit is contained in:
parent
cae63f886f
commit
db1a8d9889
@ -1,3 +1,24 @@
|
||||
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>
|
||||
|
||||
* tree-pass.h (TDF_EH): Define.
|
||||
|
@ -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.
|
||||
QImode must go into class Q_REGS.
|
||||
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)
|
||||
#undef TARGET_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
|
||||
#define TARGET_FRAME_POINTER_REQUIRED ix86_frame_pointer_required
|
||||
|
||||
|
@ -1288,19 +1288,6 @@ enum reg_class
|
||||
{ 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:
|
||||
Return the class number of the smallest class containing
|
||||
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
|
||||
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 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
|
||||
options have been processed. It is then re-examined by every call to
|
||||
@code{target_reinit}.
|
||||
|
@ -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
|
||||
update allocno live ranges, allocno hard register conflicts,
|
||||
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)
|
||||
/* No need to record conflicts for call clobbered regs if we
|
||||
have nonlocal labels around, as we don't ever try to
|
||||
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++)
|
||||
if (call_used_regs[px])
|
||||
make_regno_born (px);
|
||||
|
67
gcc/ira.c
67
gcc/ira.c
@ -729,7 +729,7 @@ static void
|
||||
setup_cover_and_important_classes (void)
|
||||
{
|
||||
int i, j, n, cl;
|
||||
bool set_p, eq_p;
|
||||
bool set_p;
|
||||
const enum reg_class *cover_classes;
|
||||
HARD_REG_SET temp_hard_regset2;
|
||||
static enum reg_class classes[LIM_REG_CLASSES + 1];
|
||||
@ -802,7 +802,7 @@ setup_cover_and_important_classes (void)
|
||||
AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
|
||||
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++)
|
||||
{
|
||||
COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
|
||||
@ -810,27 +810,22 @@ setup_cover_and_important_classes (void)
|
||||
COPY_HARD_REG_SET (temp_hard_regset2,
|
||||
reg_class_contents[ira_reg_class_cover[j]]);
|
||||
AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
|
||||
if ((enum reg_class) cl == ira_reg_class_cover[j])
|
||||
{
|
||||
eq_p = false;
|
||||
set_p = true;
|
||||
break;
|
||||
}
|
||||
else if (hard_reg_set_equal_p (temp_hard_regset,
|
||||
temp_hard_regset2))
|
||||
eq_p = true;
|
||||
if ((enum reg_class) cl == ira_reg_class_cover[j]
|
||||
|| hard_reg_set_equal_p (temp_hard_regset,
|
||||
temp_hard_regset2))
|
||||
break;
|
||||
else if (hard_reg_set_subset_p (temp_hard_regset,
|
||||
temp_hard_regset2))
|
||||
set_p = true;
|
||||
}
|
||||
if (set_p && ! eq_p)
|
||||
{
|
||||
ira_important_class_nums[cl] = ira_important_classes_num;
|
||||
ira_important_classes[ira_important_classes_num++] =
|
||||
(enum reg_class) cl;
|
||||
}
|
||||
if (set_p && j >= ira_reg_class_cover_size)
|
||||
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
|
||||
@ -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
|
||||
reg_classes (that is calculated taking only hard registers
|
||||
available for allocation into account). If the both reg_classes
|
||||
@ -1089,6 +1121,7 @@ find_reg_class_closure (void)
|
||||
setup_reg_subclasses ();
|
||||
setup_cover_and_important_classes ();
|
||||
setup_class_translate ();
|
||||
reorder_important_classes ();
|
||||
setup_reg_class_relations ();
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user