diff options
author | Vladimir Makarov <vmakarov@redhat.com> | 2008-12-09 21:25:11 +0000 |
---|---|---|
committer | Vladimir Makarov <vmakarov@gcc.gnu.org> | 2008-12-09 21:25:11 +0000 |
commit | 7db7ed3cbd2dbf17be73f254944c28d72de19ca9 (patch) | |
tree | 42be312c545d91eee361dc8d399923279541e6a2 | |
parent | 2e5d002a9e6764888b19b70711501011f1ff1bfe (diff) | |
download | gcc-7db7ed3cbd2dbf17be73f254944c28d72de19ca9.zip gcc-7db7ed3cbd2dbf17be73f254944c28d72de19ca9.tar.gz gcc-7db7ed3cbd2dbf17be73f254944c28d72de19ca9.tar.bz2 |
tm.texi (TARGET_IRA_COVER_CLASSES): Modify description.
2008-12-09 Vladimir Makarov <vmakarov@redhat.com>
* doc/tm.texi (TARGET_IRA_COVER_CLASSES): Modify description.
* doc/invoke.texi (-fira-region): Describe new option.
(-fira-algorithm): Change the values.
* ira-conflicts.c (build_conflict_bit_table,
build_allocno_conflicts): Use ira_reg_classes_intersect_p.
(ira_build_conflicts): Use flag flag_ira_region instead of
flag_ira_algorithm. Prohibit usage of callee-saved likely spilled
base registers for allocnos crossing calls.
* flags.h (enum ira_algorithm): Redefine.
(enum ira_region): New.
(flag_ira_region): New.
* cfgloopanal.c (estimate_reg_pressure_cost): Use flag_ira_region
instead of flag_ira_algorithm.
* toplev.c (flag_ira_algorithm): Change the initial value.
(flag_ira_region): New.
* ira-int.h (ira_reg_classes_intersect_p,
ira_reg_class_super_classes): New.
* ira-color.c (update_copy_costs): Use
ira_reg_classes_intersect_p. Use right class to find hard reg
index.
(update_conflict_hard_regno_costs): Ditto. Add a new parameter.
(assign_hard_reg): Ditto. Pass additional argument to
update_conflict_hard_regno_costs. Do not uncoalesce for priority
coloring.
(allocno_priorities, setup_allocno_priorities,
allocno_priority_compare_func): Move before color_allocnos.
(color_allocnos): Add priority coloring. Use flag flag_ira_region
instead of flag_ira_algorithm.
(move_spill_restore): Check classes of the same reg allocno from
different regions.
(update_curr_costs): Use ira_reg_classes_intersect_p.
(ira_reassign_conflict_allocnos): Ditto.
* opts.c (decode_options): Always set up flag_ira. Set up
flag_ira_algorithm. Warn CB can not be used for architecture.
(common_handle_option): Modify code for -fira-algorithm. Add code
to process -fira-region.
* ira-lives.c (update_allocno_pressure_excess_length): Process
superclasses too.
(set_allocno_live, clear_allocno_live, mark_reg_live,
mark_reg_dead, process_bb_node_lives): Ditto.
* ira-emit.c (ira_emit): Fix insn codes.
* ira-build.c (propagate_allocno_info): Use flag flag_ira_region
instead of flag_ira_algorithm.
(allocno_range_compare_func): Ignore classes for priority
coloring.
(setup_min_max_conflict_allocno_ids): Ditto.
(ira_flattening): Use ira_reg_classes_intersect_p.
* genpreds.c (write_enum_constraint_num): Output
CONSTRAINT__LIMIT.
* common.opt (fira-algorithm): Modify.
(fira-region): New.
* ira.c (setup_class_hard_regs): Initialize.
(setup_cover_and_important_classes): Modify code setting class
related info for priority coloring.
(setup_class_translate): Ditto.
(ira_reg_classes_intersect_p, ira_reg_class_super_classes): New.
(setup_reg_class_intersect_union): Rename to
setup_reg_class_relations. Add code for setting up new variables.
(find_reg_class_closure): Do not check targetm.ira_cover_classes.
(ira): Use flag flag_ira_region instead of flag_ira_algorithm.
* ira-costs.c (common_classes): New.
(print_costs): Use flag flag_ira_region instead of
flag_ira_algorithm.
(find_allocno_class_costs): Ditto. Use common_classes. Translate
alt_class.
(ira_costs): Allocate/deallocate common_classes.
* config/m32c/m32.h (REG_ALLOC_ORDER): Add reg 19.
(REG_CLASS_CONTENTS, reg_class, REG_CLASS_NAMES): New entries for
R02A_REGS.
* reload1.c (choose_reload_regs): Use MODE_INT for partial ints in
smallest_mode_for_size.
From-SVN: r142610
-rw-r--r-- | gcc/ChangeLog | 91 | ||||
-rw-r--r-- | gcc/cfgloopanal.c | 4 | ||||
-rw-r--r-- | gcc/common.opt | 6 | ||||
-rw-r--r-- | gcc/config/m32c/m32c.h | 5 | ||||
-rw-r--r-- | gcc/doc/invoke.texi | 32 | ||||
-rw-r--r-- | gcc/doc/tm.texi | 3 | ||||
-rw-r--r-- | gcc/flags.h | 13 | ||||
-rw-r--r-- | gcc/genpreds.c | 2 | ||||
-rw-r--r-- | gcc/ira-build.c | 27 | ||||
-rw-r--r-- | gcc/ira-color.c | 306 | ||||
-rw-r--r-- | gcc/ira-conflicts.c | 34 | ||||
-rw-r--r-- | gcc/ira-costs.c | 36 | ||||
-rw-r--r-- | gcc/ira-emit.c | 9 | ||||
-rw-r--r-- | gcc/ira-int.h | 10 | ||||
-rw-r--r-- | gcc/ira-lives.c | 186 | ||||
-rw-r--r-- | gcc/ira.c | 202 | ||||
-rw-r--r-- | gcc/opts.c | 35 | ||||
-rw-r--r-- | gcc/reload1.c | 7 | ||||
-rw-r--r-- | gcc/toplev.c | 6 |
19 files changed, 719 insertions, 295 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 87a4762..a80bdf5 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,94 @@ +2008-12-09 Vladimir Makarov <vmakarov@redhat.com> + + * doc/tm.texi (TARGET_IRA_COVER_CLASSES): Modify description. + + * doc/invoke.texi (-fira-region): Describe new option. + (-fira-algorithm): Change the values. + + * ira-conflicts.c (build_conflict_bit_table, + build_allocno_conflicts): Use ira_reg_classes_intersect_p. + (ira_build_conflicts): Use flag flag_ira_region instead of + flag_ira_algorithm. Prohibit usage of callee-saved likely spilled + base registers for allocnos crossing calls. + + * flags.h (enum ira_algorithm): Redefine. + (enum ira_region): New. + (flag_ira_region): New. + + * cfgloopanal.c (estimate_reg_pressure_cost): Use flag_ira_region + instead of flag_ira_algorithm. + + * toplev.c (flag_ira_algorithm): Change the initial value. + (flag_ira_region): New. + + * ira-int.h (ira_reg_classes_intersect_p, + ira_reg_class_super_classes): New. + + * ira-color.c (update_copy_costs): Use + ira_reg_classes_intersect_p. Use right class to find hard reg + index. + (update_conflict_hard_regno_costs): Ditto. Add a new parameter. + (assign_hard_reg): Ditto. Pass additional argument to + update_conflict_hard_regno_costs. Do not uncoalesce for priority + coloring. + (allocno_priorities, setup_allocno_priorities, + allocno_priority_compare_func): Move before color_allocnos. + (color_allocnos): Add priority coloring. Use flag flag_ira_region + instead of flag_ira_algorithm. + (move_spill_restore): Check classes of the same reg allocno from + different regions. + (update_curr_costs): Use ira_reg_classes_intersect_p. + (ira_reassign_conflict_allocnos): Ditto. + + * opts.c (decode_options): Always set up flag_ira. Set up + flag_ira_algorithm. Warn CB can not be used for architecture. + (common_handle_option): Modify code for -fira-algorithm. Add code + to process -fira-region. + + * ira-lives.c (update_allocno_pressure_excess_length): Process + superclasses too. + (set_allocno_live, clear_allocno_live, mark_reg_live, + mark_reg_dead, process_bb_node_lives): Ditto. + + * ira-emit.c (ira_emit): Fix insn codes. + + * ira-build.c (propagate_allocno_info): Use flag flag_ira_region + instead of flag_ira_algorithm. + (allocno_range_compare_func): Ignore classes for priority + coloring. + (setup_min_max_conflict_allocno_ids): Ditto. + (ira_flattening): Use ira_reg_classes_intersect_p. + + * genpreds.c (write_enum_constraint_num): Output + CONSTRAINT__LIMIT. + + * common.opt (fira-algorithm): Modify. + (fira-region): New. + + * ira.c (setup_class_hard_regs): Initialize. + (setup_cover_and_important_classes): Modify code setting class + related info for priority coloring. + (setup_class_translate): Ditto. + (ira_reg_classes_intersect_p, ira_reg_class_super_classes): New. + (setup_reg_class_intersect_union): Rename to + setup_reg_class_relations. Add code for setting up new variables. + (find_reg_class_closure): Do not check targetm.ira_cover_classes. + (ira): Use flag flag_ira_region instead of flag_ira_algorithm. + + * ira-costs.c (common_classes): New. + (print_costs): Use flag flag_ira_region instead of + flag_ira_algorithm. + (find_allocno_class_costs): Ditto. Use common_classes. Translate + alt_class. + (ira_costs): Allocate/deallocate common_classes. + + * config/m32c/m32.h (REG_ALLOC_ORDER): Add reg 19. + (REG_CLASS_CONTENTS, reg_class, REG_CLASS_NAMES): New entries for + R02A_REGS. + + * reload1.c (choose_reload_regs): Use MODE_INT for partial ints in + smallest_mode_for_size. + 2008-12-10 Ben Elliston <bje@au.ibm.com> * config/rs6000/linux-unwind.h (get_regs): Constify casts. diff --git a/gcc/cfgloopanal.c b/gcc/cfgloopanal.c index d59fa2f..88c5e95 100644 --- a/gcc/cfgloopanal.c +++ b/gcc/cfgloopanal.c @@ -396,8 +396,8 @@ estimate_reg_pressure_cost (unsigned n_new, unsigned n_old, bool speed) one. */ cost = target_spill_cost [speed] * n_new; - if (optimize && flag_ira && (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED) + if (optimize && flag_ira && (flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) && number_of_loops () <= (unsigned) IRA_MAX_LOOPS_NUM) /* IRA regional allocation deals with high register pressure better. So decrease the cost (to do more accurate the cost diff --git a/gcc/common.opt b/gcc/common.opt index 4e68067..4ffe1fd 100644 --- a/gcc/common.opt +++ b/gcc/common.opt @@ -683,7 +683,11 @@ Use integrated register allocator. fira-algorithm= Common Joined RejectNegative --fira-algorithm=[regional|CB|mixed] Set the used IRA algorithm +-fira-algorithm=[CB|priority] Set the used IRA algorithm + +fira-region= +Common Joined RejectNegative +-fira-region=[one|all|mixed] Set regions for IRA fira-coalesce Common Report Var(flag_ira_coalesce) Init(0) diff --git a/gcc/config/m32c/m32c.h b/gcc/config/m32c/m32c.h index 2fb636a..2292a33 100644 --- a/gcc/config/m32c/m32c.h +++ b/gcc/config/m32c/m32c.h @@ -224,7 +224,7 @@ machine_function; #define REG_ALLOC_ORDER { \ 0, 1, 2, 3, 4, 5, /* r0..r3, a0, a1 */ \ - 12, 13, 14, 15, 16, 17, 18, /* mem0..mem7 */ \ + 12, 13, 14, 15, 16, 17, 18, 19, /* mem0..mem7 */ \ 6, 7, 8, 9, 10, 11 /* sb, fb, sp, pc, flg, ap */ } /* How Values Fit in Registers */ @@ -270,6 +270,7 @@ machine_function; { 0x000001f0 }, /* PS - a0 a1 sb fp sp */\ { 0x0000000f }, /* SI - r0r2 r1r3 a0a1 */\ { 0x0000003f }, /* HI - r0 r1 r2 r3 a0 a1 */\ + { 0x00000033 }, /* R02A - r0r2 a0 a1 */ \ { 0x0000003f }, /* RA - r0..r3 a0 a1 */\ { 0x0000007f }, /* GENERAL */\ { 0x00000400 }, /* FLG */\ @@ -308,6 +309,7 @@ enum reg_class PS_REGS, SI_REGS, HI_REGS, + R02A_REGS, RA_REGS, GENERAL_REGS, FLG_REGS, @@ -348,6 +350,7 @@ enum reg_class "PS_REGS", \ "SI_REGS", \ "HI_REGS", \ +"R02A_REGS", \ "RA_REGS", \ "GENERAL_REGS", \ "FLG_REGS", \ diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi index 7e6da15..66d28c7 100644 --- a/gcc/doc/invoke.texi +++ b/gcc/doc/invoke.texi @@ -338,7 +338,7 @@ Objective-C and Objective-C++ Dialects}. -finline-small-functions -fipa-cp -fipa-cp-clone -fipa-matrix-reorg -fipa-pta @gol -fipa-pure-const -fipa-reference -fipa-struct-reorg @gol -fipa-type-escape -fira -fira-algorithm=@var{algorithm} @gol --fira-coalesce -fno-ira-share-save-slots @gol +-fira-region=@var{region} -fira-coalesce -fno-ira-share-save-slots @gol -fno-ira-share-spill-slots -fira-verbose=@var{n} @gol -fivopts -fkeep-inline-functions -fkeep-static-consts @gol -floop-block -floop-interchange -floop-strip-mine @gol @@ -5728,17 +5728,25 @@ allocation. It is a default if @acronym{IRA} has been ported for the target. @item -fira-algorithm=@var{algorithm} -Use specified algorithm for the integrated register allocator. The -@var{algorithm} argument should be one of @code{regional}, @code{CB}, -or @code{mixed}. The second algorithm specifies Chaitin-Briggs -coloring, the first one specifies regional coloring based on -Chaitin-Briggs coloring, and the third one which is the default -specifies a mix of Chaitin-Briggs and regional algorithms where loops -with small register pressure are ignored. The first algorithm can -give best result for machines with small size and irregular register -set, the second one is faster and generates decent code and the -smallest size code, and the mixed algorithm usually give the best -results in most cases and for most architectures. +Use specified coloring algorithm for the integrated register +allocator. The @var{algorithm} argument should be @code{priority} or +@code{CB}. The first algorithm specifies Chow's priority coloring, +the second one specifies Chaitin-Briggs coloring. The second +algorithm can be unimplemented for some architectures. If it is +implemented, it is the default because Chaitin-Briggs coloring as a +rule generates a better code. + +@item -fira-region=@var{region} +Use specified regions for the integrated register allocator. The +@var{region} argument should be one of @code{all}, @code{mixed}, or +@code{one}. The first value means using all loops as register +allocation regions, the second value which is the default means using +all loops except for loops with small register pressure as the +regions, and third one means using all function as a single region. +The first value can give best result for machines with small size and +irregular register set, the third one results in faster and generates +decent code and the smallest size code, and the default value usually +give the best results in most cases and for most architectures. @item -fira-coalesce @opindex fira-coalesce diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi index 7dfb46b..5a76a6e 100644 --- a/gcc/doc/tm.texi +++ b/gcc/doc/tm.texi @@ -2841,7 +2841,8 @@ options have been processed. It is then re-examined by every call to The default implementation returns @code{IRA_COVER_CLASSES}, if defined, otherwise there is no default implementation. You must define either this macro or @code{IRA_COVER_CLASSES} in order to use the integrated register -allocator for the target. +allocator with Chaitin-Briggs coloring. If the macro is not defined, +the only available coloring algorithm is Chow's priority coloring. @end deftypefn @defmac IRA_COVER_CLASSES diff --git a/gcc/flags.h b/gcc/flags.h index 4a209b3..0fff4f2 100644 --- a/gcc/flags.h +++ b/gcc/flags.h @@ -209,13 +209,22 @@ extern int flag_dump_rtl_in_asm; /* The algorithm used for the integrated register allocator (IRA). */ enum ira_algorithm { - IRA_ALGORITHM_REGIONAL, IRA_ALGORITHM_CB, - IRA_ALGORITHM_MIXED + IRA_ALGORITHM_PRIORITY }; extern enum ira_algorithm flag_ira_algorithm; +/* The regions used for the integrated register allocator (IRA). */ +enum ira_region +{ + IRA_REGION_ONE, + IRA_REGION_ALL, + IRA_REGION_MIXED +}; + +extern enum ira_region flag_ira_region; + extern unsigned int flag_ira_verbose; diff --git a/gcc/genpreds.c b/gcc/genpreds.c index bf53944..84b2e90 100644 --- a/gcc/genpreds.c +++ b/gcc/genpreds.c @@ -959,7 +959,7 @@ write_enum_constraint_num (void) " CONSTRAINT__UNKNOWN = 0", stdout); FOR_ALL_CONSTRAINTS (c) printf (",\n CONSTRAINT_%s", c->c_name); - puts ("\n};\n"); + puts (",\n CONSTRAINT__LIMIT\n};\n"); } /* Write out a function which looks at a string and determines what diff --git a/gcc/ira-build.c b/gcc/ira-build.c index b10aa46..9e47333 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -1583,8 +1583,8 @@ propagate_allocno_info (void) ira_loop_tree_node_t parent; enum reg_class cover_class; - if (flag_ira_algorithm != IRA_ALGORITHM_REGIONAL - && flag_ira_algorithm != IRA_ALGORITHM_MIXED) + if (flag_ira_region != IRA_REGION_ALL + && flag_ira_region != IRA_REGION_MIXED) return; for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--) for (a = ira_regno_allocno_map[i]; @@ -2116,9 +2116,10 @@ setup_min_max_allocno_live_range_point (void) } /* Sort allocnos according to their live ranges. Allocnos with - smaller cover class are put first. Allocnos with the same cove - class are ordered according their start (min). Allocnos with the - same start are ordered according their finish (max). */ + smaller cover class are put first unless we use priority coloring. + Allocnos with the same cove class are ordered according their start + (min). Allocnos with the same start are ordered according their + finish (max). */ static int allocno_range_compare_func (const void *v1p, const void *v2p) { @@ -2126,7 +2127,8 @@ allocno_range_compare_func (const void *v1p, const void *v2p) ira_allocno_t a1 = *(const ira_allocno_t *) v1p; ira_allocno_t a2 = *(const ira_allocno_t *) v2p; - if ((diff = ALLOCNO_COVER_CLASS (a1) - ALLOCNO_COVER_CLASS (a2)) != 0) + if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && (diff = ALLOCNO_COVER_CLASS (a1) - ALLOCNO_COVER_CLASS (a2)) != 0) return diff; if ((diff = ALLOCNO_MIN (a1) - ALLOCNO_MIN (a2)) != 0) return diff; @@ -2161,7 +2163,7 @@ sort_conflict_id_allocno_map (void) static void setup_min_max_conflict_allocno_ids (void) { - enum reg_class cover_class; + int cover_class; int i, j, min, max, start, finish, first_not_finished, filled_area_start; int *live_range_min, *last_lived; ira_allocno_t a; @@ -2174,7 +2176,9 @@ setup_min_max_conflict_allocno_ids (void) a = ira_conflict_id_allocno_map[i]; if (a == NULL) continue; - if (cover_class != ALLOCNO_COVER_CLASS (a)) + if (cover_class < 0 + || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && cover_class != (int) ALLOCNO_COVER_CLASS (a))) { cover_class = ALLOCNO_COVER_CLASS (a); min = i; @@ -2208,7 +2212,9 @@ setup_min_max_conflict_allocno_ids (void) a = ira_conflict_id_allocno_map[i]; if (a == NULL) continue; - if (cover_class != ALLOCNO_COVER_CLASS (a)) + if (cover_class < 0 + || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && cover_class != (int) ALLOCNO_COVER_CLASS (a))) { cover_class = ALLOCNO_COVER_CLASS (a); for (j = 0; j < ira_max_point; j++) @@ -2503,7 +2509,8 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) { ira_allocno_t live_a = ira_allocnos[n]; - if (cover_class == ALLOCNO_COVER_CLASS (live_a) + if (ira_reg_classes_intersect_p + [cover_class][ALLOCNO_COVER_CLASS (live_a)] /* Don't set up conflict for the allocno with itself. */ && num != (int) n) ira_add_allocno_conflict (a, live_a); diff --git a/gcc/ira-color.c b/gcc/ira-color.c index 4b99091..c9cb184 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -279,7 +279,8 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p) else gcc_unreachable (); - if (cover_class != ALLOCNO_COVER_CLASS (another_allocno) + cover_class = ALLOCNO_COVER_CLASS (another_allocno); + if (! ira_reg_classes_intersect_p[rclass][cover_class] || ALLOCNO_ASSIGNED_P (another_allocno)) continue; @@ -301,6 +302,8 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p) (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno), cover_class, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno)); + i = ira_class_hard_reg_index[cover_class][hard_regno]; + ira_assert (i >= 0); ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno)[i] += update_cost; ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno)[i] += update_cost; @@ -311,17 +314,19 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p) while (get_next_update_cost (&allocno, &divisor)); } -/* This function updates COSTS (decrease if DECR_P) by conflict costs - of the unassigned allocnos connected by copies with allocnos in - update_cost_queue. This update increases chances to remove some - copies. */ +/* This function updates COSTS (decrease if DECR_P) for hard_registers + of COVER_CLASS by conflict costs of the unassigned allocnos + connected by copies with allocnos in update_cost_queue. This + update increases chances to remove some copies. */ static void -update_conflict_hard_regno_costs (int *costs, bool decr_p) +update_conflict_hard_regno_costs (int *costs, enum reg_class cover_class, + bool decr_p) { int i, cost, class_size, freq, mult, div, divisor; + int index, hard_regno; int *conflict_costs; bool cont_p; - enum reg_class cover_class; + enum reg_class another_cover_class; ira_allocno_t allocno, another_allocno; ira_copy_t cp, next_cp; @@ -340,16 +345,17 @@ update_conflict_hard_regno_costs (int *costs, bool decr_p) } else gcc_unreachable (); - cover_class = ALLOCNO_COVER_CLASS (allocno); - if (cover_class != ALLOCNO_COVER_CLASS (another_allocno) + another_cover_class = ALLOCNO_COVER_CLASS (another_allocno); + if (! ira_reg_classes_intersect_p[cover_class][another_cover_class] || ALLOCNO_ASSIGNED_P (another_allocno) || ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO (another_allocno))) continue; - class_size = ira_class_hard_regs_num[cover_class]; + class_size = ira_class_hard_regs_num[another_cover_class]; ira_allocate_and_copy_costs (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno), - cover_class, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno)); + another_cover_class, + ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno)); conflict_costs = ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno); if (conflict_costs == NULL) @@ -364,13 +370,18 @@ update_conflict_hard_regno_costs (int *costs, bool decr_p) cont_p = false; for (i = class_size - 1; i >= 0; i--) { + hard_regno = ira_class_hard_regs[another_cover_class][i]; + ira_assert (hard_regno >= 0); + index = ira_class_hard_reg_index[cover_class][hard_regno]; + if (index < 0) + continue; cost = conflict_costs [i] * mult / div; if (cost == 0) continue; cont_p = true; if (decr_p) cost = -cost; - costs[i] += cost; + costs[index] += cost; } } /* Probably 5 hops will be enough. */ @@ -429,11 +440,11 @@ static bool assign_hard_reg (ira_allocno_t allocno, bool retry_p) { HARD_REG_SET conflicting_regs; - int i, j, hard_regno, best_hard_regno, class_size; + int i, j, k, hard_regno, best_hard_regno, class_size; int cost, mem_cost, min_cost, full_cost, min_full_cost, add_cost; int *a_costs; int *conflict_costs; - enum reg_class cover_class, rclass; + enum reg_class cover_class, rclass, conflict_cover_class; enum machine_mode mode; ira_allocno_t a, conflict_allocno; ira_allocno_conflict_iterator aci; @@ -490,7 +501,9 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) if (retry_p || bitmap_bit_p (consideration_allocno_bitmap, ALLOCNO_NUM (conflict_allocno))) { - ira_assert (cover_class == ALLOCNO_COVER_CLASS (conflict_allocno)); + conflict_cover_class = ALLOCNO_COVER_CLASS (conflict_allocno); + ira_assert (ira_reg_classes_intersect_p + [cover_class][conflict_cover_class]); if (allocno_coalesced_p) { if (bitmap_bit_p (processed_coalesced_allocno_bitmap, @@ -501,7 +514,8 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) } if (ALLOCNO_ASSIGNED_P (conflict_allocno)) { - if ((hard_regno = ALLOCNO_HARD_REGNO (conflict_allocno)) >= 0) + if ((hard_regno = ALLOCNO_HARD_REGNO (conflict_allocno)) >= 0 + && ira_class_hard_reg_index[cover_class][hard_regno] >= 0) { IOR_HARD_REG_SET (conflicting_regs, @@ -511,20 +525,27 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) conflicting_regs)) goto fail; } - continue; } else if (! ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO (conflict_allocno))) { ira_allocate_and_copy_costs (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_allocno), - cover_class, + conflict_cover_class, ALLOCNO_CONFLICT_HARD_REG_COSTS (conflict_allocno)); conflict_costs = ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_allocno); if (conflict_costs != NULL) for (j = class_size - 1; j >= 0; j--) - full_costs[j] -= conflict_costs[j]; + { + hard_regno = ira_class_hard_regs[cover_class][j]; + ira_assert (hard_regno >= 0); + k = (ira_class_hard_reg_index + [conflict_cover_class][hard_regno]); + if (k < 0) + continue; + full_costs[j] -= conflict_costs[k]; + } queue_update_cost (conflict_allocno, COST_HOP_DIVISOR); } } @@ -533,7 +554,7 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) } /* Take into account preferences of allocnos connected by copies to the conflict allocnos. */ - update_conflict_hard_regno_costs (full_costs, true); + update_conflict_hard_regno_costs (full_costs, cover_class, true); /* Take preferences of allocnos connected by copies into account. */ @@ -545,7 +566,7 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) if (a == allocno) break; } - update_conflict_hard_regno_costs (full_costs, false); + update_conflict_hard_regno_costs (full_costs, cover_class, false); min_cost = min_full_cost = INT_MAX; /* We don't care about giving callee saved registers to allocnos no living through calls because call clobbered registers are @@ -594,7 +615,8 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) best_hard_regno = -1; } fail: - if (best_hard_regno < 0 + if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && best_hard_regno < 0 && ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno) != allocno) { for (j = 0, a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);; @@ -1605,6 +1627,10 @@ coalesce_allocnos (bool reload_p) { next_cp = cp->next_first_allocno_copy; regno = ALLOCNO_REGNO (cp->second); + /* For priority coloring we coalesce allocnos only with + the same cover class not with intersected cover + classes as it were possible. It is done for + simplicity. */ if ((reload_p || (ALLOCNO_COVER_CLASS (cp->second) == cover_class && ALLOCNO_MODE (cp->second) == mode)) @@ -1659,12 +1685,72 @@ coalesce_allocnos (bool reload_p) ira_free (sorted_copies); } +/* Map: allocno number -> allocno priority. */ +static int *allocno_priorities; + +/* Set up priorities for N allocnos in array + CONSIDERATION_ALLOCNOS. */ +static void +setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n) +{ + int i, length, nrefs, priority, max_priority, mult; + ira_allocno_t a; + + max_priority = 0; + for (i = 0; i < n; i++) + { + a = consideration_allocnos[i]; + nrefs = ALLOCNO_NREFS (a); + ira_assert (nrefs >= 0); + mult = floor_log2 (ALLOCNO_NREFS (a)) + 1; + ira_assert (mult >= 0); + allocno_priorities[ALLOCNO_NUM (a)] + = priority + = (mult + * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_COVER_CLASS_COST (a)) + * ira_reg_class_nregs[ALLOCNO_COVER_CLASS (a)][ALLOCNO_MODE (a)]); + if (priority < 0) + priority = -priority; + if (max_priority < priority) + max_priority = priority; + } + mult = max_priority == 0 ? 1 : INT_MAX / max_priority; + for (i = 0; i < n; i++) + { + a = consideration_allocnos[i]; + length = ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a); + if (length <= 0) + length = 1; + allocno_priorities[ALLOCNO_NUM (a)] + = allocno_priorities[ALLOCNO_NUM (a)] * mult / length; + } +} + +/* Sort allocnos according to their priorities which are calculated + analogous to ones in file `global.c'. */ +static int +allocno_priority_compare_func (const void *v1p, const void *v2p) +{ + ira_allocno_t a1 = *(const ira_allocno_t *) v1p; + ira_allocno_t a2 = *(const ira_allocno_t *) v2p; + int pri1, pri2; + + pri1 = allocno_priorities[ALLOCNO_NUM (a1)]; + pri2 = allocno_priorities[ALLOCNO_NUM (a2)]; + if (pri2 - pri1) + return pri2 - pri1; + + /* If regs are equally good, sort by allocnos, so that the results of + qsort leave nothing to chance. */ + return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2); +} + /* Chaitin-Briggs coloring for allocnos in COLORING_ALLOCNO_BITMAP taking into account allocnos in CONSIDERATION_ALLOCNO_BITMAP. */ static void color_allocnos (void) { - unsigned int i; + unsigned int i, n; bitmap_iterator bi; ira_allocno_t a; @@ -1672,30 +1758,83 @@ color_allocnos (void) processed_coalesced_allocno_bitmap = ira_allocate_bitmap (); if (flag_ira_coalesce) coalesce_allocnos (false); - /* Put the allocnos into the corresponding buckets. */ - colorable_allocno_bucket = NULL; - uncolorable_allocno_bucket = NULL; - EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) + if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) { - a = ira_allocnos[i]; - if (ALLOCNO_COVER_CLASS (a) == NO_REGS) + n = 0; + EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) { - ALLOCNO_HARD_REGNO (a) = -1; - ALLOCNO_ASSIGNED_P (a) = true; - ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL); - ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL); - if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + a = ira_allocnos[i]; + if (ALLOCNO_COVER_CLASS (a) == NO_REGS) { - fprintf (ira_dump_file, " Spill"); - print_coalesced_allocno (a); - fprintf (ira_dump_file, "\n"); + ALLOCNO_HARD_REGNO (a) = -1; + ALLOCNO_ASSIGNED_P (a) = true; + ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL); + ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL); + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + { + fprintf (ira_dump_file, " Spill"); + print_coalesced_allocno (a); + fprintf (ira_dump_file, "\n"); + } + continue; } - continue; + sorted_allocnos[n++] = a; } - put_allocno_into_bucket (a); + if (n != 0) + { + setup_allocno_priorities (sorted_allocnos, n); + qsort (sorted_allocnos, n, sizeof (ira_allocno_t), + allocno_priority_compare_func); + for (i = 0; i < n; i++) + { + a = sorted_allocnos[i]; + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + { + fprintf (ira_dump_file, " "); + print_coalesced_allocno (a); + fprintf (ira_dump_file, " -- "); + } + if (assign_hard_reg (a, false)) + { + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + fprintf (ira_dump_file, "assign hard reg %d\n", + ALLOCNO_HARD_REGNO (a)); + } + else + { + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + fprintf (ira_dump_file, "assign memory\n"); + } + } + } + } + else + { + /* Put the allocnos into the corresponding buckets. */ + colorable_allocno_bucket = NULL; + uncolorable_allocno_bucket = NULL; + EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) + { + a = ira_allocnos[i]; + if (ALLOCNO_COVER_CLASS (a) == NO_REGS) + { + ALLOCNO_HARD_REGNO (a) = -1; + ALLOCNO_ASSIGNED_P (a) = true; + ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL); + ira_assert (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) == NULL); + if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) + { + fprintf (ira_dump_file, " Spill"); + print_coalesced_allocno (a); + fprintf (ira_dump_file, "\n"); + } + continue; + } + put_allocno_into_bucket (a); + } + push_allocnos_to_stack (); + pop_allocnos_from_stack (); } - push_allocnos_to_stack (); - pop_allocnos_from_stack (); if (flag_ira_coalesce) /* We don't need coalesced allocnos for ira_reassign_pseudos. */ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi) @@ -1796,8 +1935,8 @@ color_pass (ira_loop_tree_node_t loop_tree_node) /* Color all mentioned allocnos including transparent ones. */ color_allocnos (); /* Process caps. They are processed just once. */ - if (flag_ira_algorithm == IRA_ALGORITHM_MIXED - || flag_ira_algorithm == IRA_ALGORITHM_REGIONAL) + if (flag_ira_region == IRA_REGION_MIXED + || flag_ira_region == IRA_REGION_ALL) EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->all_allocnos, 0, j, bi) { a = ira_allocnos[j]; @@ -1806,9 +1945,9 @@ color_pass (ira_loop_tree_node_t loop_tree_node) /* Remove from processing in the next loop. */ bitmap_clear_bit (consideration_allocno_bitmap, j); rclass = ALLOCNO_COVER_CLASS (a); - if ((flag_ira_algorithm == IRA_ALGORITHM_MIXED - && loop_tree_node->reg_pressure[rclass] - <= ira_available_class_regs[rclass])) + if (flag_ira_region == IRA_REGION_MIXED + && (loop_tree_node->reg_pressure[rclass] + <= ira_available_class_regs[rclass])) { mode = ALLOCNO_MODE (a); hard_regno = ALLOCNO_HARD_REGNO (a); @@ -1843,6 +1982,7 @@ color_pass (ira_loop_tree_node_t loop_tree_node) mode = ALLOCNO_MODE (a); rclass = ALLOCNO_COVER_CLASS (a); hard_regno = ALLOCNO_HARD_REGNO (a); + /* Use hard register class here. ??? */ if (hard_regno >= 0) { index = ira_class_hard_reg_index[rclass][hard_regno]; @@ -1854,9 +1994,10 @@ color_pass (ira_loop_tree_node_t loop_tree_node) if (subloop_allocno == NULL || ALLOCNO_CAP (subloop_allocno) != NULL) continue; + ira_assert (ALLOCNO_COVER_CLASS (subloop_allocno) == rclass); ira_assert (bitmap_bit_p (subloop_node->all_allocnos, ALLOCNO_NUM (subloop_allocno))); - if (flag_ira_algorithm == IRA_ALGORITHM_MIXED + if ((flag_ira_region == IRA_REGION_MIXED) && (loop_tree_node->reg_pressure[rclass] <= ira_available_class_regs[rclass])) { @@ -2002,6 +2143,7 @@ move_spill_restore (void) subloop_allocno = subloop_node->regno_allocno_map[regno]; if (subloop_allocno == NULL) continue; + ira_assert (rclass == ALLOCNO_COVER_CLASS (subloop_allocno)); /* We have accumulated cost. To get the real cost of allocno usage in the loop we should subtract costs of the subloop allocnos. */ @@ -2027,6 +2169,7 @@ move_spill_restore (void) if ((parent = loop_node->parent) != NULL && (parent_allocno = parent->regno_allocno_map[regno]) != NULL) { + ira_assert (rclass == ALLOCNO_COVER_CLASS (parent_allocno)); exit_freq = ira_loop_edge_freq (loop_node, regno, true); enter_freq = ira_loop_edge_freq (loop_node, regno, false); if ((hard_regno2 = ALLOCNO_HARD_REGNO (parent_allocno)) < 0) @@ -2094,13 +2237,15 @@ update_curr_costs (ira_allocno_t a) } else gcc_unreachable (); - if (cover_class != ALLOCNO_COVER_CLASS (another_a) + if (! ira_reg_classes_intersect_p[cover_class][ALLOCNO_COVER_CLASS + (another_a)] || ! ALLOCNO_ASSIGNED_P (another_a) || (hard_regno = ALLOCNO_HARD_REGNO (another_a)) < 0) continue; rclass = REGNO_REG_CLASS (hard_regno); i = ira_class_hard_reg_index[cover_class][hard_regno]; - ira_assert (i >= 0); + if (i < 0) + continue; cost = (cp->first == a ? ira_register_move_cost[mode][rclass][cover_class] : ira_register_move_cost[mode][cover_class][rclass]); @@ -2116,66 +2261,6 @@ update_curr_costs (ira_allocno_t a) } } -/* Map: allocno number -> allocno priority. */ -static int *allocno_priorities; - -/* Set up priorities for N allocnos in array - CONSIDERATION_ALLOCNOS. */ -static void -setup_allocno_priorities (ira_allocno_t *consideration_allocnos, int n) -{ - int i, length, nrefs, priority, max_priority, mult; - ira_allocno_t a; - - max_priority = 0; - for (i = 0; i < n; i++) - { - a = consideration_allocnos[i]; - nrefs = ALLOCNO_NREFS (a); - ira_assert (nrefs >= 0); - mult = floor_log2 (ALLOCNO_NREFS (a)) + 1; - ira_assert (mult >= 0); - allocno_priorities[ALLOCNO_NUM (a)] - = priority - = (mult - * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_COVER_CLASS_COST (a)) - * ira_reg_class_nregs[ALLOCNO_COVER_CLASS (a)][ALLOCNO_MODE (a)]); - if (priority < 0) - priority = -priority; - if (max_priority < priority) - max_priority = priority; - } - mult = max_priority == 0 ? 1 : INT_MAX / max_priority; - for (i = 0; i < n; i++) - { - a = consideration_allocnos[i]; - length = ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a); - if (length <= 0) - length = 1; - allocno_priorities[ALLOCNO_NUM (a)] - = allocno_priorities[ALLOCNO_NUM (a)] * mult / length; - } -} - -/* Sort allocnos according to their priorities which are calculated - analogous to ones in file `global.c'. */ -static int -allocno_priority_compare_func (const void *v1p, const void *v2p) -{ - ira_allocno_t a1 = *(const ira_allocno_t *) v1p; - ira_allocno_t a2 = *(const ira_allocno_t *) v2p; - int pri1, pri2; - - pri1 = allocno_priorities[ALLOCNO_NUM (a1)]; - pri2 = allocno_priorities[ALLOCNO_NUM (a2)]; - if (pri2 - pri1) - return pri2 - pri1; - - /* If regs are equally good, sort by allocnos, so that the results of - qsort leave nothing to chance. */ - return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2); -} - /* Try to assign hard registers to the unassigned allocnos and allocnos conflicting with them or conflicting with allocnos whose regno >= START_REGNO. The function is called after ira_flattening, @@ -2215,7 +2300,8 @@ ira_reassign_conflict_allocnos (int start_regno) continue; FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci) { - ira_assert (cover_class == ALLOCNO_COVER_CLASS (conflict_a)); + ira_assert (ira_reg_classes_intersect_p + [cover_class][ALLOCNO_COVER_CLASS (conflict_a)]); if (bitmap_bit_p (allocnos_to_color, ALLOCNO_NUM (conflict_a))) continue; bitmap_set_bit (allocnos_to_color, ALLOCNO_NUM (conflict_a)); diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c index 6e7d769..ff116b5 100644 --- a/gcc/ira-conflicts.c +++ b/gcc/ira-conflicts.c @@ -114,7 +114,8 @@ build_conflict_bit_table (void) EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j) { live_a = ira_allocnos[j]; - if (cover_class == ALLOCNO_COVER_CLASS (live_a) + if (ira_reg_classes_intersect_p + [cover_class][ALLOCNO_COVER_CLASS (live_a)] /* Don't set up conflict for the allocno with itself. */ && num != (int) j) { @@ -555,8 +556,8 @@ build_allocno_conflicts (ira_allocno_t a) ALLOCNO_MIN (a), ALLOCNO_MAX (a), i, asi) { another_a = ira_conflict_id_allocno_map[i]; - ira_assert (ALLOCNO_COVER_CLASS (a) - == ALLOCNO_COVER_CLASS (another_a)); + ira_assert (ira_reg_classes_intersect_p + [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]); collected_conflict_allocnos[px++] = another_a; } if (ira_conflict_vector_profitable_p (a, px)) @@ -592,8 +593,8 @@ build_allocno_conflicts (ira_allocno_t a) ALLOCNO_MIN (a), ALLOCNO_MAX (a), i, asi) { another_a = ira_conflict_id_allocno_map[i]; - ira_assert (ALLOCNO_COVER_CLASS (a) - == ALLOCNO_COVER_CLASS (another_a)); + ira_assert (ira_reg_classes_intersect_p + [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]); if ((another_parent_a = ALLOCNO_CAP (another_a)) == NULL && (another_parent_a = (parent->regno_allocno_map [ALLOCNO_REGNO (another_a)])) == NULL) @@ -740,6 +741,7 @@ ira_build_conflicts (void) { ira_allocno_t a; ira_allocno_iterator ai; + HARD_REG_SET temp_hard_reg_set; if (optimize) { @@ -747,8 +749,8 @@ ira_build_conflicts (void) build_conflicts (); ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, add_copies); /* We need finished conflict table for the subsequent call. */ - if (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED) + if (flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) propagate_copies (); /* Now we can free memory for the conflict table (see function build_allocno_conflicts for details). */ @@ -759,6 +761,14 @@ ira_build_conflicts (void) } ira_free (conflicts); } + if (! CLASS_LIKELY_SPILLED_P (BASE_REG_CLASS)) + CLEAR_HARD_REG_SET (temp_hard_reg_set); + else + { + COPY_HARD_REG_SET (temp_hard_reg_set, reg_class_contents[BASE_REG_CLASS]); + AND_COMPL_HARD_REG_SET (temp_hard_reg_set, ira_no_alloc_regs); + AND_HARD_REG_SET (temp_hard_reg_set, call_used_reg_set); + } FOR_EACH_ALLOCNO (a, ai) { if (ALLOCNO_CALLS_CROSSED_NUM (a) == 0) @@ -775,9 +785,15 @@ ira_build_conflicts (void) { IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), no_caller_save_reg_set); + IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), + temp_hard_reg_set); if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0) - IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), - no_caller_save_reg_set); + { + IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), + no_caller_save_reg_set); + IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), + temp_hard_reg_set); + } } } if (optimize && internal_flag_ira_verbose > 2 && ira_dump_file != NULL) diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 3daeb07..a2df9bd 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -105,6 +105,9 @@ static enum reg_class *allocno_pref; /* Allocated buffers for allocno_pref. */ static enum reg_class *allocno_pref_buffer; +/* Record register class of each allocno with the same regno. */ +static enum reg_class *common_classes; + /* Execution frequency of the current insn. */ static int frequency; @@ -1082,8 +1085,8 @@ print_costs (FILE *f) { fprintf (f, " %s:%d", reg_class_names[rclass], COSTS_OF_ALLOCNO (allocno_costs, i)->cost[k]); - if (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED) + if (flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) fprintf (f, ",%d", COSTS_OF_ALLOCNO (total_costs, i)->cost[k]); } } @@ -1173,7 +1176,7 @@ find_allocno_class_costs (void) int rclass, a_num, parent_a_num; ira_loop_tree_node_t parent; int best_cost, allocno_cost; - enum reg_class best, alt_class, common_class; + enum reg_class best, alt_class; #ifdef FORBIDDEN_INC_DEC_CLASSES int inc_dec_p = false; #endif @@ -1187,8 +1190,8 @@ find_allocno_class_costs (void) a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) { a_num = ALLOCNO_NUM (a); - if ((flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED) + if ((flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED) && (parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) != NULL && (parent_a = parent->regno_allocno_map[i]) != NULL /* There are no caps yet. */ @@ -1247,6 +1250,7 @@ find_allocno_class_costs (void) > reg_class_size[alt_class])) alt_class = reg_class_subunion[alt_class][rclass]; } + alt_class = ira_class_translate[alt_class]; if (pass == flag_expensive_optimizations) { if (best_cost > temp_costs->mem_cost) @@ -1260,18 +1264,22 @@ find_allocno_class_costs (void) i, reg_class_names[best], reg_class_names[alt_class]); } if (best_cost > temp_costs->mem_cost) - common_class = NO_REGS; + common_classes[i] = NO_REGS; + else if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) + /* Make the common class the biggest class of best and + alt_class. */ + common_classes[i] = alt_class == NO_REGS ? best : alt_class; else /* Make the common class a cover class. Remember all allocnos with the same regno should have the same cover class. */ - common_class = ira_class_translate[best]; + common_classes[i] = ira_class_translate[best]; for (a = ira_regno_allocno_map[i]; a != NULL; a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) { a_num = ALLOCNO_NUM (a); - if (common_class == NO_REGS) + if (common_classes[i] == NO_REGS) best = NO_REGS; else { @@ -1283,7 +1291,7 @@ find_allocno_class_costs (void) for (k = 0; k < cost_classes_num; k++) { rclass = cost_classes[k]; - if (! ira_class_subset_p[rclass][common_class]) + if (! ira_class_subset_p[rclass][common_classes[i]]) continue; /* Ignore classes that are too small for this operand or invalid for an operand that was @@ -1319,6 +1327,8 @@ find_allocno_class_costs (void) } ALLOCNO_COVER_CLASS_COST (a) = allocno_cost; } + ira_assert (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY + || ira_class_translate[best] == common_classes[i]); if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL && (pass == 0 || allocno_pref[a_num] != best)) { @@ -1330,7 +1340,7 @@ find_allocno_class_costs (void) ALLOCNO_LOOP_TREE_NODE (a)->loop->num); fprintf (ira_dump_file, ") best %s, cover %s\n", reg_class_names[best], - reg_class_names[ira_class_translate[best]]); + reg_class_names[common_classes[i]]); } allocno_pref[a_num] = best; } @@ -1439,7 +1449,7 @@ setup_allocno_cover_class_and_costs (void) { i = ALLOCNO_NUM (a); mode = ALLOCNO_MODE (a); - cover_class = ira_class_translate[allocno_pref[i]]; + cover_class = common_classes[ALLOCNO_REGNO (a)]; ira_assert (allocno_pref[i] == NO_REGS || cover_class != NO_REGS); ALLOCNO_MEMORY_COST (a) = COSTS_OF_ALLOCNO (allocno_costs, i)->mem_cost; ira_set_allocno_cover_class (a, cover_class); @@ -1572,6 +1582,9 @@ ira_costs (void) allocno_pref_buffer = (enum reg_class *) ira_allocate (sizeof (enum reg_class) * ira_allocnos_num); + common_classes + = (enum reg_class *) ira_allocate (sizeof (enum reg_class) + * max_reg_num ()); find_allocno_class_costs (); setup_allocno_cover_class_and_costs (); /* Because we could process operands only as subregs, check mode of @@ -1580,6 +1593,7 @@ ira_costs (void) if (ira_register_move_cost[ALLOCNO_MODE (a)] == NULL && have_regs_of_mode[ALLOCNO_MODE (a)]) ira_init_register_move_cost (ALLOCNO_MODE (a)); + ira_free (common_classes); ira_free (allocno_pref_buffer); ira_free (total_costs); ira_free (allocno_costs); diff --git a/gcc/ira-emit.c b/gcc/ira-emit.c index 29f3fdf..536d6ee 100644 --- a/gcc/ira-emit.c +++ b/gcc/ira-emit.c @@ -1025,6 +1025,7 @@ void ira_emit (bool loops_p) { basic_block bb; + rtx insn; edge_iterator ei; edge e; ira_allocno_t a; @@ -1085,6 +1086,14 @@ ira_emit (bool loops_p) ira_free (allocno_last_set_check); ira_free (allocno_last_set); commit_edge_insertions (); + /* Fix insn codes. It is necessary to do it before reload because + reload assumes initial insn codes defined. The insn codes can be + invalidated by CFG infrastructure for example in jump + redirection. */ + FOR_EACH_BB (bb) + FOR_BB_INSNS_REVERSE (bb, insn) + if (INSN_P (insn)) + recog_memoized (insn); ira_free (at_bb_end); ira_free (at_bb_start); } diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 5c6b355..1fc6da2 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -819,6 +819,16 @@ extern enum reg_class ira_class_translate[N_REG_CLASSES]; taking all hard-registers including fixed ones into account. */ extern enum reg_class ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES]; +/* True if the two classes (that is calculated taking only hard + registers available for allocation into account) are + intersected. */ +extern bool ira_reg_classes_intersect_p[N_REG_CLASSES][N_REG_CLASSES]; + +/* Classes with end marker LIM_REG_CLASSES which are intersected with + given class (the first index). That includes given class itself. + This is calculated taking only hard registers available for + allocation into account. */ +extern enum reg_class ira_reg_class_super_classes[N_REG_CLASSES][N_REG_CLASSES]; /* The biggest important class inside of union of the two classes (that is calculated taking only hard registers available for allocation into account). If the both classes contain no hard diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index 83b5ec8..c7868f3 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -117,18 +117,23 @@ make_regno_born (int regno) static void update_allocno_pressure_excess_length (ira_allocno_t a) { - int start; - enum reg_class cover_class; + int start, i; + enum reg_class cover_class, cl; allocno_live_range_t p; cover_class = ALLOCNO_COVER_CLASS (a); - if (high_pressure_start_point[cover_class] < 0) - return; - p = ALLOCNO_LIVE_RANGES (a); - ira_assert (p != NULL); - start = (high_pressure_start_point[cover_class] > p->start - ? high_pressure_start_point[cover_class] : p->start); - ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += curr_point - start + 1; + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; + i++) + { + if (high_pressure_start_point[cl] < 0) + continue; + p = ALLOCNO_LIVE_RANGES (a); + ira_assert (p != NULL); + start = (high_pressure_start_point[cl] > p->start + ? high_pressure_start_point[cl] : p->start); + ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += curr_point - start + 1; + } } /* Process the death of register REGNO. This updates hard_regs_live @@ -165,8 +170,8 @@ static int curr_reg_pressure[N_REG_CLASSES]; static void set_allocno_live (ira_allocno_t a) { - int nregs; - enum reg_class cover_class; + int i; + enum reg_class cover_class, cl; /* Invalidate because it is referenced. */ allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; @@ -176,15 +181,17 @@ set_allocno_live (ira_allocno_t a) IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), hard_regs_live); IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), hard_regs_live); cover_class = ALLOCNO_COVER_CLASS (a); - nregs = ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)]; - curr_reg_pressure[cover_class] += nregs; - if (high_pressure_start_point[cover_class] < 0 - && (curr_reg_pressure[cover_class] - > ira_available_class_regs[cover_class])) - high_pressure_start_point[cover_class] = curr_point; - if (curr_bb_node->reg_pressure[cover_class] - < curr_reg_pressure[cover_class]) - curr_bb_node->reg_pressure[cover_class] = curr_reg_pressure[cover_class]; + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; + i++) + { + curr_reg_pressure[cl] += ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; + if (high_pressure_start_point[cl] < 0 + && (curr_reg_pressure[cl] > ira_available_class_regs[cl])) + high_pressure_start_point[cl] = curr_point; + if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl]) + curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl]; + } } /* Mark allocno A as currently not living and update current register @@ -193,26 +200,40 @@ set_allocno_live (ira_allocno_t a) static void clear_allocno_live (ira_allocno_t a) { - unsigned int i; - enum reg_class cover_class; + int i; + unsigned int j; + enum reg_class cover_class, cl; + bool set_p; /* Invalidate because it is referenced. */ allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) { cover_class = ALLOCNO_COVER_CLASS (a); - curr_reg_pressure[cover_class] - -= ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)]; - ira_assert (curr_reg_pressure[cover_class] >= 0); - if (high_pressure_start_point[cover_class] >= 0 - && (curr_reg_pressure[cover_class] - <= ira_available_class_regs[cover_class])) + set_p = false; + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) { - EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i) - { - update_allocno_pressure_excess_length (ira_allocnos[i]); - } - high_pressure_start_point[cover_class] = -1; + curr_reg_pressure[cl] -= ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; + ira_assert (curr_reg_pressure[cl] >= 0); + if (high_pressure_start_point[cl] >= 0 + && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) + set_p = true; + } + if (set_p) + { + EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j) + update_allocno_pressure_excess_length (ira_allocnos[j]); + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) + if (high_pressure_start_point[cl] >= 0 + && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) + high_pressure_start_point[cl] = -1; + } } sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a)); @@ -225,7 +246,7 @@ clear_allocno_live (ira_allocno_t a) static void mark_reg_live (rtx reg) { - int regno; + int i, regno; gcc_assert (REG_P (reg)); regno = REGNO (reg); @@ -249,7 +270,7 @@ mark_reg_live (rtx reg) else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) { int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; - enum reg_class cover_class; + enum reg_class cover_class, cl; while (regno < last) { @@ -257,20 +278,26 @@ mark_reg_live (rtx reg) && ! TEST_HARD_REG_BIT (eliminable_regset, regno)) { cover_class = ira_hard_regno_cover_class[regno]; - if (cover_class != NO_REGS) + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) { - curr_reg_pressure[cover_class]++; - if (high_pressure_start_point[cover_class] < 0 - && (curr_reg_pressure[cover_class] - > ira_available_class_regs[cover_class])) - high_pressure_start_point[cover_class] = curr_point; + curr_reg_pressure[cl]++; + if (high_pressure_start_point[cl] < 0 + && (curr_reg_pressure[cl] + > ira_available_class_regs[cl])) + high_pressure_start_point[cl] = curr_point; } make_regno_born (regno); - if (cover_class != NO_REGS - && (curr_bb_node->reg_pressure[cover_class] - < curr_reg_pressure[cover_class])) - curr_bb_node->reg_pressure[cover_class] - = curr_reg_pressure[cover_class]; + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) + { + if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl]) + curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl]; + } } regno++; } @@ -317,30 +344,41 @@ mark_reg_dead (rtx reg) } else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) { - unsigned int i; + int i; + unsigned int j; int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; - enum reg_class cover_class; + enum reg_class cover_class, cl; + bool set_p; while (regno < last) { if (TEST_HARD_REG_BIT (hard_regs_live, regno)) { + set_p = false; cover_class = ira_hard_regno_cover_class[regno]; - if (cover_class != NO_REGS) + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) + { + curr_reg_pressure[cl]--; + if (high_pressure_start_point[cl] >= 0 + && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) + set_p = true; + ira_assert (curr_reg_pressure[cl] >= 0); + } + if (set_p) { - curr_reg_pressure[cover_class]--; - if (high_pressure_start_point[cover_class] >= 0 - && (curr_reg_pressure[cover_class] - <= ira_available_class_regs[cover_class])) - { - EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i) - { - update_allocno_pressure_excess_length - (ira_allocnos[i]); - } - high_pressure_start_point[cover_class] = -1; - } - ira_assert (curr_reg_pressure[cover_class] >= 0); + EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j) + update_allocno_pressure_excess_length (ira_allocnos[j]); + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) + != LIM_REG_CLASSES; + i++) + if (high_pressure_start_point[cl] >= 0 + && (curr_reg_pressure[cl] + <= ira_available_class_regs[cl])) + high_pressure_start_point[cl] = -1; } make_regno_dead (regno); } @@ -807,18 +845,20 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) if (TEST_HARD_REG_BIT (hard_regs_live, i)) { - enum reg_class cover_class; + enum reg_class cover_class, cl; - cover_class = ira_hard_regno_cover_class[i]; - if (cover_class == NO_REGS) - continue; - curr_reg_pressure[cover_class]++; - if (curr_bb_node->reg_pressure[cover_class] - < curr_reg_pressure[cover_class]) - curr_bb_node->reg_pressure[cover_class] - = curr_reg_pressure[cover_class]; - ira_assert (curr_reg_pressure[cover_class] - <= ira_available_class_regs[cover_class]); + cover_class = ira_class_translate[REGNO_REG_CLASS (i)]; + for (j = 0; + (cl = ira_reg_class_super_classes[cover_class][j]) + != LIM_REG_CLASSES; + j++) + { + curr_reg_pressure[cl]++; + if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl]) + curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl]; + ira_assert (curr_reg_pressure[cl] + <= ira_available_class_regs[cl]); + } } EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi) { @@ -434,6 +434,8 @@ setup_class_hard_regs (void) COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); CLEAR_HARD_REG_SET (processed_hard_reg_set); + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + ira_class_hard_reg_index[cl][0] = -1; for (n = 0, i = 0; i < FIRST_PSEUDO_REGISTER; i++) { #ifdef REG_ALLOC_ORDER @@ -714,22 +716,72 @@ enum reg_class ira_important_classes[N_REG_CLASSES]; classes. */ int ira_important_class_nums[N_REG_CLASSES]; -/* Check IRA_COVER_CLASSES and sets the four global variables defined - above. */ +/* Set the four global variables defined above. */ static void setup_cover_and_important_classes (void) { - int i, j; + int i, j, n; + bool set_p, eq_p; enum reg_class cl; - const enum reg_class *classes; + const enum reg_class *cover_classes; HARD_REG_SET temp_hard_regset2; + static enum reg_class classes[LIM_REG_CLASSES + 1]; + + if (targetm.ira_cover_classes == NULL) + cover_classes = NULL; + else + cover_classes = targetm.ira_cover_classes (); + if (cover_classes == NULL) + ira_assert (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY); + else + { + for (i = 0; (cl = cover_classes[i]) != LIM_REG_CLASSES; i++) + classes[i] = cl; + classes[i] = LIM_REG_CLASSES; + } + + if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) + { + n = 0; + for (i = 0; i <= LIM_REG_CLASSES; i++) + { + if (i == NO_REGS) + continue; +#ifdef CONSTRAINT__LIMIT + for (j = 0; j < CONSTRAINT__LIMIT; j++) + if ((int) regclass_for_constraint (j) == i) + break; + if (j < CONSTRAINT__LIMIT) + { + classes[n++] = i; + continue; + } +#endif + COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[i]); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); + for (j = 0; j < LIM_REG_CLASSES; j++) + { + if (i == j) + continue; + COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[j]); + AND_COMPL_HARD_REG_SET (temp_hard_regset2, + no_unit_alloc_regs); + if (hard_reg_set_equal_p (temp_hard_regset, + temp_hard_regset2)) + break; + } + if (j >= i) + classes[n++] = i; + } + classes[n] = LIM_REG_CLASSES; + } - classes = targetm.ira_cover_classes (); ira_reg_class_cover_size = 0; for (i = 0; (cl = classes[i]) != LIM_REG_CLASSES; i++) { for (j = 0; j < i; j++) - if (reg_classes_intersect_p (cl, classes[j])) + if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY + && reg_classes_intersect_p (cl, classes[j])) gcc_unreachable (); COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); @@ -742,22 +794,34 @@ setup_cover_and_important_classes (void) COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); if (! hard_reg_set_empty_p (temp_hard_regset)) - for (j = 0; j < ira_reg_class_cover_size; j++) - { - COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); - AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); - 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 (cl == ira_reg_class_cover[j] - || (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2) - && ! hard_reg_set_equal_p (temp_hard_regset, - temp_hard_regset2))) - { - ira_important_class_nums[cl] = ira_important_classes_num; - ira_important_classes[ira_important_classes_num++] = cl; - } - } + { + set_p = eq_p = false; + for (j = 0; j < ira_reg_class_cover_size; j++) + { + COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); + 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 (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; + 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++] = cl; + } + } } } @@ -776,25 +840,44 @@ setup_class_translate (void) for (cl = 0; cl < N_REG_CLASSES; cl++) ira_class_translate[cl] = NO_REGS; + + if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY) + for (cl = 0; cl < LIM_REG_CLASSES; cl++) + { + COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); + for (i = 0; i < ira_reg_class_cover_size; i++) + { + HARD_REG_SET temp_hard_regset2; + + cover_class = ira_reg_class_cover[i]; + COPY_HARD_REG_SET (temp_hard_regset2, + reg_class_contents[cover_class]); + AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs); + if (hard_reg_set_equal_p (temp_hard_regset, temp_hard_regset2)) + ira_class_translate[cl] = cover_class; + } + } for (i = 0; i < ira_reg_class_cover_size; i++) { cover_class = ira_reg_class_cover[i]; - for (cl_ptr = &alloc_reg_class_subclasses[cover_class][0]; - (cl = *cl_ptr) != LIM_REG_CLASSES; - cl_ptr++) - { - if (ira_class_translate[cl] == NO_REGS) - ira_class_translate[cl] = cover_class; + if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY) + for (cl_ptr = &alloc_reg_class_subclasses[cover_class][0]; + (cl = *cl_ptr) != LIM_REG_CLASSES; + cl_ptr++) + { + if (ira_class_translate[cl] == NO_REGS) + ira_class_translate[cl] = cover_class; #ifdef ENABLE_IRA_CHECKING - else - { - COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); - AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); - if (! hard_reg_set_empty_p (temp_hard_regset)) - gcc_unreachable (); - } + else + { + COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]); + AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); + if (! hard_reg_set_empty_p (temp_hard_regset)) + gcc_unreachable (); + } #endif - } + } ira_class_translate[cover_class] = cover_class; } /* For classes which are not fully covered by a cover class (in @@ -842,6 +925,17 @@ setup_class_translate (void) account. */ enum reg_class ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES]; +/* True if the two classes (that is calculated taking only hard + registers available for allocation into account) are + intersected. */ +bool ira_reg_classes_intersect_p[N_REG_CLASSES][N_REG_CLASSES]; + +/* Important classes with end marker LIM_REG_CLASSES which are + supersets with given important class (the first index). That + includes given class itself. This is calculated taking only hard + registers available for allocation into account. */ +enum reg_class ira_reg_class_super_classes[N_REG_CLASSES][N_REG_CLASSES]; + /* The biggest important reg_class inside of union of the two reg_classes (that is calculated taking only hard registers available for allocation into account). If the both reg_classes @@ -851,17 +945,23 @@ enum reg_class ira_reg_class_intersect[N_REG_CLASSES][N_REG_CLASSES]; reg_class_subunion value. */ enum reg_class ira_reg_class_union[N_REG_CLASSES][N_REG_CLASSES]; -/* Set up IRA_REG_CLASS_INTERSECT and IRA_REG_CLASS_UNION. */ +/* Set up the above reg class relations. */ static void -setup_reg_class_intersect_union (void) +setup_reg_class_relations (void) { int i, cl1, cl2, cl3; HARD_REG_SET intersection_set, union_set, temp_set2; + bool important_class_p[N_REG_CLASSES]; + memset (important_class_p, 0, sizeof (important_class_p)); + for (i = 0; i < ira_important_classes_num; i++) + important_class_p[ira_important_classes[i]] = true; for (cl1 = 0; cl1 < N_REG_CLASSES; cl1++) { + ira_reg_class_super_classes[cl1][0] = LIM_REG_CLASSES; for (cl2 = 0; cl2 < N_REG_CLASSES; cl2++) { + ira_reg_classes_intersect_p[cl1][cl2] = false; ira_reg_class_intersect[cl1][cl2] = NO_REGS; COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl1]); AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs); @@ -882,6 +982,19 @@ setup_reg_class_intersect_union (void) ira_reg_class_union[cl1][cl2] = reg_class_subunion[cl1][cl2]; continue; } + ira_reg_classes_intersect_p[cl1][cl2] + = hard_reg_set_intersect_p (temp_hard_regset, temp_set2); + if (important_class_p[cl1] && important_class_p[cl2] + && hard_reg_set_subset_p (temp_hard_regset, temp_set2)) + { + enum reg_class *p; + + p = &ira_reg_class_super_classes[cl1][0]; + while (*p != LIM_REG_CLASSES) + p++; + *p++ = (enum reg_class) cl2; + *p = LIM_REG_CLASSES; + } ira_reg_class_union[cl1][cl2] = NO_REGS; COPY_HARD_REG_SET (intersection_set, reg_class_contents[cl1]); AND_HARD_REG_SET (intersection_set, reg_class_contents[cl2]); @@ -966,12 +1079,9 @@ static void find_reg_class_closure (void) { setup_reg_subclasses (); - if (targetm.ira_cover_classes) - { - setup_cover_and_important_classes (); - setup_class_translate (); - setup_reg_class_intersect_union (); - } + setup_cover_and_important_classes (); + setup_class_translate (); + setup_reg_class_relations (); } @@ -1804,8 +1914,8 @@ ira (FILE *f) if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL) fprintf (ira_dump_file, "Building IRA IR\n"); loops_p = ira_build (optimize - && (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL - || flag_ira_algorithm == IRA_ALGORITHM_MIXED)); + && (flag_ira_region == IRA_REGION_ALL + || flag_ira_region == IRA_REGION_MIXED)); saved_flag_ira_share_spill_slots = flag_ira_share_spill_slots; if (too_high_register_pressure_p ()) @@ -870,9 +870,11 @@ decode_options (unsigned int argc, const char **argv) } } - /* Use IRA if it is implemented for the target. */ - if (targetm.ira_cover_classes) - flag_ira = 1; + flag_ira = 1; + /* Use priority coloring if cover classes is not defined for the + target. */ + if (targetm.ira_cover_classes == NULL) + flag_ira_algorithm = IRA_ALGORITHM_PRIORITY; /* -O1 optimizations. */ opt1 = (optimize >= 1); @@ -1096,10 +1098,12 @@ decode_options (unsigned int argc, const char **argv) if (!flag_sel_sched_pipelining) flag_sel_sched_pipelining_outer_loops = 0; - if (flag_ira && !targetm.ira_cover_classes) + if (flag_ira && !targetm.ira_cover_classes + && flag_ira_algorithm == IRA_ALGORITHM_CB) { - inform (input_location, "-fira does not work on this architecture"); - flag_ira = 0; + inform (input_location, + "-fira-algorithm=CB does not work on this architecture"); + flag_ira_algorithm = IRA_ALGORITHM_PRIORITY; } /* Save the current optimization options if this is the first call. */ @@ -1976,16 +1980,25 @@ common_handle_option (size_t scode, const char *arg, int value, break; case OPT_fira_algorithm_: - if (!strcmp (arg, "regional")) - flag_ira_algorithm = IRA_ALGORITHM_REGIONAL; - else if (!strcmp (arg, "CB")) + if (!strcmp (arg, "CB")) flag_ira_algorithm = IRA_ALGORITHM_CB; - else if (!strcmp (arg, "mixed")) - flag_ira_algorithm = IRA_ALGORITHM_MIXED; + else if (!strcmp (arg, "priority")) + flag_ira_algorithm = IRA_ALGORITHM_PRIORITY; else warning (0, "unknown ira algorithm \"%s\"", arg); break; + case OPT_fira_region_: + if (!strcmp (arg, "one")) + flag_ira_region = IRA_REGION_ONE; + else if (!strcmp (arg, "all")) + flag_ira_region = IRA_REGION_ALL; + else if (!strcmp (arg, "mixed")) + flag_ira_region = IRA_REGION_MIXED; + else + warning (0, "unknown ira region \"%s\"", arg); + break; + case OPT_fira_verbose_: flag_ira_verbose = value; break; diff --git a/gcc/reload1.c b/gcc/reload1.c index ac1e874..ffde2bf 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -6084,9 +6084,10 @@ choose_reload_regs (struct insn_chain *chain) need_mode = mode; else need_mode - = smallest_mode_for_size (GET_MODE_BITSIZE (mode) - + byte * BITS_PER_UNIT, - GET_MODE_CLASS (mode)); + = smallest_mode_for_size + (GET_MODE_BITSIZE (mode) + byte * BITS_PER_UNIT, + GET_MODE_CLASS (mode) == MODE_PARTIAL_INT + ? MODE_INT : GET_MODE_CLASS (mode)); if ((GET_MODE_SIZE (GET_MODE (last_reg)) >= GET_MODE_SIZE (need_mode)) diff --git a/gcc/toplev.c b/gcc/toplev.c index 42ad2a4..8417cfe 100644 --- a/gcc/toplev.c +++ b/gcc/toplev.c @@ -271,9 +271,11 @@ int flag_next_runtime = 0; enum tls_model flag_tls_default = TLS_MODEL_GLOBAL_DYNAMIC; -/* Set the default algorithm for the integrated register allocator. */ +/* Set the default region and algorithm for the integrated register + allocator. */ -enum ira_algorithm flag_ira_algorithm = IRA_ALGORITHM_MIXED; +enum ira_algorithm flag_ira_algorithm = IRA_ALGORITHM_CB; +enum ira_region flag_ira_region = IRA_REGION_MIXED; /* Set the default value for -fira-verbose. */ |