diff options
-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 87a4762f688..a80bdf54977 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 d59fa2fb505..88c5e956264 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 4e680676c5b..4ffe1fd0518 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 2fb636a5a30..2292a33bb5a 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 7e6da15515d..66d28c77f9c 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 7dfb46b3a0d..5a76a6e5e69 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 4a209b32c12..0fff4f2acd7 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 bf53944e297..84b2e90d9e0 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 b10aa460cef..9e47333d46e 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 4b9909194d6..c9cb1845fe4 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 6e7d7692b67..ff116b5da8a 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 3daeb075d34..a2df9bde9ae 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 29f3fdf6fa7..536d6ee47f4 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 5c6b355ecc8..1fc6da265e2 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 83b5ec85e6f..c7868f39a54 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) { diff --git a/gcc/ira.c b/gcc/ira.c index 4b6854272f1..44f7032bf31 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -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 ()) diff --git a/gcc/opts.c b/gcc/opts.c index a87fb498b15..42e3beeb926 100644 --- a/gcc/opts.c +++ b/gcc/opts.c @@ -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 ac1e874b124..ffde2bf94d8 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 42ad2a48fde..8417cfed6cb 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. */ |