From 9f724a5879643ac5fce0742debda3ca2e458cdd5 Mon Sep 17 00:00:00 2001 From: vmakarov Date: Wed, 22 Jul 2009 22:00:17 +0000 Subject: [PATCH] 2009-07-22 Vladimir Makarov 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@149962 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 21 ++++++++++++++++ gcc/config/i386/i386.c | 19 ++++++++++++++ gcc/config/i386/i386.h | 13 ---------- gcc/doc/tm.texi | 4 +++ gcc/ira-lives.c | 18 +++++++++++++- gcc/ira.c | 67 +++++++++++++++++++++++++++++++++++++------------- 6 files changed, 111 insertions(+), 31 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 7f3f7561603..774c458a3bf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,24 @@ +2009-07-22 Vladimir Makarov + + 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 * tree-pass.h (TDF_EH): Define. diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index 463d43ef0dc..c11c34aefde 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -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 diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h index f9b9dd17803..15ac4d38247 100644 --- a/gcc/config/i386/i386.h +++ b/gcc/config/i386/i386.h @@ -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 diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 41ed0317521..8157714e1f6 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -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}. diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index 0812c840634..c010f679d37 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -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); diff --git a/gcc/ira.c b/gcc/ira.c index 7a2efe9dc86..e4caf31fb8d 100644 --- a/gcc/ira.c +++ b/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 (); } -- 2.11.0