This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
RFA: patch for PR37488
- From: Vladimir Makarov <vmakarov at redhat dot com>
- To: gcc-patches <gcc-patches at gcc dot gnu dot org>
- Cc: Jeffrey Law <law at redhat dot com>, Kenneth Zadeck <Kenneth dot Zadeck at naturalbridge dot com>
- Date: Thu, 02 Jul 2009 17:53:00 -0400
- Subject: RFA: patch for PR37488
The following patch solves PR37488. The details of the problem can
be found on
http://gcc.gnu.org/bugzilla/show_bug.cgi?id=37488
The patch was successfully bootstrapped and tested on x86 and x86_64. It
was benchmarked on SPEC2000 on x86 with -O2 -march=i686 -mfpmath=sse
-msse2. The average scores are practically the same.
Ok to commit?
2009-07-02 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.
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi (revision 149057)
+++ gcc/doc/tm.texi (working copy)
@@ -2905,6 +2905,10 @@ purposes. If a move between two registe
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}.
Index: gcc/ira-lives.c
===================================================================
--- gcc/ira-lives.c (revision 149057)
+++ gcc/ira-lives.c (working copy)
@@ -814,6 +814,22 @@ process_single_reg_class_operands (bool
}
}
+/* 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_nod
/* 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);
Index: gcc/ira.c
===================================================================
--- gcc/ira.c (revision 149057)
+++ gcc/ira.c (working copy)
@@ -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 ();
}
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h (revision 149057)
+++ gcc/config/i386/i386.h (working copy)
@@ -1325,19 +1325,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
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c (revision 149057)
+++ gcc/config/i386/i386.c (working copy)
@@ -26005,6 +26005,22 @@ ix86_free_from_memory (enum machine_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
@@ -30525,6 +30541,9 @@ ix86_enum_va_list (int idx, const char *
#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
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-i386.h"