aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog91
-rw-r--r--gcc/cfgloopanal.c4
-rw-r--r--gcc/common.opt6
-rw-r--r--gcc/config/m32c/m32c.h5
-rw-r--r--gcc/doc/invoke.texi32
-rw-r--r--gcc/doc/tm.texi3
-rw-r--r--gcc/flags.h13
-rw-r--r--gcc/genpreds.c2
-rw-r--r--gcc/ira-build.c27
-rw-r--r--gcc/ira-color.c306
-rw-r--r--gcc/ira-conflicts.c34
-rw-r--r--gcc/ira-costs.c36
-rw-r--r--gcc/ira-emit.c9
-rw-r--r--gcc/ira-int.h10
-rw-r--r--gcc/ira-lives.c186
-rw-r--r--gcc/ira.c202
-rw-r--r--gcc/opts.c35
-rw-r--r--gcc/reload1.c7
-rw-r--r--gcc/toplev.c6
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)
{
diff --git a/gcc/ira.c b/gcc/ira.c
index 4b68542..44f7032 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 a87fb49..42e3bee 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 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. */