tm.texi (TARGET_IRA_COVER_CLASSES): Modify description.

2008-12-09  Vladimir Makarov  <vmakarov@redhat.com>

	* doc/tm.texi (TARGET_IRA_COVER_CLASSES): Modify description.

	* doc/invoke.texi (-fira-region): Describe new option.
	(-fira-algorithm): Change the values.

	* ira-conflicts.c (build_conflict_bit_table,
	build_allocno_conflicts): Use ira_reg_classes_intersect_p.
	(ira_build_conflicts): Use flag flag_ira_region instead of
	flag_ira_algorithm.  Prohibit usage of callee-saved likely spilled
	base registers for allocnos crossing calls.

	* flags.h (enum ira_algorithm): Redefine.
	(enum ira_region): New.
	(flag_ira_region): New.

	* cfgloopanal.c (estimate_reg_pressure_cost): Use flag_ira_region
	instead of flag_ira_algorithm.

	* toplev.c (flag_ira_algorithm): Change the initial value.
	(flag_ira_region): New.

	* ira-int.h (ira_reg_classes_intersect_p,
	ira_reg_class_super_classes): New.

	* ira-color.c (update_copy_costs): Use
	ira_reg_classes_intersect_p.  Use right class to find hard reg
	index.
	(update_conflict_hard_regno_costs): Ditto.  Add a new parameter.
	(assign_hard_reg): Ditto.  Pass additional argument to
	update_conflict_hard_regno_costs.  Do not uncoalesce for priority
	coloring.
	(allocno_priorities, setup_allocno_priorities,
	allocno_priority_compare_func): Move before color_allocnos.
	(color_allocnos): Add priority coloring.  Use flag flag_ira_region
	instead of flag_ira_algorithm.
	(move_spill_restore): Check classes of the same reg allocno from
	different regions.
	(update_curr_costs): Use ira_reg_classes_intersect_p.
	(ira_reassign_conflict_allocnos): Ditto.

	* opts.c (decode_options): Always set up flag_ira.  Set up
	flag_ira_algorithm.  Warn CB can not be used for architecture.
	(common_handle_option): Modify code for -fira-algorithm.  Add code
	to process -fira-region.

	* ira-lives.c (update_allocno_pressure_excess_length): Process
	superclasses too.
	(set_allocno_live, clear_allocno_live, mark_reg_live,
	mark_reg_dead, process_bb_node_lives): Ditto.

	* ira-emit.c (ira_emit): Fix insn codes.
	
	* ira-build.c (propagate_allocno_info): Use flag flag_ira_region
	instead of flag_ira_algorithm.
	(allocno_range_compare_func): Ignore classes for priority
	coloring.
	(setup_min_max_conflict_allocno_ids): Ditto.
	(ira_flattening): Use ira_reg_classes_intersect_p.

	* genpreds.c (write_enum_constraint_num): Output
	CONSTRAINT__LIMIT.
	
	* common.opt (fira-algorithm): Modify.
	(fira-region): New.

	* ira.c (setup_class_hard_regs): Initialize.
	(setup_cover_and_important_classes): Modify code setting class
	related info for priority coloring.
	(setup_class_translate): Ditto.
	(ira_reg_classes_intersect_p, ira_reg_class_super_classes): New.
	(setup_reg_class_intersect_union): Rename to
	setup_reg_class_relations.  Add code for setting up new variables.
	(find_reg_class_closure): Do not check targetm.ira_cover_classes.
	(ira): Use flag flag_ira_region instead of flag_ira_algorithm.

	* ira-costs.c (common_classes): New.
	(print_costs): Use flag flag_ira_region instead of
	flag_ira_algorithm.
	(find_allocno_class_costs): Ditto.  Use common_classes.  Translate
	alt_class.
	(ira_costs): Allocate/deallocate common_classes.
	
	* config/m32c/m32.h (REG_ALLOC_ORDER): Add reg 19.
	(REG_CLASS_CONTENTS, reg_class, REG_CLASS_NAMES): New entries for
	R02A_REGS.

	* reload1.c (choose_reload_regs): Use MODE_INT for partial ints in
	smallest_mode_for_size.

From-SVN: r142610
This commit is contained in:
Vladimir Makarov 2008-12-09 21:25:11 +00:00 committed by Vladimir Makarov
parent 2e5d002a9e
commit 7db7ed3cbd
19 changed files with 719 additions and 295 deletions

View File

@ -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.

View File

@ -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

View File

@ -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)

View File

@ -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", \

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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

View File

@ -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);

View File

@ -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;
}
sorted_allocnos[n++] = 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");
}
}
continue;
}
put_allocno_into_bucket (a);
}
push_allocnos_to_stack ();
pop_allocnos_from_stack ();
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 ();
}
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));

View File

@ -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)

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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)
{

202
gcc/ira.c
View File

@ -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 ())

View File

@ -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;

View File

@ -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))

View File

@ -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. */