* IRA improvements 1/4
@ 2010-07-07 13:32 Vladimir Makarov
2010-07-07 20:27 ` Bernd Schmidt
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Vladimir Makarov @ 2010-07-07 13:32 UTC (permalink / raw)
To: gcc-patches; +Cc: Jeffrey Law
[-- Attachment #1: Type: text/plain, Size: 20453 bytes --]
This patch removes cover classes. The cover classes were introduced
because classical graph coloring algorithms work on on intersected
registers classes. As our experience shows defining cover classes can
create a lot of performance problems for some targets and as
consequence few targets have to use less powerful priority coloring
algorithm instead of Preston-Briggs graph coloring algorithm.
So removing cover classes makes GCC more portable. But the major
idea for the patch is to not only make GCC profitable but to improve
performance too.
Irregular register file architectures (like x86) force to use
smaller register classes (not just GENERAL_REGS) because other
registers might be not profitable. Taking this requirement into
account in more adequate way (than just available register number)
could improve quality of graph coloring RA. Regular register file
architectures also need this because some registers are not available
in some parts of the code (e.g. registers used for argument passing)
or not profitable (e.g. call clobbered registers).
The patch makes graph coloring works on dynamically calculated classes
(which is just a hard reg set) of registers profitable for given
allocno. More correctly, the approximation of such classes used which
forms a tree of such classes. Here is a simple x86 example to get the
idea of the change. Let pseudo P conflicts with 7 other pseudos
P1-P7. P and P7 can use any general register (it means that they are
profitable too), P1-P6 can use only AX. In the old version of IRA P is
not trivially colorable. With this patch, P is trivially colorable
because the algorithm can easily figure out that the impact of P1-P6
on P is just 1 registers (not 6 as IRA before the patch).
The patch also permits to use registers from different old cover
classes. For example, if we have pseudo which is only used for moving
value from one memory location to another one, we could use general or
floating point registers on most architectures. In the previous
version of IRA, only general registers were used for such case because
general and floating registers usually belonged to different cover
classes.
The patch removes -fira-coalesce because it is really hard to
implement it with the new dynamically calculated allocno classes.
The patch uses also new spilling algorithms because of the same reason.
Removing -fira-coalesce is not a big deal because it is not used and
its most functionality is implemented by IRA preferencing technique.
The code for new trivial colorability test is still fast but it
slower than the previous one. Code for cost calculation needs to
process more classes too (like FLOAT_INT_REGS). That slows down RA
significantly because the test and cost calculation are critical parts
of IRA. A lot of work was done to speed up other parts of IRA to
compensate this slow down. The subsequent patches are devoted to
speeding other parts of IRA.
Is the patch ok to commit the patch to the trunk?
2010-07-07 Vladimir Makarov <vmakarov@redhat.com>
* target-def.h (TARGET_IRA_COVER_CLASSES): Remove.
* target.def (ira_cover_classes): Remove.
* doc/tm.texi: Remove TARGET_IRA_COVER_CLASSES and
IRA_COVER_CLASSES.
* doc/tm.texi.in: Ditto.
* doc/invoke.texi (flag_ira_coalesce): Remove.
* ira-conflicts.c: Remove mentioning cover classes from the file.
Use ALLOCNO_CLASS instead of ALLOCNO_COVER_CLASS. Use
ALLOCNO_COVER_CLASS_COST instead of ALLOCNO_CLASS_COST.
* targhooks.c (default_ira_cover_classes): Remove.
* targhooks.h (default_ira_cover_classes): Ditto.
* haifa-sched.c: Remove mentioning cover classes from the file.
Use ira_reg_pressure_cover instead of ira_reg_class_cover. Use
ira_pressure_classes and ira_pressure_classes_num instead of
ira_reg_class_cover_size and ira_reg_class_cover. Use
sched_regno_pressure_class instead of sched_regno_cover_class.
(mark_regno_birth_or_death, setup_insn_reg_pressure_info): Use
ira_reg_class_max_nregs instead of ira_reg_class_nregs.
* ira-int.h: Add 2010 to Copyright. Remove mentioning cover
classes from the file.
(allocno_hard_regs_t, allocno_hard_regs_node_t): New typedefs.
(struct allocno_hard_regs, struct allocno_hard_regs_node): New.
(struct ira_allocno): Rename cover_class to aclass and make it a
bitfield. Rename cover_class_cost and updated_cover_class_cost to
class_cost and updated_class_cost. Remove splay_removed_p and
left_conflict_size. Add new members colorable_p,
profitable_hard_regs, hard_regs_node, hard_regs_subnodes_start,
hard_regs_subnodes_num.
(ALLOCNO_SPLAY_REMOVED_P, ALLOCNO_LEFT_CONFLICTS_SIZE): Remove.
(ALLOCNO_COLORABLE_P, ALLOCNO_PROFITABLE_HARD_REGS,
ALLOCNO_HARD_REGS_NODE, ALLOCNO_HARD_REGS_SUBNODES_START,
ALLOCNO_HARD_REGS_SUBNODES_NUM): New macros.
(ALLOCNO_COVER_CLASS): Rename to ALLOCNO_CLASS.
(ALLOCNO_COVER_CLASS_COST, ALLOCNO_UPDATED_COVER_CLASS_COST):
Rename to ALLOCNO_CLASS_COST and ALLOCNO_UPDATED__CLASS_COST.
(ira_max_nregs): Remove.
(prohibited_class_mode_regs): Rename to
ira_prohibited_class_mode_regs.
(ira_reg_allocno_class_p, ira_reg_pressure_class_p): New.
(ira_reg_class_union): Rename to ira_reg_class_subunion.
(ira_reg_class_superunion): New external.
(ira_debug_class_cover): Rename to ira_debug_allocno_classes.
(ira_set_allocno_cover_class): Rename to ira_set_allocno_class.
(ira_tune_allocno_costs_and_cover_classes): Rename to
ira_tune_allocno_costs.
(ira_debug_hard_regs_forest): New.
(ira_hard_reg_set_intersection_p, hard_reg_set_size): New
functions.
(ira_allocate_and_set_costs, ira_allocate_and_copy_costs,
ira_allocate_and_accumulate_costs,
ira_allocate_and_set_or_copy_costs): Rename cover_class to aclass.
* opts.c (decode_options): Remove ira_cover_class check.
* ira-color.c: Remove mentioning cover classes from the file. Use
ALLOCNO_CLASS, ALLOCNO_CLASS_COST, and ALLOCNO_UPDATED_CLASS_COST
instead of ALLOCNO_COVER_CLASS, ALLOCNO_COVER_CLASS_COST, and
ALLOCNO_UPDATED_COVER_CLASS_COST.
(splay-tree.h): Remove include.
(allocno_coalesced_p, processed_coalesced_allocno_bitmap): Move
before copy_freq_compare_func.
(allocnos_for_spilling, removed_splay_allocno_vec): Remove.
(allocno_hard_regs_vec, allocno_hard_regs_htab, node_check_tick,
hard_regs_roots, hard_regs_node_vec, allocno_hard_regs_nodes_num,
allocno_hard_regs_nodes): New definitions.
(allocno_hard_regs_hash, allocno_hard_regs_eq, find_hard_regs,
insert_hard_regs, init_allocno_hard_regs, add_allocno_hard_regs,
finish_allocno_hard_regs, allocno_hard_regs_compare,
create_new_allocno_hard_regs_node,
add_new_allocno_hard_regs_node_to_forest,
add_allocno_hard_regs_to_forest, collect_allocno_hard_regs_cover,
setup_allocno_hard_regs_nodes_parent, first_common_ancestor_node,
print_hard_reg_set, print_hard_regs_subforest,
print_hard_regs_forest, ira_debug_hard_regs_forest,
remove_unused_allocno_hard_regs_nodes,
enumerate_allocno_hard_regs_nodes): New functions.
(allocnos_have_intersected_live_ranges_p,
pseudos_have_intersected_live_ranges_p): Move before
copy_freq_compare_func.
(allocno_hard_regs_subnode_t): New typedef.
(struct allocno_hard_regs_subnode): New.
(allocno_hard_regs_subnodes, allocno_hard_regs_subnode_index): New
definitions.
(setup_allocno_hard_regs_subnode_index,
get_allocno_hard_regs_subnodes_num,
form_allocno_hard_regs_nodes_forest,
finish_allocno_hard_regs_nodes_tree,
finish_allocno_hard_regs_nodes_forest,
setup_left_conflict_sizes_p, update_left_conflict_sizes_p,
setup_profitable_hard_regs): New functions.
(update_copy_costs): Remove assert. Skip cost update if the hard
reg does not belong the class.
(print_coalesced_allocno): Remove.
(assign_hard_reg): Assume no coalesced allocnos. Process only
profitable hard regs.
(uncolorable_allocnos_num): Make it scalar.
(allocno_spill_priority): Make it inline. Use
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM and ira_reg_class_max_nregs
instead of ALLOCNO_LEFT_CONFLICTS_SIZE and
ira_reg_class_max_nregs.
(get_coalesced_allocnos_attributes): Remove.
(bucket_allocno_compare_func): Assume no coalesced allocnos.
(sort_bucket): Add compare function as a parameter.
(add_allocno_to_ordered_bucket): Assume no coalesced allocnos.
(uncolorable_allocnos_splay_tree, USE_SPLAY_P): Remove.
(push_allocno_to_stack): Rewrite for checking new allocno
colorability.
(remove_allocno_from_bucket_and_push): Use
ira_print_expanded_allocno instead of print_coalesced_allocno.
Print cost too. Remove assert.
(push_only_colorable): Pass new parameter to sort_bucket.
(push_allocno_to_spill): Remove.
(allocno_spill_priority_compare): Make it inline and rewrite.
(splay_tree_allocate, splay_tree_free): Remove.
(allocno_spill_sort_compare): New function.
(push_allocnos_to_stack): Sort allocnos for spilling once. Assume
uncoalesced allocnos. Don't build and use splay tree. Choose
first allocno in uncolorable allocno bucket to spill.
(setup_allocno_available_regs_num): Assume uncoalesced allocnos,
check only profitable hard regs. Print info about hard regs
nodes.
(setup_allocno_left_conflicts_size): Remove.
(put_allocno_into_bucket): Don't call
setup_allocno_left_conflicts_size. Use
setup_left_conflict_sizes_p.
(copy_freq_compare_func, merge_allocnos,
coalesced_allocno_conflict_p): Move before
coalesced_pseudo_reg_freq_compare.
(coalesced_allocno_conflict_p, coalesce_allocnos): Ditto. Remove
parameter. Assume it true.
(slot_coalesced_allocno_live_ranges_intersect_p,
setup_slot_coalesced_allocno_live_ranges): Ditto.
(improve_allocation): New.
(color_allocnos): Don't coalesce. Use ira_print_expanded_allocno
instead of print_coalesced_allocno. Call
setup_profitable_hard_regs, form_allocno_hard_regs_nodes_forest,
and improve_allocation.
(do_coloring): Remove allocation and freeing splay_tree_node_pool.
(ira_sort_regnos_for_alter_reg): Call coalesce_allocnos without
parameter. Don't setup members {first,next}_coalesced_allocno.
(color): Remove allocating and freeing removed_splay_allocno_vec.
(fast_allocation): Use ira_prohibited_class_mode_regs instead of
prohibited_class_mode_regs.
* ira-lives.c: Remove mentioning cover classes from the file.
(inc_register_pressure, dec_register_pressure): Check for pressure
class.
(mark_pseudo_regno_live, mark_hard_reg_live,
mark_pseudo_regno_dead, mark_hard_reg_dead): Use pressure class.
(single_reg_class): Use ira_reg_class_nregs instead of
ira_reg_class_max_nregs.
(process_bb_node_lives): Use pressure classes.
* ira-emit.c: Remove mentioning cover classes from the file. Use
ALLOCNO_CLASS instead of ALLOCNO_COVER_CLASS.
(change_loop): Use pressure classes.
(modify_move_list): Call ira_set_allocno_class instead of
ira_set_allocno_cover_class.
* ira-build.c: Remove mentioning cover classes from the file. Use
ALLOCNO_CLASS and ALLOCNO_CLASS_COST instead of
ALLOCNO_COVER_CLASS and ALLOCNO_COVER_CLASS_COST. Use
ALLOCNO_UPDATED_CLASS_COST instead of
ALLOCNO_UPDATED_COVER_CLASS_COST.
(ira_create_allocno): Remove initialization of
ALLOCNO_MAY_BE_SPILLED_P, ALLOCNO_SPLAY_REMOVED_P. Initialize
ALLOCNO_PROFITABLE_HARD_REGS, ALLOCNO_HARD_REGS_NODE,
ALLOCNO_HARD_REGS_SUBNODES_START, ALLOCNO_HARD_REGS_SUBNODES_NUM.
(ira_set_allocno_cover_class): Rename to ira_set_allocno_class.
(create_cap_allocno): Ditto. Remove assert. Don't propagate
ALLOCNO_AVAILABLE_REGS_NUM.
(ira_free_allocno_costs): New function.
(finish_allocno): Change a part of code into call of
ira_free_allocno_costs.
(ira_remove_allocno_copy_from_list): Remove.
(low_pressure_loop_node_p): Use pressure classes.
(allocno_range_compare_func): Don't compare classes.
(setup_min_max_conflict_allocno_ids): Ditto.
* loop-invariant.c: Remove mentioning cover classes from the file.
Use ira_pressure_classes and ira_pressure_classes_num instead of
ira_reg_class_cover_size and ira_reg_class_cover.
(get_cover_class_and_nregs): Rename to
get_cover_pressure_and_nregs. Use ira_reg_class_max_nregs instead
of ira_reg_class_nregs. Use reg_allocno_class instead of
reg_cover_class.
(get_inv_cost): Use instead ira_stack_reg_pressure_class of
STACK_REG_COVER_CLASS.
(get_regno_cover_class): Rename to get_regno_pressure_class.
* common.opt (fira-coalesce): Remove.
* ira.c: Remove mentioning cover classes from the file. Add
comments about coloring without cover classes. Use ALLOCNO_CLASS
instead of ALLOCNO_COVER_CLASS.
(ira_max_memory_move_cost, ira_max_register_move_cost,
ira_max_may_move_in_cost, ira_max_may_move_out_cost): New
definitions.
(alloc_reg_class_subclasses, setup_reg_subclasses): Move it before
setup_class_subset_and_memory_move_costs.
(setup_class_subset_and_memory_move_costs): Call
setup_reg_subclasses. Setup ira_max_memory_move_cost.
(ira_reg_allocno_class_p, ira_pressure_classes_num,
ira_pressure_classes, ira_pressure_class_translate,
ira_stack_reg_pressure_class): New definitions.
(ira_reg_class_cover_size, ira_reg_class_cover): Rename to
ira_allocno_classes_num and ira_allocno_classes.
(setup_stack_reg_pressure_class, setup_pressure_classes): New.
(setup_cover_and_important_classes): Rename to
setup_allocno_and_important_classes.
(ira_class_translate): Rename to ira_allocno_class_translate.
(setup_class_translate_array): New.
(cover_class_order): Rename to allocno_class_order.
(setup_class_translate): Call it for allocno and pressure classes.
(ira_reg_class_union): Rename to ira_reg_class_subunion.
(ira_reg_class_superunion): New definition.
(setup_reg_class_relations): Set up ira_reg_class_superunion.
(print_class_cover): Rename to print_classes.
(ira_debug_class_cover): Rename to ira_debug_allocno_classes.
(find_reg_class_closure): Rename to find_reg_classes. Don't call
setup_reg_subclasses.
(ira_hard_regno_cover_class): Rename to
ira_hard_regno_allocno_class.
(setup_hard_regno_cover_class): Rename to setup_hard_regno_aclass.
(ira_max_nregs): Remove.
(ira_reg_class_nregs): Rename to ira_reg_class_max_nregs.
(ira_reg_class_min_nregs): New definition.
(setup_reg_class_nregs): Set up ira_reg_class_min_nregs.
(prohibited_class_mode_regs): Rename to
ira_prohibited_class_mode_regs.
(clarify_prohibited_class_mode_regs): New function.
(ira_init_register_move_cost): Set up ira_max_register_move_cost,
ira_max_may_move_in_cost, and ira_max_may_move_out_cost.
(ira_init_once): Initialize them.
(free_register_move_costs): Process them.
(ira_init): Move calls of find_reg_classes and
setup_hard_regno_aclass after setup_reg_class_nregs. Call
clarify_prohibited_class_mode_regs.
(setup_reg_renumber): Don't use ALLOCNO_REG.
(too_high_register_pressure_p): Use pressure classes.
* sched-deps.c: Remove mentioning cover classes from the file.
Use ira_reg_pressure_cover instead of ira_reg_class_cover. Use
ira_pressure_classes and ira_pressure_classes_num instead of
ira_reg_class_cover_size and ira_reg_class_cover.
(mark_insn_hard_regno_birth, mark_hard_regno_death): Use
sched_regno_pressure_class instead of sched_regno_cover_class.
(mark_insn_pseudo_birth, mark_pseudo_death): Ditto. Use
ira_reg_class_max_nregs instead of ira_reg_class_nregs.
* ira.h: Add 2010 to Copyright.
(ira_hard_regno_cover_class): Rename to
ira_hard_regno_allocno_class.
(ira_reg_class_cover_size, ira_reg_class_cover): Rename to
ira_allocno_classes_num and ira_allocno_classes.
(ira_class_translate): Rename to ira_allocno_class_translate.
(ira_pressure_classes_num, ira_pressure_classes,
ira_pressure_class_translate, ira_stack_reg_pressure_class): New
definitions.
(ira_reg_class_nregs): Rename to ira_reg_class_max_nregs.
(ira_reg_class_min_nregs): New definition.
* ira-costs.c: Add 2010 to Copyright. Remove mentioning cover
classes from the file. Use ALLOCNO_CLASS instead of
ALLOCNO_COVER_CLASS. Use ALLOCNO_CLASS_COST instead of
ALLOCNO_COVER_CLASS_COST.
(regno_cover_class): Rename to regno_aclass.
(record_reg_classes): Use ira_reg_class_subunion instead of
ira_reg_class_union.
(record_address_regs): Check overflow.
(scan_one_insn): Ditto.
(print_allocno_costs): Print total mem cost fore regional
allocation.
(print_pseudo_costs): Use REG_N_REFS.
(find_costs_and_classes): Use classes intersected with them on the
1st pass. Check overflow. Use ira_reg_class_subunion instead of
ira_reg_class_union. Use ira_allocno_class_translate and
regno_aclass instead of ira_class_translate and regno_cover_class.
Modify code for finding regno_aclass. Setup preferred classes for
the next pass.
(setup_allocno_cover_class_and_costs): Rename to
setup_allocno_class_and_costs. Use regno_aclass instead of
regno_cover_class. Use ira_set_allocno_class instead of
ira_set_allocno_cover_class.
(init_costs, finish_costs): Use regno_aclass instead of
regno_cover_class.
(ira_costs): Use setup_allocno_class_and_costs instead of
setup_allocno_cover_class_and_costs.
(ira_tune_allocno_costs_and_cover_classes): Rename to
ira_tune_allocno_costs. Check overflow. Skip conflict hard regs.
* rtl.h (reg_cover_class): Rename to reg_allocno_class.
* sched-int.h: Remove mentioning cover classes from the file.
(sched_regno_cover_class): Rename to sched_regno_pressure_class.
* reginfo.c: Add 2010 to Copyright. Remove mentioning cover
classes from the file.
(struct reg_pref): Rename coverclass into allocnoclass.
(reg_cover_class): Rename to reg_allocno_class.
* Makefile.in (ira-color.o): Remove SPLAY_TREE_H from
dependencies.
* config/alpha/alpha.h (IRA_COVER_CLASSES): Remove.
* config/arm/arm.h (IRA_COVER_CLASSES): Ditto.
* config/avr/avr.h (IRA_COVER_CLASSES): Ditto.
* config/bfin/bfin.h (IRA_COVER_CLASSES): Ditto.
* config/crx/crx.h (IRA_COVER_CLASSES): Ditto.
* config/cris/cris.h (IRA_COVER_CLASSES): Ditto.
* config/fr30/fr30.h (IRA_COVER_CLASSES): Ditto.
* config/frv/frv.h (IRA_COVER_CLASSES): Ditto.
* config/h8300/h8300.h (IRA_COVER_CLASSES): Ditto.
* config/i386/i386.h (STACK_REG_COVER_CLASS): Ditto.
* config/i386/i386.c (TARGET_IRA_COVER_CLASSES,
i386_ira_cover_classes): Ditto.
* config/ia64/ia64.h (IRA_COVER_CLASSES): Ditto.
* config/iq2000/iq2000.h (IRA_COVER_CLASSES): Ditto.
* config/m32r/m32r.h (IRA_COVER_CLASSES): Ditto.
* config/m68k/m68k.h (IRA_COVER_CLASSES): Ditto.
* config/mcore/mcore.h (IRA_COVER_CLASSES): Ditto.
* config/mep/mep.h (IRA_COVER_CLASSES): Ditto.
* config/mips/mips.c (TARGET_IRA_COVER_CLASSES,
mips_ira_cover_classes): Ditto.
* config/mn10300/mn10300.h (IRA_COVER_CLASSES): Ditto.
* config/moxie/moxie.h (IRA_COVER_CLASSES): Ditto.
* config/pa/pa64-regs.h (IRA_COVER_CLASSES): Ditto.
* config/pa/pa32-regs.h (IRA_COVER_CLASSES): Ditto.
* config/picochip/picochip.h (IRA_COVER_CLASSES): Ditto.
* config/rs6000/rs6000.h (IRA_COVER_CLASSES_PRE_VSX,
IRA_COVER_CLASSES_VSX): Ditto.
* config/rs6000/rs6000.c (TARGET_IRA_COVER_CLASSES,
rs6000_ira_cover_classes): Ditto.
* config/rx/rx.h (IRA_COVER_CLASSES): Ditto.
* config/s390/s390.h (IRA_COVER_CLASSES): Ditto.
* config/score/score.h (IRA_COVER_CLASSES): Ditto.
* config/sh/sh.h (IRA_COVER_CLASSES): Ditto.
* config/sparc/sparc.h (IRA_COVER_CLASSES): Ditto.
* config/spu/spu.h (IRA_COVER_CLASSES): Ditto.
* config/stormy16/stormy16.h (IRA_COVER_CLASSES): Ditto.
* config/v850/v850.h (IRA_COVER_CLASSES): Ditto.
* config/vax/vax.h (IRA_COVER_CLASSES): Ditto.
* config/xtensa/xtensa.h (IRA_COVER_CLASSES): Ditto.
[-- Attachment #2: cover.patch --]
[-- Type: text/plain, Size: 347124 bytes --]
Index: target-def.h
===================================================================
--- target-def.h (revision 161709)
+++ target-def.h (working copy)
@@ -104,10 +104,6 @@
TARGET_ASM_UNALIGNED_DI_OP, \
TARGET_ASM_UNALIGNED_TI_OP}
-#ifndef IRA_COVER_CLASSES
-#define TARGET_IRA_COVER_CLASSES 0
-#endif
-
#if !defined (TARGET_FUNCTION_INCOMING_ARG) && !defined (FUNCTION_INCOMING_ARG)
#define TARGET_FUNCTION_INCOMING_ARG TARGET_FUNCTION_ARG
#endif
Index: target.def
===================================================================
--- target.def (revision 161709)
+++ target.def (working copy)
@@ -1927,13 +1927,6 @@ DEFHOOK
tree, (tree type, tree expr),
hook_tree_tree_tree_null)
-/* Return the array of IRA cover classes for the current target. */
-DEFHOOK
-(ira_cover_classes,
- "",
- const reg_class_t *, (void),
- default_ira_cover_classes)
-
/* Return the class for a secondary reload, and fill in extra information. */
DEFHOOK
(secondary_reload,
Index: doc/tm.texi
===================================================================
--- doc/tm.texi (revision 161709)
+++ doc/tm.texi (working copy)
@@ -2888,33 +2888,6 @@ as below:
@end smallexample
@end defmac
-@deftypefn {Target Hook} {const reg_class_t *} TARGET_IRA_COVER_CLASSES (void)
-Return an array of cover classes for the Integrated Register Allocator
-(@acronym{IRA}). Cover classes are a set of non-intersecting register
-classes covering all hard registers used for register allocation
-purposes. If a move between two registers in the same cover class is
-possible, it should be cheaper than a load or store of the registers.
-The array is terminated by a @code{LIM_REG_CLASSES} element.
-
-The order of cover classes in the array is important. If two classes
-have the same cost of usage for a pseudo, the class occurred first in
-the array is chosen for the pseudo.
-
-This hook is called once at compiler startup, after the command-line
-options have been processed. It is then re-examined by every call to
-@code{target_reinit}.
-
-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 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
-See the documentation for @code{TARGET_IRA_COVER_CLASSES}.
-@end defmac
-
@node Old Constraints
@section Obsolete Macros for Defining Constraints
@cindex defining constraints, obsolete method
Index: doc/tm.texi.in
===================================================================
--- doc/tm.texi.in (revision 161709)
+++ doc/tm.texi.in (working copy)
@@ -2888,33 +2888,6 @@ as below:
@end smallexample
@end defmac
-@hook TARGET_IRA_COVER_CLASSES
-Return an array of cover classes for the Integrated Register Allocator
-(@acronym{IRA}). Cover classes are a set of non-intersecting register
-classes covering all hard registers used for register allocation
-purposes. If a move between two registers in the same cover class is
-possible, it should be cheaper than a load or store of the registers.
-The array is terminated by a @code{LIM_REG_CLASSES} element.
-
-The order of cover classes in the array is important. If two classes
-have the same cost of usage for a pseudo, the class occurred first in
-the array is chosen for the pseudo.
-
-This hook is called once at compiler startup, after the command-line
-options have been processed. It is then re-examined by every call to
-@code{target_reinit}.
-
-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 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
-See the documentation for @code{TARGET_IRA_COVER_CLASSES}.
-@end defmac
-
@node Old Constraints
@section Obsolete Macros for Defining Constraints
@cindex defining constraints, obsolete method
Index: doc/invoke.texi
===================================================================
--- doc/invoke.texi (revision 161709)
+++ doc/invoke.texi (working copy)
@@ -348,7 +348,7 @@ Objective-C and Objective-C++ Dialects}.
-finline-small-functions -fipa-cp -fipa-cp-clone -fipa-matrix-reorg -fipa-pta @gol
-fipa-profile -fipa-pure-const -fipa-reference -fipa-struct-reorg @gol
-fira-algorithm=@var{algorithm} @gol
--fira-region=@var{region} -fira-coalesce @gol
+-fira-region=@var{region} @gol
-fira-loop-pressure -fno-ira-share-save-slots @gol
-fno-ira-share-spill-slots -fira-verbose=@var{n} @gol
-fivopts -fkeep-inline-functions -fkeep-static-consts @gol
@@ -6390,11 +6390,6 @@ irregular register set, the third one re
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
-Do optimistic register coalescing. This option might be profitable for
-architectures with big regular register files.
-
@item -fira-loop-pressure
@opindex fira-loop-pressure
Use IRA to evaluate register pressure in loops for decision to move
Index: ira-conflicts.c
===================================================================
--- ira-conflicts.c (revision 161709)
+++ ira-conflicts.c (working copy)
@@ -69,7 +69,7 @@ build_conflict_bit_table (void)
{
int i, num, id, allocated_words_num, conflict_bit_vec_words_num;
unsigned int j;
- enum reg_class cover_class;
+ enum reg_class aclass;
ira_allocno_t allocno, live_a;
live_range_t r;
ira_allocno_iterator ai;
@@ -132,13 +132,13 @@ build_conflict_bit_table (void)
allocno = r->allocno;
num = ALLOCNO_NUM (allocno);
id = ALLOCNO_CONFLICT_ID (allocno);
- cover_class = ALLOCNO_COVER_CLASS (allocno);
+ aclass = ALLOCNO_CLASS (allocno);
sparseset_set_bit (allocnos_live, num);
EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j)
{
live_a = ira_allocnos[j];
if (ira_reg_classes_intersect_p
- [cover_class][ALLOCNO_COVER_CLASS (live_a)]
+ [aclass][ALLOCNO_CLASS (live_a)]
/* Don't set up conflict for the allocno with itself. */
&& num != (int) j)
{
@@ -343,7 +343,7 @@ process_regs_for_copy (rtx reg1, rtx reg
int allocno_preferenced_hard_regno, cost, index, offset1, offset2;
bool only_regs_p;
ira_allocno_t a;
- enum reg_class rclass, cover_class;
+ enum reg_class rclass, aclass;
enum machine_mode mode;
ira_copy_t cp;
@@ -383,30 +383,30 @@ process_regs_for_copy (rtx reg1, rtx reg
return false;
rclass = REGNO_REG_CLASS (allocno_preferenced_hard_regno);
mode = ALLOCNO_MODE (a);
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
if (only_regs_p && insn != NULL_RTX
&& reg_class_size[rclass] <= (unsigned) CLASS_MAX_NREGS (rclass, mode))
/* It is already taken into account in ira-costs.c. */
return false;
- index = ira_class_hard_reg_index[cover_class][allocno_preferenced_hard_regno];
+ index = ira_class_hard_reg_index[aclass][allocno_preferenced_hard_regno];
if (index < 0)
- /* Can not be tied. It is not in the cover class. */
+ /* Can not be tied. It is not in the allocno class. */
return false;
if (HARD_REGISTER_P (reg1))
- cost = ira_get_register_move_cost (mode, cover_class, rclass) * freq;
+ cost = ira_get_register_move_cost (mode, aclass, rclass) * freq;
else
- cost = ira_get_register_move_cost (mode, rclass, cover_class) * freq;
+ cost = ira_get_register_move_cost (mode, rclass, aclass) * freq;
do
{
ira_allocate_and_set_costs
- (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
- ALLOCNO_COVER_CLASS_COST (a));
+ (&ALLOCNO_HARD_REG_COSTS (a), aclass,
+ ALLOCNO_CLASS_COST (a));
ira_allocate_and_set_costs
- (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), cover_class, 0);
+ (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), aclass, 0);
ALLOCNO_HARD_REG_COSTS (a)[index] -= cost;
ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost;
- if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_COVER_CLASS_COST (a))
- ALLOCNO_COVER_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index];
+ if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_CLASS_COST (a))
+ ALLOCNO_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index];
a = ira_parent_or_cap_allocno (a);
}
while (a != NULL);
@@ -569,7 +569,7 @@ build_allocno_conflicts (ira_allocno_t a
{
another_a = ira_conflict_id_allocno_map[i];
ira_assert (ira_reg_classes_intersect_p
- [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]);
+ [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]);
collected_conflict_allocnos[px++] = another_a;
}
if (ira_conflict_vector_profitable_p (a, px))
@@ -595,20 +595,20 @@ build_allocno_conflicts (ira_allocno_t a
parent_a = ira_parent_or_cap_allocno (a);
if (parent_a == NULL)
return;
- ira_assert (ALLOCNO_COVER_CLASS (a) == ALLOCNO_COVER_CLASS (parent_a));
+ ira_assert (ALLOCNO_CLASS (a) == ALLOCNO_CLASS (parent_a));
parent_num = ALLOCNO_NUM (parent_a);
FOR_EACH_BIT_IN_MINMAX_SET (allocno_conflicts,
ALLOCNO_MIN (a), ALLOCNO_MAX (a), i, asi)
{
another_a = ira_conflict_id_allocno_map[i];
ira_assert (ira_reg_classes_intersect_p
- [ALLOCNO_COVER_CLASS (a)][ALLOCNO_COVER_CLASS (another_a)]);
+ [ALLOCNO_CLASS (a)][ALLOCNO_CLASS (another_a)]);
another_parent_a = ira_parent_or_cap_allocno (another_a);
if (another_parent_a == NULL)
continue;
ira_assert (ALLOCNO_NUM (another_parent_a) >= 0);
- ira_assert (ALLOCNO_COVER_CLASS (another_a)
- == ALLOCNO_COVER_CLASS (another_parent_a));
+ ira_assert (ALLOCNO_CLASS (another_a)
+ == ALLOCNO_CLASS (another_parent_a));
SET_MINMAX_SET_BIT (conflicts[parent_num],
ALLOCNO_CONFLICT_ID (another_parent_a),
ALLOCNO_MIN (parent_a),
@@ -710,14 +710,14 @@ print_allocno_conflicts (FILE * file, bo
ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs);
AND_HARD_REG_SET (conflicting_hard_regs,
- reg_class_contents[ALLOCNO_COVER_CLASS (a)]);
+ reg_class_contents[ALLOCNO_CLASS (a)]);
print_hard_reg_set (file, "\n;; total conflict hard regs:",
conflicting_hard_regs);
COPY_HARD_REG_SET (conflicting_hard_regs,
ALLOCNO_CONFLICT_HARD_REGS (a));
AND_COMPL_HARD_REG_SET (conflicting_hard_regs, ira_no_alloc_regs);
AND_HARD_REG_SET (conflicting_hard_regs,
- reg_class_contents[ALLOCNO_COVER_CLASS (a)]);
+ reg_class_contents[ALLOCNO_CLASS (a)]);
print_hard_reg_set (file, ";; conflict hard regs:",
conflicting_hard_regs);
putc ('\n', file);
Index: targhooks.c
===================================================================
--- targhooks.c (revision 161709)
+++ targhooks.c (working copy)
@@ -813,15 +813,6 @@ default_branch_target_register_class (vo
return NO_REGS;
}
-#ifdef IRA_COVER_CLASSES
-const reg_class_t *
-default_ira_cover_classes (void)
-{
- static reg_class_t classes[] = IRA_COVER_CLASSES;
- return classes;
-}
-#endif
-
reg_class_t
default_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED,
reg_class_t reload_class_i ATTRIBUTE_UNUSED,
Index: targhooks.h
===================================================================
--- targhooks.h (revision 161709)
+++ targhooks.h (working copy)
@@ -116,9 +116,6 @@ extern rtx default_static_chain (const_t
extern void default_trampoline_init (rtx, tree, rtx);
extern int default_return_pops_args (tree, tree, int);
extern reg_class_t default_branch_target_register_class (void);
-#ifdef IRA_COVER_CLASSES
-extern const reg_class_t *default_ira_cover_classes (void);
-#endif
extern reg_class_t default_secondary_reload (bool, rtx, reg_class_t,
enum machine_mode,
secondary_reload_info *);
Index: haifa-sched.c
===================================================================
--- haifa-sched.c (revision 161709)
+++ haifa-sched.c (working copy)
@@ -592,11 +592,11 @@ schedule_insns (void)
up. */
bool sched_pressure_p;
-/* Map regno -> its cover class. The map defined only when
+/* Map regno -> its pressure class. The map defined only when
SCHED_PRESSURE_P is true. */
-enum reg_class *sched_regno_cover_class;
+enum reg_class *sched_regno_pressure_class;
-/* The current register pressure. Only elements corresponding cover
+/* The current register pressure. Only elements corresponding pressure
classes are defined. */
static int curr_reg_pressure[N_REG_CLASSES];
@@ -626,39 +626,41 @@ sched_init_region_reg_pressure_info (voi
static void
mark_regno_birth_or_death (int regno, bool birth_p)
{
- enum reg_class cover_class;
+ enum reg_class pressure_class;
- cover_class = sched_regno_cover_class[regno];
+ pressure_class = sched_regno_pressure_class[regno];
if (regno >= FIRST_PSEUDO_REGISTER)
{
- if (cover_class != NO_REGS)
+ if (pressure_class != NO_REGS)
{
if (birth_p)
{
bitmap_set_bit (curr_reg_live, regno);
- curr_reg_pressure[cover_class]
- += ira_reg_class_nregs[cover_class][PSEUDO_REGNO_MODE (regno)];
+ curr_reg_pressure[pressure_class]
+ += (ira_reg_class_max_nregs
+ [pressure_class][PSEUDO_REGNO_MODE (regno)]);
}
else
{
bitmap_clear_bit (curr_reg_live, regno);
- curr_reg_pressure[cover_class]
- -= ira_reg_class_nregs[cover_class][PSEUDO_REGNO_MODE (regno)];
+ curr_reg_pressure[pressure_class]
+ -= (ira_reg_class_max_nregs
+ [pressure_class][PSEUDO_REGNO_MODE (regno)]);
}
}
}
- else if (cover_class != NO_REGS
+ else if (pressure_class != NO_REGS
&& ! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
{
if (birth_p)
{
bitmap_set_bit (curr_reg_live, regno);
- curr_reg_pressure[cover_class]++;
+ curr_reg_pressure[pressure_class]++;
}
else
{
bitmap_clear_bit (curr_reg_live, regno);
- curr_reg_pressure[cover_class]--;
+ curr_reg_pressure[pressure_class]--;
}
}
}
@@ -672,8 +674,8 @@ initiate_reg_pressure_info (bitmap live)
unsigned int j;
bitmap_iterator bi;
- for (i = 0; i < ira_reg_class_cover_size; i++)
- curr_reg_pressure[ira_reg_class_cover[i]] = 0;
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ curr_reg_pressure[ira_pressure_classes[i]] = 0;
bitmap_clear (curr_reg_live);
EXECUTE_IF_SET_IN_BITMAP (live, 0, j, bi)
if (current_nr_blocks == 1 || bitmap_bit_p (region_ref_regs, j))
@@ -742,9 +744,9 @@ save_reg_pressure (void)
{
int i;
- for (i = 0; i < ira_reg_class_cover_size; i++)
- saved_reg_pressure[ira_reg_class_cover[i]]
- = curr_reg_pressure[ira_reg_class_cover[i]];
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ saved_reg_pressure[ira_pressure_classes[i]]
+ = curr_reg_pressure[ira_pressure_classes[i]];
bitmap_copy (saved_reg_live, curr_reg_live);
}
@@ -754,9 +756,9 @@ restore_reg_pressure (void)
{
int i;
- for (i = 0; i < ira_reg_class_cover_size; i++)
- curr_reg_pressure[ira_reg_class_cover[i]]
- = saved_reg_pressure[ira_reg_class_cover[i]];
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ curr_reg_pressure[ira_pressure_classes[i]]
+ = saved_reg_pressure[ira_pressure_classes[i]];
bitmap_copy (curr_reg_live, saved_reg_live);
}
@@ -774,7 +776,7 @@ dying_use_p (struct reg_use_data *use)
}
/* Print info about the current register pressure and its excess for
- each cover class. */
+ each pressure class. */
static void
print_curr_reg_pressure (void)
{
@@ -782,9 +784,9 @@ print_curr_reg_pressure (void)
enum reg_class cl;
fprintf (sched_dump, ";;\t");
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- cl = ira_reg_class_cover[i];
+ cl = ira_pressure_classes[i];
gcc_assert (curr_reg_pressure[cl] >= 0);
fprintf (sched_dump, " %s:%d(%d)", reg_class_names[cl],
curr_reg_pressure[cl],
@@ -1127,23 +1129,24 @@ setup_insn_reg_pressure_info (rtx insn)
gcc_checking_assert (!DEBUG_INSN_P (insn));
excess_cost_change = 0;
- for (i = 0; i < ira_reg_class_cover_size; i++)
- death[ira_reg_class_cover[i]] = 0;
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ death[ira_pressure_classes[i]] = 0;
for (use = INSN_REG_USE_LIST (insn); use != NULL; use = use->next_insn_use)
if (dying_use_p (use))
{
- cl = sched_regno_cover_class[use->regno];
+ cl = sched_regno_pressure_class[use->regno];
if (use->regno < FIRST_PSEUDO_REGISTER)
death[cl]++;
else
- death[cl] += ira_reg_class_nregs[cl][PSEUDO_REGNO_MODE (use->regno)];
+ death[cl]
+ += ira_reg_class_max_nregs[cl][PSEUDO_REGNO_MODE (use->regno)];
}
pressure_info = INSN_REG_PRESSURE (insn);
max_reg_pressure = INSN_MAX_REG_PRESSURE (insn);
gcc_assert (pressure_info != NULL && max_reg_pressure != NULL);
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- cl = ira_reg_class_cover[i];
+ cl = ira_pressure_classes[i];
gcc_assert (curr_reg_pressure[cl] >= 0);
change = (int) pressure_info[i].set_increase - death[cl];
before = MAX (0, max_reg_pressure[i] - ira_available_class_regs[cl]);
@@ -1588,9 +1591,9 @@ setup_insn_max_reg_pressure (rtx after,
static int max_reg_pressure[N_REG_CLASSES];
save_reg_pressure ();
- for (i = 0; i < ira_reg_class_cover_size; i++)
- max_reg_pressure[ira_reg_class_cover[i]]
- = curr_reg_pressure[ira_reg_class_cover[i]];
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ max_reg_pressure[ira_pressure_classes[i]]
+ = curr_reg_pressure[ira_pressure_classes[i]];
for (insn = NEXT_INSN (after);
insn != NULL_RTX && ! BARRIER_P (insn)
&& BLOCK_FOR_INSN (insn) == BLOCK_FOR_INSN (after);
@@ -1598,24 +1601,24 @@ setup_insn_max_reg_pressure (rtx after,
if (NONDEBUG_INSN_P (insn))
{
eq_p = true;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- p = max_reg_pressure[ira_reg_class_cover[i]];
+ p = max_reg_pressure[ira_pressure_classes[i]];
if (INSN_MAX_REG_PRESSURE (insn)[i] != p)
{
eq_p = false;
INSN_MAX_REG_PRESSURE (insn)[i]
- = max_reg_pressure[ira_reg_class_cover[i]];
+ = max_reg_pressure[ira_pressure_classes[i]];
}
}
if (update_p && eq_p)
break;
update_register_pressure (insn);
- for (i = 0; i < ira_reg_class_cover_size; i++)
- if (max_reg_pressure[ira_reg_class_cover[i]]
- < curr_reg_pressure[ira_reg_class_cover[i]])
- max_reg_pressure[ira_reg_class_cover[i]]
- = curr_reg_pressure[ira_reg_class_cover[i]];
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ if (max_reg_pressure[ira_pressure_classes[i]]
+ < curr_reg_pressure[ira_pressure_classes[i]])
+ max_reg_pressure[ira_pressure_classes[i]]
+ = curr_reg_pressure[ira_pressure_classes[i]];
}
restore_reg_pressure ();
}
@@ -1629,13 +1632,13 @@ update_reg_and_insn_max_reg_pressure (rt
int i;
int before[N_REG_CLASSES];
- for (i = 0; i < ira_reg_class_cover_size; i++)
- before[i] = curr_reg_pressure[ira_reg_class_cover[i]];
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ before[i] = curr_reg_pressure[ira_pressure_classes[i]];
update_register_pressure (insn);
- for (i = 0; i < ira_reg_class_cover_size; i++)
- if (curr_reg_pressure[ira_reg_class_cover[i]] != before[i])
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ if (curr_reg_pressure[ira_pressure_classes[i]] != before[i])
break;
- if (i < ira_reg_class_cover_size)
+ if (i < ira_pressure_classes_num)
setup_insn_max_reg_pressure (insn, true);
}
@@ -1681,9 +1684,9 @@ schedule_insn (rtx insn)
if (pressure_info != NULL)
{
fputc (':', sched_dump);
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
fprintf (sched_dump, "%s%+d(%d)",
- reg_class_names[ira_reg_class_cover[i]],
+ reg_class_names[ira_pressure_classes[i]],
pressure_info[i].set_increase, pressure_info[i].change);
}
fputc ('\n', sched_dump);
@@ -3452,13 +3455,13 @@ sched_init (void)
int i, max_regno = max_reg_num ();
ira_set_pseudo_classes (sched_verbose ? sched_dump : NULL);
- sched_regno_cover_class
+ sched_regno_pressure_class
= (enum reg_class *) xmalloc (max_regno * sizeof (enum reg_class));
for (i = 0; i < max_regno; i++)
- sched_regno_cover_class[i]
+ sched_regno_pressure_class[i]
= (i < FIRST_PSEUDO_REGISTER
- ? ira_class_translate[REGNO_REG_CLASS (i)]
- : reg_cover_class (i));
+ ? ira_pressure_class_translate[REGNO_REG_CLASS (i)]
+ : ira_pressure_class_translate[reg_allocno_class (i)]);
curr_reg_live = BITMAP_ALLOC (NULL);
saved_reg_live = BITMAP_ALLOC (NULL);
region_ref_regs = BITMAP_ALLOC (NULL);
@@ -3563,7 +3566,7 @@ sched_finish (void)
haifa_finish_h_i_d ();
if (sched_pressure_p)
{
- free (sched_regno_cover_class);
+ free (sched_regno_pressure_class);
BITMAP_FREE (region_ref_regs);
BITMAP_FREE (saved_reg_live);
BITMAP_FREE (curr_reg_live);
Index: ira-int.h
===================================================================
--- ira-int.h (revision 161709)
+++ ira-int.h (working copy)
@@ -1,5 +1,5 @@
/* Integrated Register Allocator (IRA) intercommunication header file.
- Copyright (C) 2006, 2007, 2008, 2009
+ Copyright (C) 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Vladimir Makarov <vmakarov@redhat.com>.
@@ -119,7 +119,7 @@ struct ira_loop_tree_node
bool entered_from_non_parent_p;
/* Maximal register pressure inside loop for given register class
- (defined only for the cover classes). */
+ (defined only for the pressure classes). */
int reg_pressure[N_REG_CLASSES];
/* Numbers of allocnos referred or living in the loop node (except
@@ -191,11 +191,8 @@ extern ira_loop_tree_node_t ira_loop_nod
\f
/* The structure describes program points where a given allocno lives.
- To save memory we store allocno conflicts only for the same cover
- class allocnos which is enough to assign hard registers. To find
- conflicts for other allocnos (e.g. to assign stack memory slot) we
- use the live ranges. If the live ranges of two allocnos are
- intersected, the allocnos are in conflict. */
+ If the live ranges of two allocnos are intersected, the allocnos
+ are in conflict. */
struct live_range
{
/* Allocno whose live range is described by given structure. */
@@ -222,6 +219,57 @@ extern int ira_max_point;
live ranges with given start/finish point. */
extern live_range_t *ira_start_point_ranges, *ira_finish_point_ranges;
+/* See below. */
+typedef struct allocno_hard_regs *allocno_hard_regs_t;
+
+/* The structure contains information about hard registers can be
+ assigned to allocnos. Usually it is allocno profitable hard
+ registers but in some cases this set can be a bit different. Major
+ reason of the difference is a requirement to use hard register sets
+ that form a tree or a forest (set of trees), i.e. hard register set
+ of a node should contain hard register sets of its subnodes. */
+struct allocno_hard_regs
+{
+ /* Hard registers can be assigned to an allocno. */
+ HARD_REG_SET set;
+ /* Overall (spilling) cost of all allocnos with given register
+ set. */
+ long long int cost;
+};
+
+/* See below. */
+typedef struct allocno_hard_regs_node *allocno_hard_regs_node_t;
+
+/* A node representing allocno hard registers. Such nodes form a
+ forest (set of trees). Each subnode of given node in the forest
+ refers for hard register set (usually allocno profitable hard
+ register set) which is a subset of one referred from given
+ node. */
+struct allocno_hard_regs_node
+{
+ /* Set up number of the node in preorder traversing of the forest. */
+ int preorder_num;
+ /* Used for different calculation like finding conflict size of an
+ allocno. */
+ int check;
+ /* Used for calculation of conflict size of an allocno. The
+ conflict size of the allocno is maximal number of given allocno
+ hard registers needed for allocation of the conflicting allocnos.
+ Given allocno is trivially colored if this number plus the number
+ of hard registers needed for given allocno is not greater than
+ the number of given allocno hard register set. */
+ int conflict_size;
+ /* The number of hard registers given by member hard_regs. */
+ int hard_regs_num;
+ /* The following member is used to form the final forest. */
+ bool used_p;
+ /* Pointer to the corresponding profitable hard registers. */
+ allocno_hard_regs_t hard_regs;
+ /* Parent, first subnode, previous and next node with the same
+ parent in the forest. */
+ allocno_hard_regs_node_t parent, first, prev, next;
+};
+
/* A structure representing an allocno (allocation entity). Allocno
represents a pseudo-register in an allocation region. If
pseudo-register does not live in a region but it lives in the
@@ -268,10 +316,10 @@ struct ira_allocno
int freq;
/* Register class which should be used for allocation for given
allocno. NO_REGS means that we should use memory. */
- enum reg_class cover_class;
+ enum reg_class aclass;
/* Minimal accumulated and updated costs of usage register of the
- cover class for the allocno. */
- int cover_class_cost, updated_cover_class_cost;
+ allocno class. */
+ int class_cost, updated_class_cost;
/* Minimal accumulated, and updated costs of memory for the allocno.
At the allocation start, the original and updated costs are
equal. The updated cost may be changed after finishing
@@ -313,9 +361,7 @@ struct ira_allocno
which given allocno can conflict. */
int min, max;
/* Vector of accumulated conflicting allocnos with NULL end marker
- (if CONFLICT_VEC_P is true) or conflict bit vector otherwise.
- Only allocnos with the same cover class are in the vector or in
- the bit vector. */
+ (if CONFLICT_VEC_P is true) or conflict bit vector otherwise. */
void *conflict_allocno_array;
/* The unique member value represents given allocno in conflict bit
vectors. */
@@ -324,7 +370,7 @@ struct ira_allocno
unsigned int conflict_allocno_array_size;
/* Initial and accumulated hard registers conflicting with this
allocno and as a consequences can not be assigned to the allocno.
- All non-allocatable hard regs and hard regs of cover classes
+ All non-allocatable hard regs and hard regs of register classes
different from given allocno one are included in the sets. */
HARD_REG_SET conflict_hard_regs, total_conflict_hard_regs;
/* Number of accumulated conflicts in the vector of conflicting
@@ -371,46 +417,42 @@ struct ira_allocno
/* TRUE if it is put on the stack to make other allocnos
colorable. */
unsigned int may_be_spilled_p : 1;
- /* TRUE if the allocno was removed from the splay tree used to
- choose allocn for spilling (see ira-color.c::. */
- unsigned int splay_removed_p : 1;
/* TRUE if conflicts for given allocno are represented by vector of
pointers to the conflicting allocnos. Otherwise, we use a bit
vector where a bit with given index represents allocno with the
same number. */
unsigned int conflict_vec_p : 1;
+ /* TRUE if the allocno is trivially colorable. */
+ unsigned int colorable_p : 1;
/* Non NULL if we remove restoring value from given allocno to
MEM_OPTIMIZED_DEST at loop exit (see ira-emit.c) because the
allocno value is not changed inside the loop. */
ira_allocno_t mem_optimized_dest;
/* Array of usage costs (accumulated and the one updated during
- coloring) for each hard register of the allocno cover class. The
+ coloring) for each hard register of the allocno class. The
member value can be NULL if all costs are the same and equal to
- COVER_CLASS_COST. For example, the costs of two different hard
+ CLASS_COST. For example, the costs of two different hard
registers can be different if one hard register is callee-saved
and another one is callee-used and the allocno lives through
calls. Another example can be case when for some insn the
corresponding pseudo-register value should be put in specific
register class (e.g. AREG for x86) which is a strict subset of
- the allocno cover class (GENERAL_REGS for x86). We have updated
- costs to reflect the situation when the usage cost of a hard
- register is decreased because the allocno is connected to another
- allocno by a copy and the another allocno has been assigned to
- the hard register. */
+ the allocno class (GENERAL_REGS for x86). We have updated costs
+ to reflect the situation when the usage cost of a hard register
+ is decreased because the allocno is connected to another allocno
+ by a copy and the another allocno has been assigned to the hard
+ register. */
int *hard_reg_costs, *updated_hard_reg_costs;
/* Array of decreasing costs (accumulated and the one updated during
coloring) for allocnos conflicting with given allocno for hard
- regno of the allocno cover class. The member value can be NULL
- if all costs are the same. These costs are used to reflect
- preferences of other allocnos not assigned yet during assigning
- to given allocno. */
+ regno of the allocno class. The member value can be NULL if all
+ costs are the same. These costs are used to reflect preferences
+ of other allocnos not assigned yet during assigning to given
+ allocno. */
int *conflict_hard_reg_costs, *updated_conflict_hard_reg_costs;
- /* Size (in hard registers) of the same cover class allocnos with
- TRUE in_graph_p value and conflicting with given allocno during
- each point of graph coloring. */
- int left_conflicts_size;
- /* Number of hard registers of the allocno cover class really
- available for the allocno allocation. */
+ /* Number of hard registers of the allocno class really
+ available for the allocno allocation. It is number of the
+ profitable hard regs. */
int available_regs_num;
/* Allocnos in a bucket (used in coloring) chained by the following
two members. */
@@ -418,6 +460,20 @@ struct ira_allocno
ira_allocno_t prev_bucket_allocno;
/* Used for temporary purposes. */
int temp;
+ /* Profitable hard regs available for this pseudo allocation. It
+ means that the set excludes unavailable hard regs and hard regs
+ conflicting with given pseudo. They should be of the allocno
+ class. */
+ HARD_REG_SET profitable_hard_regs;
+ /* The allocno hard registers node. */
+ allocno_hard_regs_node_t hard_regs_node;
+ /* Array of structures allocno_hard_regs_subnode representing
+ given allocno hard registers node (the 1st element in the array)
+ and all its subnodes in the tree (forest) of allocno hard
+ register nodes (see comments above). */
+ int hard_regs_subnodes_start;
+ /* The length of the previous array. */
+ int hard_regs_subnodes_num;
};
/* All members of the allocno structures should be accessed only
@@ -454,8 +510,8 @@ struct ira_allocno
#define ALLOCNO_IN_GRAPH_P(A) ((A)->in_graph_p)
#define ALLOCNO_ASSIGNED_P(A) ((A)->assigned_p)
#define ALLOCNO_MAY_BE_SPILLED_P(A) ((A)->may_be_spilled_p)
-#define ALLOCNO_SPLAY_REMOVED_P(A) ((A)->splay_removed_p)
#define ALLOCNO_CONFLICT_VEC_P(A) ((A)->conflict_vec_p)
+#define ALLOCNO_COLORABLE_P(A) ((A)->colorable_p)
#define ALLOCNO_MODE(A) ((A)->mode)
#define ALLOCNO_COPIES(A) ((A)->allocno_copies)
#define ALLOCNO_HARD_REG_COSTS(A) ((A)->hard_reg_costs)
@@ -464,10 +520,9 @@ struct ira_allocno
((A)->conflict_hard_reg_costs)
#define ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS(A) \
((A)->updated_conflict_hard_reg_costs)
-#define ALLOCNO_LEFT_CONFLICTS_SIZE(A) ((A)->left_conflicts_size)
-#define ALLOCNO_COVER_CLASS(A) ((A)->cover_class)
-#define ALLOCNO_COVER_CLASS_COST(A) ((A)->cover_class_cost)
-#define ALLOCNO_UPDATED_COVER_CLASS_COST(A) ((A)->updated_cover_class_cost)
+#define ALLOCNO_CLASS(A) ((A)->aclass)
+#define ALLOCNO_CLASS_COST(A) ((A)->class_cost)
+#define ALLOCNO_UPDATED_CLASS_COST(A) ((A)->updated_class_cost)
#define ALLOCNO_MEMORY_COST(A) ((A)->memory_cost)
#define ALLOCNO_UPDATED_MEMORY_COST(A) ((A)->updated_memory_cost)
#define ALLOCNO_EXCESS_PRESSURE_POINTS_NUM(A) ((A)->excess_pressure_points_num)
@@ -481,6 +536,10 @@ struct ira_allocno
#define ALLOCNO_MIN(A) ((A)->min)
#define ALLOCNO_MAX(A) ((A)->max)
#define ALLOCNO_CONFLICT_ID(A) ((A)->conflict_id)
+#define ALLOCNO_PROFITABLE_HARD_REGS(A) ((A)->profitable_hard_regs)
+#define ALLOCNO_HARD_REGS_NODE(A) ((A)->hard_regs_node)
+#define ALLOCNO_HARD_REGS_SUBNODES_START(A) ((A)->hard_regs_subnodes_start)
+#define ALLOCNO_HARD_REGS_SUBNODES_NUM(A) ((A)->hard_regs_subnodes_num)
/* Map regno -> allocnos with given regno (see comments for
allocno member `next_regno_allocno'). */
@@ -565,8 +624,6 @@ extern int ira_reg_cost, ira_mem_cost;
extern int ira_load_cost, ira_store_cost, ira_shuffle_cost;
extern int ira_move_loops_num, ira_additional_jumps_num;
-/* Maximal value of element of array ira_reg_class_nregs. */
-extern int ira_max_nregs;
\f
/* This page contains a bitset implementation called 'min/max sets' used to
record conflicts in IRA.
@@ -762,7 +819,7 @@ extern short ira_class_hard_reg_index[N_
/* Array whose values are hard regset of hard registers available for
the allocation of given register class whose HARD_REGNO_MODE_OK
values for given mode are zero. */
-extern HARD_REG_SET prohibited_class_mode_regs
+extern HARD_REG_SET ira_prohibited_class_mode_regs
[N_REG_CLASSES][NUM_MACHINE_MODES];
/* Array whose values are hard regset of hard registers for which
@@ -770,11 +827,17 @@ extern HARD_REG_SET prohibited_class_mod
prohibited. */
extern HARD_REG_SET ira_prohibited_mode_move_regs[NUM_MACHINE_MODES];
+/* Map class->true if class is a possible allocno class, false
+ otherwise. */
+extern bool ira_reg_allocno_class_p[N_REG_CLASSES];
+
+/* Map class->true if class is a pressure class, false otherwise. */
+extern bool ira_reg_pressure_class_p[N_REG_CLASSES];
+
/* The value is number of elements in the subsequent array. */
extern int ira_important_classes_num;
-/* The array containing non-empty classes (including non-empty cover
- classes) which are subclasses of cover classes. Such classes is
+/* The array containing all non-empty classes. Such classes is
important for calculation of the hard register usage costs. */
extern enum reg_class ira_important_classes[N_REG_CLASSES];
@@ -799,15 +862,18 @@ extern bool ira_reg_classes_intersect_p[
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
- registers available for allocation, the value is calculated with
- taking all hard-registers including fixed ones into account. In
- other words, the value is the corresponding reg_class_subunion
- value. */
-extern enum reg_class ira_reg_class_union[N_REG_CLASSES][N_REG_CLASSES];
+extern enum reg_class
+ ira_reg_class_super_classes[N_REG_CLASSES][N_REG_CLASSES];
+
+/* The biggest (smallest) important class inside of (covering) union
+ of the two classes (that is calculated taking only hard registers
+ available for allocation into account). If the both classes
+ contain no hard registers available for allocation, the value is
+ calculated with taking all hard-registers including fixed ones into
+ account. In other words, the value is the corresponding
+ reg_class_subunion (reg_class_superunion) value. */
+extern enum reg_class ira_reg_class_subunion[N_REG_CLASSES][N_REG_CLASSES];
+extern enum reg_class ira_reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES];
extern void *ira_allocate (size_t);
extern void *ira_reallocate (void *, size_t);
@@ -816,7 +882,7 @@ extern bitmap ira_allocate_bitmap (void)
extern void ira_free_bitmap (bitmap);
extern void ira_print_disposition (FILE *);
extern void ira_debug_disposition (void);
-extern void ira_debug_class_cover (void);
+extern void ira_debug_allocno_classes (void);
extern void ira_init_register_move_cost (enum machine_mode);
/* The length of the two following arrays. */
@@ -846,7 +912,7 @@ extern void ira_traverse_loop_tree (bool
extern ira_allocno_t ira_parent_allocno (ira_allocno_t);
extern ira_allocno_t ira_parent_or_cap_allocno (ira_allocno_t);
extern ira_allocno_t ira_create_allocno (int, bool, ira_loop_tree_node_t);
-extern void ira_set_allocno_cover_class (ira_allocno_t, enum reg_class);
+extern void ira_set_allocno_class (ira_allocno_t, enum reg_class);
extern bool ira_conflict_vector_profitable_p (ira_allocno_t, int);
extern void ira_allocate_allocno_conflict_vec (ira_allocno_t, int);
extern void ira_allocate_allocno_conflicts (ira_allocno_t, int);
@@ -880,7 +946,7 @@ extern void ira_init_costs_once (void);
extern void ira_init_costs (void);
extern void ira_finish_costs_once (void);
extern void ira_costs (void);
-extern void ira_tune_allocno_costs_and_cover_classes (void);
+extern void ira_tune_allocno_costs (void);
/* ira-lives.c */
@@ -898,6 +964,7 @@ extern void ira_debug_conflicts (bool);
extern void ira_build_conflicts (void);
/* ira-color.c */
+extern void ira_debug_hard_regs_forest (void);
extern int ira_loop_edge_freq (ira_loop_tree_node_t, int, bool);
extern void ira_reassign_conflict_allocnos (int);
extern void ira_initiate_assign (void);
@@ -1137,6 +1204,34 @@ ira_allocno_conflict_iter_next (ira_allo
\f
+/* The function returns TRUE if at least one hard register from ones
+ starting with HARD_REGNO and containing value of MODE are in set
+ HARD_REGSET. */
+static inline bool
+ira_hard_reg_set_intersection_p (int hard_regno, enum machine_mode mode,
+ HARD_REG_SET hard_regset)
+{
+ int i;
+
+ gcc_assert (hard_regno >= 0);
+ for (i = hard_regno_nregs[hard_regno][mode] - 1; i >= 0; i--)
+ if (TEST_HARD_REG_BIT (hard_regset, hard_regno + i))
+ return true;
+ return false;
+}
+
+/* Return number of hard registers in hard register SET. */
+static inline int
+hard_reg_set_size (HARD_REG_SET set)
+{
+ int i, size;
+
+ for (size = i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (TEST_HARD_REG_BIT (set, i))
+ size++;
+ return size;
+}
+
/* The function returns TRUE if hard registers starting with
HARD_REGNO and containing value of MODE are not in set
HARD_REGSET. */
@@ -1159,61 +1254,61 @@ ira_hard_reg_not_in_set_p (int hard_regn
initialization of the cost vectors. We do this only when it is
really necessary. */
-/* Allocate cost vector *VEC for hard registers of COVER_CLASS and
+/* Allocate cost vector *VEC for hard registers of ACLASS and
initialize the elements by VAL if it is necessary */
static inline void
-ira_allocate_and_set_costs (int **vec, enum reg_class cover_class, int val)
+ira_allocate_and_set_costs (int **vec, enum reg_class aclass, int val)
{
int i, *reg_costs;
int len;
if (*vec != NULL)
return;
- *vec = reg_costs = ira_allocate_cost_vector (cover_class);
- len = ira_class_hard_regs_num[cover_class];
+ *vec = reg_costs = ira_allocate_cost_vector (aclass);
+ len = ira_class_hard_regs_num[aclass];
for (i = 0; i < len; i++)
reg_costs[i] = val;
}
-/* Allocate cost vector *VEC for hard registers of COVER_CLASS and
+/* Allocate cost vector *VEC for hard registers of ACLASS and
copy values of vector SRC into the vector if it is necessary */
static inline void
-ira_allocate_and_copy_costs (int **vec, enum reg_class cover_class, int *src)
+ira_allocate_and_copy_costs (int **vec, enum reg_class aclass, int *src)
{
int len;
if (*vec != NULL || src == NULL)
return;
- *vec = ira_allocate_cost_vector (cover_class);
- len = ira_class_hard_regs_num[cover_class];
+ *vec = ira_allocate_cost_vector (aclass);
+ len = ira_class_hard_regs_num[aclass];
memcpy (*vec, src, sizeof (int) * len);
}
-/* Allocate cost vector *VEC for hard registers of COVER_CLASS and
+/* Allocate cost vector *VEC for hard registers of ACLASS and
add values of vector SRC into the vector if it is necessary */
static inline void
-ira_allocate_and_accumulate_costs (int **vec, enum reg_class cover_class,
+ira_allocate_and_accumulate_costs (int **vec, enum reg_class aclass,
int *src)
{
int i, len;
if (src == NULL)
return;
- len = ira_class_hard_regs_num[cover_class];
+ len = ira_class_hard_regs_num[aclass];
if (*vec == NULL)
{
- *vec = ira_allocate_cost_vector (cover_class);
+ *vec = ira_allocate_cost_vector (aclass);
memset (*vec, 0, sizeof (int) * len);
}
for (i = 0; i < len; i++)
(*vec)[i] += src[i];
}
-/* Allocate cost vector *VEC for hard registers of COVER_CLASS and
+/* Allocate cost vector *VEC for hard registers of ACLASS and
copy values of vector SRC into the vector or initialize it by VAL
(if SRC is null). */
static inline void
-ira_allocate_and_set_or_copy_costs (int **vec, enum reg_class cover_class,
+ira_allocate_and_set_or_copy_costs (int **vec, enum reg_class aclass,
int val, int *src)
{
int i, *reg_costs;
@@ -1221,8 +1316,8 @@ ira_allocate_and_set_or_copy_costs (int
if (*vec != NULL)
return;
- *vec = reg_costs = ira_allocate_cost_vector (cover_class);
- len = ira_class_hard_regs_num[cover_class];
+ *vec = reg_costs = ira_allocate_cost_vector (aclass);
+ len = ira_class_hard_regs_num[aclass];
if (src != NULL)
memcpy (reg_costs, src, sizeof (int) * len);
else
Index: ira-color.c
===================================================================
--- ira-color.c (revision 161709)
+++ ira-color.c (working copy)
@@ -37,7 +37,6 @@ along with GCC; see the file COPYING3.
#include "reload.h"
#include "params.h"
#include "df.h"
-#include "splay-tree.h"
#include "ira-int.h"
/* This file contains code for regional graph coloring, spill/restore
@@ -53,77 +52,879 @@ static bitmap coloring_allocno_bitmap;
allocnos. */
static bitmap consideration_allocno_bitmap;
-/* TRUE if we coalesced some allocnos. In other words, if we got
- loops formed by members first_coalesced_allocno and
- next_coalesced_allocno containing more one allocno. */
-static bool allocno_coalesced_p;
-
-/* Bitmap used to prevent a repeated allocno processing because of
- coalescing. */
-static bitmap processed_coalesced_allocno_bitmap;
-
/* All allocnos sorted according their priorities. */
static ira_allocno_t *sorted_allocnos;
/* Vec representing the stack of allocnos used during coloring. */
static VEC(ira_allocno_t,heap) *allocno_stack_vec;
-/* Array used to choose an allocno for spilling. */
-static ira_allocno_t *allocnos_for_spilling;
+\f
+
+/* Definition of vector of allocno hard registers. */
+DEF_VEC_P(allocno_hard_regs_t);
+DEF_VEC_ALLOC_P(allocno_hard_regs_t, heap);
+
+/* Vector of unique allocno hard registers. */
+static VEC(allocno_hard_regs_t, heap) *allocno_hard_regs_vec;
+
+/* Returns hash value for allocno hard registers V. */
+static hashval_t
+allocno_hard_regs_hash (const void *v)
+{
+ const struct allocno_hard_regs *hv = (const struct allocno_hard_regs *) v;
+
+ return iterative_hash (&hv->set, sizeof (HARD_REG_SET), 0);
+}
+
+/* Compares allocno hard registers V1 and V2. */
+static int
+allocno_hard_regs_eq (const void *v1, const void *v2)
+{
+ const struct allocno_hard_regs *hv1 = (const struct allocno_hard_regs *) v1;
+ const struct allocno_hard_regs *hv2 = (const struct allocno_hard_regs *) v2;
+
+ return hard_reg_set_equal_p (hv1->set, hv2->set);
+}
+
+/* Hash table of unique allocno hard registers. */
+static htab_t allocno_hard_regs_htab;
+
+/* Return allocno hard registers in the hash table equal to HV. */
+static allocno_hard_regs_t
+find_hard_regs (allocno_hard_regs_t hv)
+{
+ return (allocno_hard_regs_t) htab_find (allocno_hard_regs_htab, hv);
+}
+
+/* Insert allocno hard registers HV in the hash table (if it is not
+ there yet) and return the value which in the table. */
+static allocno_hard_regs_t
+insert_hard_regs (allocno_hard_regs_t hv)
+{
+ PTR *slot = htab_find_slot (allocno_hard_regs_htab, hv, INSERT);
+
+ if (*slot == NULL)
+ *slot = hv;
+ return (allocno_hard_regs_t) *slot;
+}
+
+/* Initialize data concerning allocno hard registers. */
+static void
+init_allocno_hard_regs (void)
+{
+ allocno_hard_regs_vec = VEC_alloc (allocno_hard_regs_t, heap, 200);
+ allocno_hard_regs_htab
+ = htab_create (200, allocno_hard_regs_hash, allocno_hard_regs_eq, NULL);
+}
+
+/* Add (or update info about) allocno hard registers with SET and
+ COST. */
+static allocno_hard_regs_t
+add_allocno_hard_regs (HARD_REG_SET set, long long int cost)
+{
+ struct allocno_hard_regs temp;
+ allocno_hard_regs_t hv;
+
+ gcc_assert (! hard_reg_set_empty_p (set));
+ COPY_HARD_REG_SET (temp.set, set);
+ if ((hv = find_hard_regs (&temp)) != NULL)
+ hv->cost += cost;
+ else
+ {
+ hv = ((struct allocno_hard_regs *)
+ ira_allocate (sizeof (struct allocno_hard_regs)));
+ COPY_HARD_REG_SET (hv->set, set);
+ hv->cost = cost;
+ VEC_safe_push (allocno_hard_regs_t, heap, allocno_hard_regs_vec, hv);
+ insert_hard_regs (hv);
+ }
+ return hv;
+}
+
+/* Finalize data concerning allocno hard registers. */
+static void
+finish_allocno_hard_regs (void)
+{
+ int i;
+ allocno_hard_regs_t hv;
+
+ for (i = 0;
+ VEC_iterate (allocno_hard_regs_t, allocno_hard_regs_vec, i, hv);
+ i++)
+ ira_free (hv);
+ htab_delete (allocno_hard_regs_htab);
+ VEC_free (allocno_hard_regs_t, heap, allocno_hard_regs_vec);
+}
-/* Pool for splay tree nodes. */
-static alloc_pool splay_tree_node_pool;
+/* Sort hard regs according to their frequency of usage. */
+static int
+allocno_hard_regs_compare (const void *v1p, const void *v2p)
+{
+ allocno_hard_regs_t hv1 = *(const allocno_hard_regs_t *) v1p;
+ allocno_hard_regs_t hv2 = *(const allocno_hard_regs_t *) v2p;
-/* When an allocno is removed from the splay tree, it is put in the
- following vector for subsequent inserting it into the splay tree
- after putting all colorable allocnos onto the stack. The allocno
- could be removed from and inserted to the splay tree every time
- when its spilling priority is changed but such solution would be
- more costly although simpler. */
-static VEC(ira_allocno_t,heap) *removed_splay_allocno_vec;
+ if (hv2->cost > hv1->cost)
+ return 1;
+ else if (hv2->cost < hv1->cost)
+ return -1;
+ else
+ return 0;
+}
\f
-/* This page contains functions used to find conflicts using allocno
- live ranges. */
+/* Used for finding a common ancestor of two allocno hard registers
+ nodes in the forrest. It is also used to figure out allocno
+ colorability. */
+static int node_check_tick;
-/* Return TRUE if live ranges of allocnos A1 and A2 intersect. It is
- used to find a conflict for new allocnos or allocnos with the
- different cover classes. */
-static bool
-allocnos_have_intersected_live_ranges_p (ira_allocno_t a1, ira_allocno_t a2)
+/* Roots of the forest containing hard register sets can be assigned
+ to allocnos. */
+static allocno_hard_regs_node_t hard_regs_roots;
+
+/* Definition of vector of allocno hard register nodes. */
+DEF_VEC_P(allocno_hard_regs_node_t);
+DEF_VEC_ALLOC_P(allocno_hard_regs_node_t, heap);
+
+/* Vector used to create the forrest. */
+static VEC(allocno_hard_regs_node_t, heap) *hard_regs_node_vec;
+
+/* Create and return allocno hard registers node containing allocno
+ hard registers HV. */
+static allocno_hard_regs_node_t
+create_new_allocno_hard_regs_node (allocno_hard_regs_t hv)
{
- if (a1 == a2)
- return false;
- if (ALLOCNO_REG (a1) != NULL && ALLOCNO_REG (a2) != NULL
- && (ORIGINAL_REGNO (ALLOCNO_REG (a1))
- == ORIGINAL_REGNO (ALLOCNO_REG (a2))))
- return false;
- return ira_allocno_live_ranges_intersect_p (ALLOCNO_LIVE_RANGES (a1),
- ALLOCNO_LIVE_RANGES (a2));
+ allocno_hard_regs_node_t new_node;
+
+ new_node = ((struct allocno_hard_regs_node *)
+ ira_allocate (sizeof (struct allocno_hard_regs_node)));
+ new_node->check = 0;
+ new_node->hard_regs = hv;
+ new_node->hard_regs_num = hard_reg_set_size (hv->set);
+ new_node->first = NULL;
+ new_node->used_p = false;
+ return new_node;
}
-#ifdef ENABLE_IRA_CHECKING
+/* Add allocno hard registers node NEW_NODE to the forest on its level
+ given by ROOTS. */
+static void
+add_new_allocno_hard_regs_node_to_forest (allocno_hard_regs_node_t *roots,
+ allocno_hard_regs_node_t new_node)
+{
+ new_node->next = *roots;
+ if (new_node->next != NULL)
+ new_node->next->prev = new_node;
+ new_node->prev = NULL;
+ *roots = new_node;
+}
-/* Return TRUE if live ranges of pseudo-registers REGNO1 and REGNO2
- intersect. This should be used when there is only one region.
- Currently this is used during reload. */
-static bool
-pseudos_have_intersected_live_ranges_p (int regno1, int regno2)
+/* Add allocno hard registers HV (or its best approximation if it is
+ not possible) to the forest on its level given by ROOTS. */
+static void
+add_allocno_hard_regs_to_forest (allocno_hard_regs_node_t *roots,
+ allocno_hard_regs_t hv)
{
- ira_allocno_t a1, a2;
+ unsigned int i, start;
+ allocno_hard_regs_node_t node, prev, new_node;
+ HARD_REG_SET temp_set;
+ allocno_hard_regs_t hv2;
- ira_assert (regno1 >= FIRST_PSEUDO_REGISTER
- && regno2 >= FIRST_PSEUDO_REGISTER);
- /* Reg info caclulated by dataflow infrastructure can be different
- from one calculated by regclass. */
- if ((a1 = ira_loop_tree_root->regno_allocno_map[regno1]) == NULL
- || (a2 = ira_loop_tree_root->regno_allocno_map[regno2]) == NULL)
- return false;
- return allocnos_have_intersected_live_ranges_p (a1, a2);
+ start = VEC_length (allocno_hard_regs_node_t, hard_regs_node_vec);
+ for (node = *roots; node != NULL; node = node->next)
+ {
+ if (hard_reg_set_equal_p (hv->set, node->hard_regs->set))
+ return;
+ if (hard_reg_set_subset_p (hv->set, node->hard_regs->set))
+ {
+ add_allocno_hard_regs_to_forest (&node->first, hv);
+ return;
+ }
+ if (hard_reg_set_subset_p (node->hard_regs->set, hv->set))
+ VEC_safe_push (allocno_hard_regs_node_t, heap,
+ hard_regs_node_vec, node);
+ else if (hard_reg_set_intersect_p (hv->set, node->hard_regs->set))
+ {
+ COPY_HARD_REG_SET (temp_set, hv->set);
+ AND_HARD_REG_SET (temp_set, node->hard_regs->set);
+ hv2 = add_allocno_hard_regs (temp_set, hv->cost);
+ add_allocno_hard_regs_to_forest (&node->first, hv2);
+ }
+ }
+ if (VEC_length (allocno_hard_regs_node_t, hard_regs_node_vec)
+ > start + 1)
+ {
+ /* Create a new node which contains nodes in hard_regs_node_vec. */
+ CLEAR_HARD_REG_SET (temp_set);
+ for (i = start;
+ i < VEC_length (allocno_hard_regs_node_t, hard_regs_node_vec);
+ i++)
+ {
+ node = VEC_index (allocno_hard_regs_node_t, hard_regs_node_vec, i);
+ IOR_HARD_REG_SET (temp_set, node->hard_regs->set);
+ }
+ hv = add_allocno_hard_regs (temp_set, hv->cost);
+ new_node = create_new_allocno_hard_regs_node (hv);
+ prev = NULL;
+ for (i = start;
+ i < VEC_length (allocno_hard_regs_node_t, hard_regs_node_vec);
+ i++)
+ {
+ node = VEC_index (allocno_hard_regs_node_t, hard_regs_node_vec, i);
+ if (node->prev == NULL)
+ *roots = node->next;
+ else
+ node->prev->next = node->next;
+ if (node->next != NULL)
+ node->next->prev = node->prev;
+ if (prev == NULL)
+ new_node->first = node;
+ else
+ prev->next = node;
+ node->prev = prev;
+ node->next = NULL;
+ prev = node;
+ }
+ add_new_allocno_hard_regs_node_to_forest (roots, new_node);
+ }
+ VEC_truncate (allocno_hard_regs_node_t, hard_regs_node_vec, start);
}
-#endif
+/* Add allocno hard registers nodes starting with the forrest level
+ given by FIRTS which contains biggest set inside SET. */
+static void
+collect_allocno_hard_regs_cover (allocno_hard_regs_node_t first,
+ HARD_REG_SET set)
+{
+ allocno_hard_regs_node_t node;
+
+ ira_assert (first != NULL);
+ for (node = first; node != NULL; node = node->next)
+ if (hard_reg_set_subset_p (node->hard_regs->set, set))
+ VEC_safe_push (allocno_hard_regs_node_t, heap, hard_regs_node_vec,
+ node);
+ else if (hard_reg_set_intersect_p (set, node->hard_regs->set))
+ collect_allocno_hard_regs_cover (node->first, set);
+}
+
+/* Set up field parent as PARENT in all allocno hard registers nodes
+ in forest given by FIRST. */
+static void
+setup_allocno_hard_regs_nodes_parent (allocno_hard_regs_node_t first,
+ allocno_hard_regs_node_t parent)
+{
+ allocno_hard_regs_node_t node;
+
+ for (node = first; node != NULL; node = node->next)
+ {
+ node->parent = parent;
+ setup_allocno_hard_regs_nodes_parent (node->first, node);
+ }
+}
+
+/* Return allocno hard registers node which is a first common ancestor
+ node of FIRST and SECOND in the forest. */
+static allocno_hard_regs_node_t
+first_common_ancestor_node (allocno_hard_regs_node_t first,
+ allocno_hard_regs_node_t second)
+{
+ allocno_hard_regs_node_t node;
+
+ node_check_tick++;
+ for (node = first; node != NULL; node = node->parent)
+ node->check = node_check_tick;
+ for (node = second; node != NULL; node = node->parent)
+ if (node->check == node_check_tick)
+ return node;
+ return first_common_ancestor_node (second, first);
+}
+
+/* Print hard reg set SET to F. */
+static void
+print_hard_reg_set (FILE *f, HARD_REG_SET set, bool new_line_p)
+{
+ int i, start;
+
+ for (start = -1, i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ {
+ if (TEST_HARD_REG_BIT (set, i))
+ {
+ if (i == 0 || ! TEST_HARD_REG_BIT (set, i - 1))
+ start = i;
+ }
+ if (start >= 0
+ && (i == FIRST_PSEUDO_REGISTER - 1 || ! TEST_HARD_REG_BIT (set, i)))
+ {
+ if (start == i - 1)
+ fprintf (f, " %d", start);
+ else if (start == i - 2)
+ fprintf (f, " %d %d", start, start + 1);
+ else
+ fprintf (f, " %d-%d", start, i - 1);
+ start = -1;
+ }
+ }
+ if (new_line_p)
+ fprintf (f, "\n");
+}
+
+/* Print allocno hard register subforest given by ROOTS and its LEVEL
+ to F. */
+static void
+print_hard_regs_subforest (FILE *f, allocno_hard_regs_node_t roots,
+ int level)
+{
+ int i;
+ allocno_hard_regs_node_t node;
+
+ for (node = roots; node != NULL; node = node->next)
+ {
+ fprintf (f, " ");
+ for (i = 0; i < level * 2; i++)
+ fprintf (f, " ");
+ fprintf (f, "%d:(", node->preorder_num);
+ print_hard_reg_set (f, node->hard_regs->set, false);
+ fprintf (f, ")@%lld\n", node->hard_regs->cost);
+ print_hard_regs_subforest (f, node->first, level + 1);
+ }
+}
+
+/* Print the allocno hard register forest to F. */
+static void
+print_hard_regs_forest (FILE *f)
+{
+ fprintf (f, " Hard reg set forest:\n");
+ print_hard_regs_subforest (f, hard_regs_roots, 1);
+}
+
+/* Print the allocno hard register forest to stderr. */
+void
+ira_debug_hard_regs_forest (void)
+{
+ print_hard_regs_forest (stderr);
+}
+
+/* Remove unused allocno hard registers nodes from forest given by its
+ *ROOTS. */
+static void
+remove_unused_allocno_hard_regs_nodes (allocno_hard_regs_node_t *roots)
+{
+ allocno_hard_regs_node_t node, prev, next, last;
+
+ for (prev = NULL, node = *roots; node != NULL; node = next)
+ {
+ next = node->next;
+ if (node->used_p)
+ {
+ remove_unused_allocno_hard_regs_nodes (&node->first);
+ prev = node;
+ }
+ else
+ {
+ for (last = node->first;
+ last != NULL && last->next != NULL;
+ last = last->next)
+ ;
+ if (last != NULL)
+ {
+ if (prev == NULL)
+ *roots = node->first;
+ else
+ prev->next = node->first;
+ if (next != NULL)
+ next->prev = last;
+ last->next = next;
+ next = node->first;
+ }
+ else
+ {
+ if (prev == NULL)
+ *roots = next;
+ else
+ prev->next = next;
+ if (next != NULL)
+ next->prev = prev;
+ }
+ ira_free (node);
+ }
+ }
+}
+
+/* Set up fields preorder_num starting with START_NUM in all allocno
+ hard registers nodes in forest given by FIRST. Return biggest set
+ PREORDER_NUM increased by 1. */
+static int
+enumerate_allocno_hard_regs_nodes (allocno_hard_regs_node_t first,
+ allocno_hard_regs_node_t parent,
+ int start_num)
+{
+ allocno_hard_regs_node_t node;
+
+ for (node = first; node != NULL; node = node->next)
+ {
+ node->preorder_num = start_num++;
+ node->parent = parent;
+ start_num = enumerate_allocno_hard_regs_nodes (node->first, node,
+ start_num);
+ }
+ return start_num;
+}
+
+/* Number of allocno hard registers nodes in the forest. */
+static int allocno_hard_regs_nodes_num;
+
+/* Table preorder number of allocno hard registers node in the forest
+ -> the allocno hard registers node. */
+static allocno_hard_regs_node_t *allocno_hard_regs_nodes;
+
+/* See below. */
+typedef struct allocno_hard_regs_subnode *allocno_hard_regs_subnode_t;
+
+/* The structure is used to describes all subnodes (not only immediate
+ ones) in the mentioned above tree for given allocno hard register
+ node. The usage of such data accelerates calculation of
+ colorability of given allocno. */
+struct allocno_hard_regs_subnode
+{
+ /* The conflict size of conflicting allocnos whose hard register
+ sets are equal sets (plus supersets if given node is given
+ allocno hard registers node) of one in the given node. */
+ int left_conflict_size;
+ /* The summary conflict size of conflicting allocnos whose hard
+ register sets are strict subsets of one in the given node.
+ Overall conflict size is
+ left_conflict_subnodes_size
+ + MIN (max_node_impact - left_conflict_subnodes_size,
+ left_conflict_size)
+ */
+ short left_conflict_subnodes_size;
+ short max_node_impact;
+};
+
+/* Container for hard regs subnodes of all allocnos. */
+static allocno_hard_regs_subnode_t allocno_hard_regs_subnodes;
+
+/* Table (preorder number of allocno hard registers node in the
+ forest, preorder number of allocno hard registers subnode) -> index
+ of the subnode relative to the node. -1 if it is not a
+ subnode. */
+static int *allocno_hard_regs_subnode_index;
+
+/* Setup arrays ALLOCNO_HARD_REGS_NODES and
+ ALLOCNO_HARD_REGS_SUBNODE_INDEX. */
+static void
+setup_allocno_hard_regs_subnode_index (allocno_hard_regs_node_t first)
+{
+ allocno_hard_regs_node_t node, parent;
+ int index;
+
+ for (node = first; node != NULL; node = node->next)
+ {
+ allocno_hard_regs_nodes[node->preorder_num] = node;
+ for (parent = node; parent != NULL; parent = parent->parent)
+ {
+ index = parent->preorder_num * allocno_hard_regs_nodes_num;
+ allocno_hard_regs_subnode_index[index + node->preorder_num]
+ = node->preorder_num - parent->preorder_num;
+ }
+ setup_allocno_hard_regs_subnode_index (node->first);
+ }
+}
+
+/* Count all allocno hard registers nodes in tree ROOT. */
+static int
+get_allocno_hard_regs_subnodes_num (allocno_hard_regs_node_t root)
+{
+ int len = 1;
+
+ for (root = root->first; root != NULL; root = root->next)
+ len += get_allocno_hard_regs_subnodes_num (root);
+ return len;
+}
+
+/* Build the forest of allocno hard registers nodes and assign each
+ allocno a node from the forest. */
+static void
+form_allocno_hard_regs_nodes_forest (void)
+{
+ unsigned int i, j, size, len;
+ int start;
+ ira_allocno_t a;
+ allocno_hard_regs_t hv;
+ bitmap_iterator bi;
+ HARD_REG_SET temp;
+ allocno_hard_regs_node_t node, allocno_hard_regs_node;
+
+ node_check_tick = 0;
+ init_allocno_hard_regs ();
+ hard_regs_roots = NULL;
+ hard_regs_node_vec = VEC_alloc (allocno_hard_regs_node_t, heap, 100);
+ for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, i))
+ {
+ CLEAR_HARD_REG_SET (temp);
+ SET_HARD_REG_BIT (temp, i);
+ hv = add_allocno_hard_regs (temp, 0);
+ node = create_new_allocno_hard_regs_node (hv);
+ add_new_allocno_hard_regs_node_to_forest (&hard_regs_roots, node);
+ }
+ start = VEC_length (allocno_hard_regs_t, allocno_hard_regs_vec);
+ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
+ {
+ a = ira_allocnos[i];
+ if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ continue;
+ hv = (add_allocno_hard_regs
+ (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a)));
+ }
+ SET_HARD_REG_SET (temp);
+ AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs);
+ add_allocno_hard_regs (temp, 0);
+ qsort (VEC_address (allocno_hard_regs_t, allocno_hard_regs_vec) + start,
+ VEC_length (allocno_hard_regs_t, allocno_hard_regs_vec) - start,
+ sizeof (allocno_hard_regs_t), allocno_hard_regs_compare);
+ for (i = start;
+ VEC_iterate (allocno_hard_regs_t, allocno_hard_regs_vec, i, hv);
+ i++)
+ {
+ add_allocno_hard_regs_to_forest (&hard_regs_roots, hv);
+ ira_assert (VEC_length (allocno_hard_regs_node_t,
+ hard_regs_node_vec) == 0);
+ }
+ /* We need to set up parent fields for right work of
+ first_common_ancestor_node. */
+ setup_allocno_hard_regs_nodes_parent (hard_regs_roots, NULL);
+ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
+ {
+ a = ira_allocnos[i];
+ if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ continue;
+ VEC_truncate (allocno_hard_regs_node_t, hard_regs_node_vec, 0);
+ collect_allocno_hard_regs_cover (hard_regs_roots,
+ ALLOCNO_PROFITABLE_HARD_REGS (a));
+ allocno_hard_regs_node = NULL;
+ for (j = 0;
+ VEC_iterate (allocno_hard_regs_node_t, hard_regs_node_vec,
+ j, node);
+ j++)
+ allocno_hard_regs_node
+ = (j == 0
+ ? node
+ : first_common_ancestor_node (node, allocno_hard_regs_node));
+ /* That is a temporary storage. */
+ allocno_hard_regs_node->used_p = true;
+ ALLOCNO_HARD_REGS_NODE (a) = allocno_hard_regs_node;
+ }
+ ira_assert (hard_regs_roots->next == NULL);
+ hard_regs_roots->used_p = true;
+ remove_unused_allocno_hard_regs_nodes (&hard_regs_roots);
+ allocno_hard_regs_nodes_num
+ = enumerate_allocno_hard_regs_nodes (hard_regs_roots, NULL, 0);
+ allocno_hard_regs_nodes
+ = ((allocno_hard_regs_node_t *)
+ ira_allocate (allocno_hard_regs_nodes_num
+ * sizeof (allocno_hard_regs_node_t)));
+ size = allocno_hard_regs_nodes_num * allocno_hard_regs_nodes_num;
+ allocno_hard_regs_subnode_index
+ = (int *) ira_allocate (size * sizeof (int));
+ for (i = 0; i < size; i++)
+ allocno_hard_regs_subnode_index[i] = -1;
+ setup_allocno_hard_regs_subnode_index (hard_regs_roots);
+ start = 0;
+ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
+ {
+ a = ira_allocnos[i];
+ if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ continue;
+ len = get_allocno_hard_regs_subnodes_num (ALLOCNO_HARD_REGS_NODE (a));
+ ALLOCNO_HARD_REGS_SUBNODES_START (a) = start;
+ ALLOCNO_HARD_REGS_SUBNODES_NUM (a) = len;
+ start += len;
+ }
+ allocno_hard_regs_subnodes
+ = ((allocno_hard_regs_subnode_t)
+ ira_allocate (sizeof (struct allocno_hard_regs_subnode) * start));
+ VEC_free (allocno_hard_regs_node_t, heap, hard_regs_node_vec);
+}
+
+/* Free tree of allocno hard registers nodes given by its ROOT. */
+static void
+finish_allocno_hard_regs_nodes_tree (allocno_hard_regs_node_t root)
+{
+ allocno_hard_regs_node_t child, next;
+
+ for (child = root->first; child != NULL; child = next)
+ {
+ next = child->next;
+ finish_allocno_hard_regs_nodes_tree (child);
+ }
+ ira_free (root);
+}
+
+/* Finish work with the forest of allocno hard registers nodes. */
+static void
+finish_allocno_hard_regs_nodes_forest (void)
+{
+ allocno_hard_regs_node_t node, next;
+
+ ira_free (allocno_hard_regs_subnodes);
+ for (node = hard_regs_roots; node != NULL; node = next)
+ {
+ next = node->next;
+ finish_allocno_hard_regs_nodes_tree (node);
+ }
+ ira_free (allocno_hard_regs_nodes);
+ ira_free (allocno_hard_regs_subnode_index);
+ finish_allocno_hard_regs ();
+}
+
+/* Set up left conflict sizes and left conflict subnodes sizes of hard
+ registers subnodes of allocno A. Return TRUE if allocno A is
+ trivially colorable. */
+static bool
+setup_left_conflict_sizes_p (ira_allocno_t a)
+{
+ int i, node_preorder_num, size, start, parent_i;
+ int conflict_size, left_conflict_subnodes_size;
+ ira_allocno_t conflict_a;
+ ira_allocno_conflict_iterator aci;
+ HARD_REG_SET profitable_hard_regs;
+ allocno_hard_regs_subnode_t subnodes;
+ allocno_hard_regs_node_t node, conflict_node, temp_node, parent;
+ HARD_REG_SET node_set, conflict_node_set;
+
+ node_check_tick++;
+ subnodes = allocno_hard_regs_subnodes + ALLOCNO_HARD_REGS_SUBNODES_START (a);
+ COPY_HARD_REG_SET (profitable_hard_regs, ALLOCNO_PROFITABLE_HARD_REGS (a));
+ node = ALLOCNO_HARD_REGS_NODE (a);
+ node_preorder_num = node->preorder_num;
+ COPY_HARD_REG_SET (node_set, node->hard_regs->set);
+ FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
+ {
+ if (! ALLOCNO_IN_GRAPH_P (conflict_a)
+ || ! hard_reg_set_intersect_p (profitable_hard_regs,
+ ALLOCNO_PROFITABLE_HARD_REGS (conflict_a)))
+ continue;
+ conflict_node = ALLOCNO_HARD_REGS_NODE (conflict_a);
+ COPY_HARD_REG_SET (conflict_node_set, conflict_node->hard_regs->set);
+ if (hard_reg_set_subset_p (node_set, conflict_node_set))
+ temp_node = node;
+ else
+ {
+ ira_assert (hard_reg_set_subset_p (conflict_node_set, node_set));
+ temp_node = conflict_node;
+ }
+ if (temp_node->check != node_check_tick)
+ {
+ temp_node->check = node_check_tick;
+ temp_node->conflict_size = 0;
+ }
+ temp_node->conflict_size
+ += (ira_reg_class_max_nregs
+ [ALLOCNO_CLASS (conflict_a)][ALLOCNO_MODE (conflict_a)]);
+ }
+ for (i = 0; i < ALLOCNO_HARD_REGS_SUBNODES_NUM (a); i++)
+ {
+ temp_node = allocno_hard_regs_nodes[i + node_preorder_num];
+ ira_assert (temp_node->preorder_num == i + node_preorder_num);
+ subnodes[i].left_conflict_size
+ = (temp_node->check != node_check_tick ? 0 : temp_node->conflict_size);
+ if (hard_reg_set_subset_p (temp_node->hard_regs->set,
+ profitable_hard_regs))
+ subnodes[i].max_node_impact = temp_node->hard_regs_num;
+ else
+ {
+ HARD_REG_SET temp_set;
+ int j, n;
+ enum reg_class aclass;
+
+ COPY_HARD_REG_SET (temp_set, temp_node->hard_regs->set);
+ AND_HARD_REG_SET (temp_set, profitable_hard_regs);
+ aclass = ALLOCNO_CLASS (a);
+ for (n = 0, j = ira_class_hard_regs_num[aclass] - 1; j >= 0; j--)
+ if (TEST_HARD_REG_BIT (temp_set, ira_class_hard_regs[aclass][j]))
+ n++;
+ subnodes[i].max_node_impact = n;
+ }
+ subnodes[i].left_conflict_subnodes_size = 0;
+ }
+ start = node_preorder_num * allocno_hard_regs_nodes_num;
+ for (i = ALLOCNO_HARD_REGS_SUBNODES_NUM (a) - 1; i >= 0; i--)
+ {
+ size = (subnodes[i].left_conflict_subnodes_size
+ + MIN (subnodes[i].max_node_impact
+ - subnodes[i].left_conflict_subnodes_size,
+ subnodes[i].left_conflict_size));
+ parent = allocno_hard_regs_nodes[i + node_preorder_num]->parent;
+ if (parent == NULL)
+ continue;
+ parent_i
+ = allocno_hard_regs_subnode_index[start + parent->preorder_num];
+ if (parent_i < 0)
+ continue;
+ subnodes[parent_i].left_conflict_subnodes_size += size;
+ }
+ left_conflict_subnodes_size = subnodes[0].left_conflict_subnodes_size;
+ conflict_size
+ = (left_conflict_subnodes_size
+ + MIN (subnodes[0].max_node_impact - left_conflict_subnodes_size,
+ subnodes[0].left_conflict_size));
+ conflict_size
+ += ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)];
+ ALLOCNO_COLORABLE_P (a) = conflict_size <= ALLOCNO_AVAILABLE_REGS_NUM (a);
+ return ALLOCNO_COLORABLE_P (a);
+}
+
+/* Update left conflict sizes of hard registers subnodes of allocno A
+ after removing allocno REMOVED_A from the conflict graph. Return
+ TRUE if A is trivially colorable. */
+static bool
+update_left_conflict_sizes_p (ira_allocno_t a, ira_allocno_t removed_a)
+{
+ int i, conflict_size, before_conflict_size, diff, start;
+ int node_preorder_num, parent_i;
+ allocno_hard_regs_node_t node, removed_node, parent;
+ allocno_hard_regs_subnode_t subnodes;
+
+ node = ALLOCNO_HARD_REGS_NODE (a);
+ node_preorder_num = node->preorder_num;
+ removed_node = ALLOCNO_HARD_REGS_NODE (removed_a);
+ ira_assert (hard_reg_set_subset_p (removed_node->hard_regs->set,
+ node->hard_regs->set)
+ || hard_reg_set_subset_p (node->hard_regs->set,
+ removed_node->hard_regs->set));
+ start = node_preorder_num * allocno_hard_regs_nodes_num;
+ i = allocno_hard_regs_subnode_index[start + removed_node->preorder_num];
+ if (i < 0)
+ i = 0;
+ subnodes = allocno_hard_regs_subnodes + ALLOCNO_HARD_REGS_SUBNODES_START (a);
+ before_conflict_size
+ = (subnodes[i].left_conflict_subnodes_size
+ + MIN (subnodes[i].max_node_impact
+ - subnodes[i].left_conflict_subnodes_size,
+ subnodes[i].left_conflict_size));
+ subnodes[i].left_conflict_size
+ -= (ira_reg_class_max_nregs
+ [ALLOCNO_CLASS (removed_a)][ALLOCNO_MODE (removed_a)]);
+ for (;;)
+ {
+ conflict_size
+ = (subnodes[i].left_conflict_subnodes_size
+ + MIN (subnodes[i].max_node_impact
+ - subnodes[i].left_conflict_subnodes_size,
+ subnodes[i].left_conflict_size));
+ if ((diff = before_conflict_size - conflict_size) == 0)
+ break;
+ ira_assert (conflict_size < before_conflict_size);
+ parent = allocno_hard_regs_nodes[i + node_preorder_num]->parent;
+ if (parent == NULL)
+ break;
+ parent_i
+ = allocno_hard_regs_subnode_index[start + parent->preorder_num];
+ if (parent_i < 0)
+ break;
+ i = parent_i;
+ before_conflict_size
+ = (subnodes[i].left_conflict_subnodes_size
+ + MIN (subnodes[i].max_node_impact
+ - subnodes[i].left_conflict_subnodes_size,
+ subnodes[i].left_conflict_size));
+ subnodes[i].left_conflict_subnodes_size -= diff;
+ }
+ if (i == 0
+ && (conflict_size
+ + ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
+ <= ALLOCNO_AVAILABLE_REGS_NUM (a)))
+ {
+ ALLOCNO_COLORABLE_P (a) = true;
+ return true;
+ }
+ ira_assert (! ALLOCNO_COLORABLE_P (a));
+ return false;
+}
+
+/* Set up profitable hard registers for each allocno being
+ colored. */
+static void
+setup_profitable_hard_regs (void)
+{
+ unsigned int i;
+ int j, hard_regno, class_size;
+ ira_allocno_t a, conflict_a;
+ ira_allocno_conflict_iterator aci;
+ bitmap_iterator bi;
+ enum reg_class aclass;
+ enum machine_mode mode;
+
+ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
+ {
+ a = ira_allocnos[i];
+ if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS)
+ continue;
+ if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL
+ && ALLOCNO_CLASS_COST (a) > ALLOCNO_MEMORY_COST (a))
+ CLEAR_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a));
+ else
+ {
+ mode = ALLOCNO_MODE (a);
+ COPY_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ reg_class_contents[aclass]);
+ AND_COMPL_HARD_REG_SET
+ (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ ira_prohibited_class_mode_regs[aclass][mode]);
+ AND_COMPL_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ ira_no_alloc_regs);
+ AND_COMPL_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+ }
+ }
+ EXECUTE_IF_SET_IN_BITMAP (consideration_allocno_bitmap, 0, i, bi)
+ {
+ a = ira_allocnos[i];
+ if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS
+ || ! ALLOCNO_ASSIGNED_P (a)
+ || (hard_regno = ALLOCNO_HARD_REGNO (a)) < 0)
+ continue;
+ FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
+ AND_COMPL_HARD_REG_SET
+ (ALLOCNO_PROFITABLE_HARD_REGS (conflict_a),
+ ira_reg_mode_hard_regset[hard_regno][ALLOCNO_MODE (a)]);
+ }
+ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
+ {
+ int min_cost = INT_MAX;
+ int *costs;
+
+ a = ira_allocnos[i];
+ if ((aclass = ALLOCNO_CLASS (a)) == NO_REGS
+ || hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ continue;
+ if ((costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a)) != NULL
+ || (costs = ALLOCNO_HARD_REG_COSTS (a)) != NULL)
+ {
+ class_size = ira_class_hard_regs_num[aclass];
+ mode = ALLOCNO_MODE (a);
+ for (j = 0; j < class_size; j++)
+ {
+ hard_regno = ira_class_hard_regs[aclass][j];
+ if (! TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ hard_regno))
+ continue;
+ if (ALLOCNO_UPDATED_MEMORY_COST (a) < costs[j])
+ CLEAR_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ hard_regno);
+ else if (min_cost > costs[j])
+ min_cost = costs[j];
+ }
+ }
+ else if (ALLOCNO_UPDATED_MEMORY_COST (a)
+ < ALLOCNO_UPDATED_CLASS_COST (a))
+ CLEAR_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a));
+ if (ALLOCNO_UPDATED_CLASS_COST (a) > min_cost)
+ ALLOCNO_UPDATED_CLASS_COST (a) = min_cost;
+ }
+}
\f
@@ -135,7 +936,8 @@ pseudos_have_intersected_live_ranges_p (
static bool allocated_hardreg_p[FIRST_PSEUDO_REGISTER];
/* Describes one element in a queue of allocnos whose costs need to be
- updated. Each allocno in the queue is known to have a cover class. */
+ updated. Each allocno in the queue is known to have an allocno
+ class. */
struct update_cost_queue_elem
{
/* This element is in the queue iff CHECK == update_cost_check. */
@@ -199,7 +1001,7 @@ start_update_cost (void)
}
/* Add (ALLOCNO, DIVISOR) to the end of update_cost_queue,
- unless ALLOCNO is already in the queue, or has no cover class. */
+ unless ALLOCNO is already in the queue, or has NO_REGS class. */
static inline void
queue_update_cost (ira_allocno_t allocno, int divisor)
{
@@ -207,7 +1009,7 @@ queue_update_cost (ira_allocno_t allocno
elem = &update_cost_queue_elems[ALLOCNO_NUM (allocno)];
if (elem->check != update_cost_check
- && ALLOCNO_COVER_CLASS (allocno) != NO_REGS)
+ && ALLOCNO_CLASS (allocno) != NO_REGS)
{
elem->check = update_cost_check;
elem->divisor = divisor;
@@ -245,17 +1047,17 @@ update_copy_costs (ira_allocno_t allocno
{
int i, cost, update_cost, hard_regno, divisor;
enum machine_mode mode;
- enum reg_class rclass, cover_class;
+ enum reg_class rclass, aclass;
ira_allocno_t another_allocno;
ira_copy_t cp, next_cp;
hard_regno = ALLOCNO_HARD_REGNO (allocno);
ira_assert (hard_regno >= 0);
- cover_class = ALLOCNO_COVER_CLASS (allocno);
- if (cover_class == NO_REGS)
+ aclass = ALLOCNO_CLASS (allocno);
+ if (aclass == NO_REGS)
return;
- i = ira_class_hard_reg_index[cover_class][hard_regno];
+ i = ira_class_hard_reg_index[aclass][hard_regno];
ira_assert (i >= 0);
rclass = REGNO_REG_CLASS (hard_regno);
@@ -279,14 +1081,14 @@ update_copy_costs (ira_allocno_t allocno
else
gcc_unreachable ();
- cover_class = ALLOCNO_COVER_CLASS (another_allocno);
- if (! ira_reg_classes_intersect_p[rclass][cover_class]
+ aclass = ALLOCNO_CLASS (another_allocno);
+ if (! ira_reg_classes_intersect_p[rclass][aclass]
|| ALLOCNO_ASSIGNED_P (another_allocno))
continue;
cost = (cp->second == allocno
- ? ira_get_register_move_cost (mode, rclass, cover_class)
- : ira_get_register_move_cost (mode, cover_class, rclass));
+ ? ira_get_register_move_cost (mode, rclass, aclass)
+ : ira_get_register_move_cost (mode, aclass, rclass));
if (decr_p)
cost = -cost;
@@ -295,15 +1097,15 @@ update_copy_costs (ira_allocno_t allocno
continue;
ira_allocate_and_set_or_copy_costs
- (&ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno), cover_class,
- ALLOCNO_UPDATED_COVER_CLASS_COST (another_allocno),
+ (&ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno), aclass,
+ ALLOCNO_UPDATED_CLASS_COST (another_allocno),
ALLOCNO_HARD_REG_COSTS (another_allocno));
ira_allocate_and_set_or_copy_costs
(&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);
+ aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
+ i = ira_class_hard_reg_index[aclass][hard_regno];
+ if (i < 0)
+ continue;
ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno)[i] += update_cost;
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno)[i]
+= update_cost;
@@ -315,18 +1117,18 @@ update_copy_costs (ira_allocno_t allocno
}
/* This function updates COSTS (decrease if DECR_P) for hard_registers
- of COVER_CLASS by conflict costs of the unassigned allocnos
+ of ACLASS 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, enum reg_class cover_class,
+update_conflict_hard_regno_costs (int *costs, enum reg_class aclass,
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 another_cover_class;
+ enum reg_class another_aclass;
ira_allocno_t allocno, another_allocno;
ira_copy_t cp, next_cp;
@@ -345,17 +1147,16 @@ update_conflict_hard_regno_costs (int *c
}
else
gcc_unreachable ();
- another_cover_class = ALLOCNO_COVER_CLASS (another_allocno);
- if (! ira_reg_classes_intersect_p[cover_class][another_cover_class]
+ another_aclass = ALLOCNO_CLASS (another_allocno);
+ if (! ira_reg_classes_intersect_p[aclass][another_aclass]
|| ALLOCNO_ASSIGNED_P (another_allocno)
|| ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO
(another_allocno)))
continue;
- class_size = ira_class_hard_regs_num[another_cover_class];
+ class_size = ira_class_hard_regs_num[another_aclass];
ira_allocate_and_copy_costs
(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno),
- another_cover_class,
- ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
+ another_aclass, ALLOCNO_CONFLICT_HARD_REG_COSTS (another_allocno));
conflict_costs
= ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno);
if (conflict_costs == NULL)
@@ -370,9 +1171,9 @@ update_conflict_hard_regno_costs (int *c
cont_p = false;
for (i = class_size - 1; i >= 0; i--)
{
- hard_regno = ira_class_hard_regs[another_cover_class][i];
+ hard_regno = ira_class_hard_regs[another_aclass][i];
ira_assert (hard_regno >= 0);
- index = ira_class_hard_reg_index[cover_class][hard_regno];
+ index = ira_class_hard_reg_index[aclass][hard_regno];
if (index < 0)
continue;
cost = conflict_costs [i] * mult / div;
@@ -403,8 +1204,8 @@ allocno_cost_compare_func (const void *v
ira_allocno_t p2 = *(const ira_allocno_t *) v2p;
int c1, c2;
- c1 = ALLOCNO_UPDATED_MEMORY_COST (p1) - ALLOCNO_UPDATED_COVER_CLASS_COST (p1);
- c2 = ALLOCNO_UPDATED_MEMORY_COST (p2) - ALLOCNO_UPDATED_COVER_CLASS_COST (p2);
+ c1 = ALLOCNO_UPDATED_MEMORY_COST (p1) - ALLOCNO_UPDATED_CLASS_COST (p1);
+ c2 = ALLOCNO_UPDATED_MEMORY_COST (p2) - ALLOCNO_UPDATED_CLASS_COST (p2);
if (c1 - c2)
return c1 - c2;
@@ -413,40 +1214,20 @@ allocno_cost_compare_func (const void *v
return ALLOCNO_NUM (p1) - ALLOCNO_NUM (p2);
}
-/* Print all allocnos coalesced with ALLOCNO. */
-static void
-print_coalesced_allocno (ira_allocno_t allocno)
-{
- ira_allocno_t a;
-
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- ira_print_expanded_allocno (a);
- if (a == allocno)
- break;
- fprintf (ira_dump_file, "+");
- }
-}
-
-/* Choose a hard register for ALLOCNO (or for all coalesced allocnos
- represented by ALLOCNO). If RETRY_P is TRUE, it means that the
- function called from function `ira_reassign_conflict_allocnos' and
- `allocno_reload_assign'. This function implements the optimistic
- coalescing too: if we failed to assign a hard register to set of
- the coalesced allocnos, we put them onto the coloring stack for
- subsequent separate assigning. */
+/* Choose a hard register for allocno A. If RETRY_P is TRUE, it means
+ that the function called from function
+ `ira_reassign_conflict_allocnos' and `allocno_reload_assign'. */
static bool
-assign_hard_reg (ira_allocno_t allocno, bool retry_p)
+assign_hard_reg (ira_allocno_t a, bool retry_p)
{
- HARD_REG_SET conflicting_regs;
+ HARD_REG_SET conflicting_regs, profitable_hard_regs;
int i, j, k, hard_regno, best_hard_regno, class_size;
int cost, mem_cost, min_cost, full_cost, min_full_cost;
int *a_costs;
int *conflict_costs;
- enum reg_class cover_class, conflict_cover_class;
+ enum reg_class aclass, conflict_aclass;
enum machine_mode mode;
- ira_allocno_t a, conflict_allocno;
+ ira_allocno_t conflict_a;
ira_allocno_conflict_iterator aci;
static int costs[FIRST_PSEUDO_REGISTER], full_costs[FIRST_PSEUDO_REGISTER];
#ifndef HONOR_REG_ALLOC_ORDER
@@ -457,119 +1238,110 @@ assign_hard_reg (ira_allocno_t allocno,
bool no_stack_reg_p;
#endif
- ira_assert (! ALLOCNO_ASSIGNED_P (allocno));
- cover_class = ALLOCNO_COVER_CLASS (allocno);
- class_size = ira_class_hard_regs_num[cover_class];
- mode = ALLOCNO_MODE (allocno);
+ ira_assert (! ALLOCNO_ASSIGNED_P (a));
+ aclass = ALLOCNO_CLASS (a);
+ if (retry_p)
+ COPY_HARD_REG_SET (profitable_hard_regs,
+ reg_class_contents[aclass]);
+ else
+ COPY_HARD_REG_SET (profitable_hard_regs,
+ ALLOCNO_PROFITABLE_HARD_REGS (a));
+ class_size = ira_class_hard_regs_num[aclass];
+ mode = ALLOCNO_MODE (a);
CLEAR_HARD_REG_SET (conflicting_regs);
best_hard_regno = -1;
memset (full_costs, 0, sizeof (int) * class_size);
mem_cost = 0;
- if (allocno_coalesced_p)
- bitmap_clear (processed_coalesced_allocno_bitmap);
memset (costs, 0, sizeof (int) * class_size);
memset (full_costs, 0, sizeof (int) * class_size);
#ifdef STACK_REGS
no_stack_reg_p = false;
#endif
- start_update_cost ();
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- mem_cost += ALLOCNO_UPDATED_MEMORY_COST (a);
- IOR_HARD_REG_SET (conflicting_regs,
- ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
- ira_allocate_and_copy_costs (&ALLOCNO_UPDATED_HARD_REG_COSTS (a),
- cover_class, ALLOCNO_HARD_REG_COSTS (a));
- a_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a);
+ if (! retry_p)
+ start_update_cost ();
+ mem_cost += ALLOCNO_UPDATED_MEMORY_COST (a);
+ IOR_HARD_REG_SET (conflicting_regs,
+ ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+ ira_allocate_and_copy_costs (&ALLOCNO_UPDATED_HARD_REG_COSTS (a),
+ aclass, ALLOCNO_HARD_REG_COSTS (a));
+ a_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a);
#ifdef STACK_REGS
- no_stack_reg_p = no_stack_reg_p || ALLOCNO_TOTAL_NO_STACK_REG_P (a);
+ no_stack_reg_p = no_stack_reg_p || ALLOCNO_TOTAL_NO_STACK_REG_P (a);
#endif
- cost = ALLOCNO_UPDATED_COVER_CLASS_COST (a);
- for (i = 0; i < class_size; i++)
- if (a_costs != NULL)
- {
- costs[i] += a_costs[i];
- full_costs[i] += a_costs[i];
- }
- else
- {
- costs[i] += cost;
- full_costs[i] += cost;
- }
- /* Take preferences of conflicting allocnos into account. */
- FOR_EACH_ALLOCNO_CONFLICT (a, conflict_allocno, aci)
- /* Reload can give another class so we need to check all
- allocnos. */
- if (retry_p || bitmap_bit_p (consideration_allocno_bitmap,
- ALLOCNO_NUM (conflict_allocno)))
+ cost = ALLOCNO_UPDATED_CLASS_COST (a);
+ for (i = 0; i < class_size; i++)
+ if (a_costs != NULL)
+ {
+ costs[i] += a_costs[i];
+ full_costs[i] += a_costs[i];
+ }
+ else
+ {
+ costs[i] += cost;
+ full_costs[i] += cost;
+ }
+ /* Take preferences of conflicting allocnos into account. */
+ FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
+ /* Reload can give another class so we need to check all
+ allocnos. */
+ if (retry_p
+ || (bitmap_bit_p (consideration_allocno_bitmap,
+ ALLOCNO_NUM (conflict_a))
+ && ((ALLOCNO_ASSIGNED_P (conflict_a)
+ && ALLOCNO_HARD_REGNO (conflict_a) >= 0)
+ || (hard_reg_set_intersect_p
+ (profitable_hard_regs,
+ ALLOCNO_PROFITABLE_HARD_REGS (conflict_a))))))
+ {
+ conflict_aclass = ALLOCNO_CLASS (conflict_a);
+ ira_assert (ira_reg_classes_intersect_p[aclass][conflict_aclass]);
+ if (ALLOCNO_ASSIGNED_P (conflict_a))
{
- 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,
- ALLOCNO_NUM (conflict_allocno)))
- continue;
- bitmap_set_bit (processed_coalesced_allocno_bitmap,
- ALLOCNO_NUM (conflict_allocno));
- }
- if (ALLOCNO_ASSIGNED_P (conflict_allocno))
- {
- 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,
- ira_reg_mode_hard_regset
- [hard_regno][ALLOCNO_MODE (conflict_allocno)]);
- if (hard_reg_set_subset_p (reg_class_contents[cover_class],
- conflicting_regs))
- goto fail;
- }
- }
- else if (! ALLOCNO_MAY_BE_SPILLED_P (ALLOCNO_FIRST_COALESCED_ALLOCNO
- (conflict_allocno)))
+ if ((hard_regno = ALLOCNO_HARD_REGNO (conflict_a)) >= 0
+ && ira_class_hard_reg_index[aclass][hard_regno] >= 0)
{
- ira_allocate_and_copy_costs
- (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_allocno),
- 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--)
- {
- 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);
+ IOR_HARD_REG_SET (conflicting_regs,
+ ira_reg_mode_hard_regset
+ [hard_regno][ALLOCNO_MODE (conflict_a)]);
+ /* Using profitable hard regs. */
+ if (hard_reg_set_subset_p (profitable_hard_regs,
+ conflicting_regs))
+ goto fail;
}
}
- if (a == allocno)
- break;
- }
- /* Take into account preferences of allocnos connected by copies to
- the conflict allocnos. */
- update_conflict_hard_regno_costs (full_costs, cover_class, true);
-
- /* Take preferences of allocnos connected by copies into
- account. */
- start_update_cost ();
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ else if (! retry_p
+ && ! ALLOCNO_MAY_BE_SPILLED_P (conflict_a))
+ {
+ ira_allocate_and_copy_costs
+ (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_a),
+ conflict_aclass, ALLOCNO_CONFLICT_HARD_REG_COSTS (conflict_a));
+ conflict_costs
+ = ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (conflict_a);
+ if (conflict_costs != NULL)
+ for (j = class_size - 1; j >= 0; j--)
+ {
+ hard_regno = ira_class_hard_regs[aclass][j];
+ ira_assert (hard_regno >= 0);
+ k = ira_class_hard_reg_index[conflict_aclass][hard_regno];
+ if (k < 0)
+ continue;
+ full_costs[j] -= conflict_costs[k];
+ }
+ queue_update_cost (conflict_a, COST_HOP_DIVISOR);
+ }
+ }
+ if (! retry_p)
{
+ /* Take into account preferences of allocnos connected by copies
+ to the conflict allocnos. */
+ update_conflict_hard_regno_costs (full_costs, aclass, true);
+
+ /* Take preferences of allocnos connected by copies into
+ account. */
+ start_update_cost ();
queue_update_cost (a, COST_HOP_DIVISOR);
- if (a == allocno)
- break;
+ update_conflict_hard_regno_costs (full_costs, aclass, 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
@@ -577,15 +1349,15 @@ assign_hard_reg (ira_allocno_t allocno,
REG_ALLOC_ORDER). */
for (i = 0; i < class_size; i++)
{
- hard_regno = ira_class_hard_regs[cover_class][i];
+ hard_regno = ira_class_hard_regs[aclass][i];
#ifdef STACK_REGS
if (no_stack_reg_p
&& FIRST_STACK_REG <= hard_regno && hard_regno <= LAST_STACK_REG)
continue;
#endif
+ /* Checking only profitable hard regs. */
if (! ira_hard_reg_not_in_set_p (hard_regno, mode, conflicting_regs)
- || TEST_HARD_REG_BIT (prohibited_class_mode_regs[cover_class][mode],
- hard_regno))
+ || ! TEST_HARD_REG_BIT (profitable_hard_regs, hard_regno))
continue;
cost = costs[i];
full_cost = full_costs[i];
@@ -620,50 +1392,15 @@ assign_hard_reg (ira_allocno_t allocno,
best_hard_regno = -1;
}
fail:
- 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);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- ira_assert (! ALLOCNO_IN_GRAPH_P (a));
- sorted_allocnos[j++] = a;
- if (a == allocno)
- break;
- }
- qsort (sorted_allocnos, j, sizeof (ira_allocno_t),
- allocno_cost_compare_func);
- for (i = 0; i < j; i++)
- {
- a = sorted_allocnos[i];
- ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = a;
- ALLOCNO_NEXT_COALESCED_ALLOCNO (a) = a;
- VEC_safe_push (ira_allocno_t, heap, allocno_stack_vec, a);
- if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
- {
- fprintf (ira_dump_file, " Pushing");
- print_coalesced_allocno (a);
- fprintf (ira_dump_file, "\n");
- }
- }
- return false;
- }
if (best_hard_regno >= 0)
allocated_hardreg_p[best_hard_regno] = true;
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- ALLOCNO_HARD_REGNO (a) = best_hard_regno;
- ALLOCNO_ASSIGNED_P (a) = true;
- if (best_hard_regno >= 0)
- update_copy_costs (a, true);
- ira_assert (ALLOCNO_COVER_CLASS (a) == cover_class);
- /* We don't need updated costs anymore: */
- ira_free_allocno_updated_costs (a);
- if (a == allocno)
- break;
- }
+ ALLOCNO_HARD_REGNO (a) = best_hard_regno;
+ ALLOCNO_ASSIGNED_P (a) = true;
+ if (best_hard_regno >= 0)
+ update_copy_costs (a, true);
+ ira_assert (ALLOCNO_CLASS (a) == aclass);
+ /* We don't need updated costs anymore: */
+ ira_free_allocno_updated_costs (a);
return best_hard_regno >= 0;
}
@@ -678,9 +1415,8 @@ static ira_allocno_t colorable_allocno_b
spilling. */
static ira_allocno_t uncolorable_allocno_bucket;
-/* Each element of the array contains the current number of allocnos
- of given *cover* class in the uncolorable_bucket. */
-static int uncolorable_allocnos_num[N_REG_CLASSES];
+/* The current number of allocnos in the uncolorable_bucket. */
+static int uncolorable_allocnos_num;
/* Return the current spill priority of allocno A. The less the
number, the more preferable the allocno for spilling. */
@@ -688,50 +1424,30 @@ static int
allocno_spill_priority (ira_allocno_t a)
{
return (ALLOCNO_TEMP (a)
- / (ALLOCNO_LEFT_CONFLICTS_SIZE (a)
- * ira_reg_class_nregs[ALLOCNO_COVER_CLASS (a)][ALLOCNO_MODE (a)]
+ / (ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a)
+ * ira_reg_class_max_nregs[ALLOCNO_CLASS (a)][ALLOCNO_MODE (a)]
+ 1));
}
-/* Add ALLOCNO to bucket *BUCKET_PTR. ALLOCNO should be not in a bucket
+/* Add A to bucket *BUCKET_PTR. A should be not in a bucket
before the call. */
static void
-add_allocno_to_bucket (ira_allocno_t allocno, ira_allocno_t *bucket_ptr)
+add_allocno_to_bucket (ira_allocno_t a, ira_allocno_t *bucket_ptr)
{
- ira_allocno_t first_allocno;
- enum reg_class cover_class;
+ ira_allocno_t first_a;
if (bucket_ptr == &uncolorable_allocno_bucket
- && (cover_class = ALLOCNO_COVER_CLASS (allocno)) != NO_REGS)
- {
- uncolorable_allocnos_num[cover_class]++;
- ira_assert (uncolorable_allocnos_num[cover_class] > 0);
- }
- first_allocno = *bucket_ptr;
- ALLOCNO_NEXT_BUCKET_ALLOCNO (allocno) = first_allocno;
- ALLOCNO_PREV_BUCKET_ALLOCNO (allocno) = NULL;
- if (first_allocno != NULL)
- ALLOCNO_PREV_BUCKET_ALLOCNO (first_allocno) = allocno;
- *bucket_ptr = allocno;
-}
-
-/* The function returns frequency and number of available hard
- registers for allocnos coalesced with ALLOCNO. */
-static void
-get_coalesced_allocnos_attributes (ira_allocno_t allocno, int *freq, int *num)
-{
- ira_allocno_t a;
-
- *freq = 0;
- *num = 0;
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ && ALLOCNO_CLASS (a) != NO_REGS)
{
- *freq += ALLOCNO_FREQ (a);
- *num += ALLOCNO_AVAILABLE_REGS_NUM (a);
- if (a == allocno)
- break;
+ uncolorable_allocnos_num++;
+ ira_assert (uncolorable_allocnos_num > 0);
}
+ first_a = *bucket_ptr;
+ ALLOCNO_NEXT_BUCKET_ALLOCNO (a) = first_a;
+ ALLOCNO_PREV_BUCKET_ALLOCNO (a) = NULL;
+ if (first_a != NULL)
+ ALLOCNO_PREV_BUCKET_ALLOCNO (first_a) = a;
+ *bucket_ptr = a;
}
/* Compare two allocnos to define which allocno should be pushed first
@@ -748,10 +1464,12 @@ bucket_allocno_compare_func (const void
ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
int diff, a1_freq, a2_freq, a1_num, a2_num;
- if ((diff = (int) ALLOCNO_COVER_CLASS (a2) - ALLOCNO_COVER_CLASS (a1)) != 0)
+ if ((diff = (int) ALLOCNO_CLASS (a2) - ALLOCNO_CLASS (a1)) != 0)
return diff;
- get_coalesced_allocnos_attributes (a1, &a1_freq, &a1_num);
- get_coalesced_allocnos_attributes (a2, &a2_freq, &a2_num);
+ a1_freq = ALLOCNO_FREQ (a1);
+ a1_num = ALLOCNO_AVAILABLE_REGS_NUM (a1);
+ a2_freq = ALLOCNO_FREQ (a2);
+ a2_num = ALLOCNO_AVAILABLE_REGS_NUM (a2);
if ((diff = a2_num - a1_num) != 0)
return diff;
else if ((diff = a1_freq - a2_freq) != 0)
@@ -762,7 +1480,8 @@ bucket_allocno_compare_func (const void
/* Sort bucket *BUCKET_PTR and return the result through
BUCKET_PTR. */
static void
-sort_bucket (ira_allocno_t *bucket_ptr)
+sort_bucket (ira_allocno_t *bucket_ptr,
+ int (*compare_func) (const void *, const void *))
{
ira_allocno_t a, head;
int n;
@@ -771,8 +1490,7 @@ sort_bucket (ira_allocno_t *bucket_ptr)
sorted_allocnos[n++] = a;
if (n <= 1)
return;
- qsort (sorted_allocnos, n, sizeof (ira_allocno_t),
- bucket_allocno_compare_func);
+ qsort (sorted_allocnos, n, sizeof (ira_allocno_t), compare_func);
head = NULL;
for (n--; n >= 0; n--)
{
@@ -794,13 +1512,12 @@ add_allocno_to_ordered_bucket (ira_alloc
ira_allocno_t *bucket_ptr)
{
ira_allocno_t before, after;
- enum reg_class cover_class;
if (bucket_ptr == &uncolorable_allocno_bucket
- && (cover_class = ALLOCNO_COVER_CLASS (allocno)) != NO_REGS)
+ && ALLOCNO_CLASS (allocno) != NO_REGS)
{
- uncolorable_allocnos_num[cover_class]++;
- ira_assert (uncolorable_allocnos_num[cover_class] > 0);
+ uncolorable_allocnos_num++;
+ ira_assert (uncolorable_allocnos_num > 0);
}
for (before = *bucket_ptr, after = NULL;
before != NULL;
@@ -823,13 +1540,12 @@ static void
delete_allocno_from_bucket (ira_allocno_t allocno, ira_allocno_t *bucket_ptr)
{
ira_allocno_t prev_allocno, next_allocno;
- enum reg_class cover_class;
if (bucket_ptr == &uncolorable_allocno_bucket
- && (cover_class = ALLOCNO_COVER_CLASS (allocno)) != NO_REGS)
+ && ALLOCNO_CLASS (allocno) != NO_REGS)
{
- uncolorable_allocnos_num[cover_class]--;
- ira_assert (uncolorable_allocnos_num[cover_class] >= 0);
+ uncolorable_allocnos_num--;
+ ira_assert (uncolorable_allocnos_num >= 0);
}
prev_allocno = ALLOCNO_PREV_BUCKET_ALLOCNO (allocno);
next_allocno = ALLOCNO_NEXT_BUCKET_ALLOCNO (allocno);
@@ -844,109 +1560,41 @@ delete_allocno_from_bucket (ira_allocno_
ALLOCNO_PREV_BUCKET_ALLOCNO (next_allocno) = prev_allocno;
}
-/* Splay tree for each cover class. The trees are indexed by the
- corresponding cover classes. Splay trees contain uncolorable
- allocnos. */
-static splay_tree uncolorable_allocnos_splay_tree[N_REG_CLASSES];
-
-/* If the following macro is TRUE, splay tree is used to choose an
- allocno of the corresponding cover class for spilling. When the
- number uncolorable allocnos of given cover class decreases to some
- threshold, linear array search is used to find the best allocno for
- spilling. This threshold is actually pretty big because, although
- splay trees asymptotically is much faster, each splay tree
- operation is sufficiently costly especially taking cache locality
- into account. */
-#define USE_SPLAY_P(CLASS) (uncolorable_allocnos_num[CLASS] > 4000)
-
-/* Put ALLOCNO onto the coloring stack without removing it from its
+/* Put A onto the coloring stack without removing it from its
bucket. Pushing allocno to the coloring stack can result in moving
conflicting allocnos from the uncolorable bucket to the colorable
one. */
static void
-push_allocno_to_stack (ira_allocno_t allocno)
+push_allocno_to_stack (ira_allocno_t a)
{
- int left_conflicts_size, conflict_size, size;
- ira_allocno_t a, conflict_allocno;
- enum reg_class cover_class;
+ ira_allocno_t conflict_a;
+ enum reg_class aclass;
ira_allocno_conflict_iterator aci;
- ALLOCNO_IN_GRAPH_P (allocno) = false;
- VEC_safe_push (ira_allocno_t, heap, allocno_stack_vec, allocno);
- cover_class = ALLOCNO_COVER_CLASS (allocno);
- if (cover_class == NO_REGS)
+ ALLOCNO_IN_GRAPH_P (a) = false;
+ VEC_safe_push (ira_allocno_t, heap, allocno_stack_vec, a);
+ aclass = ALLOCNO_CLASS (a);
+ if (aclass == NO_REGS)
return;
- size = ira_reg_class_nregs[cover_class][ALLOCNO_MODE (allocno)];
- if (allocno_coalesced_p)
- bitmap_clear (processed_coalesced_allocno_bitmap);
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
{
- FOR_EACH_ALLOCNO_CONFLICT (a, conflict_allocno, aci)
- {
- conflict_allocno = ALLOCNO_FIRST_COALESCED_ALLOCNO (conflict_allocno);
- if (bitmap_bit_p (coloring_allocno_bitmap,
- ALLOCNO_NUM (conflict_allocno)))
- {
- ira_assert (cover_class
- == ALLOCNO_COVER_CLASS (conflict_allocno));
- if (allocno_coalesced_p)
- {
- if (bitmap_bit_p (processed_coalesced_allocno_bitmap,
- ALLOCNO_NUM (conflict_allocno)))
- continue;
- bitmap_set_bit (processed_coalesced_allocno_bitmap,
- ALLOCNO_NUM (conflict_allocno));
- }
- if (ALLOCNO_IN_GRAPH_P (conflict_allocno)
- && ! ALLOCNO_ASSIGNED_P (conflict_allocno))
- {
- left_conflicts_size
- = ALLOCNO_LEFT_CONFLICTS_SIZE (conflict_allocno);
- conflict_size
- = (ira_reg_class_nregs
- [cover_class][ALLOCNO_MODE (conflict_allocno)]);
- ira_assert
- (ALLOCNO_LEFT_CONFLICTS_SIZE (conflict_allocno) >= size);
- if (left_conflicts_size + conflict_size
- <= ALLOCNO_AVAILABLE_REGS_NUM (conflict_allocno))
- {
- ALLOCNO_LEFT_CONFLICTS_SIZE (conflict_allocno) -= size;
- continue;
- }
- left_conflicts_size
- = ALLOCNO_LEFT_CONFLICTS_SIZE (conflict_allocno) - size;
- if (uncolorable_allocnos_splay_tree[cover_class] != NULL
- && !ALLOCNO_SPLAY_REMOVED_P (conflict_allocno)
- && USE_SPLAY_P (cover_class))
- {
- ira_assert
- (splay_tree_lookup
- (uncolorable_allocnos_splay_tree[cover_class],
- (splay_tree_key) conflict_allocno) != NULL);
- splay_tree_remove
- (uncolorable_allocnos_splay_tree[cover_class],
- (splay_tree_key) conflict_allocno);
- ALLOCNO_SPLAY_REMOVED_P (conflict_allocno) = true;
- VEC_safe_push (ira_allocno_t, heap,
- removed_splay_allocno_vec,
- conflict_allocno);
- }
- ALLOCNO_LEFT_CONFLICTS_SIZE (conflict_allocno)
- = left_conflicts_size;
- if (left_conflicts_size + conflict_size
- <= ALLOCNO_AVAILABLE_REGS_NUM (conflict_allocno))
- {
- delete_allocno_from_bucket
- (conflict_allocno, &uncolorable_allocno_bucket);
- add_allocno_to_ordered_bucket
- (conflict_allocno, &colorable_allocno_bucket);
- }
- }
+ if (! ALLOCNO_COLORABLE_P (conflict_a)
+ && ALLOCNO_IN_GRAPH_P (conflict_a)
+ && ! ALLOCNO_ASSIGNED_P (conflict_a)
+ && (hard_reg_set_intersect_p
+ (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ ALLOCNO_PROFITABLE_HARD_REGS (conflict_a))))
+ {
+ ira_assert (bitmap_bit_p (coloring_allocno_bitmap,
+ ALLOCNO_NUM (conflict_a)));
+ if (update_left_conflict_sizes_p (conflict_a, a))
+ {
+ delete_allocno_from_bucket
+ (conflict_a, &uncolorable_allocno_bucket);
+ add_allocno_to_ordered_bucket
+ (conflict_a, &colorable_allocno_bucket);
}
}
- if (a == allocno)
- break;
}
}
@@ -955,8 +1603,6 @@ push_allocno_to_stack (ira_allocno_t all
static void
remove_allocno_from_bucket_and_push (ira_allocno_t allocno, bool colorable_p)
{
- enum reg_class cover_class;
-
if (colorable_p)
delete_allocno_from_bucket (allocno, &colorable_allocno_bucket);
else
@@ -964,24 +1610,14 @@ remove_allocno_from_bucket_and_push (ira
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
{
fprintf (ira_dump_file, " Pushing");
- print_coalesced_allocno (allocno);
+ ira_print_expanded_allocno (allocno);
if (colorable_p)
- fprintf (ira_dump_file, "\n");
+ fprintf (ira_dump_file, "(cost %d)\n", ALLOCNO_TEMP (allocno));
else
fprintf (ira_dump_file, "(potential spill: %spri=%d, cost=%d)\n",
ALLOCNO_BAD_SPILL_P (allocno) ? "bad spill, " : "",
allocno_spill_priority (allocno), ALLOCNO_TEMP (allocno));
}
- cover_class = ALLOCNO_COVER_CLASS (allocno);
- ira_assert ((colorable_p
- && (ALLOCNO_LEFT_CONFLICTS_SIZE (allocno)
- + ira_reg_class_nregs[cover_class][ALLOCNO_MODE (allocno)]
- <= ALLOCNO_AVAILABLE_REGS_NUM (allocno)))
- || (! colorable_p
- && (ALLOCNO_LEFT_CONFLICTS_SIZE (allocno)
- + ira_reg_class_nregs[cover_class][ALLOCNO_MODE
- (allocno)]
- > ALLOCNO_AVAILABLE_REGS_NUM (allocno))));
if (! colorable_p)
ALLOCNO_MAY_BE_SPILLED_P (allocno) = true;
push_allocno_to_stack (allocno);
@@ -991,24 +1627,11 @@ remove_allocno_from_bucket_and_push (ira
static void
push_only_colorable (void)
{
- sort_bucket (&colorable_allocno_bucket);
+ sort_bucket (&colorable_allocno_bucket, bucket_allocno_compare_func);
for (;colorable_allocno_bucket != NULL;)
remove_allocno_from_bucket_and_push (colorable_allocno_bucket, true);
}
-/* Puts ALLOCNO chosen for potential spilling onto the coloring
- stack. */
-static void
-push_allocno_to_spill (ira_allocno_t allocno)
-{
- delete_allocno_from_bucket (allocno, &uncolorable_allocno_bucket);
- ALLOCNO_MAY_BE_SPILLED_P (allocno) = true;
- if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
- fprintf (ira_dump_file, " Pushing p%d(%d) (spill for NO_REGS)\n",
- ALLOCNO_NUM (allocno), ALLOCNO_REGNO (allocno));
- push_allocno_to_stack (allocno);
-}
-
/* Return the frequency of exit edges (if EXIT_P) or entry from/to the
loop given by its LOOP_NODE. */
int
@@ -1056,7 +1679,7 @@ calculate_allocno_spill_cost (ira_allocn
ira_loop_tree_node_t parent_node, loop_node;
regno = ALLOCNO_REGNO (a);
- cost = ALLOCNO_UPDATED_MEMORY_COST (a) - ALLOCNO_UPDATED_COVER_CLASS_COST (a);
+ cost = ALLOCNO_UPDATED_MEMORY_COST (a) - ALLOCNO_UPDATED_CLASS_COST (a);
if (ALLOCNO_CAP (a) != NULL)
return cost;
loop_node = ALLOCNO_LOOP_TREE_NODE (a);
@@ -1065,7 +1688,7 @@ calculate_allocno_spill_cost (ira_allocn
if ((parent_allocno = parent_node->regno_allocno_map[regno]) == NULL)
return cost;
mode = ALLOCNO_MODE (a);
- rclass = ALLOCNO_COVER_CLASS (a);
+ rclass = ALLOCNO_CLASS (a);
if (ALLOCNO_HARD_REGNO (parent_allocno) < 0)
cost -= (ira_memory_move_cost[mode][rclass][0]
* ira_loop_edge_freq (loop_node, regno, true)
@@ -1082,22 +1705,18 @@ calculate_allocno_spill_cost (ira_allocn
return cost;
}
-/* Compare keys in the splay tree used to choose best allocno for
- spilling. The best allocno has the minimal key. */
-static int
-allocno_spill_priority_compare (splay_tree_key k1, splay_tree_key k2)
+/* Used for sorting allocnos for spilling. */
+static inline int
+allocno_spill_priority_compare (ira_allocno_t a1, ira_allocno_t a2)
{
int pri1, pri2, diff;
- ira_allocno_t a1 = (ira_allocno_t) k1, a2 = (ira_allocno_t) k2;
- pri1 = (ALLOCNO_TEMP (a1)
- / (ALLOCNO_LEFT_CONFLICTS_SIZE (a1)
- * ira_reg_class_nregs[ALLOCNO_COVER_CLASS (a1)][ALLOCNO_MODE (a1)]
- + 1));
- pri2 = (ALLOCNO_TEMP (a2)
- / (ALLOCNO_LEFT_CONFLICTS_SIZE (a2)
- * ira_reg_class_nregs[ALLOCNO_COVER_CLASS (a2)][ALLOCNO_MODE (a2)]
- + 1));
+ if (ALLOCNO_BAD_SPILL_P (a1) && ! ALLOCNO_BAD_SPILL_P (a2))
+ return 1;
+ if (ALLOCNO_BAD_SPILL_P (a2) && ! ALLOCNO_BAD_SPILL_P (a1))
+ return -1;
+ pri1 = allocno_spill_priority (a1);
+ pri2 = allocno_spill_priority (a2);
if ((diff = pri1 - pri2) != 0)
return diff;
if ((diff = ALLOCNO_TEMP (a1) - ALLOCNO_TEMP (a2)) != 0)
@@ -1105,36 +1724,14 @@ allocno_spill_priority_compare (splay_tr
return ALLOCNO_NUM (a1) - ALLOCNO_NUM (a2);
}
-/* Allocate data of SIZE for the splay trees. We allocate only spay
- tree roots or splay tree nodes. If you change this, please rewrite
- the function. */
-static void *
-splay_tree_allocate (int size, void *data ATTRIBUTE_UNUSED)
-{
- if (size != sizeof (struct splay_tree_node_s))
- return ira_allocate (size);
- return pool_alloc (splay_tree_node_pool);
-}
-
-/* Free data NODE for the splay trees. We allocate and free only spay
- tree roots or splay tree nodes. If you change this, please rewrite
- the function. */
-static void
-splay_tree_free (void *node, void *data ATTRIBUTE_UNUSED)
+/* Used for sorting allocnos for spilling. */
+static int
+allocno_spill_sort_compare (const void *v1p, const void *v2p)
{
- int i;
- enum reg_class cover_class;
+ ira_allocno_t p1 = *(const ira_allocno_t *) v1p;
+ ira_allocno_t p2 = *(const ira_allocno_t *) v2p;
- for (i = 0; i < ira_reg_class_cover_size; i++)
- {
- cover_class = ira_reg_class_cover[i];
- if (node == uncolorable_allocnos_splay_tree[cover_class])
- {
- ira_free (node);
- return;
- }
- }
- pool_free (splay_tree_node_pool, node);
+ return allocno_spill_priority_compare (p1, p2);
}
/* Push allocnos to the coloring stack. The order of allocnos in the
@@ -1142,174 +1739,32 @@ splay_tree_free (void *node, void *data
static void
push_allocnos_to_stack (void)
{
- ira_allocno_t allocno, a, i_allocno, *allocno_vec;
- enum reg_class cover_class, rclass;
- int allocno_pri, i_allocno_pri, allocno_cost, i_allocno_cost;
- int i, j, num, cover_class_allocnos_num[N_REG_CLASSES];
- ira_allocno_t *cover_class_allocnos[N_REG_CLASSES];
+ ira_allocno_t a;
int cost;
- /* Initialize. */
- VEC_truncate(ira_allocno_t, removed_splay_allocno_vec, 0);
- for (i = 0; i < ira_reg_class_cover_size; i++)
- {
- cover_class = ira_reg_class_cover[i];
- cover_class_allocnos_num[cover_class] = 0;
- cover_class_allocnos[cover_class] = NULL;
- uncolorable_allocnos_splay_tree[cover_class] = NULL;
- }
/* Calculate uncolorable allocno spill costs. */
- for (allocno = uncolorable_allocno_bucket;
- allocno != NULL;
- allocno = ALLOCNO_NEXT_BUCKET_ALLOCNO (allocno))
- if ((cover_class = ALLOCNO_COVER_CLASS (allocno)) != NO_REGS)
+ for (a = uncolorable_allocno_bucket;
+ a != NULL;
+ a = ALLOCNO_NEXT_BUCKET_ALLOCNO (a))
+ if (ALLOCNO_CLASS (a) != NO_REGS)
{
- cover_class_allocnos_num[cover_class]++;
- cost = 0;
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- cost += calculate_allocno_spill_cost (a);
- if (a == allocno)
- break;
- }
+ cost = calculate_allocno_spill_cost (a);
/* ??? Remove cost of copies between the coalesced
allocnos. */
- ALLOCNO_TEMP (allocno) = cost;
- }
- /* Define place where to put uncolorable allocnos of the same cover
- class. */
- for (num = i = 0; i < ira_reg_class_cover_size; i++)
- {
- cover_class = ira_reg_class_cover[i];
- ira_assert (cover_class_allocnos_num[cover_class]
- == uncolorable_allocnos_num[cover_class]);
- if (cover_class_allocnos_num[cover_class] != 0)
- {
- cover_class_allocnos[cover_class] = allocnos_for_spilling + num;
- num += cover_class_allocnos_num[cover_class];
- cover_class_allocnos_num[cover_class] = 0;
- }
- if (USE_SPLAY_P (cover_class))
- uncolorable_allocnos_splay_tree[cover_class]
- = splay_tree_new_with_allocator (allocno_spill_priority_compare,
- NULL, NULL, splay_tree_allocate,
- splay_tree_free, NULL);
- }
- ira_assert (num <= ira_allocnos_num);
- /* Collect uncolorable allocnos of each cover class. */
- for (allocno = uncolorable_allocno_bucket;
- allocno != NULL;
- allocno = ALLOCNO_NEXT_BUCKET_ALLOCNO (allocno))
- if ((cover_class = ALLOCNO_COVER_CLASS (allocno)) != NO_REGS)
- {
- cover_class_allocnos
- [cover_class][cover_class_allocnos_num[cover_class]++] = allocno;
- if (uncolorable_allocnos_splay_tree[cover_class] != NULL)
- splay_tree_insert (uncolorable_allocnos_splay_tree[cover_class],
- (splay_tree_key) allocno,
- (splay_tree_value) allocno);
+ ALLOCNO_TEMP (a) = cost;
}
+ sort_bucket (&uncolorable_allocno_bucket, allocno_spill_sort_compare);
for (;;)
{
push_only_colorable ();
- allocno = uncolorable_allocno_bucket;
- if (allocno == NULL)
+ a = uncolorable_allocno_bucket;
+ if (a == NULL)
break;
- cover_class = ALLOCNO_COVER_CLASS (allocno);
- if (cover_class == NO_REGS)
- {
- push_allocno_to_spill (allocno);
- continue;
- }
- /* Potential spilling. */
- ira_assert
- (ira_reg_class_nregs[cover_class][ALLOCNO_MODE (allocno)] > 0);
- if (USE_SPLAY_P (cover_class))
- {
- for (;VEC_length (ira_allocno_t, removed_splay_allocno_vec) != 0;)
- {
- allocno = VEC_pop (ira_allocno_t, removed_splay_allocno_vec);
- ALLOCNO_SPLAY_REMOVED_P (allocno) = false;
- rclass = ALLOCNO_COVER_CLASS (allocno);
- if (ALLOCNO_LEFT_CONFLICTS_SIZE (allocno)
- + ira_reg_class_nregs [rclass][ALLOCNO_MODE (allocno)]
- > ALLOCNO_AVAILABLE_REGS_NUM (allocno))
- splay_tree_insert
- (uncolorable_allocnos_splay_tree[rclass],
- (splay_tree_key) allocno, (splay_tree_value) allocno);
- }
- allocno = ((ira_allocno_t)
- splay_tree_min
- (uncolorable_allocnos_splay_tree[cover_class])->key);
- splay_tree_remove (uncolorable_allocnos_splay_tree[cover_class],
- (splay_tree_key) allocno);
- }
- else
- {
- num = cover_class_allocnos_num[cover_class];
- ira_assert (num > 0);
- allocno_vec = cover_class_allocnos[cover_class];
- allocno = NULL;
- allocno_pri = allocno_cost = 0;
- /* Sort uncolorable allocno to find the one with the lowest
- spill cost. */
- for (i = 0, j = num - 1; i <= j;)
- {
- i_allocno = allocno_vec[i];
- if (! ALLOCNO_IN_GRAPH_P (i_allocno)
- && ALLOCNO_IN_GRAPH_P (allocno_vec[j]))
- {
- i_allocno = allocno_vec[j];
- allocno_vec[j] = allocno_vec[i];
- allocno_vec[i] = i_allocno;
- }
- if (ALLOCNO_IN_GRAPH_P (i_allocno))
- {
- i++;
- ira_assert (ALLOCNO_TEMP (i_allocno) != INT_MAX);
- i_allocno_cost = ALLOCNO_TEMP (i_allocno);
- i_allocno_pri = allocno_spill_priority (i_allocno);
- if (allocno == NULL
- || (! ALLOCNO_BAD_SPILL_P (i_allocno)
- && ALLOCNO_BAD_SPILL_P (allocno))
- || (! (ALLOCNO_BAD_SPILL_P (i_allocno)
- && ! ALLOCNO_BAD_SPILL_P (allocno))
- && (allocno_pri > i_allocno_pri
- || (allocno_pri == i_allocno_pri
- && (allocno_cost > i_allocno_cost
- || (allocno_cost == i_allocno_cost
- && (ALLOCNO_NUM (allocno)
- > ALLOCNO_NUM (i_allocno))))))))
- {
- allocno = i_allocno;
- allocno_cost = i_allocno_cost;
- allocno_pri = i_allocno_pri;
- }
- }
- if (! ALLOCNO_IN_GRAPH_P (allocno_vec[j]))
- j--;
- }
- ira_assert (allocno != NULL && j >= 0);
- cover_class_allocnos_num[cover_class] = j + 1;
- }
- ira_assert (ALLOCNO_IN_GRAPH_P (allocno)
- && ALLOCNO_COVER_CLASS (allocno) == cover_class
- && (ALLOCNO_LEFT_CONFLICTS_SIZE (allocno)
- + ira_reg_class_nregs[cover_class][ALLOCNO_MODE
- (allocno)]
- > ALLOCNO_AVAILABLE_REGS_NUM (allocno)));
- remove_allocno_from_bucket_and_push (allocno, false);
+ remove_allocno_from_bucket_and_push (a, false);
}
ira_assert (colorable_allocno_bucket == NULL
&& uncolorable_allocno_bucket == NULL);
- for (i = 0; i < ira_reg_class_cover_size; i++)
- {
- cover_class = ira_reg_class_cover[i];
- ira_assert (uncolorable_allocnos_num[cover_class] == 0);
- if (uncolorable_allocnos_splay_tree[cover_class] != NULL)
- splay_tree_delete (uncolorable_allocnos_splay_tree[cover_class]);
- }
+ ira_assert (uncolorable_allocnos_num == 0);
}
/* Pop the coloring stack and assign hard registers to the popped
@@ -1318,19 +1773,19 @@ static void
pop_allocnos_from_stack (void)
{
ira_allocno_t allocno;
- enum reg_class cover_class;
+ enum reg_class aclass;
for (;VEC_length (ira_allocno_t, allocno_stack_vec) != 0;)
{
allocno = VEC_pop (ira_allocno_t, allocno_stack_vec);
- cover_class = ALLOCNO_COVER_CLASS (allocno);
+ aclass = ALLOCNO_CLASS (allocno);
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
{
fprintf (ira_dump_file, " Popping");
- print_coalesced_allocno (allocno);
+ ira_print_expanded_allocno (allocno);
fprintf (ira_dump_file, " -- ");
}
- if (cover_class == NO_REGS)
+ if (aclass == NO_REGS)
{
ALLOCNO_HARD_REGNO (allocno) = -1;
ALLOCNO_ASSIGNED_P (allocno) = true;
@@ -1355,132 +1810,47 @@ pop_allocnos_from_stack (void)
}
}
-/* Set up number of available hard registers for ALLOCNO. */
+/* Set up number of available hard registers for A. */
static void
-setup_allocno_available_regs_num (ira_allocno_t allocno)
+setup_allocno_available_regs_num (ira_allocno_t a)
{
- int i, n, hard_regs_num, hard_regno;
+ int i, n, hard_regno, hard_regs_num;
enum machine_mode mode;
- enum reg_class cover_class;
- ira_allocno_t a;
+ enum reg_class aclass;
HARD_REG_SET temp_set;
- cover_class = ALLOCNO_COVER_CLASS (allocno);
- ALLOCNO_AVAILABLE_REGS_NUM (allocno) = ira_available_class_regs[cover_class];
- if (cover_class == NO_REGS)
+ aclass = ALLOCNO_CLASS (a);
+ ALLOCNO_AVAILABLE_REGS_NUM (a) = 0;
+ if (aclass == NO_REGS)
return;
- CLEAR_HARD_REG_SET (temp_set);
- ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) == allocno);
- hard_regs_num = ira_class_hard_regs_num[cover_class];
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- IOR_HARD_REG_SET (temp_set, ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
- if (a == allocno)
- break;
- }
- mode = ALLOCNO_MODE (allocno);
+ COPY_HARD_REG_SET (temp_set, ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+ mode = ALLOCNO_MODE (a);
+ hard_regs_num = ira_class_hard_regs_num[aclass];
for (n = 0, i = hard_regs_num - 1; i >= 0; i--)
{
- hard_regno = ira_class_hard_regs[cover_class][i];
- if (TEST_HARD_REG_BIT (temp_set, hard_regno)
- || TEST_HARD_REG_BIT (prohibited_class_mode_regs[cover_class][mode],
- hard_regno))
+ hard_regno = ira_class_hard_regs[aclass][i];
+ if (! ira_hard_reg_set_intersection_p (hard_regno, mode, temp_set)
+ && TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a), hard_regno))
n++;
}
- if (internal_flag_ira_verbose > 2 && n > 0 && ira_dump_file != NULL)
- fprintf (ira_dump_file, " Reg %d of %s has %d regs less\n",
- ALLOCNO_REGNO (allocno), reg_class_names[cover_class], n);
- ALLOCNO_AVAILABLE_REGS_NUM (allocno) -= n;
-}
-
-/* Set up ALLOCNO_LEFT_CONFLICTS_SIZE for ALLOCNO. */
-static void
-setup_allocno_left_conflicts_size (ira_allocno_t allocno)
-{
- int i, hard_regs_num, hard_regno, conflict_allocnos_size;
- ira_allocno_t a, conflict_allocno;
- enum reg_class cover_class;
- HARD_REG_SET temp_set;
- ira_allocno_conflict_iterator aci;
-
- cover_class = ALLOCNO_COVER_CLASS (allocno);
- hard_regs_num = ira_class_hard_regs_num[cover_class];
- CLEAR_HARD_REG_SET (temp_set);
- ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) == allocno);
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- IOR_HARD_REG_SET (temp_set, ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
- if (a == allocno)
- break;
- }
- AND_HARD_REG_SET (temp_set, reg_class_contents[cover_class]);
- AND_COMPL_HARD_REG_SET (temp_set, ira_no_alloc_regs);
- conflict_allocnos_size = 0;
- if (! hard_reg_set_empty_p (temp_set))
- for (i = 0; i < (int) hard_regs_num; i++)
- {
- hard_regno = ira_class_hard_regs[cover_class][i];
- if (TEST_HARD_REG_BIT (temp_set, hard_regno))
- {
- conflict_allocnos_size++;
- CLEAR_HARD_REG_BIT (temp_set, hard_regno);
- if (hard_reg_set_empty_p (temp_set))
- break;
- }
- }
- CLEAR_HARD_REG_SET (temp_set);
- if (allocno_coalesced_p)
- bitmap_clear (processed_coalesced_allocno_bitmap);
- if (cover_class != NO_REGS)
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (allocno);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- FOR_EACH_ALLOCNO_CONFLICT (a, conflict_allocno, aci)
- {
- conflict_allocno
- = ALLOCNO_FIRST_COALESCED_ALLOCNO (conflict_allocno);
- if (bitmap_bit_p (consideration_allocno_bitmap,
- ALLOCNO_NUM (conflict_allocno)))
- {
- ira_assert (cover_class
- == ALLOCNO_COVER_CLASS (conflict_allocno));
- if (allocno_coalesced_p)
- {
- if (bitmap_bit_p (processed_coalesced_allocno_bitmap,
- ALLOCNO_NUM (conflict_allocno)))
- continue;
- bitmap_set_bit (processed_coalesced_allocno_bitmap,
- ALLOCNO_NUM (conflict_allocno));
- }
- if (! ALLOCNO_ASSIGNED_P (conflict_allocno))
- conflict_allocnos_size
- += (ira_reg_class_nregs
- [cover_class][ALLOCNO_MODE (conflict_allocno)]);
- else if ((hard_regno = ALLOCNO_HARD_REGNO (conflict_allocno))
- >= 0)
- {
- int last = (hard_regno
- + hard_regno_nregs
- [hard_regno][ALLOCNO_MODE (conflict_allocno)]);
-
- while (hard_regno < last)
- {
- if (! TEST_HARD_REG_BIT (temp_set, hard_regno))
- {
- conflict_allocnos_size++;
- SET_HARD_REG_BIT (temp_set, hard_regno);
- }
- hard_regno++;
- }
- }
- }
- }
- if (a == allocno)
- break;
- }
- ALLOCNO_LEFT_CONFLICTS_SIZE (allocno) = conflict_allocnos_size;
+ ALLOCNO_AVAILABLE_REGS_NUM (a) = n;
+ if (internal_flag_ira_verbose <= 2 || ira_dump_file == NULL)
+ return;
+ fprintf
+ (ira_dump_file,
+ " Allocno a%dr%d of %s(%d) has %d avail. regs (confl. regs): ",
+ ALLOCNO_NUM (a), ALLOCNO_REGNO (a),
+ reg_class_names[aclass], ira_class_hard_regs_num[aclass], n);
+ print_hard_reg_set (ira_dump_file, ALLOCNO_PROFITABLE_HARD_REGS (a), false);
+ fprintf (ira_dump_file, " (");
+ print_hard_reg_set (ira_dump_file, temp_set, false);
+ fprintf (ira_dump_file, " ) %snode: ",
+ hard_reg_set_equal_p (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ ALLOCNO_HARD_REGS_NODE (a)->hard_regs->set)
+ ? "" : "^");
+ print_hard_reg_set (ira_dump_file,
+ ALLOCNO_HARD_REGS_NODE (a)->hard_regs->set, false);
+ fprintf (ira_dump_file, "\n");
}
/* Put ALLOCNO in a bucket corresponding to its number and size of its
@@ -1488,215 +1858,14 @@ setup_allocno_left_conflicts_size (ira_a
static void
put_allocno_into_bucket (ira_allocno_t allocno)
{
- enum reg_class cover_class;
-
- cover_class = ALLOCNO_COVER_CLASS (allocno);
- if (ALLOCNO_FIRST_COALESCED_ALLOCNO (allocno) != allocno)
- return;
ALLOCNO_IN_GRAPH_P (allocno) = true;
- setup_allocno_left_conflicts_size (allocno);
setup_allocno_available_regs_num (allocno);
- if (ALLOCNO_LEFT_CONFLICTS_SIZE (allocno)
- + ira_reg_class_nregs[cover_class][ALLOCNO_MODE (allocno)]
- <= ALLOCNO_AVAILABLE_REGS_NUM (allocno))
+ if (setup_left_conflict_sizes_p (allocno))
add_allocno_to_bucket (allocno, &colorable_allocno_bucket);
else
add_allocno_to_bucket (allocno, &uncolorable_allocno_bucket);
}
-/* The function is used to sort allocnos according to their execution
- frequencies. */
-static int
-copy_freq_compare_func (const void *v1p, const void *v2p)
-{
- ira_copy_t cp1 = *(const ira_copy_t *) v1p, cp2 = *(const ira_copy_t *) v2p;
- int pri1, pri2;
-
- pri1 = cp1->freq;
- pri2 = cp2->freq;
- if (pri2 - pri1)
- return pri2 - pri1;
-
- /* If freqencies are equal, sort by copies, so that the results of
- qsort leave nothing to chance. */
- return cp1->num - cp2->num;
-}
-
-/* Merge two sets of coalesced allocnos given correspondingly by
- allocnos A1 and A2 (more accurately merging A2 set into A1
- set). */
-static void
-merge_allocnos (ira_allocno_t a1, ira_allocno_t a2)
-{
- ira_allocno_t a, first, last, next;
-
- first = ALLOCNO_FIRST_COALESCED_ALLOCNO (a1);
- if (first == ALLOCNO_FIRST_COALESCED_ALLOCNO (a2))
- return;
- for (last = a2, a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a2);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = first;
- if (a == a2)
- break;
- last = a;
- }
- next = ALLOCNO_NEXT_COALESCED_ALLOCNO (first);
- ALLOCNO_NEXT_COALESCED_ALLOCNO (first) = a2;
- ALLOCNO_NEXT_COALESCED_ALLOCNO (last) = next;
-}
-
-/* Return TRUE if there are conflicting allocnos from two sets of
- coalesced allocnos given correspondingly by allocnos A1 and A2. If
- RELOAD_P is TRUE, we use live ranges to find conflicts because
- conflicts are represented only for allocnos of the same cover class
- and during the reload pass we coalesce allocnos for sharing stack
- memory slots. */
-static bool
-coalesced_allocno_conflict_p (ira_allocno_t a1, ira_allocno_t a2,
- bool reload_p)
-{
- ira_allocno_t a, conflict_allocno;
- ira_allocno_conflict_iterator aci;
-
- if (allocno_coalesced_p)
- {
- bitmap_clear (processed_coalesced_allocno_bitmap);
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a1);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- bitmap_set_bit (processed_coalesced_allocno_bitmap, ALLOCNO_NUM (a));
- if (a == a1)
- break;
- }
- }
- for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a2);;
- a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
- {
- if (reload_p)
- {
- for (conflict_allocno = ALLOCNO_NEXT_COALESCED_ALLOCNO (a1);;
- conflict_allocno
- = ALLOCNO_NEXT_COALESCED_ALLOCNO (conflict_allocno))
- {
- if (allocnos_have_intersected_live_ranges_p (a,
- conflict_allocno))
- return true;
- if (conflict_allocno == a1)
- break;
- }
- }
- else
- {
- FOR_EACH_ALLOCNO_CONFLICT (a, conflict_allocno, aci)
- if (conflict_allocno == a1
- || (allocno_coalesced_p
- && bitmap_bit_p (processed_coalesced_allocno_bitmap,
- ALLOCNO_NUM (conflict_allocno))))
- return true;
- }
- if (a == a2)
- break;
- }
- return false;
-}
-
-/* The major function for aggressive allocno coalescing. For the
- reload pass (RELOAD_P) we coalesce only spilled allocnos. If some
- allocnos have been coalesced, we set up flag
- allocno_coalesced_p. */
-static void
-coalesce_allocnos (bool reload_p)
-{
- ira_allocno_t a;
- ira_copy_t cp, next_cp, *sorted_copies;
- enum reg_class cover_class;
- enum machine_mode mode;
- unsigned int j;
- int i, n, cp_num, regno;
- bitmap_iterator bi;
-
- sorted_copies = (ira_copy_t *) ira_allocate (ira_copies_num
- * sizeof (ira_copy_t));
- cp_num = 0;
- /* Collect copies. */
- EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, j, bi)
- {
- a = ira_allocnos[j];
- regno = ALLOCNO_REGNO (a);
- if ((! reload_p && ALLOCNO_ASSIGNED_P (a))
- || (reload_p
- && (! ALLOCNO_ASSIGNED_P (a) || ALLOCNO_HARD_REGNO (a) >= 0
- || (regno < ira_reg_equiv_len
- && (ira_reg_equiv_const[regno] != NULL_RTX
- || ira_reg_equiv_invariant_p[regno])))))
- continue;
- cover_class = ALLOCNO_COVER_CLASS (a);
- mode = ALLOCNO_MODE (a);
- for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
- {
- if (cp->first == a)
- {
- 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))
- && (cp->insn != NULL || cp->constraint_p)
- && ((! reload_p && ! ALLOCNO_ASSIGNED_P (cp->second))
- || (reload_p
- && ALLOCNO_ASSIGNED_P (cp->second)
- && ALLOCNO_HARD_REGNO (cp->second) < 0
- && (regno >= ira_reg_equiv_len
- || (! ira_reg_equiv_invariant_p[regno]
- && ira_reg_equiv_const[regno] == NULL_RTX)))))
- sorted_copies[cp_num++] = cp;
- }
- else if (cp->second == a)
- next_cp = cp->next_second_allocno_copy;
- else
- gcc_unreachable ();
- }
- }
- qsort (sorted_copies, cp_num, sizeof (ira_copy_t), copy_freq_compare_func);
- /* Coalesced copies, most frequently executed first. */
- for (; cp_num != 0;)
- {
- for (i = 0; i < cp_num; i++)
- {
- cp = sorted_copies[i];
- if (! coalesced_allocno_conflict_p (cp->first, cp->second, reload_p))
- {
- allocno_coalesced_p = true;
- if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
- fprintf
- (ira_dump_file,
- " Coalescing copy %d:a%dr%d-a%dr%d (freq=%d)\n",
- cp->num, ALLOCNO_NUM (cp->first), ALLOCNO_REGNO (cp->first),
- ALLOCNO_NUM (cp->second), ALLOCNO_REGNO (cp->second),
- cp->freq);
- merge_allocnos (cp->first, cp->second);
- i++;
- break;
- }
- }
- /* Collect the rest of copies. */
- for (n = 0; i < cp_num; i++)
- {
- cp = sorted_copies[i];
- if (ALLOCNO_FIRST_COALESCED_ALLOCNO (cp->first)
- != ALLOCNO_FIRST_COALESCED_ALLOCNO (cp->second))
- sorted_copies[n++] = cp;
- }
- cp_num = n;
- }
- ira_free (sorted_copies);
-}
-
/* Map: allocno number -> allocno priority. */
static int *allocno_priorities;
@@ -1719,22 +1888,185 @@ setup_allocno_priorities (ira_allocno_t
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)]);
+ * (ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a))
+ * ira_reg_class_max_nregs[ALLOCNO_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++)
+ 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;
+ }
+}
+
+/* Improve the allocation by spilling some allocnos and assigning the
+ freed hard registers to other allocnos if it decreases the overall
+ allocation cost. */
+static void
+improve_allocation (void)
+{
+ unsigned int i;
+ int j, k, n, hard_regno, conflict_hard_regno, base_cost, class_size;
+ int spill_cost, min_cost, nregs, conflict_nregs, r, best;
+ bool try_p;
+ enum reg_class aclass;
+ enum machine_mode mode;
+ int *allocno_costs;
+ int costs[FIRST_PSEUDO_REGISTER];
+ HARD_REG_SET conflict_hard_regs;
+ ira_allocno_t a, conflict_a;
+ bitmap_iterator bi;
+ ira_allocno_conflict_iterator aci;
+
+ n = 0;
+ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
+ {
+ a = ira_allocnos[i];
+ if (hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ continue;
+ aclass = ALLOCNO_CLASS (a);
+ allocno_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (a);
+ if (allocno_costs == NULL)
+ allocno_costs = ALLOCNO_HARD_REG_COSTS (a);
+ if ((hard_regno = ALLOCNO_HARD_REGNO (a)) < 0)
+ base_cost = ALLOCNO_UPDATED_MEMORY_COST (a);
+ else if (allocno_costs == NULL)
+ continue;
+ else
+ base_cost
+ = allocno_costs[ira_class_hard_reg_index[aclass][hard_regno]];
+ try_p = false;
+ ira_assert (hard_reg_set_subset_p
+ (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ reg_class_contents[aclass]));
+ class_size = ira_class_hard_regs_num[aclass];
+ for (j = 0; j < class_size; j++)
+ {
+ hard_regno = ira_class_hard_regs[aclass][j];
+ if (! TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ hard_regno))
+ continue;
+ ira_assert (ira_class_hard_reg_index[aclass][hard_regno] == j);
+ k = allocno_costs == NULL ? 0 : j;
+ costs[hard_regno]
+ = (allocno_costs == NULL
+ ? ALLOCNO_UPDATED_CLASS_COST (a) : allocno_costs[k]);
+ costs[hard_regno] -= base_cost;
+ if (costs[hard_regno] < 0)
+ try_p = true;
+ }
+ if (! try_p)
+ continue;
+ mode = ALLOCNO_MODE (a);
+ COPY_HARD_REG_SET (conflict_hard_regs,
+ ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
+ FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
+ {
+ if ((conflict_hard_regno = ALLOCNO_HARD_REGNO (conflict_a)) < 0)
+ continue;
+ spill_cost = ALLOCNO_UPDATED_MEMORY_COST (conflict_a);
+ k = (ira_class_hard_reg_index
+ [ALLOCNO_CLASS (conflict_a)][conflict_hard_regno]);
+ ira_assert (k >= 0);
+ if ((allocno_costs = ALLOCNO_UPDATED_HARD_REG_COSTS (conflict_a))
+ != NULL)
+ spill_cost -= allocno_costs[k];
+ else if ((allocno_costs = ALLOCNO_HARD_REG_COSTS (conflict_a))
+ != NULL)
+ spill_cost -= allocno_costs[k];
+ else
+ spill_cost -= ALLOCNO_UPDATED_CLASS_COST (conflict_a);
+ conflict_nregs
+ = hard_regno_nregs[conflict_hard_regno][ALLOCNO_MODE (conflict_a)];
+ for (r = conflict_hard_regno;
+ r >= 0 && r + hard_regno_nregs[r][mode] > conflict_hard_regno;
+ r--)
+ if (TEST_HARD_REG_BIT
+ (ALLOCNO_PROFITABLE_HARD_REGS (a), r)
+ && ira_hard_reg_not_in_set_p (r, mode, conflict_hard_regs))
+ costs[r] += spill_cost;
+ for (r = conflict_hard_regno + 1;
+ r < conflict_hard_regno + conflict_nregs;
+ r++)
+ if (TEST_HARD_REG_BIT
+ (ALLOCNO_PROFITABLE_HARD_REGS (a), r)
+ && ira_hard_reg_not_in_set_p (r, mode, conflict_hard_regs))
+ costs[r] += spill_cost;
+ }
+ min_cost = INT_MAX;
+ best = -1;
+ for (j = 0; j < class_size; j++)
+ {
+ hard_regno = ira_class_hard_regs[aclass][j];
+ if (TEST_HARD_REG_BIT (ALLOCNO_PROFITABLE_HARD_REGS (a),
+ hard_regno)
+ && (ira_hard_reg_not_in_set_p
+ (hard_regno, ALLOCNO_MODE (a),
+ ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a)))
+ && min_cost > costs[hard_regno])
+ {
+ best = hard_regno;
+ min_cost = costs[hard_regno];
+ }
+ }
+ if (min_cost >= 0)
+ continue;
+ nregs = hard_regno_nregs[best][mode];
+ FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
+ {
+ if ((conflict_hard_regno = ALLOCNO_HARD_REGNO (conflict_a)) < 0)
+ continue;
+ conflict_nregs
+ = hard_regno_nregs[conflict_hard_regno][ALLOCNO_MODE (conflict_a)];
+ if (best + nregs <= conflict_hard_regno
+ || conflict_hard_regno + conflict_nregs <= best)
+ /* No intersection. */
+ continue;
+ ALLOCNO_HARD_REGNO (conflict_a) = -1;
+ sorted_allocnos[n++] = conflict_a;
+ if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
+ fprintf (ira_dump_file, "Spilling a%dr%d for a%dr%d\n",
+ ALLOCNO_NUM (conflict_a), ALLOCNO_REGNO (conflict_a),
+ ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
+ }
+ ALLOCNO_HARD_REGNO (a) = best;
+ if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
+ fprintf (ira_dump_file, "Assigning %d to a%dr%d\n",
+ best, ALLOCNO_NUM (a), ALLOCNO_REGNO (a));
+ }
+ if (n == 0)
+ return;
+ qsort (sorted_allocnos, n, sizeof (ira_allocno_t),
+ allocno_cost_compare_func);
+ for (j = 0; j < n; j++)
{
- 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;
+ a = sorted_allocnos[j];
+ ALLOCNO_ASSIGNED_P (a) = false;
+ if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+ {
+ fprintf (ira_dump_file, " ");
+ ira_print_expanded_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");
+ }
}
}
@@ -1766,17 +2098,13 @@ color_allocnos (void)
bitmap_iterator bi;
ira_allocno_t a;
- allocno_coalesced_p = false;
- processed_coalesced_allocno_bitmap = ira_allocate_bitmap ();
- if (flag_ira_coalesce)
- coalesce_allocnos (false);
if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
{
n = 0;
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
{
a = ira_allocnos[i];
- if (ALLOCNO_COVER_CLASS (a) == NO_REGS)
+ if (ALLOCNO_CLASS (a) == NO_REGS)
{
ALLOCNO_HARD_REGNO (a) = -1;
ALLOCNO_ASSIGNED_P (a) = true;
@@ -1785,7 +2113,7 @@ color_allocnos (void)
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
{
fprintf (ira_dump_file, " Spill");
- print_coalesced_allocno (a);
+ ira_print_expanded_allocno (a);
fprintf (ira_dump_file, "\n");
}
continue;
@@ -1803,7 +2131,7 @@ color_allocnos (void)
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
{
fprintf (ira_dump_file, " ");
- print_coalesced_allocno (a);
+ ira_print_expanded_allocno (a);
fprintf (ira_dump_file, " -- ");
}
if (assign_hard_reg (a, false))
@@ -1822,41 +2150,44 @@ color_allocnos (void)
}
else
{
- /* Put the allocnos into the corresponding buckets. */
- colorable_allocno_bucket = NULL;
- uncolorable_allocno_bucket = NULL;
+ setup_profitable_hard_regs ();
+ form_allocno_hard_regs_nodes_forest ();
+ if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
+ print_hard_regs_forest (ira_dump_file);
EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, i, bi)
{
a = ira_allocnos[i];
- if (ALLOCNO_COVER_CLASS (a) == NO_REGS)
+ if (ALLOCNO_CLASS (a) != NO_REGS
+ && ! hard_reg_set_empty_p (ALLOCNO_PROFITABLE_HARD_REGS (a)))
+ ALLOCNO_IN_GRAPH_P (a) = true;
+ else
{
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);
+ /* We don't need updated costs anymore. */
+ ira_free_allocno_updated_costs (a);
if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
{
fprintf (ira_dump_file, " Spill");
- print_coalesced_allocno (a);
+ ira_print_expanded_allocno (a);
fprintf (ira_dump_file, "\n");
}
- continue;
}
- put_allocno_into_bucket (a);
+ }
+ /* 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_IN_GRAPH_P (a))
+ put_allocno_into_bucket (a);
}
push_allocnos_to_stack ();
pop_allocnos_from_stack ();
+ finish_allocno_hard_regs_nodes_forest ();
}
- 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)
- {
- a = ira_allocnos[i];
- ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = a;
- ALLOCNO_NEXT_COALESCED_ALLOCNO (a) = a;
- }
- ira_free_bitmap (processed_coalesced_allocno_bitmap);
- allocno_coalesced_p = false;
+ improve_allocation ();
}
\f
@@ -1902,15 +2233,15 @@ print_loop_title (ira_loop_tree_node_t l
EXECUTE_IF_SET_IN_BITMAP (loop_tree_node->border_allocnos, 0, j, bi)
fprintf (ira_dump_file, " %dr%d", j, ALLOCNO_REGNO (ira_allocnos[j]));
fprintf (ira_dump_file, "\n Pressure:");
- for (j = 0; (int) j < ira_reg_class_cover_size; j++)
+ for (j = 0; (int) j < ira_pressure_classes_num; j++)
{
- enum reg_class cover_class;
+ enum reg_class pclass;
- cover_class = ira_reg_class_cover[j];
- if (loop_tree_node->reg_pressure[cover_class] == 0)
+ pclass = ira_pressure_classes[j];
+ if (loop_tree_node->reg_pressure[pclass] == 0)
continue;
- fprintf (ira_dump_file, " %s=%d", reg_class_names[cover_class],
- loop_tree_node->reg_pressure[cover_class]);
+ fprintf (ira_dump_file, " %s=%d", reg_class_names[pclass],
+ loop_tree_node->reg_pressure[pclass]);
}
fprintf (ira_dump_file, "\n");
}
@@ -1927,7 +2258,7 @@ color_pass (ira_loop_tree_node_t loop_tr
unsigned int j;
bitmap_iterator bi;
enum machine_mode mode;
- enum reg_class rclass, cover_class;
+ enum reg_class rclass, aclass, pclass;
ira_allocno_t a, subloop_allocno;
ira_loop_tree_node_t subloop_node;
@@ -1956,10 +2287,11 @@ color_pass (ira_loop_tree_node_t loop_tr
continue;
/* Remove from processing in the next loop. */
bitmap_clear_bit (consideration_allocno_bitmap, j);
- rclass = ALLOCNO_COVER_CLASS (a);
+ rclass = ALLOCNO_CLASS (a);
+ pclass = ira_pressure_class_translate[rclass];
if (flag_ira_region == IRA_REGION_MIXED
- && (loop_tree_node->reg_pressure[rclass]
- <= ira_available_class_regs[rclass]))
+ && (loop_tree_node->reg_pressure[pclass]
+ <= ira_available_class_regs[pclass]))
{
mode = ALLOCNO_MODE (a);
hard_regno = ALLOCNO_HARD_REGNO (a);
@@ -1992,7 +2324,8 @@ color_pass (ira_loop_tree_node_t loop_tr
a = ira_allocnos[j];
ira_assert (ALLOCNO_CAP_MEMBER (a) == NULL);
mode = ALLOCNO_MODE (a);
- rclass = ALLOCNO_COVER_CLASS (a);
+ rclass = ALLOCNO_CLASS (a);
+ pclass = ira_pressure_class_translate[rclass];
hard_regno = ALLOCNO_HARD_REGNO (a);
/* Use hard register class here. ??? */
if (hard_regno >= 0)
@@ -2006,12 +2339,12 @@ color_pass (ira_loop_tree_node_t loop_tr
if (subloop_allocno == NULL
|| ALLOCNO_CAP (subloop_allocno) != NULL)
continue;
- ira_assert (ALLOCNO_COVER_CLASS (subloop_allocno) == rclass);
+ ira_assert (ALLOCNO_CLASS (subloop_allocno) == rclass);
ira_assert (bitmap_bit_p (subloop_node->all_allocnos,
ALLOCNO_NUM (subloop_allocno)));
if ((flag_ira_region == IRA_REGION_MIXED)
- && (loop_tree_node->reg_pressure[rclass]
- <= ira_available_class_regs[rclass]))
+ && (loop_tree_node->reg_pressure[pclass]
+ <= ira_available_class_regs[pclass]))
{
if (! ALLOCNO_ASSIGNED_P (subloop_allocno))
{
@@ -2048,23 +2381,22 @@ color_pass (ira_loop_tree_node_t loop_tr
}
else
{
- cover_class = ALLOCNO_COVER_CLASS (subloop_allocno);
+ aclass = ALLOCNO_CLASS (subloop_allocno);
cost = (ira_get_register_move_cost (mode, rclass, rclass)
* (exit_freq + enter_freq));
ira_allocate_and_set_or_copy_costs
- (&ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno), cover_class,
- ALLOCNO_UPDATED_COVER_CLASS_COST (subloop_allocno),
+ (&ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno), aclass,
+ ALLOCNO_UPDATED_CLASS_COST (subloop_allocno),
ALLOCNO_HARD_REG_COSTS (subloop_allocno));
ira_allocate_and_set_or_copy_costs
(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (subloop_allocno),
- cover_class, 0,
- ALLOCNO_CONFLICT_HARD_REG_COSTS (subloop_allocno));
+ aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (subloop_allocno));
ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index] -= cost;
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (subloop_allocno)[index]
-= cost;
- if (ALLOCNO_UPDATED_COVER_CLASS_COST (subloop_allocno)
+ if (ALLOCNO_UPDATED_CLASS_COST (subloop_allocno)
> ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index])
- ALLOCNO_UPDATED_COVER_CLASS_COST (subloop_allocno)
+ ALLOCNO_UPDATED_CLASS_COST (subloop_allocno)
= ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index];
ALLOCNO_UPDATED_MEMORY_COST (subloop_allocno)
+= (ira_memory_move_cost[mode][rclass][0] * enter_freq
@@ -2080,12 +2412,6 @@ static void
do_coloring (void)
{
coloring_allocno_bitmap = ira_allocate_bitmap ();
- allocnos_for_spilling
- = (ira_allocno_t *) ira_allocate (sizeof (ira_allocno_t)
- * ira_allocnos_num);
- splay_tree_node_pool = create_alloc_pool ("splay tree nodes",
- sizeof (struct splay_tree_node_s),
- 100);
if (internal_flag_ira_verbose > 0 && ira_dump_file != NULL)
fprintf (ira_dump_file, "\n**** Allocnos coloring:\n\n");
@@ -2094,9 +2420,7 @@ do_coloring (void)
if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL)
ira_print_disposition (ira_dump_file);
- free_alloc_pool (splay_tree_node_pool);
ira_free_bitmap (coloring_allocno_bitmap);
- ira_free (allocnos_for_spilling);
}
\f
@@ -2140,12 +2464,12 @@ move_spill_restore (void)
|| !bitmap_bit_p (loop_node->border_allocnos, ALLOCNO_NUM (a)))
continue;
mode = ALLOCNO_MODE (a);
- rclass = ALLOCNO_COVER_CLASS (a);
+ rclass = ALLOCNO_CLASS (a);
index = ira_class_hard_reg_index[rclass][hard_regno];
ira_assert (index >= 0);
cost = (ALLOCNO_MEMORY_COST (a)
- (ALLOCNO_HARD_REG_COSTS (a) == NULL
- ? ALLOCNO_COVER_CLASS_COST (a)
+ ? ALLOCNO_CLASS_COST (a)
: ALLOCNO_HARD_REG_COSTS (a)[index]));
for (subloop_node = loop_node->subloops;
subloop_node != NULL;
@@ -2155,13 +2479,13 @@ 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));
+ ira_assert (rclass == ALLOCNO_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. */
cost -= (ALLOCNO_MEMORY_COST (subloop_allocno)
- (ALLOCNO_HARD_REG_COSTS (subloop_allocno) == NULL
- ? ALLOCNO_COVER_CLASS_COST (subloop_allocno)
+ ? ALLOCNO_CLASS_COST (subloop_allocno)
: ALLOCNO_HARD_REG_COSTS (subloop_allocno)[index]));
exit_freq = ira_loop_edge_freq (subloop_node, regno, true);
enter_freq = ira_loop_edge_freq (subloop_node, regno, false);
@@ -2181,7 +2505,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));
+ ira_assert (rclass == ALLOCNO_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)
@@ -2226,14 +2550,14 @@ update_curr_costs (ira_allocno_t a)
{
int i, hard_regno, cost;
enum machine_mode mode;
- enum reg_class cover_class, rclass;
+ enum reg_class aclass, rclass;
ira_allocno_t another_a;
ira_copy_t cp, next_cp;
ira_free_allocno_updated_costs (a);
ira_assert (! ALLOCNO_ASSIGNED_P (a));
- cover_class = ALLOCNO_COVER_CLASS (a);
- if (cover_class == NO_REGS)
+ aclass = ALLOCNO_CLASS (a);
+ if (aclass == NO_REGS)
return;
mode = ALLOCNO_MODE (a);
for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
@@ -2250,25 +2574,23 @@ update_curr_costs (ira_allocno_t a)
}
else
gcc_unreachable ();
- if (! ira_reg_classes_intersect_p[cover_class][ALLOCNO_COVER_CLASS
- (another_a)]
+ if (! ira_reg_classes_intersect_p[aclass][ALLOCNO_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];
+ i = ira_class_hard_reg_index[aclass][hard_regno];
if (i < 0)
continue;
cost = (cp->first == a
- ? ira_get_register_move_cost (mode, rclass, cover_class)
- : ira_get_register_move_cost (mode, cover_class, rclass));
+ ? ira_get_register_move_cost (mode, rclass, aclass)
+ : ira_get_register_move_cost (mode, aclass, rclass));
ira_allocate_and_set_or_copy_costs
- (&ALLOCNO_UPDATED_HARD_REG_COSTS (a),
- cover_class, ALLOCNO_COVER_CLASS_COST (a),
+ (&ALLOCNO_UPDATED_HARD_REG_COSTS (a), aclass, ALLOCNO_CLASS_COST (a),
ALLOCNO_HARD_REG_COSTS (a));
ira_allocate_and_set_or_copy_costs
(&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a),
- cover_class, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
+ aclass, 0, ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
ALLOCNO_UPDATED_HARD_REG_COSTS (a)[i] -= cp->freq * cost;
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a)[i] -= cp->freq * cost;
}
@@ -2286,7 +2608,7 @@ ira_reassign_conflict_allocnos (int star
int i, allocnos_to_color_num;
ira_allocno_t a, conflict_a;
ira_allocno_conflict_iterator aci;
- enum reg_class cover_class;
+ enum reg_class aclass;
bitmap allocnos_to_color;
ira_allocno_iterator ai;
@@ -2297,7 +2619,7 @@ ira_reassign_conflict_allocnos (int star
if (! ALLOCNO_ASSIGNED_P (a)
&& ! bitmap_bit_p (allocnos_to_color, ALLOCNO_NUM (a)))
{
- if (ALLOCNO_COVER_CLASS (a) != NO_REGS)
+ if (ALLOCNO_CLASS (a) != NO_REGS)
sorted_allocnos[allocnos_to_color_num++] = a;
else
{
@@ -2309,12 +2631,12 @@ ira_reassign_conflict_allocnos (int star
bitmap_set_bit (allocnos_to_color, ALLOCNO_NUM (a));
}
if (ALLOCNO_REGNO (a) < start_regno
- || (cover_class = ALLOCNO_COVER_CLASS (a)) == NO_REGS)
+ || (aclass = ALLOCNO_CLASS (a)) == NO_REGS)
continue;
FOR_EACH_ALLOCNO_CONFLICT (a, conflict_a, aci)
{
ira_assert (ira_reg_classes_intersect_p
- [cover_class][ALLOCNO_COVER_CLASS (conflict_a)]);
+ [aclass][ALLOCNO_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));
@@ -2350,6 +2672,52 @@ ira_reassign_conflict_allocnos (int star
\f
+/* This page contains functions used to find conflicts using allocno
+ live ranges. */
+
+/* Return TRUE if live ranges of allocnos A1 and A2 intersect. It is
+ used to find a conflict for new allocnos or allocnos with the
+ different allocno classes. */
+static bool
+allocnos_have_intersected_live_ranges_p (ira_allocno_t a1, ira_allocno_t a2)
+{
+ rtx reg1, reg2;
+
+ if (a1 == a2)
+ return false;
+ reg1 = regno_reg_rtx[ALLOCNO_REGNO (a1)];
+ reg2 = regno_reg_rtx[ALLOCNO_REGNO (a2)];
+ if (reg1 != NULL && reg2 != NULL
+ && ORIGINAL_REGNO (reg1) == ORIGINAL_REGNO (reg2))
+ return false;
+ return ira_allocno_live_ranges_intersect_p (ALLOCNO_LIVE_RANGES (a1),
+ ALLOCNO_LIVE_RANGES (a2));
+}
+
+#ifdef ENABLE_IRA_CHECKING
+
+/* Return TRUE if live ranges of pseudo-registers REGNO1 and REGNO2
+ intersect. This should be used when there is only one region.
+ Currently this is used during reload. */
+static bool
+pseudos_have_intersected_live_ranges_p (int regno1, int regno2)
+{
+ ira_allocno_t a1, a2;
+
+ ira_assert (regno1 >= FIRST_PSEUDO_REGISTER
+ && regno2 >= FIRST_PSEUDO_REGISTER);
+ /* Reg info caclulated by dataflow infrastructure can be different
+ from one calculated by regclass. */
+ if ((a1 = ira_loop_tree_root->regno_allocno_map[regno1]) == NULL
+ || (a2 = ira_loop_tree_root->regno_allocno_map[regno2]) == NULL)
+ return false;
+ return allocnos_have_intersected_live_ranges_p (a1, a2);
+}
+
+#endif
+
+\f
+
/* This page contains code to coalesce memory stack slots used by
spilled allocnos. This results in smaller stack frame, better data
locality, and in smaller code for some architectures like
@@ -2357,6 +2725,180 @@ ira_reassign_conflict_allocnos (int star
On the other hand, it can worsen insn scheduling after the RA but
in practice it is less important than smaller stack frames. */
+/* TRUE if we coalesced some allocnos. In other words, if we got
+ loops formed by members first_coalesced_allocno and
+ next_coalesced_allocno containing more one allocno. */
+static bool allocno_coalesced_p;
+
+/* Bitmap used to prevent a repeated allocno processing because of
+ coalescing. */
+static bitmap processed_coalesced_allocno_bitmap;
+
+/* The function is used to sort allocnos according to their execution
+ frequencies. */
+static int
+copy_freq_compare_func (const void *v1p, const void *v2p)
+{
+ ira_copy_t cp1 = *(const ira_copy_t *) v1p, cp2 = *(const ira_copy_t *) v2p;
+ int pri1, pri2;
+
+ pri1 = cp1->freq;
+ pri2 = cp2->freq;
+ if (pri2 - pri1)
+ return pri2 - pri1;
+
+ /* If freqencies are equal, sort by copies, so that the results of
+ qsort leave nothing to chance. */
+ return cp1->num - cp2->num;
+}
+
+/* Merge two sets of coalesced allocnos given correspondingly by
+ allocnos A1 and A2 (more accurately merging A2 set into A1
+ set). */
+static void
+merge_allocnos (ira_allocno_t a1, ira_allocno_t a2)
+{
+ ira_allocno_t a, first, last, next;
+
+ first = ALLOCNO_FIRST_COALESCED_ALLOCNO (a1);
+ a = ALLOCNO_FIRST_COALESCED_ALLOCNO (a2);
+ if (first == a)
+ return;
+ for (last = a2, a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a2);;
+ a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ {
+ ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = first;
+ if (a == a2)
+ break;
+ last = a;
+ }
+ next = ALLOCNO_NEXT_COALESCED_ALLOCNO (first);
+ ALLOCNO_NEXT_COALESCED_ALLOCNO (first) = a2;
+ ALLOCNO_NEXT_COALESCED_ALLOCNO (last) = next;
+}
+
+/* Return TRUE if there are conflicting allocnos from two sets of
+ coalesced allocnos given correspondingly by allocnos A1 and A2. We
+ use live ranges to find conflicts because conflicts are represented
+ only for allocnos of the same allocno class and during the reload
+ pass we coalesce allocnos for sharing stack memory slots. */
+static bool
+coalesced_allocno_conflict_p (ira_allocno_t a1, ira_allocno_t a2)
+{
+ ira_allocno_t a, conflict_a;
+
+ if (allocno_coalesced_p)
+ {
+ bitmap_clear (processed_coalesced_allocno_bitmap);
+ for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a1);;
+ a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ {
+ bitmap_set_bit (processed_coalesced_allocno_bitmap, ALLOCNO_NUM (a));
+ if (a == a1)
+ break;
+ }
+ }
+ for (a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a2);;
+ a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a))
+ {
+ for (conflict_a = ALLOCNO_NEXT_COALESCED_ALLOCNO (a1);;
+ conflict_a = ALLOCNO_NEXT_COALESCED_ALLOCNO (conflict_a))
+ {
+ if (allocnos_have_intersected_live_ranges_p (a, conflict_a))
+ return true;
+ if (conflict_a == a1)
+ break;
+ }
+ if (a == a2)
+ break;
+ }
+ return false;
+}
+
+/* The major function for aggressive allocno coalescing. We coalesce
+ only spilled allocnos. If some allocnos have been coalesced, we
+ set up flag allocno_coalesced_p. */
+static void
+coalesce_allocnos (void)
+{
+ ira_allocno_t a;
+ ira_copy_t cp, next_cp, *sorted_copies;
+ unsigned int j;
+ int i, n, cp_num, regno;
+ bitmap_iterator bi;
+
+ sorted_copies = (ira_copy_t *) ira_allocate (ira_copies_num
+ * sizeof (ira_copy_t));
+ cp_num = 0;
+ /* Collect copies. */
+ EXECUTE_IF_SET_IN_BITMAP (coloring_allocno_bitmap, 0, j, bi)
+ {
+ a = ira_allocnos[j];
+ regno = ALLOCNO_REGNO (a);
+ if (! ALLOCNO_ASSIGNED_P (a) || ALLOCNO_HARD_REGNO (a) >= 0
+ || (regno < ira_reg_equiv_len
+ && (ira_reg_equiv_const[regno] != NULL_RTX
+ || ira_reg_equiv_invariant_p[regno])))
+ continue;
+ for (cp = ALLOCNO_COPIES (a); cp != NULL; cp = next_cp)
+ {
+ if (cp->first == a)
+ {
+ next_cp = cp->next_first_allocno_copy;
+ regno = ALLOCNO_REGNO (cp->second);
+ /* For priority coloring we coalesce allocnos only with
+ the same allocno class not with intersected allocno
+ classes as it were possible. It is done for
+ simplicity. */
+ if ((cp->insn != NULL || cp->constraint_p)
+ && ALLOCNO_ASSIGNED_P (cp->second)
+ && ALLOCNO_HARD_REGNO (cp->second) < 0
+ && (regno >= ira_reg_equiv_len
+ || (! ira_reg_equiv_invariant_p[regno]
+ && ira_reg_equiv_const[regno] == NULL_RTX)))
+ sorted_copies[cp_num++] = cp;
+ }
+ else if (cp->second == a)
+ next_cp = cp->next_second_allocno_copy;
+ else
+ gcc_unreachable ();
+ }
+ }
+ qsort (sorted_copies, cp_num, sizeof (ira_copy_t), copy_freq_compare_func);
+ /* Coalesced copies, most frequently executed first. */
+ for (; cp_num != 0;)
+ {
+ for (i = 0; i < cp_num; i++)
+ {
+ cp = sorted_copies[i];
+ if (! coalesced_allocno_conflict_p (cp->first, cp->second))
+ {
+ allocno_coalesced_p = true;
+ if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL)
+ fprintf
+ (ira_dump_file,
+ " Coalescing copy %d:a%dr%d-a%dr%d (freq=%d)\n",
+ cp->num, ALLOCNO_NUM (cp->first), ALLOCNO_REGNO (cp->first),
+ ALLOCNO_NUM (cp->second), ALLOCNO_REGNO (cp->second),
+ cp->freq);
+ merge_allocnos (cp->first, cp->second);
+ i++;
+ break;
+ }
+ }
+ /* Collect the rest of copies. */
+ for (n = 0; i < cp_num; i++)
+ {
+ cp = sorted_copies[i];
+ if (ALLOCNO_FIRST_COALESCED_ALLOCNO (cp->first)
+ != ALLOCNO_FIRST_COALESCED_ALLOCNO (cp->second))
+ sorted_copies[n++] = cp;
+ }
+ cp_num = n;
+ }
+ ira_free (sorted_copies);
+}
+
/* Usage cost and order number of coalesced allocno set to which
given pseudo register belongs to. */
static int *regno_coalesced_allocno_cost;
@@ -2419,8 +2961,10 @@ coalesced_pseudo_reg_slot_compare (const
if ((diff = slot_num1 - slot_num2) != 0)
return (frame_pointer_needed
|| !FRAME_GROWS_DOWNWARD == STACK_GROWS_DOWNWARD ? diff : -diff);
- total_size1 = MAX (PSEUDO_REGNO_BYTES (regno1), regno_max_ref_width[regno1]);
- total_size2 = MAX (PSEUDO_REGNO_BYTES (regno2), regno_max_ref_width[regno2]);
+ total_size1 = MAX (PSEUDO_REGNO_BYTES (regno1),
+ regno_max_ref_width[regno1]);
+ total_size2 = MAX (PSEUDO_REGNO_BYTES (regno2),
+ regno_max_ref_width[regno2]);
if ((diff = total_size2 - total_size1) != 0)
return diff;
return regno1 - regno2;
@@ -2619,10 +3163,8 @@ ira_sort_regnos_for_alter_reg (int *pseu
int max_regno = max_reg_num ();
int i, regno, num, slot_num;
ira_allocno_t allocno, a;
- ira_allocno_iterator ai;
ira_allocno_t *spilled_coalesced_allocnos;
- processed_coalesced_allocno_bitmap = ira_allocate_bitmap ();
/* Set up allocnos can be coalesced. */
coloring_allocno_bitmap = ira_allocate_bitmap ();
for (i = 0; i < n; i++)
@@ -2630,11 +3172,11 @@ ira_sort_regnos_for_alter_reg (int *pseu
regno = pseudo_regnos[i];
allocno = ira_regno_allocno_map[regno];
if (allocno != NULL)
- bitmap_set_bit (coloring_allocno_bitmap,
- ALLOCNO_NUM (allocno));
+ bitmap_set_bit (coloring_allocno_bitmap, ALLOCNO_NUM (allocno));
}
allocno_coalesced_p = false;
- coalesce_allocnos (true);
+ processed_coalesced_allocno_bitmap = ira_allocate_bitmap ();
+ coalesce_allocnos ();
ira_free_bitmap (coloring_allocno_bitmap);
regno_coalesced_allocno_cost
= (int *) ira_allocate (max_regno * sizeof (int));
@@ -2702,13 +3244,6 @@ ira_sort_regnos_for_alter_reg (int *pseu
/* Sort regnos according the slot numbers. */
regno_max_ref_width = reg_max_ref_width;
qsort (pseudo_regnos, n, sizeof (int), coalesced_pseudo_reg_slot_compare);
- /* Uncoalesce allocnos which is necessary for (re)assigning during
- the reload pass. */
- FOR_EACH_ALLOCNO (a, ai)
- {
- ALLOCNO_FIRST_COALESCED_ALLOCNO (a) = a;
- ALLOCNO_NEXT_COALESCED_ALLOCNO (a) = a;
- }
ira_free (regno_coalesced_allocno_num);
ira_free (regno_coalesced_allocno_cost);
}
@@ -2726,7 +3261,7 @@ ira_mark_allocation_change (int regno)
{
ira_allocno_t a = ira_regno_allocno_map[regno];
int old_hard_regno, hard_regno, cost;
- enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
+ enum reg_class aclass = ALLOCNO_CLASS (a);
ira_assert (a != NULL);
hard_regno = reg_renumber[regno];
@@ -2736,11 +3271,11 @@ ira_mark_allocation_change (int regno)
cost = -ALLOCNO_MEMORY_COST (a);
else
{
- ira_assert (ira_class_hard_reg_index[cover_class][old_hard_regno] >= 0);
+ ira_assert (ira_class_hard_reg_index[aclass][old_hard_regno] >= 0);
cost = -(ALLOCNO_HARD_REG_COSTS (a) == NULL
- ? ALLOCNO_COVER_CLASS_COST (a)
+ ? ALLOCNO_CLASS_COST (a)
: ALLOCNO_HARD_REG_COSTS (a)
- [ira_class_hard_reg_index[cover_class][old_hard_regno]]);
+ [ira_class_hard_reg_index[aclass][old_hard_regno]]);
update_copy_costs (a, false);
}
ira_overall_cost -= cost;
@@ -2750,12 +3285,12 @@ ira_mark_allocation_change (int regno)
ALLOCNO_HARD_REGNO (a) = -1;
cost += ALLOCNO_MEMORY_COST (a);
}
- else if (ira_class_hard_reg_index[cover_class][hard_regno] >= 0)
+ else if (ira_class_hard_reg_index[aclass][hard_regno] >= 0)
{
cost += (ALLOCNO_HARD_REG_COSTS (a) == NULL
- ? ALLOCNO_COVER_CLASS_COST (a)
+ ? ALLOCNO_CLASS_COST (a)
: ALLOCNO_HARD_REG_COSTS (a)
- [ira_class_hard_reg_index[cover_class][hard_regno]]);
+ [ira_class_hard_reg_index[aclass][hard_regno]]);
update_copy_costs (a, true);
}
else
@@ -2787,16 +3322,17 @@ static bool
allocno_reload_assign (ira_allocno_t a, HARD_REG_SET forbidden_regs)
{
int hard_regno;
- enum reg_class cover_class;
+ enum reg_class aclass;
int regno = ALLOCNO_REGNO (a);
HARD_REG_SET saved;
COPY_HARD_REG_SET (saved, ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a));
IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), forbidden_regs);
if (! flag_caller_saves && ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
- IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), call_used_reg_set);
+ IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
+ call_used_reg_set);
ALLOCNO_ASSIGNED_P (a) = false;
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
update_curr_costs (a);
assign_hard_reg (a, true);
hard_regno = ALLOCNO_HARD_REGNO (a);
@@ -2805,13 +3341,13 @@ allocno_reload_assign (ira_allocno_t a,
ALLOCNO_HARD_REGNO (a) = -1;
else
{
- ira_assert (ira_class_hard_reg_index[cover_class][hard_regno] >= 0);
- ira_overall_cost -= (ALLOCNO_MEMORY_COST (a)
- - (ALLOCNO_HARD_REG_COSTS (a) == NULL
- ? ALLOCNO_COVER_CLASS_COST (a)
- : ALLOCNO_HARD_REG_COSTS (a)
- [ira_class_hard_reg_index
- [cover_class][hard_regno]]));
+ ira_assert (ira_class_hard_reg_index[aclass][hard_regno] >= 0);
+ ira_overall_cost
+ -= (ALLOCNO_MEMORY_COST (a)
+ - (ALLOCNO_HARD_REG_COSTS (a) == NULL
+ ? ALLOCNO_CLASS_COST (a)
+ : ALLOCNO_HARD_REG_COSTS (a)[ira_class_hard_reg_index
+ [aclass][hard_regno]]));
if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0
&& ! ira_hard_reg_not_in_set_p (hard_regno, ALLOCNO_MODE (a),
call_used_reg_set))
@@ -2918,7 +3454,7 @@ ira_reassign_pseudos (int *spilled_pseud
fprintf (ira_dump_file,
" Try Assign %d(a%d), cost=%d", regno, ALLOCNO_NUM (a),
ALLOCNO_MEMORY_COST (a)
- - ALLOCNO_COVER_CLASS_COST (a));
+ - ALLOCNO_CLASS_COST (a));
allocno_reload_assign (a, forbidden_regs);
if (reg_renumber[regno] >= 0)
{
@@ -3108,7 +3644,7 @@ calculate_spill_cost (int *regnos, rtx i
ira_assert (hard_regno >= 0);
a = ira_regno_allocno_map[regno];
length += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
- cost += ALLOCNO_MEMORY_COST (a) - ALLOCNO_COVER_CLASS_COST (a);
+ cost += ALLOCNO_MEMORY_COST (a) - ALLOCNO_CLASS_COST (a);
nregs = hard_regno_nregs[hard_regno][ALLOCNO_MODE (a)];
for (j = 0; j < nregs; j++)
if (! TEST_HARD_REG_BIT (call_used_reg_set, hard_regno + j))
@@ -3123,11 +3659,11 @@ calculate_spill_cost (int *regnos, rtx i
saved_cost = 0;
if (in_p)
saved_cost += ira_memory_move_cost
- [ALLOCNO_MODE (a)][ALLOCNO_COVER_CLASS (a)][1];
+ [ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)][1];
if (out_p)
saved_cost
+= ira_memory_move_cost
- [ALLOCNO_MODE (a)][ALLOCNO_COVER_CLASS (a)][0];
+ [ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)][0];
cost -= REG_FREQ_FROM_BB (BLOCK_FOR_INSN (insn)) * saved_cost;
}
}
@@ -3213,13 +3749,10 @@ static void
color (void)
{
allocno_stack_vec = VEC_alloc (ira_allocno_t, heap, ira_allocnos_num);
- removed_splay_allocno_vec
- = VEC_alloc (ira_allocno_t, heap, ira_allocnos_num);
memset (allocated_hardreg_p, 0, sizeof (allocated_hardreg_p));
ira_initiate_assign ();
do_coloring ();
ira_finish_assign ();
- VEC_free (ira_allocno_t, heap, removed_splay_allocno_vec);
VEC_free (ira_allocno_t, heap, allocno_stack_vec);
move_spill_restore ();
}
@@ -3239,7 +3772,7 @@ fast_allocation (void)
#ifdef STACK_REGS
bool no_stack_reg_p;
#endif
- enum reg_class cover_class;
+ enum reg_class aclass;
enum machine_mode mode;
ira_allocno_t a;
ira_allocno_iterator ai;
@@ -3266,20 +3799,20 @@ fast_allocation (void)
for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
for (j = r->start; j <= r->finish; j++)
IOR_HARD_REG_SET (conflict_hard_regs, used_hard_regs[j]);
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
ALLOCNO_ASSIGNED_P (a) = true;
ALLOCNO_HARD_REGNO (a) = -1;
- if (hard_reg_set_subset_p (reg_class_contents[cover_class],
+ if (hard_reg_set_subset_p (reg_class_contents[aclass],
conflict_hard_regs))
continue;
mode = ALLOCNO_MODE (a);
#ifdef STACK_REGS
no_stack_reg_p = ALLOCNO_NO_STACK_REG_P (a);
#endif
- class_size = ira_class_hard_regs_num[cover_class];
+ class_size = ira_class_hard_regs_num[aclass];
for (j = 0; j < class_size; j++)
{
- hard_regno = ira_class_hard_regs[cover_class][j];
+ hard_regno = ira_class_hard_regs[aclass][j];
#ifdef STACK_REGS
if (no_stack_reg_p && FIRST_STACK_REG <= hard_regno
&& hard_regno <= LAST_STACK_REG)
@@ -3287,7 +3820,7 @@ fast_allocation (void)
#endif
if (!ira_hard_reg_not_in_set_p (hard_regno, mode, conflict_hard_regs)
|| (TEST_HARD_REG_BIT
- (prohibited_class_mode_regs[cover_class][mode], hard_regno)))
+ (ira_prohibited_class_mode_regs[aclass][mode], hard_regno)))
continue;
ALLOCNO_HARD_REGNO (a) = hard_regno;
for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
@@ -3317,7 +3850,7 @@ ira_color (void)
FOR_EACH_ALLOCNO (a, ai)
{
ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a);
- ALLOCNO_UPDATED_COVER_CLASS_COST (a) = ALLOCNO_COVER_CLASS_COST (a);
+ ALLOCNO_UPDATED_CLASS_COST (a) = ALLOCNO_CLASS_COST (a);
}
if (ira_conflicts_p)
color ();
Index: opts.c
===================================================================
--- opts.c (revision 161709)
+++ opts.c (working copy)
@@ -785,11 +785,6 @@ decode_options (unsigned int argc, const
}
}
- /* 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);
flag_defer_pop = opt1;
@@ -1076,14 +1071,6 @@ decode_options (unsigned int argc, const
if (!flag_sel_sched_pipelining)
flag_sel_sched_pipelining_outer_loops = 0;
- if (!targetm.ira_cover_classes
- && flag_ira_algorithm == IRA_ALGORITHM_CB)
- {
- inform (input_location,
- "-fira-algorithm=CB does not work on this architecture");
- flag_ira_algorithm = IRA_ALGORITHM_PRIORITY;
- }
-
if (flag_conserve_stack)
{
if (!PARAM_SET_P (PARAM_LARGE_STACK_FRAME))
Index: ira-lives.c
===================================================================
--- ira-lives.c (revision 161709)
+++ ira-lives.c (working copy)
@@ -63,8 +63,8 @@ static int curr_point;
register pressure excess. Excess pressure for a register class at
some point means that there are more allocnos of given register
class living at the point than number of hard-registers of the
- class available for the allocation. It is defined only for cover
- classes. */
+ class available for the allocation. It is defined only for
+ pressure classes. */
static int high_pressure_start_point[N_REG_CLASSES];
/* Allocnos live at current point in the scan. */
@@ -130,14 +130,17 @@ static void
update_allocno_pressure_excess_length (ira_allocno_t a)
{
int start, i;
- enum reg_class cover_class, cl;
+ enum reg_class aclass, pclass, cl;
live_range_t p;
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
+ pclass = ira_pressure_class_translate[aclass];
for (i = 0;
- (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES;
+ (cl = ira_reg_class_super_classes[pclass][i]) != LIM_REG_CLASSES;
i++)
{
+ if (! ira_reg_pressure_class_p[cl])
+ continue;
if (high_pressure_start_point[cl] < 0)
continue;
p = ALLOCNO_LIVE_RANGES (a);
@@ -162,24 +165,26 @@ make_allocno_dead (ira_allocno_t a)
sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a));
}
-/* The current register pressures for each cover class for the current
+/* The current register pressures for each pressure class for the current
basic block. */
static int curr_reg_pressure[N_REG_CLASSES];
-/* Record that register pressure for COVER_CLASS increased by N
- registers. Update the current register pressure, maximal register
- pressure for the current BB and the start point of the register
- pressure excess. */
+/* Record that register pressure for PCLASS increased by N registers.
+ Update the current register pressure, maximal register pressure for
+ the current BB and the start point of the register pressure
+ excess. */
static void
-inc_register_pressure (enum reg_class cover_class, int n)
+inc_register_pressure (enum reg_class pclass, int n)
{
int i;
enum reg_class cl;
for (i = 0;
- (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES;
+ (cl = ira_reg_class_super_classes[pclass][i]) != LIM_REG_CLASSES;
i++)
{
+ if (! ira_reg_pressure_class_p[cl])
+ continue;
curr_reg_pressure[cl] += n;
if (high_pressure_start_point[cl] < 0
&& (curr_reg_pressure[cl] > ira_available_class_regs[cl]))
@@ -189,13 +194,13 @@ inc_register_pressure (enum reg_class co
}
}
-/* Record that register pressure for COVER_CLASS has decreased by
- NREGS registers; update current register pressure, start point of
- the register pressure excess, and register pressure excess length
- for living allocnos. */
+/* Record that register pressure for PCLASS has decreased by NREGS
+ registers; update current register pressure, start point of the
+ register pressure excess, and register pressure excess length for
+ living allocnos. */
static void
-dec_register_pressure (enum reg_class cover_class, int nregs)
+dec_register_pressure (enum reg_class pclass, int nregs)
{
int i;
unsigned int j;
@@ -203,9 +208,11 @@ dec_register_pressure (enum reg_class co
bool set_p = false;
for (i = 0;
- (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES;
+ (cl = ira_reg_class_super_classes[pclass][i]) != LIM_REG_CLASSES;
i++)
{
+ if (! ira_reg_pressure_class_p[cl])
+ continue;
curr_reg_pressure[cl] -= nregs;
ira_assert (curr_reg_pressure[cl] >= 0);
if (high_pressure_start_point[cl] >= 0
@@ -217,12 +224,15 @@ dec_register_pressure (enum reg_class co
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;
+ (cl = ira_reg_class_super_classes[pclass][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;
+ {
+ if (! ira_reg_pressure_class_p[cl])
+ continue;
+ if (high_pressure_start_point[cl] >= 0
+ && curr_reg_pressure[cl] <= ira_available_class_regs[cl])
+ high_pressure_start_point[cl] = -1;
+ }
}
}
@@ -232,7 +242,7 @@ static void
mark_pseudo_regno_live (int regno)
{
ira_allocno_t a = ira_curr_regno_allocno_map[regno];
- enum reg_class cl;
+ enum reg_class pclass;
int nregs;
if (a == NULL)
@@ -244,9 +254,9 @@ mark_pseudo_regno_live (int regno)
if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)))
return;
- cl = ALLOCNO_COVER_CLASS (a);
- nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)];
- inc_register_pressure (cl, nregs);
+ pclass = ira_pressure_class_translate[ALLOCNO_CLASS (a)];
+ nregs = ira_reg_class_max_nregs[pclass][ALLOCNO_MODE (a)];
+ inc_register_pressure (pclass, nregs);
make_allocno_born (a);
}
@@ -261,14 +271,16 @@ mark_hard_reg_live (rtx reg)
if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
{
int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
+ enum reg_class aclass, pclass;
while (regno < last)
{
if (! TEST_HARD_REG_BIT (hard_regs_live, regno)
&& ! TEST_HARD_REG_BIT (eliminable_regset, regno))
{
- enum reg_class cover_class = ira_hard_regno_cover_class[regno];
- inc_register_pressure (cover_class, 1);
+ aclass = ira_hard_regno_allocno_class[regno];
+ pclass = ira_pressure_class_translate[aclass];
+ inc_register_pressure (pclass, 1);
make_hard_regno_born (regno);
}
regno++;
@@ -309,8 +321,8 @@ mark_pseudo_regno_dead (int regno)
if (! sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a)))
return;
- cl = ALLOCNO_COVER_CLASS (a);
- nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)];
+ cl = ira_pressure_class_translate[ALLOCNO_CLASS (a)];
+ nregs = ira_reg_class_max_nregs[cl][ALLOCNO_MODE (a)];
dec_register_pressure (cl, nregs);
make_allocno_dead (a);
@@ -326,13 +338,15 @@ mark_hard_reg_dead (rtx reg)
if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
{
int last = regno + hard_regno_nregs[regno][GET_MODE (reg)];
+ enum reg_class aclass, pclass;
while (regno < last)
{
if (TEST_HARD_REG_BIT (hard_regs_live, regno))
{
- enum reg_class cover_class = ira_hard_regno_cover_class[regno];
- dec_register_pressure (cover_class, 1);
+ aclass = ira_hard_regno_allocno_class[regno];
+ pclass = ira_pressure_class_translate[aclass];
+ dec_register_pressure (pclass, 1);
make_hard_regno_dead (regno);
}
regno++;
@@ -376,7 +390,7 @@ make_pseudo_conflict (rtx reg, enum reg_
return advance_p;
a = ira_curr_regno_allocno_map[REGNO (reg)];
- if (! reg_classes_intersect_p (cl, ALLOCNO_COVER_CLASS (a)))
+ if (! reg_classes_intersect_p (cl, ALLOCNO_CLASS (a)))
return advance_p;
if (advance_p)
@@ -446,7 +460,7 @@ check_and_make_def_conflict (int alt, in
return;
a = ira_curr_regno_allocno_map[REGNO (dreg)];
- acl = ALLOCNO_COVER_CLASS (a);
+ acl = ALLOCNO_CLASS (a);
if (! reg_classes_intersect_p (acl, def_cl))
return;
@@ -676,7 +690,7 @@ single_reg_class (const char *constraint
: REG_CLASS_FROM_CONSTRAINT (c, constraints));
if ((cl != NO_REGS && next_cl != cl)
|| (ira_available_class_regs[next_cl]
- > ira_reg_class_nregs[next_cl][GET_MODE (op)]))
+ > ira_reg_class_max_nregs[next_cl][GET_MODE (op)]))
return NO_REGS;
cl = next_cl;
break;
@@ -689,7 +703,7 @@ single_reg_class (const char *constraint
if ((cl != NO_REGS && next_cl != cl)
|| next_cl == NO_REGS
|| (ira_available_class_regs[next_cl]
- > ira_reg_class_nregs[next_cl][GET_MODE (op)]))
+ > ira_reg_class_max_nregs[next_cl][GET_MODE (op)]))
return NO_REGS;
cl = next_cl;
break;
@@ -764,7 +778,7 @@ ira_implicitly_set_insn_hard_regs (HARD_
regs in this class are fixed. */
&& ira_available_class_regs[cl] != 0
&& (ira_available_class_regs[cl]
- <= ira_reg_class_nregs[cl][mode]))
+ <= ira_reg_class_max_nregs[cl][mode]))
IOR_HARD_REG_SET (*set, reg_class_contents[cl]);
break;
}
@@ -806,14 +820,14 @@ process_single_reg_class_operands (bool
&& (regno = REGNO (operand)) >= FIRST_PSEUDO_REGISTER)
{
enum machine_mode mode;
- enum reg_class cover_class;
+ enum reg_class aclass;
operand_a = ira_curr_regno_allocno_map[regno];
mode = ALLOCNO_MODE (operand_a);
- cover_class = ALLOCNO_COVER_CLASS (operand_a);
- if (ira_class_subset_p[cl][cover_class]
+ aclass = ALLOCNO_CLASS (operand_a);
+ if (ira_class_subset_p[cl][aclass]
&& ira_class_hard_regs_num[cl] != 0
- && (ira_class_hard_reg_index[cover_class]
+ && (ira_class_hard_reg_index[aclass]
[ira_class_hard_regs[cl][0]]) >= 0
&& reg_class_size[cl] <= (unsigned) CLASS_MAX_NREGS (cl, mode))
{
@@ -821,15 +835,15 @@ process_single_reg_class_operands (bool
cost
= (freq
* (in_p
- ? ira_get_register_move_cost (mode, cover_class, cl)
- : ira_get_register_move_cost (mode, cl, cover_class)));
+ ? ira_get_register_move_cost (mode, aclass, cl)
+ : ira_get_register_move_cost (mode, cl, aclass)));
ira_allocate_and_set_costs
- (&ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a), cover_class, 0);
- size = ira_reg_class_nregs[cover_class][mode];
+ (&ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a), aclass, 0);
+ size = ira_reg_class_max_nregs[aclass][mode];
for (i = 0; i < size; i++)
ALLOCNO_CONFLICT_HARD_REG_COSTS (operand_a)
[ira_class_hard_reg_index
- [cover_class][ira_class_hard_regs[cl][i]]]
+ [aclass][ira_class_hard_regs[cl][i]]]
-= cost;
}
}
@@ -886,10 +900,10 @@ process_bb_node_lives (ira_loop_tree_nod
bb = loop_tree_node->bb;
if (bb != NULL)
{
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- curr_reg_pressure[ira_reg_class_cover[i]] = 0;
- high_pressure_start_point[ira_reg_class_cover[i]] = -1;
+ curr_reg_pressure[ira_pressure_classes[i]] = 0;
+ high_pressure_start_point[ira_pressure_classes[i]] = -1;
}
curr_bb_node = loop_tree_node;
reg_live_out = DF_LR_OUT (bb);
@@ -900,14 +914,17 @@ process_bb_node_lives (ira_loop_tree_nod
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
if (TEST_HARD_REG_BIT (hard_regs_live, i))
{
- enum reg_class cover_class, cl;
+ enum reg_class aclass, pclass, cl;
- cover_class = ira_class_translate[REGNO_REG_CLASS (i)];
+ aclass = ira_allocno_class_translate[REGNO_REG_CLASS (i)];
+ pclass = ira_pressure_class_translate[aclass];
for (j = 0;
- (cl = ira_reg_class_super_classes[cover_class][j])
+ (cl = ira_reg_class_super_classes[pclass][j])
!= LIM_REG_CLASSES;
j++)
{
+ if (! ira_reg_pressure_class_p[cl])
+ continue;
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];
@@ -1121,15 +1138,15 @@ process_bb_node_lives (ira_loop_tree_nod
}
/* Propagate register pressure to upper loop tree nodes: */
if (loop_tree_node != ira_loop_tree_root)
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- enum reg_class cover_class;
+ enum reg_class pclass;
- cover_class = ira_reg_class_cover[i];
- if (loop_tree_node->reg_pressure[cover_class]
- > loop_tree_node->parent->reg_pressure[cover_class])
- loop_tree_node->parent->reg_pressure[cover_class]
- = loop_tree_node->reg_pressure[cover_class];
+ pclass = ira_pressure_classes[i];
+ if (loop_tree_node->reg_pressure[pclass]
+ > loop_tree_node->parent->reg_pressure[pclass])
+ loop_tree_node->parent->reg_pressure[pclass]
+ = loop_tree_node->reg_pressure[pclass];
}
}
Index: ira-emit.c
===================================================================
--- ira-emit.c (revision 161709)
+++ ira-emit.c (working copy)
@@ -289,7 +289,9 @@ entered_from_non_parent_p (ira_loop_tree
edge e;
edge_iterator ei;
- for (bb_node = loop_node->children; bb_node != NULL; bb_node = bb_node->next)
+ for (bb_node = loop_node->children;
+ bb_node != NULL;
+ bb_node = bb_node->next)
if (bb_node->bb != NULL)
{
FOR_EACH_EDGE (e, ei, bb_node->bb->preds)
@@ -444,7 +446,7 @@ change_loop (ira_loop_tree_node_t node)
bool used_p;
ira_allocno_t allocno, parent_allocno, *map;
rtx insn, original_reg;
- enum reg_class cover_class;
+ enum reg_class aclass, pclass;
ira_loop_tree_node_t parent;
if (node != ira_loop_tree_root)
@@ -473,7 +475,8 @@ change_loop (ira_loop_tree_node_t node)
{
allocno = ira_allocnos[i];
regno = ALLOCNO_REGNO (allocno);
- cover_class = ALLOCNO_COVER_CLASS (allocno);
+ aclass = ALLOCNO_CLASS (allocno);
+ pclass = ira_pressure_class_translate[aclass];
parent_allocno = map[regno];
ira_assert (regno < ira_reg_equiv_len);
/* We generate the same hard register move because the
@@ -486,8 +489,8 @@ change_loop (ira_loop_tree_node_t node)
&& (ALLOCNO_HARD_REGNO (allocno)
== ALLOCNO_HARD_REGNO (parent_allocno))
&& (ALLOCNO_HARD_REGNO (allocno) < 0
- || (parent->reg_pressure[cover_class] + 1
- <= ira_available_class_regs[cover_class])
+ || (parent->reg_pressure[pclass] + 1
+ <= ira_available_class_regs[pclass])
|| TEST_HARD_REG_BIT (ira_prohibited_mode_move_regs
[ALLOCNO_MODE (allocno)],
ALLOCNO_HARD_REGNO (allocno))
@@ -724,8 +727,8 @@ modify_move_list (move_t list)
= ira_create_allocno (ALLOCNO_REGNO (set_move->to), false,
ALLOCNO_LOOP_TREE_NODE (set_move->to));
ALLOCNO_MODE (new_allocno) = ALLOCNO_MODE (set_move->to);
- ira_set_allocno_cover_class
- (new_allocno, ALLOCNO_COVER_CLASS (set_move->to));
+ ira_set_allocno_class
+ (new_allocno, ALLOCNO_CLASS (set_move->to));
ALLOCNO_ASSIGNED_P (new_allocno) = true;
ALLOCNO_HARD_REGNO (new_allocno) = -1;
ALLOCNO_REG (new_allocno)
@@ -774,7 +777,7 @@ emit_move_list (move_t list, int freq)
int cost;
rtx result, insn;
enum machine_mode mode;
- enum reg_class cover_class;
+ enum reg_class aclass;
start_sequence ();
for (; list != NULL; list = list->next)
@@ -791,13 +794,13 @@ emit_move_list (move_t list, int freq)
recog_memoized (insn);
emit_insn (list->insn);
mode = ALLOCNO_MODE (list->to);
- cover_class = ALLOCNO_COVER_CLASS (list->to);
+ aclass = ALLOCNO_CLASS (list->to);
cost = 0;
if (ALLOCNO_HARD_REGNO (list->to) < 0)
{
if (ALLOCNO_HARD_REGNO (list->from) >= 0)
{
- cost = ira_memory_move_cost[mode][cover_class][0] * freq;
+ cost = ira_memory_move_cost[mode][aclass][0] * freq;
ira_store_cost += cost;
}
}
@@ -805,13 +808,13 @@ emit_move_list (move_t list, int freq)
{
if (ALLOCNO_HARD_REGNO (list->to) >= 0)
{
- cost = ira_memory_move_cost[mode][cover_class][0] * freq;
+ cost = ira_memory_move_cost[mode][aclass][0] * freq;
ira_load_cost += cost;
}
}
else
{
- cost = (ira_get_register_move_cost (mode, cover_class, cover_class)
+ cost = (ira_get_register_move_cost (mode, aclass, aclass)
* freq);
ira_shuffle_cost += cost;
}
@@ -890,7 +893,7 @@ update_costs (ira_allocno_t a, bool read
ALLOCNO_NREFS (a)++;
ALLOCNO_FREQ (a) += freq;
ALLOCNO_MEMORY_COST (a)
- += (ira_memory_move_cost[ALLOCNO_MODE (a)][ALLOCNO_COVER_CLASS (a)]
+ += (ira_memory_move_cost[ALLOCNO_MODE (a)][ALLOCNO_CLASS (a)]
[read_p ? 1 : 0] * freq);
if (ALLOCNO_CAP (a) != NULL)
a = ALLOCNO_CAP (a);
@@ -944,7 +947,8 @@ add_range_and_copies_from_move_list (mov
IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (to), hard_regs_live);
IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (from),
hard_regs_live);
- IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (to), hard_regs_live);
+ IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (to),
+ hard_regs_live);
update_costs (from, true, freq);
update_costs (to, false, freq);
cp = ira_add_allocno_copy (from, to, freq, false, move->insn, NULL);
Index: ira-build.c
===================================================================
--- ira-build.c (revision 161709)
+++ ira-build.c (working copy)
@@ -410,7 +410,8 @@ initiate_allocnos (void)
= VEC_alloc (ira_allocno_t, heap, max_reg_num () * 2);
ira_conflict_id_allocno_map = NULL;
ira_regno_allocno_map
- = (ira_allocno_t *) ira_allocate (max_reg_num () * sizeof (ira_allocno_t));
+ = (ira_allocno_t *) ira_allocate (max_reg_num ()
+ * sizeof (ira_allocno_t));
memset (ira_regno_allocno_map, 0, max_reg_num () * sizeof (ira_allocno_t));
}
@@ -418,7 +419,8 @@ initiate_allocnos (void)
LOOP_TREE_NODE. Add the allocno to the list of allocnos with the
same regno if CAP_P is FALSE. */
ira_allocno_t
-ira_create_allocno (int regno, bool cap_p, ira_loop_tree_node_t loop_tree_node)
+ira_create_allocno (int regno, bool cap_p,
+ ira_loop_tree_node_t loop_tree_node)
{
ira_allocno_t a;
@@ -461,18 +463,17 @@ ira_create_allocno (int regno, bool cap_
ALLOCNO_IN_GRAPH_P (a) = false;
ALLOCNO_ASSIGNED_P (a) = false;
ALLOCNO_MAY_BE_SPILLED_P (a) = false;
- ALLOCNO_SPLAY_REMOVED_P (a) = false;
ALLOCNO_CONFLICT_VEC_P (a) = false;
+ ALLOCNO_COLORABLE_P (a) = false;
ALLOCNO_MODE (a) = (regno < 0 ? VOIDmode : PSEUDO_REGNO_MODE (regno));
ALLOCNO_COPIES (a) = NULL;
ALLOCNO_HARD_REG_COSTS (a) = NULL;
ALLOCNO_CONFLICT_HARD_REG_COSTS (a) = NULL;
ALLOCNO_UPDATED_HARD_REG_COSTS (a) = NULL;
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) = NULL;
- ALLOCNO_LEFT_CONFLICTS_SIZE (a) = -1;
- ALLOCNO_COVER_CLASS (a) = NO_REGS;
- ALLOCNO_UPDATED_COVER_CLASS_COST (a) = 0;
- ALLOCNO_COVER_CLASS_COST (a) = 0;
+ ALLOCNO_CLASS (a) = NO_REGS;
+ ALLOCNO_UPDATED_CLASS_COST (a) = 0;
+ ALLOCNO_CLASS_COST (a) = 0;
ALLOCNO_MEMORY_COST (a) = 0;
ALLOCNO_UPDATED_MEMORY_COST (a) = 0;
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) = 0;
@@ -484,6 +485,10 @@ ira_create_allocno (int regno, bool cap_
ALLOCNO_MIN (a) = INT_MAX;
ALLOCNO_MAX (a) = -1;
ALLOCNO_CONFLICT_ID (a) = ira_allocnos_num;
+ CLEAR_HARD_REG_SET (ALLOCNO_PROFITABLE_HARD_REGS (a));
+ ALLOCNO_HARD_REGS_NODE (a) = NULL;
+ ALLOCNO_HARD_REGS_SUBNODES_START (a) = 0;
+ ALLOCNO_HARD_REGS_SUBNODES_NUM (a) = 0;
VEC_safe_push (ira_allocno_t, heap, allocno_vec, a);
ira_allocnos = VEC_address (ira_allocno_t, allocno_vec);
ira_allocnos_num = VEC_length (ira_allocno_t, allocno_vec);
@@ -493,15 +498,16 @@ ira_create_allocno (int regno, bool cap_
return a;
}
-/* Set up cover class for A and update its conflict hard registers. */
+/* Set up register class for A and update its conflict hard
+ registers. */
void
-ira_set_allocno_cover_class (ira_allocno_t a, enum reg_class cover_class)
+ira_set_allocno_class (ira_allocno_t a, enum reg_class aclass)
{
- ALLOCNO_COVER_CLASS (a) = cover_class;
+ ALLOCNO_CLASS (a) = aclass;
IOR_COMPL_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a),
- reg_class_contents[cover_class]);
+ reg_class_contents[aclass]);
IOR_COMPL_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a),
- reg_class_contents[cover_class]);
+ reg_class_contents[aclass]);
}
/* Merge hard register conflicts from allocno FROM into allocno TO. If
@@ -777,24 +783,21 @@ create_cap_allocno (ira_allocno_t a)
{
ira_allocno_t cap;
ira_loop_tree_node_t parent;
- enum reg_class cover_class;
+ enum reg_class aclass;
- ira_assert (ALLOCNO_FIRST_COALESCED_ALLOCNO (a) == a
- && ALLOCNO_NEXT_COALESCED_ALLOCNO (a) == a);
parent = ALLOCNO_LOOP_TREE_NODE (a)->parent;
cap = ira_create_allocno (ALLOCNO_REGNO (a), true, parent);
ALLOCNO_MODE (cap) = ALLOCNO_MODE (a);
- cover_class = ALLOCNO_COVER_CLASS (a);
- ira_set_allocno_cover_class (cap, cover_class);
- ALLOCNO_AVAILABLE_REGS_NUM (cap) = ALLOCNO_AVAILABLE_REGS_NUM (a);
+ aclass = ALLOCNO_CLASS (a);
+ ira_set_allocno_class (cap, aclass);
ALLOCNO_CAP_MEMBER (cap) = a;
ALLOCNO_CAP (a) = cap;
- ALLOCNO_COVER_CLASS_COST (cap) = ALLOCNO_COVER_CLASS_COST (a);
+ ALLOCNO_CLASS_COST (cap) = ALLOCNO_CLASS_COST (a);
ALLOCNO_MEMORY_COST (cap) = ALLOCNO_MEMORY_COST (a);
ira_allocate_and_copy_costs
- (&ALLOCNO_HARD_REG_COSTS (cap), cover_class, ALLOCNO_HARD_REG_COSTS (a));
+ (&ALLOCNO_HARD_REG_COSTS (cap), aclass, ALLOCNO_HARD_REG_COSTS (a));
ira_allocate_and_copy_costs
- (&ALLOCNO_CONFLICT_HARD_REG_COSTS (cap), cover_class,
+ (&ALLOCNO_CONFLICT_HARD_REG_COSTS (cap), aclass,
ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
ALLOCNO_BAD_SPILL_P (cap) = ALLOCNO_BAD_SPILL_P (a);
ALLOCNO_NREFS (cap) = ALLOCNO_NREFS (a);
@@ -977,37 +980,49 @@ ira_finish_allocno_live_range_list (live
void
ira_free_allocno_updated_costs (ira_allocno_t a)
{
- enum reg_class cover_class;
+ enum reg_class aclass;
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) != NULL)
- ira_free_cost_vector (ALLOCNO_UPDATED_HARD_REG_COSTS (a), cover_class);
+ ira_free_cost_vector (ALLOCNO_UPDATED_HARD_REG_COSTS (a), aclass);
ALLOCNO_UPDATED_HARD_REG_COSTS (a) = NULL;
if (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) != NULL)
ira_free_cost_vector (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a),
- cover_class);
+ aclass);
ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) = NULL;
}
-/* Free the memory allocated for allocno A. */
+/* Free and nullify all cost vectors allocated earlier for allocno
+ A. */
static void
-finish_allocno (ira_allocno_t a)
+ira_free_allocno_costs (ira_allocno_t a)
{
- enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
+ enum reg_class aclass = ALLOCNO_CLASS (a);
- ira_allocnos[ALLOCNO_NUM (a)] = NULL;
- ira_conflict_id_allocno_map[ALLOCNO_CONFLICT_ID (a)] = NULL;
- if (ALLOCNO_CONFLICT_ALLOCNO_ARRAY (a) != NULL)
- ira_free (ALLOCNO_CONFLICT_ALLOCNO_ARRAY (a));
if (ALLOCNO_HARD_REG_COSTS (a) != NULL)
- ira_free_cost_vector (ALLOCNO_HARD_REG_COSTS (a), cover_class);
+ ira_free_cost_vector (ALLOCNO_HARD_REG_COSTS (a), aclass);
if (ALLOCNO_CONFLICT_HARD_REG_COSTS (a) != NULL)
- ira_free_cost_vector (ALLOCNO_CONFLICT_HARD_REG_COSTS (a), cover_class);
+ ira_free_cost_vector (ALLOCNO_CONFLICT_HARD_REG_COSTS (a), aclass);
if (ALLOCNO_UPDATED_HARD_REG_COSTS (a) != NULL)
- ira_free_cost_vector (ALLOCNO_UPDATED_HARD_REG_COSTS (a), cover_class);
+ ira_free_cost_vector (ALLOCNO_UPDATED_HARD_REG_COSTS (a), aclass);
if (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) != NULL)
ira_free_cost_vector (ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a),
- cover_class);
+ aclass);
+ ALLOCNO_HARD_REG_COSTS (a) = NULL;
+ ALLOCNO_CONFLICT_HARD_REG_COSTS (a) = NULL;
+ ALLOCNO_UPDATED_HARD_REG_COSTS (a) = NULL;
+ ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) = NULL;
+}
+
+/* Free the memory allocated for allocno A. */
+static void
+finish_allocno (ira_allocno_t a)
+{
+ ira_allocnos[ALLOCNO_NUM (a)] = NULL;
+ ira_conflict_id_allocno_map[ALLOCNO_CONFLICT_ID (a)] = NULL;
+ if (ALLOCNO_CONFLICT_ALLOCNO_ARRAY (a) != NULL)
+ ira_free (ALLOCNO_CONFLICT_ALLOCNO_ARRAY (a));
+ ira_free_allocno_costs (a);
ira_finish_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a));
pool_free (allocno_pool, a);
}
@@ -1129,48 +1144,6 @@ ira_add_allocno_copy_to_list (ira_copy_t
ALLOCNO_COPIES (second) = cp;
}
-/* Detach a copy CP from allocnos involved into the copy. */
-void
-ira_remove_allocno_copy_from_list (ira_copy_t cp)
-{
- ira_allocno_t first = cp->first, second = cp->second;
- ira_copy_t prev, next;
-
- next = cp->next_first_allocno_copy;
- prev = cp->prev_first_allocno_copy;
- if (prev == NULL)
- ALLOCNO_COPIES (first) = next;
- else if (prev->first == first)
- prev->next_first_allocno_copy = next;
- else
- prev->next_second_allocno_copy = next;
- if (next != NULL)
- {
- if (next->first == first)
- next->prev_first_allocno_copy = prev;
- else
- next->prev_second_allocno_copy = prev;
- }
- cp->prev_first_allocno_copy = cp->next_first_allocno_copy = NULL;
-
- next = cp->next_second_allocno_copy;
- prev = cp->prev_second_allocno_copy;
- if (prev == NULL)
- ALLOCNO_COPIES (second) = next;
- else if (prev->second == second)
- prev->next_second_allocno_copy = next;
- else
- prev->next_first_allocno_copy = next;
- if (next != NULL)
- {
- if (next->second == second)
- next->prev_second_allocno_copy = prev;
- else
- next->prev_first_allocno_copy = prev;
- }
- cp->prev_second_allocno_copy = cp->next_second_allocno_copy = NULL;
-}
-
/* Make a copy CP a canonical copy where number of the
first allocno is less than the second one. */
void
@@ -1313,55 +1286,54 @@ finish_copies (void)
\f
-/* Pools for cost vectors. It is defined only for cover classes. */
+/* Pools for cost vectors. It is defined only for allocno classes. */
static alloc_pool cost_vector_pool[N_REG_CLASSES];
/* The function initiates work with hard register cost vectors. It
- creates allocation pool for each cover class. */
+ creates allocation pool for each allocno class. */
static void
initiate_cost_vectors (void)
{
int i;
- enum reg_class cover_class;
+ enum reg_class aclass;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_allocno_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- cost_vector_pool[cover_class]
+ aclass = ira_allocno_classes[i];
+ cost_vector_pool[aclass]
= create_alloc_pool ("cost vectors",
- sizeof (int)
- * ira_class_hard_regs_num[cover_class],
+ sizeof (int) * ira_class_hard_regs_num[aclass],
100);
}
}
-/* Allocate and return a cost vector VEC for COVER_CLASS. */
+/* Allocate and return a cost vector VEC for ACLASS. */
int *
-ira_allocate_cost_vector (enum reg_class cover_class)
+ira_allocate_cost_vector (enum reg_class aclass)
{
- return (int *) pool_alloc (cost_vector_pool[cover_class]);
+ return (int *) pool_alloc (cost_vector_pool[aclass]);
}
-/* Free a cost vector VEC for COVER_CLASS. */
+/* Free a cost vector VEC for ACLASS. */
void
-ira_free_cost_vector (int *vec, enum reg_class cover_class)
+ira_free_cost_vector (int *vec, enum reg_class aclass)
{
ira_assert (vec != NULL);
- pool_free (cost_vector_pool[cover_class], vec);
+ pool_free (cost_vector_pool[aclass], vec);
}
/* Finish work with hard register cost vectors. Release allocation
- pool for each cover class. */
+ pool for each allocno class. */
static void
finish_cost_vectors (void)
{
int i;
- enum reg_class cover_class;
+ enum reg_class aclass;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_allocno_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- free_alloc_pool (cost_vector_pool[cover_class]);
+ aclass = ira_allocno_classes[i];
+ free_alloc_pool (cost_vector_pool[aclass]);
}
}
@@ -1592,7 +1564,7 @@ propagate_allocno_info (void)
int i;
ira_allocno_t a, parent_a;
ira_loop_tree_node_t parent;
- enum reg_class cover_class;
+ enum reg_class aclass;
if (flag_ira_region != IRA_REGION_ALL
&& flag_ira_region != IRA_REGION_MIXED)
@@ -1618,17 +1590,17 @@ propagate_allocno_info (void)
+= ALLOCNO_CALLS_CROSSED_NUM (a);
ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a)
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a);
- cover_class = ALLOCNO_COVER_CLASS (a);
- ira_assert (cover_class == ALLOCNO_COVER_CLASS (parent_a));
+ aclass = ALLOCNO_CLASS (a);
+ ira_assert (aclass == ALLOCNO_CLASS (parent_a));
ira_allocate_and_accumulate_costs
- (&ALLOCNO_HARD_REG_COSTS (parent_a), cover_class,
+ (&ALLOCNO_HARD_REG_COSTS (parent_a), aclass,
ALLOCNO_HARD_REG_COSTS (a));
ira_allocate_and_accumulate_costs
(&ALLOCNO_CONFLICT_HARD_REG_COSTS (parent_a),
- cover_class,
+ aclass,
ALLOCNO_CONFLICT_HARD_REG_COSTS (a));
- ALLOCNO_COVER_CLASS_COST (parent_a)
- += ALLOCNO_COVER_CLASS_COST (a);
+ ALLOCNO_CLASS_COST (parent_a)
+ += ALLOCNO_CLASS_COST (a);
ALLOCNO_MEMORY_COST (parent_a) += ALLOCNO_MEMORY_COST (a);
}
}
@@ -1708,16 +1680,16 @@ static bool
low_pressure_loop_node_p (ira_loop_tree_node_t node)
{
int i;
- enum reg_class cover_class;
+ enum reg_class pclass;
if (node->bb != NULL)
return false;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- if (node->reg_pressure[cover_class]
- > ira_available_class_regs[cover_class])
+ pclass = ira_pressure_classes[i];
+ if (node->reg_pressure[pclass] > ira_available_class_regs[pclass]
+ && ira_available_class_regs[pclass] > 1)
return false;
}
return true;
@@ -1933,7 +1905,7 @@ ira_rebuild_regno_allocno_list (int regn
static void
propagate_some_info_from_allocno (ira_allocno_t a, ira_allocno_t from_a)
{
- enum reg_class cover_class;
+ enum reg_class aclass;
merge_hard_reg_conflicts (from_a, a, false);
ALLOCNO_NREFS (a) += ALLOCNO_NREFS (from_a);
@@ -1944,14 +1916,14 @@ propagate_some_info_from_allocno (ira_al
+= ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a);
if (! ALLOCNO_BAD_SPILL_P (from_a))
ALLOCNO_BAD_SPILL_P (a) = false;
- cover_class = ALLOCNO_COVER_CLASS (from_a);
- ira_assert (cover_class == ALLOCNO_COVER_CLASS (a));
- ira_allocate_and_accumulate_costs (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
+ aclass = ALLOCNO_CLASS (from_a);
+ ira_assert (aclass == ALLOCNO_CLASS (a));
+ ira_allocate_and_accumulate_costs (&ALLOCNO_HARD_REG_COSTS (a), aclass,
ALLOCNO_HARD_REG_COSTS (from_a));
ira_allocate_and_accumulate_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
- cover_class,
+ aclass,
ALLOCNO_CONFLICT_HARD_REG_COSTS (from_a));
- ALLOCNO_COVER_CLASS_COST (a) += ALLOCNO_COVER_CLASS_COST (from_a);
+ ALLOCNO_CLASS_COST (a) += ALLOCNO_CLASS_COST (from_a);
ALLOCNO_MEMORY_COST (a) += ALLOCNO_MEMORY_COST (from_a);
}
@@ -2099,8 +2071,8 @@ remove_low_level_allocnos (void)
/* Remove loops from consideration. We remove all loops except for
root if ALL_P or loops for which a separate allocation will not
improve the result. We have to do this after allocno creation and
- their costs and cover class evaluation because only after that the
- register pressure can be known and is calculated. */
+ their costs and allocno class evaluation because only after that
+ the register pressure can be known and is calculated. */
static void
remove_unnecessary_regions (bool all_p)
{
@@ -2147,33 +2119,33 @@ update_bad_spill_attribute (void)
ira_allocno_t a;
ira_allocno_iterator ai;
live_range_t r;
- enum reg_class cover_class;
+ enum reg_class aclass;
bitmap_head dead_points[N_REG_CLASSES];
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_allocno_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- bitmap_initialize (&dead_points[cover_class], ®_obstack);
+ aclass = ira_allocno_classes[i];
+ bitmap_initialize (&dead_points[aclass], ®_obstack);
}
FOR_EACH_ALLOCNO (a, ai)
{
- cover_class = ALLOCNO_COVER_CLASS (a);
- if (cover_class == NO_REGS)
+ aclass = ALLOCNO_CLASS (a);
+ if (aclass == NO_REGS)
continue;
for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
- bitmap_set_bit (&dead_points[cover_class], r->finish);
+ bitmap_set_bit (&dead_points[aclass], r->finish);
}
FOR_EACH_ALLOCNO (a, ai)
{
- cover_class = ALLOCNO_COVER_CLASS (a);
- if (cover_class == NO_REGS)
+ aclass = ALLOCNO_CLASS (a);
+ if (aclass == NO_REGS)
continue;
if (! ALLOCNO_BAD_SPILL_P (a))
continue;
for (r = ALLOCNO_LIVE_RANGES (a); r != NULL; r = r->next)
{
for (i = r->start + 1; i < r->finish; i++)
- if (bitmap_bit_p (&dead_points[cover_class], i))
+ if (bitmap_bit_p (&dead_points[aclass], i))
break;
if (i < r->finish)
break;
@@ -2181,10 +2153,10 @@ update_bad_spill_attribute (void)
if (r != NULL)
ALLOCNO_BAD_SPILL_P (a) = false;
}
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_allocno_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- bitmap_clear (&dead_points[cover_class]);
+ aclass = ira_allocno_classes[i];
+ bitmap_clear (&dead_points[aclass]);
}
}
@@ -2250,10 +2222,10 @@ setup_min_max_allocno_live_range_point (
}
/* Sort allocnos according to their live ranges. Allocnos with
- 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). */
+ smaller allocno 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)
{
@@ -2261,9 +2233,6 @@ allocno_range_compare_func (const void *
ira_allocno_t a1 = *(const ira_allocno_t *) v1p;
ira_allocno_t a2 = *(const ira_allocno_t *) v2p;
- 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;
if ((diff = ALLOCNO_MAX (a1) - ALLOCNO_MAX (a2)) != 0)
@@ -2297,24 +2266,22 @@ sort_conflict_id_allocno_map (void)
static void
setup_min_max_conflict_allocno_ids (void)
{
- int cover_class;
+ int aclass;
int i, j, min, max, start, finish, first_not_finished, filled_area_start;
int *live_range_min, *last_lived;
ira_allocno_t a;
live_range_min = (int *) ira_allocate (sizeof (int) * ira_allocnos_num);
- cover_class = -1;
+ aclass = -1;
first_not_finished = -1;
for (i = 0; i < ira_allocnos_num; i++)
{
a = ira_conflict_id_allocno_map[i];
if (a == NULL)
continue;
- if (cover_class < 0
- || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
- && cover_class != (int) ALLOCNO_COVER_CLASS (a)))
+ if (aclass < 0)
{
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
min = i;
first_not_finished = i;
}
@@ -2339,18 +2306,16 @@ setup_min_max_conflict_allocno_ids (void
ALLOCNO_MIN (a) = min;
}
last_lived = (int *) ira_allocate (sizeof (int) * ira_max_point);
- cover_class = -1;
+ aclass = -1;
filled_area_start = -1;
for (i = ira_allocnos_num - 1; i >= 0; i--)
{
a = ira_conflict_id_allocno_map[i];
if (a == NULL)
continue;
- if (cover_class < 0
- || (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
- && cover_class != (int) ALLOCNO_COVER_CLASS (a)))
+ if (aclass < 0)
{
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
for (j = 0; j < ira_max_point; j++)
last_lived[j] = -1;
filled_area_start = ira_max_point;
@@ -2501,7 +2466,7 @@ ira_flattening (int max_regno_before_emi
int hard_regs_num;
bool new_pseudos_p, merged_p, mem_dest_p;
unsigned int n;
- enum reg_class cover_class;
+ enum reg_class aclass;
ira_allocno_t a, parent_a, first, second, node_first, node_second;
ira_copy_t cp;
ira_loop_tree_node_t node;
@@ -2511,7 +2476,8 @@ ira_flattening (int max_regno_before_emi
sparseset allocnos_live;
regno_top_level_allocno_map
- = (ira_allocno_t *) ira_allocate (max_reg_num () * sizeof (ira_allocno_t));
+ = (ira_allocno_t *) ira_allocate (max_reg_num ()
+ * sizeof (ira_allocno_t));
memset (regno_top_level_allocno_map, 0,
max_reg_num () * sizeof (ira_allocno_t));
new_pseudos_p = merged_p = false;
@@ -2573,8 +2539,8 @@ ira_flattening (int max_regno_before_emi
ira_assert (ALLOCNO_CALLS_CROSSED_NUM (parent_a) >= 0
&& ALLOCNO_NREFS (parent_a) >= 0
&& ALLOCNO_FREQ (parent_a) >= 0);
- cover_class = ALLOCNO_COVER_CLASS (parent_a);
- hard_regs_num = ira_class_hard_regs_num[cover_class];
+ aclass = ALLOCNO_CLASS (parent_a);
+ hard_regs_num = ira_class_hard_regs_num[aclass];
if (ALLOCNO_HARD_REG_COSTS (a) != NULL
&& ALLOCNO_HARD_REG_COSTS (parent_a) != NULL)
for (j = 0; j < hard_regs_num; j++)
@@ -2585,8 +2551,8 @@ ira_flattening (int max_regno_before_emi
for (j = 0; j < hard_regs_num; j++)
ALLOCNO_CONFLICT_HARD_REG_COSTS (parent_a)[j]
-= ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[j];
- ALLOCNO_COVER_CLASS_COST (parent_a)
- -= ALLOCNO_COVER_CLASS_COST (a);
+ ALLOCNO_CLASS_COST (parent_a)
+ -= ALLOCNO_CLASS_COST (a);
ALLOCNO_MEMORY_COST (parent_a) -= ALLOCNO_MEMORY_COST (a);
parent_a = ira_parent_allocno (parent_a);
if (parent_a == NULL)
@@ -2623,14 +2589,14 @@ ira_flattening (int max_regno_before_emi
|| ALLOCNO_CAP_MEMBER (a) != NULL)
continue;
num = ALLOCNO_NUM (a);
- cover_class = ALLOCNO_COVER_CLASS (a);
+ aclass = ALLOCNO_CLASS (a);
sparseset_set_bit (allocnos_live, num);
EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, n)
{
ira_allocno_t live_a = ira_allocnos[n];
if (ira_reg_classes_intersect_p
- [cover_class][ALLOCNO_COVER_CLASS (live_a)]
+ [aclass][ALLOCNO_CLASS (live_a)]
/* Don't set up conflict for the allocno with itself. */
&& num != (int) n)
ira_add_allocno_conflict (a, live_a);
@@ -2709,7 +2675,7 @@ ira_flattening (int max_regno_before_emi
ALLOCNO_CAP (a) = NULL;
/* Restore updated costs for assignments from reload. */
ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a);
- ALLOCNO_UPDATED_COVER_CLASS_COST (a) = ALLOCNO_COVER_CLASS_COST (a);
+ ALLOCNO_UPDATED_CLASS_COST (a) = ALLOCNO_CLASS_COST (a);
if (! ALLOCNO_ASSIGNED_P (a))
ira_free_allocno_updated_costs (a);
ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL);
@@ -2778,29 +2744,28 @@ update_conflict_hard_reg_costs (void)
FOR_EACH_ALLOCNO (a, ai)
{
- enum reg_class cover_class = ALLOCNO_COVER_CLASS (a);
+ enum reg_class aclass = ALLOCNO_CLASS (a);
enum reg_class pref = reg_preferred_class (ALLOCNO_REGNO (a));
if (reg_class_size[pref] != 1)
continue;
- index = (ira_class_hard_reg_index[cover_class]
- [ira_class_hard_regs[pref][0]]);
+ index = ira_class_hard_reg_index[aclass][ira_class_hard_regs[pref][0]];
if (index < 0)
continue;
if (ALLOCNO_CONFLICT_HARD_REG_COSTS (a) == NULL
|| ALLOCNO_HARD_REG_COSTS (a) == NULL)
continue;
min = INT_MAX;
- for (i = ira_class_hard_regs_num[cover_class] - 1; i >= 0; i--)
- if (ALLOCNO_HARD_REG_COSTS (a)[i] > ALLOCNO_COVER_CLASS_COST (a)
+ for (i = ira_class_hard_regs_num[aclass] - 1; i >= 0; i--)
+ if (ALLOCNO_HARD_REG_COSTS (a)[i] > ALLOCNO_CLASS_COST (a)
&& min > ALLOCNO_HARD_REG_COSTS (a)[i])
min = ALLOCNO_HARD_REG_COSTS (a)[i];
if (min == INT_MAX)
continue;
ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
- cover_class, 0);
+ aclass, 0);
ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index]
- -= min - ALLOCNO_COVER_CLASS_COST (a);
+ -= min - ALLOCNO_CLASS_COST (a);
}
}
@@ -2835,7 +2800,7 @@ ira_build (bool loops_p)
propagate_allocno_info ();
create_caps ();
}
- ira_tune_allocno_costs_and_cover_classes ();
+ ira_tune_allocno_costs ();
#ifdef ENABLE_IRA_CHECKING
check_allocno_creation ();
#endif
Index: loop-invariant.c
===================================================================
--- loop-invariant.c (revision 161709)
+++ loop-invariant.c (working copy)
@@ -64,7 +64,7 @@ struct loop_data
struct loop *outermost_exit; /* The outermost exit of the loop. */
bool has_call; /* True if the loop contains a call. */
/* Maximal register pressure inside loop for given register class
- (defined only for the cover classes). */
+ (defined only for the pressure classes). */
int max_reg_pressure[N_REG_CLASSES];
/* Loop regs referenced and live pseudo-registers. */
bitmap_head regs_ref;
@@ -1012,13 +1012,13 @@ free_use_list (struct use *use)
}
}
-/* Return cover class and number of hard registers (through *NREGS)
+/* Return pressure class and number of hard registers (through *NREGS)
for destination of INSN. */
static enum reg_class
-get_cover_class_and_nregs (rtx insn, int *nregs)
+get_pressure_class_and_nregs (rtx insn, int *nregs)
{
rtx reg;
- enum reg_class cover_class;
+ enum reg_class pressure_class;
rtx set = single_set (insn);
/* Considered invariant insns have only one set. */
@@ -1029,19 +1029,23 @@ get_cover_class_and_nregs (rtx insn, int
if (MEM_P (reg))
{
*nregs = 0;
- cover_class = NO_REGS;
+ pressure_class = NO_REGS;
}
else
{
if (! REG_P (reg))
reg = NULL_RTX;
if (reg == NULL_RTX)
- cover_class = GENERAL_REGS;
+ pressure_class = GENERAL_REGS;
else
- cover_class = reg_cover_class (REGNO (reg));
- *nregs = ira_reg_class_nregs[cover_class][GET_MODE (SET_SRC (set))];
+ {
+ pressure_class = reg_allocno_class (REGNO (reg));
+ pressure_class = ira_pressure_class_translate[pressure_class];
+ }
+ *nregs
+ = ira_reg_class_max_nregs[pressure_class][GET_MODE (SET_SRC (set))];
}
- return cover_class;
+ return pressure_class;
}
/* Calculates cost and number of registers needed for moving invariant INV
@@ -1064,8 +1068,8 @@ get_inv_cost (struct invariant *inv, int
regs_needed[0] = 0;
else
{
- for (i = 0; i < ira_reg_class_cover_size; i++)
- regs_needed[ira_reg_class_cover[i]] = 0;
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ regs_needed[ira_pressure_classes[i]] = 0;
}
if (inv->move
@@ -1078,10 +1082,10 @@ get_inv_cost (struct invariant *inv, int
else
{
int nregs;
- enum reg_class cover_class;
+ enum reg_class pressure_class;
- cover_class = get_cover_class_and_nregs (inv->insn, &nregs);
- regs_needed[cover_class] += nregs;
+ pressure_class = get_pressure_class_and_nregs (inv->insn, &nregs);
+ regs_needed[pressure_class] += nregs;
}
if (!inv->cheap_address
@@ -1112,7 +1116,7 @@ get_inv_cost (struct invariant *inv, int
&& constant_pool_constant_p (SET_SRC (set)))
{
if (flag_ira_loop_pressure)
- regs_needed[STACK_REG_COVER_CLASS] += 2;
+ regs_needed[ira_stack_reg_pressure_class] += 2;
else
regs_needed[0] += 2;
}
@@ -1131,10 +1135,10 @@ get_inv_cost (struct invariant *inv, int
check_p = aregs_needed[0] != 0;
else
{
- for (i = 0; i < ira_reg_class_cover_size; i++)
- if (aregs_needed[ira_reg_class_cover[i]] != 0)
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ if (aregs_needed[ira_pressure_classes[i]] != 0)
break;
- check_p = i < ira_reg_class_cover_size;
+ check_p = i < ira_pressure_classes_num;
}
if (check_p
/* We need to check always_executed, since if the original value of
@@ -1151,10 +1155,10 @@ get_inv_cost (struct invariant *inv, int
else
{
int nregs;
- enum reg_class cover_class;
+ enum reg_class pressure_class;
- cover_class = get_cover_class_and_nregs (inv->insn, &nregs);
- aregs_needed[cover_class] -= nregs;
+ pressure_class = get_pressure_class_and_nregs (inv->insn, &nregs);
+ aregs_needed[pressure_class] -= nregs;
}
}
@@ -1162,9 +1166,9 @@ get_inv_cost (struct invariant *inv, int
regs_needed[0] += aregs_needed[0];
else
{
- for (i = 0; i < ira_reg_class_cover_size; i++)
- regs_needed[ira_reg_class_cover[i]]
- += aregs_needed[ira_reg_class_cover[i]];
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ regs_needed[ira_pressure_classes[i]]
+ += aregs_needed[ira_pressure_classes[i]];
}
(*comp_cost) += acomp_cost;
}
@@ -1195,19 +1199,19 @@ gain_for_invariant (struct invariant *in
else
{
int i;
- enum reg_class cover_class;
+ enum reg_class pressure_class;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- if ((int) new_regs[cover_class]
- + (int) regs_needed[cover_class]
- + LOOP_DATA (curr_loop)->max_reg_pressure[cover_class]
+ pressure_class = ira_pressure_classes[i];
+ if ((int) new_regs[pressure_class]
+ + (int) regs_needed[pressure_class]
+ + LOOP_DATA (curr_loop)->max_reg_pressure[pressure_class]
+ IRA_LOOP_RESERVED_REGS
- > ira_available_class_regs[cover_class])
+ > ira_available_class_regs[pressure_class])
break;
}
- if (i < ira_reg_class_cover_size)
+ if (i < ira_pressure_classes_num)
/* There will be register pressure excess and we want not to
make this loop invariant motion. All loop invariants with
non-positive gains will be rejected in function
@@ -1270,9 +1274,9 @@ best_gain_for_invariant (struct invarian
regs_needed[0] = aregs_needed[0];
else
{
- for (i = 0; i < ira_reg_class_cover_size; i++)
- regs_needed[ira_reg_class_cover[i]]
- = aregs_needed[ira_reg_class_cover[i]];
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ regs_needed[ira_pressure_classes[i]]
+ = aregs_needed[ira_pressure_classes[i]];
}
}
}
@@ -1349,8 +1353,8 @@ find_invariants_to_move (bool speed)
new_regs[0] = regs_needed[0] = 0;
else
{
- for (i = 0; (int) i < ira_reg_class_cover_size; i++)
- new_regs[ira_reg_class_cover[i]] = 0;
+ for (i = 0; (int) i < ira_pressure_classes_num; i++)
+ new_regs[ira_pressure_classes[i]] = 0;
}
while ((gain = best_gain_for_invariant (&inv, regs_needed,
new_regs, regs_used, speed)) > 0)
@@ -1360,9 +1364,9 @@ find_invariants_to_move (bool speed)
new_regs[0] += regs_needed[0];
else
{
- for (i = 0; (int) i < ira_reg_class_cover_size; i++)
- new_regs[ira_reg_class_cover[i]]
- += regs_needed[ira_reg_class_cover[i]];
+ for (i = 0; (int) i < ira_pressure_classes_num; i++)
+ new_regs[ira_pressure_classes[i]]
+ += regs_needed[ira_pressure_classes[i]];
}
}
}
@@ -1515,7 +1519,7 @@ move_invariants (struct loop *loop)
setup_reg_classes (REGNO (inv->reg),
reg_preferred_class (inv->orig_regno),
reg_alternate_class (inv->orig_regno),
- reg_cover_class (inv->orig_regno));
+ reg_allocno_class (inv->orig_regno));
else
setup_reg_classes (REGNO (inv->reg),
GENERAL_REGS, NO_REGS, GENERAL_REGS);
@@ -1599,7 +1603,7 @@ free_loop_data (struct loop *loop)
/* Registers currently living. */
static bitmap_head curr_regs_live;
-/* Current reg pressure for each cover class. */
+/* Current reg pressure for each pressure class. */
static int curr_reg_pressure[N_REG_CLASSES];
/* Record all regs that are set in any one insn. Communication from
@@ -1610,23 +1614,26 @@ static rtx regs_set[(FIRST_PSEUDO_REGIST
/* Number of regs stored in the previous array. */
static int n_regs_set;
-/* Return cover class and number of needed hard registers (through
+/* Return pressure class and number of needed hard registers (through
*NREGS) of register REGNO. */
static enum reg_class
-get_regno_cover_class (int regno, int *nregs)
+get_regno_pressure_class (int regno, int *nregs)
{
if (regno >= FIRST_PSEUDO_REGISTER)
{
- enum reg_class cover_class = reg_cover_class (regno);
+ enum reg_class pressure_class;
- *nregs = ira_reg_class_nregs[cover_class][PSEUDO_REGNO_MODE (regno)];
- return cover_class;
+ pressure_class = reg_allocno_class (regno);
+ pressure_class = ira_pressure_class_translate[pressure_class];
+ *nregs
+ = ira_reg_class_max_nregs[pressure_class][PSEUDO_REGNO_MODE (regno)];
+ return pressure_class;
}
else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)
&& ! TEST_HARD_REG_BIT (eliminable_regset, regno))
{
*nregs = 1;
- return ira_class_translate[REGNO_REG_CLASS (regno)];
+ return ira_pressure_class_translate[REGNO_REG_CLASS (regno)];
}
else
{
@@ -1641,18 +1648,18 @@ static void
change_pressure (int regno, bool incr_p)
{
int nregs;
- enum reg_class cover_class;
+ enum reg_class pressure_class;
- cover_class = get_regno_cover_class (regno, &nregs);
+ pressure_class = get_regno_pressure_class (regno, &nregs);
if (! incr_p)
- curr_reg_pressure[cover_class] -= nregs;
+ curr_reg_pressure[pressure_class] -= nregs;
else
{
- curr_reg_pressure[cover_class] += nregs;
- if (LOOP_DATA (curr_loop)->max_reg_pressure[cover_class]
- < curr_reg_pressure[cover_class])
- LOOP_DATA (curr_loop)->max_reg_pressure[cover_class]
- = curr_reg_pressure[cover_class];
+ curr_reg_pressure[pressure_class] += nregs;
+ if (LOOP_DATA (curr_loop)->max_reg_pressure[pressure_class]
+ < curr_reg_pressure[pressure_class])
+ LOOP_DATA (curr_loop)->max_reg_pressure[pressure_class]
+ = curr_reg_pressure[pressure_class];
}
}
@@ -1810,8 +1817,8 @@ calculate_loop_reg_pressure (void)
bitmap_ior_into (&LOOP_DATA (loop)->regs_live, DF_LR_IN (bb));
bitmap_copy (&curr_regs_live, DF_LR_IN (bb));
- for (i = 0; i < ira_reg_class_cover_size; i++)
- curr_reg_pressure[ira_reg_class_cover[i]] = 0;
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ curr_reg_pressure[ira_pressure_classes[i]] = 0;
EXECUTE_IF_SET_IN_BITMAP (&curr_regs_live, 0, j, bi)
change_pressure (j, true);
@@ -1861,11 +1868,11 @@ calculate_loop_reg_pressure (void)
EXECUTE_IF_SET_IN_BITMAP (&LOOP_DATA (loop)->regs_live, 0, j, bi)
if (! bitmap_bit_p (&LOOP_DATA (loop)->regs_ref, j))
{
- enum reg_class cover_class;
+ enum reg_class pressure_class;
int nregs;
- cover_class = get_regno_cover_class (j, &nregs);
- LOOP_DATA (loop)->max_reg_pressure[cover_class] -= nregs;
+ pressure_class = get_regno_pressure_class (j, &nregs);
+ LOOP_DATA (loop)->max_reg_pressure[pressure_class] -= nregs;
}
}
if (dump_file == NULL)
@@ -1883,15 +1890,15 @@ calculate_loop_reg_pressure (void)
EXECUTE_IF_SET_IN_BITMAP (&LOOP_DATA (loop)->regs_live, 0, j, bi)
fprintf (dump_file, " %d", j);
fprintf (dump_file, "\n Pressure:");
- for (i = 0; (int) i < ira_reg_class_cover_size; i++)
+ for (i = 0; (int) i < ira_pressure_classes_num; i++)
{
- enum reg_class cover_class;
+ enum reg_class pressure_class;
- cover_class = ira_reg_class_cover[i];
- if (LOOP_DATA (loop)->max_reg_pressure[cover_class] == 0)
+ pressure_class = ira_pressure_classes[i];
+ if (LOOP_DATA (loop)->max_reg_pressure[pressure_class] == 0)
continue;
- fprintf (dump_file, " %s=%d", reg_class_names[cover_class],
- LOOP_DATA (loop)->max_reg_pressure[cover_class]);
+ fprintf (dump_file, " %s=%d", reg_class_names[pressure_class],
+ LOOP_DATA (loop)->max_reg_pressure[pressure_class]);
}
fprintf (dump_file, "\n");
}
Index: common.opt
===================================================================
--- common.opt (revision 161709)
+++ common.opt (working copy)
@@ -747,10 +747,6 @@ fira-region=
Common Joined RejectNegative
-fira-region=[one|all|mixed] Set regions for IRA
-fira-coalesce
-Common Report Var(flag_ira_coalesce) Init(0)
-Do optimistic coalescing.
-
fira-loop-pressure
Common Report Var(flag_ira_loop_pressure)
Use IRA based register pressure calculation
Index: ira.c
===================================================================
--- ira.c (revision 161709)
+++ ira.c (working copy)
@@ -38,40 +38,51 @@ along with GCC; see the file COPYING3.
the other regions. Therefore data structure representing a
region is called loop_tree_node.
- o *Cover class* is a register class belonging to a set of
- non-intersecting register classes containing all of the
- hard-registers available for register allocation. The set of
- all cover classes for a target is defined in the corresponding
- machine-description file according some criteria. Such notion
- is needed because Chaitin-Briggs algorithm works on
- non-intersected register classes.
+ o *Allocno class* is a register class used for allocation of
+ given allocno. It means that only hard register of given
+ register class can be assigned to given allocno. In reality,
+ even smaller subset of (*profitable*) hard registers can be
+ assigned. In rare cases, the subset can be even smaller
+ because our modification of Chaitin-Briggs algorithm requires
+ that sets of hard registers can be assigned to allocnos forms a
+ forest, i.e. the sets can be ordered in a way where any
+ previous set is not intersected with given set or is a superset
+ of given set.
+
+ o *Pressure class* is a register class belonging to a set of
+ register classes containing all of the hard-registers available
+ for register allocation. The set of all pressure classes for a
+ target is defined in the corresponding machine-description file
+ according some criteria. Register pressure is calculated only
+ for pressure classes and it affects some IRA decisions as
+ forming allocation regions.
o *Allocno* represents the live range of a pseudo-register in a
region. Besides the obvious attributes like the corresponding
- pseudo-register number, cover class, conflicting allocnos and
+ pseudo-register number, allocno class, conflicting allocnos and
conflicting hard-registers, there are a few allocno attributes
which are important for understanding the allocation algorithm:
- - *Live ranges*. This is a list of ranges of *program
- points* where the allocno lives. Program points represent
- places where a pseudo can be born or become dead (there are
+ - *Live ranges*. This is a list of ranges of *program points*
+ where the allocno lives. Program points represent places
+ where a pseudo can be born or become dead (there are
approximately two times more program points than the insns)
and they are represented by integers starting with 0. The
- live ranges are used to find conflicts between allocnos of
- different cover classes. They also play very important role
- for the transformation of the IRA internal representation of
- several regions into a one region representation. The later is
- used during the reload pass work because each allocno
- represents all of the corresponding pseudo-registers.
+ live ranges are used to find conflicts between allocnos.
+ They also play very important role for the transformation of
+ the IRA internal representation of several regions into a one
+ region representation. The later is used during the reload
+ pass work because each allocno represents all of the
+ corresponding pseudo-registers.
- *Hard-register costs*. This is a vector of size equal to the
- number of available hard-registers of the allocno's cover
- class. The cost of a callee-clobbered hard-register for an
- allocno is increased by the cost of save/restore code around
- the calls through the given allocno's life. If the allocno
- is a move instruction operand and another operand is a
- hard-register of the allocno's cover class, the cost of the
- hard-register is decreased by the move cost.
+ number of available hard-registers of the allocno class. The
+ cost of a callee-clobbered hard-register for an allocno is
+ increased by the cost of save/restore code around the calls
+ through the given allocno's life. If the allocno is a move
+ instruction operand and another operand is a hard-register of
+ the allocno class, the cost of the hard-register is decreased
+ by the move cost.
When an allocno is assigned, the hard-register with minimal
full cost is used. Initially, a hard-register's full cost is
@@ -139,12 +150,12 @@ along with GCC; see the file COPYING3.
* First, IRA builds regions and creates allocnos (file
ira-build.c) and initializes most of their attributes.
- * Then IRA finds a cover class for each allocno and calculates
- its initial (non-accumulated) cost of memory and each
- hard-register of its cover class (file ira-cost.c).
+ * Then IRA finds an allocno class for each allocno and
+ calculates its initial (non-accumulated) cost of memory and
+ each hard-register of its allocno class (file ira-cost.c).
* IRA creates live ranges of each allocno, calulates register
- pressure for each cover class in each region, sets up
+ pressure for each pressure class in each region, sets up
conflict hard registers for each allocno and info about calls
the allocno lives through (file ira-lives.c).
@@ -157,17 +168,25 @@ along with GCC; see the file COPYING3.
* IRA creates all caps (file ira-build.c).
- * Having live-ranges of allocnos and their cover classes, IRA
- creates conflicting allocnos of the same cover class for each
- allocno. Conflicting allocnos are stored as a bit vector or
- array of pointers to the conflicting allocnos whatever is
- more profitable (file ira-conflicts.c). At this point IRA
- creates allocno copies.
+ * Having live-ranges of allocnos and their classes, IRA creates
+ conflicting allocnos for each allocno. Conflicting allocnos
+ are stored as a bit vector or array of pointers to the
+ conflicting allocnos whatever is more profitable (file
+ ira-conflicts.c). At this point IRA creates allocno copies.
o Coloring. Now IRA has all necessary info to start graph coloring
process. It is done in each region on top-down traverse of the
region tree (file ira-color.c). There are following subpasses:
+ * Finding profitable hard registers of corresponding allocno
+ class for each allocno. For example, only callee-saved hard
+ registers are frequently profitable for allocnos living
+ through colors. If the profitable hard register set of
+ allocno does not form a tree based on subset relation, we use
+ some approximation to form the tree. This approximation is
+ used to figure out trivial colorability of allocnos. The
+ approximation is a pretty rare case.
+
* Optional aggressive coalescing of allocnos in the region.
* Putting allocnos onto the coloring stack. IRA uses Briggs
@@ -175,7 +194,18 @@ along with GCC; see the file COPYING3.
Chaitin's coloring. Therefore IRA does not spill allocnos at
this point. There is some freedom in the order of putting
allocnos on the stack which can affect the final result of
- the allocation. IRA uses some heuristics to improve the order.
+ the allocation. IRA uses some heuristics to improve the
+ order. We also use a modification of Chaitin-Briggs
+ algorithm which works for intersected register classes of
+ allocnos. To figure out trivial colorability of allocnos,
+ the mentioned above tree of hard register sets is used. To
+ get an idea how the algorithm works in i386 example, let us
+ consider an allocno to which any general hard register can be
+ assigned. If the allocno conflicts with eight allocnos to
+ which only EAX register can be assigned, given allocno is
+ still trivially colorable because all conflicting allocnos
+ might be assigned only to EAX and all other general hard
+ registers are still free.
* Popping the allocnos from the stack and assigning them hard
registers. If IRA can not assign a hard register to an
@@ -196,8 +226,8 @@ along with GCC; see the file COPYING3.
When default regional allocation algorithm is used
(-fira-algorithm=mixed), IRA just propagates the assignment
for allocnos if the register pressure in the region for the
- corresponding cover class is less than number of available
- hard registers for given cover class.
+ corresponding pressure class is less than number of available
+ hard registers for given pressure class.
o Spill/restore code moving. When IRA performs an allocation
by traversing regions in top-down order, it does not know what
@@ -212,28 +242,29 @@ along with GCC; see the file COPYING3.
practice, so there is no real need for a better time complexity
algorithm.
- o Code change. After coloring, two allocnos representing the same
- pseudo-register outside and inside a region respectively may be
- assigned to different locations (hard-registers or memory). In
- this case IRA creates and uses a new pseudo-register inside the
- region and adds code to move allocno values on the region's
- borders. This is done during top-down traversal of the regions
- (file ira-emit.c). In some complicated cases IRA can create a
- new allocno to move allocno values (e.g. when a swap of values
- stored in two hard-registers is needed). At this stage, the
- new allocno is marked as spilled. IRA still creates the
- pseudo-register and the moves on the region borders even when
- both allocnos were assigned to the same hard-register. If the
- reload pass spills a pseudo-register for some reason, the
- effect will be smaller because another allocno will still be in
- the hard-register. In most cases, this is better then spilling
- both allocnos. If reload does not change the allocation
- for the two pseudo-registers, the trivial move will be removed
- by post-reload optimizations. IRA does not generate moves for
+ o Code change. After coloring, two allocnos representing the
+ same pseudo-register outside and inside a region respectively
+ may be assigned to different locations (hard-registers or
+ memory). In this case IRA creates and uses a new
+ pseudo-register inside the region and adds code to move allocno
+ values on the region's borders. This is done during top-down
+ traversal of the regions (file ira-emit.c). In some
+ complicated cases IRA can create a new allocno to move allocno
+ values (e.g. when a swap of values stored in two hard-registers
+ is needed). At this stage, the new allocno is marked as
+ spilled. IRA still creates the pseudo-register and the moves
+ on the region borders even when both allocnos were assigned to
+ the same hard-register. If the reload pass spills a
+ pseudo-register for some reason, the effect will be smaller
+ because another allocno will still be in the hard-register. In
+ most cases, this is better then spilling both allocnos. If
+ reload does not change the allocation for the two
+ pseudo-registers, the trivial move will be removed by
+ post-reload optimizations. IRA does not generate moves for
allocnos assigned to the same hard register when the default
regional allocation algorithm is used and the register pressure
- in the region for the corresponding allocno cover class is less
- than number of available hard registers for given cover class.
+ in the region for the corresponding pressure class is less than
+ number of available hard registers for given pressure class.
IRA also does some optimizations to remove redundant stores and
to reduce code duplication on the region borders.
@@ -353,7 +384,8 @@ HARD_REG_SET eliminable_regset;
/* Map: hard regs X modes -> set of hard registers for storing value
of given mode starting with given hard register. */
-HARD_REG_SET ira_reg_mode_hard_regset[FIRST_PSEUDO_REGISTER][NUM_MACHINE_MODES];
+HARD_REG_SET
+ ira_reg_mode_hard_regset[FIRST_PSEUDO_REGISTER][NUM_MACHINE_MODES];
/* Array analogous to target hook TARGET_MEMORY_MOVE_COST. */
short int ira_memory_move_cost[MAX_MACHINE_MODE][N_REG_CLASSES][2];
@@ -361,6 +393,12 @@ short int ira_memory_move_cost[MAX_MACHI
/* Array based on TARGET_REGISTER_MOVE_COST. */
move_table *ira_register_move_cost[MAX_MACHINE_MODE];
+/* The following two variables are array analogs of the macros
+ MEMORY_MOVE_COST and REGISTER_MOVE_COST but they contain maximumal
+ cost not minimumal as the previous two ones do. */
+static short int ira_max_memory_move_cost[MAX_MACHINE_MODE][N_REG_CLASSES][2];
+static move_table *ira_max_register_move_cost[MAX_MACHINE_MODE];
+
/* Similar to may_move_in_cost but it is calculated in IRA instead of
regclass. Another difference is that we take only available hard
registers into account to figure out that one register class is a
@@ -373,6 +411,11 @@ move_table *ira_may_move_in_cost[MAX_MAC
subset of the another one. */
move_table *ira_may_move_out_cost[MAX_MACHINE_MODE];
+/* Similar to ira_may_move_in_cost and ira_may_move_out_cost but they
+ return maximal cost. */
+static move_table *ira_max_may_move_in_cost[MAX_MACHINE_MODE];
+static move_table *ira_max_may_move_out_cost[MAX_MACHINE_MODE];
+
/* Register class subset relation: TRUE if the first class is a subset
of the second one considering only hard registers available for the
allocation. */
@@ -416,7 +459,7 @@ short ira_class_hard_regs[N_REG_CLASSES]
the hard register numbers. */
short ira_non_ordered_class_hard_regs[N_REG_CLASSES][FIRST_PSEUDO_REGISTER];
-/* The number of elements of the above array for given register
+/* The number of elements of the two above arrays for given register
class. */
int ira_class_hard_regs_num[N_REG_CLASSES];
@@ -509,11 +552,56 @@ setup_alloc_regs (bool use_hard_frame_p)
\f
-/* Set up IRA_MEMORY_MOVE_COST, IRA_REGISTER_MOVE_COST. */
+/* For each reg class, table listing all the classes contained in it
+ (excluding the class itself. Non-allocatable registers are
+ excluded from the consideration). */
+static enum reg_class
+ alloc_reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES];
+
+/* Initialize the table of subclasses of each reg class. */
+static void
+setup_reg_subclasses (void)
+{
+ int i, j;
+ HARD_REG_SET temp_hard_regset2;
+
+ for (i = 0; i < N_REG_CLASSES; i++)
+ for (j = 0; j < N_REG_CLASSES; j++)
+ alloc_reg_class_subclasses[i][j] = LIM_REG_CLASSES;
+
+ for (i = 0; i < N_REG_CLASSES; i++)
+ {
+ if (i == (int) NO_REGS)
+ continue;
+
+ COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[i]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+ if (hard_reg_set_empty_p (temp_hard_regset))
+ continue;
+ for (j = 0; j < N_REG_CLASSES; j++)
+ if (i != j)
+ {
+ enum reg_class *p;
+
+ 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_subset_p (temp_hard_regset,
+ temp_hard_regset2))
+ continue;
+ p = &alloc_reg_class_subclasses[j][0];
+ while (*p != LIM_REG_CLASSES) p++;
+ *p = (enum reg_class) i;
+ }
+ }
+}
+
+\f
+
+/* Set up IRA_MEMORY_MOVE_COST and IRA_MAX_MEMORY_MOVE_COST. */
static void
setup_class_subset_and_memory_move_costs (void)
{
- int cl, cl2, mode;
+ int cl, cl2, mode, cost;
HARD_REG_SET temp_hard_regset2;
for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
@@ -524,34 +612,60 @@ setup_class_subset_and_memory_move_costs
if (cl != (int) NO_REGS)
for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
{
- ira_memory_move_cost[mode][cl][0] =
- memory_move_cost ((enum machine_mode) mode,
- (enum reg_class) cl, false);
- ira_memory_move_cost[mode][cl][1] =
- memory_move_cost ((enum machine_mode) mode,
- (enum reg_class) cl, true);
+ ira_max_memory_move_cost[mode][cl][0]
+ = ira_memory_move_cost[mode][cl][0]
+ = memory_move_cost ((enum machine_mode) mode,
+ (enum reg_class) cl, false);
+ ira_max_memory_move_cost[mode][cl][1]
+ = ira_memory_move_cost[mode][cl][1]
+ = memory_move_cost ((enum machine_mode) mode,
+ (enum reg_class) cl, true);
/* Costs for NO_REGS are used in cost calculation on the
1st pass when the preferred register classes are not
known yet. In this case we take the best scenario. */
if (ira_memory_move_cost[mode][NO_REGS][0]
> ira_memory_move_cost[mode][cl][0])
- ira_memory_move_cost[mode][NO_REGS][0]
+ ira_max_memory_move_cost[mode][NO_REGS][0]
+ = ira_memory_move_cost[mode][NO_REGS][0]
= ira_memory_move_cost[mode][cl][0];
if (ira_memory_move_cost[mode][NO_REGS][1]
> ira_memory_move_cost[mode][cl][1])
- ira_memory_move_cost[mode][NO_REGS][1]
+ ira_max_memory_move_cost[mode][NO_REGS][1]
+ = ira_memory_move_cost[mode][NO_REGS][1]
= ira_memory_move_cost[mode][cl][1];
}
- for (cl2 = (int) N_REG_CLASSES - 1; cl2 >= 0; cl2--)
- {
- 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[cl2]);
- AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
- ira_class_subset_p[cl][cl2]
- = hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2);
- }
}
+ for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--)
+ for (cl2 = (int) N_REG_CLASSES - 1; cl2 >= 0; cl2--)
+ {
+ 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[cl2]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+ ira_class_subset_p[cl][cl2]
+ = hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2);
+ if (! hard_reg_set_empty_p (temp_hard_regset2)
+ && hard_reg_set_subset_p (reg_class_contents[cl2],
+ reg_class_contents[cl]))
+ for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
+ {
+ cost = ira_memory_move_cost[mode][cl2][0];
+ if (cost > ira_max_memory_move_cost[mode][cl][0])
+ ira_max_memory_move_cost[mode][cl][0] = cost;
+ cost = ira_memory_move_cost[mode][cl2][1];
+ if (cost > ira_max_memory_move_cost[mode][cl][1])
+ ira_max_memory_move_cost[mode][cl][1] = cost;
+ }
+ }
+ for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--)
+ for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
+ {
+ ira_memory_move_cost[mode][cl][0]
+ = ira_max_memory_move_cost[mode][cl][0];
+ ira_memory_move_cost[mode][cl][1]
+ = ira_max_memory_move_cost[mode][cl][1];
+ }
+ setup_reg_subclasses ();
}
\f
@@ -667,65 +781,42 @@ ira_debug_disposition (void)
\f
-/* For each reg class, table listing all the classes contained in it
- (excluding the class itself. Non-allocatable registers are
- excluded from the consideration). */
-static enum reg_class alloc_reg_class_subclasses[N_REG_CLASSES][N_REG_CLASSES];
-
-/* Initialize the table of subclasses of each reg class. */
-static void
-setup_reg_subclasses (void)
-{
- int i, j;
- HARD_REG_SET temp_hard_regset2;
+/* Number of allocno classes. Allocno classes are register classes
+ which can be used for allocations of allocnos. */
+int ira_allocno_classes_num;
+
+/* The array containing allocno classes. Only first
+ IRA_ALLOCNO_CLASSES_NUM elements are used for this. */
+enum reg_class ira_allocno_classes[N_REG_CLASSES];
+
+/* Map class->true if class is a possible allocno class, false
+ otherwise. */
+bool ira_reg_allocno_class_p[N_REG_CLASSES];
+
+/* Number of pressure classes. Pressure classes are register classes
+ for which we calculate register pressure. */
+int ira_pressure_classes_num;
+
+/* The array containing pressure classes. Only first
+ IRA_PRESSURE_CLASSES_NUM elements are used for this. */
+enum reg_class ira_pressure_classes[N_REG_CLASSES];
+
+/* Map of all register classes to corresponding pressure classes
+ containing the given class. If given class is not a subset of an
+ pressure class, we translate it into the cheapest pressure class. */
+enum reg_class ira_pressure_class_translate[N_REG_CLASSES];
+
+/* Bigest pressure register class containing stack registers. NO_REGS
+ if there are no stack registers. */
+enum reg_class ira_stack_reg_pressure_class;
- for (i = 0; i < N_REG_CLASSES; i++)
- for (j = 0; j < N_REG_CLASSES; j++)
- alloc_reg_class_subclasses[i][j] = LIM_REG_CLASSES;
-
- for (i = 0; i < N_REG_CLASSES; i++)
- {
- if (i == (int) NO_REGS)
- continue;
-
- COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[i]);
- AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
- if (hard_reg_set_empty_p (temp_hard_regset))
- continue;
- for (j = 0; j < N_REG_CLASSES; j++)
- if (i != j)
- {
- enum reg_class *p;
-
- 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_subset_p (temp_hard_regset,
- temp_hard_regset2))
- continue;
- p = &alloc_reg_class_subclasses[j][0];
- while (*p != LIM_REG_CLASSES) p++;
- *p = (enum reg_class) i;
- }
- }
-}
-
-\f
-
-/* Number of cover classes. Cover classes is non-intersected register
- classes containing all hard-registers available for the
- allocation. */
-int ira_reg_class_cover_size;
-
-/* The array containing cover classes (see also comments for macro
- IRA_COVER_CLASSES). Only first IRA_REG_CLASS_COVER_SIZE elements are
- used for this. */
-enum reg_class ira_reg_class_cover[N_REG_CLASSES];
+/* Map class->true if class is a pressure class, false otherwise. */
+bool ira_reg_pressure_class_p[N_REG_CLASSES];
/* The number of elements in the subsequent array. */
int ira_important_classes_num;
-/* The array containing non-empty classes (including non-empty cover
- classes) which are subclasses of cover classes. Such classes is
+/* The array containing all non-empty classes. Such classes is
important for calculation of the hard register usage costs. */
enum reg_class ira_important_classes[N_REG_CLASSES];
@@ -734,76 +825,167 @@ enum reg_class ira_important_classes[N_R
classes. */
int ira_important_class_nums[N_REG_CLASSES];
-/* Set the four global variables defined above. */
+/* Set up ira_stack_reg_pressure_class. */
static void
-setup_cover_and_important_classes (void)
+setup_stack_reg_pressure_class (void)
{
- int i, j, n, cl;
- bool set_p;
- const reg_class_t *cover_classes;
- HARD_REG_SET temp_hard_regset2;
- static enum reg_class classes[LIM_REG_CLASSES + 1];
+ ira_stack_reg_pressure_class = NO_REGS;
+#ifdef STACK_REGS
+ {
+ int i, best, size;
+ enum reg_class cl;
+ HARD_REG_SET temp_hard_regset2;
+
+ CLEAR_HARD_REG_SET (temp_hard_regset);
+ for (i = FIRST_STACK_REG; i <= LAST_STACK_REG; i++)
+ SET_HARD_REG_BIT (temp_hard_regset, i);
+ best = 0;
+ for (i = 0; i < ira_pressure_classes_num; i++)
+ {
+ cl = ira_pressure_classes[i];
+ COPY_HARD_REG_SET (temp_hard_regset2, temp_hard_regset);
+ AND_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
+ size = hard_reg_set_size (temp_hard_regset2);
+ if (best < size)
+ {
+ best = size;
+ ira_stack_reg_pressure_class = cl;
+ }
+ }
+ }
+#endif
+}
- 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] = (enum reg_class) cl;
- classes[i] = LIM_REG_CLASSES;
- }
+/* Find pressure classes. */
+static void
+setup_pressure_classes (void)
+{
+ int cost, i, n, curr;
+ int cl, cl2;
+ enum reg_class pressure_classes[N_REG_CLASSES];
+ int m;
+ HARD_REG_SET temp_hard_regset2;
+ bool insert_p;
- if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
+ n = 0;
+ for (cl = 0; cl < N_REG_CLASSES; cl++)
{
- n = 0;
- for (i = 0; i <= LIM_REG_CLASSES; i++)
+ if (ira_available_class_regs[cl] == 0)
+ continue;
+ for (m = 0; m < NUM_MACHINE_MODES; m++)
{
- if (i == NO_REGS)
+ COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset,
+ ira_prohibited_class_mode_regs[cl][m]);
+ if (hard_reg_set_empty_p (temp_hard_regset))
continue;
-#ifdef CONSTRAINT_NUM_DEFINED_P
- for (j = 0; j < CONSTRAINT__LIMIT; j++)
- if ((int) REG_CLASS_FOR_CONSTRAINT ((enum constraint_num) j) == i)
- break;
- if (j < CONSTRAINT__LIMIT)
+ cost = ira_get_register_move_cost ((enum machine_mode) m,
+ (enum reg_class) cl,
+ (enum reg_class) cl);
+ if (cost <= ira_max_memory_move_cost[m][cl][1]
+ || cost <= ira_max_memory_move_cost[m][cl][0])
+ break;
+ }
+ if (m >= NUM_MACHINE_MODES)
+ continue;
+ curr = 0;
+ insert_p = true;
+ 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 < n; i++)
+ {
+ cl2 = pressure_classes[i];
+ COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl2]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+ if (hard_reg_set_subset_p (temp_hard_regset, temp_hard_regset2)
+ && (! hard_reg_set_equal_p (temp_hard_regset, temp_hard_regset2)
+ || cl2 == (int) GENERAL_REGS))
{
- classes[n++] = (enum reg_class) i;
+ pressure_classes[curr++] = (enum reg_class) cl2;
+ insert_p = false;
continue;
}
+ if (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset)
+ && (! hard_reg_set_equal_p (temp_hard_regset2, temp_hard_regset)
+ || cl == (int) GENERAL_REGS))
+ continue;
+ pressure_classes[curr++] = (enum reg_class) cl2;
+ }
+ if (insert_p)
+ pressure_classes[curr++] = (enum reg_class) cl;
+ n = curr;
+ }
+#ifdef ENABLE_IRA_CHECKING
+ /* Check pressure classes correctness. */
+ CLEAR_HARD_REG_SET (temp_hard_regset);
+ CLEAR_HARD_REG_SET (temp_hard_regset2);
+ for (cl = 0; cl <= LIM_REG_CLASSES; cl++)
+ {
+ for (i = 0; i < n; i++)
+ if ((int) pressure_classes[i] == cl)
+ break;
+ IOR_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
+ if (i >= n)
+ IOR_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl]);
+ }
+ AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
+ ira_assert (hard_reg_set_subset_p (temp_hard_regset2, temp_hard_regset));
#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++] = (enum reg_class) i;
+ ira_pressure_classes_num = 0;
+ for (i = 0; i < n; i++)
+ {
+ cl = (int) pressure_classes[i];
+ ira_reg_pressure_class_p[cl] = true;
+ ira_pressure_classes[ira_pressure_classes_num++] = (enum reg_class) cl;
+ }
+ setup_stack_reg_pressure_class ();
+}
+
+/* Set the four global variables defined above. */
+static void
+setup_allocno_and_important_classes (void)
+{
+ int i, j, n, cl;
+ bool set_p;
+ HARD_REG_SET temp_hard_regset2;
+ static enum reg_class classes[LIM_REG_CLASSES + 1];
+
+ n = 0;
+ for (i = 0; i <= LIM_REG_CLASSES; i++)
+ {
+ 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 < n; j++)
+ {
+ cl = classes[j];
+ COPY_HARD_REG_SET (temp_hard_regset2, reg_class_contents[cl]);
+ 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;
}
- classes[n] = LIM_REG_CLASSES;
+ if (j >= n)
+ classes[n++] = (enum reg_class) i;
+ else if (i == GENERAL_REGS)
+ /* Prefer general regs. For i386 example, it means that
+ we prefer GENERAL_REGS over INDEX_REGS or LEGACY_REGS
+ (all of them consists of the same available hard
+ registers). */
+ classes[j] = (enum reg_class) i;
}
+ classes[n] = LIM_REG_CLASSES;
- ira_reg_class_cover_size = 0;
+ ira_allocno_classes_num = 0;
for (i = 0; (cl = classes[i]) != LIM_REG_CLASSES; i++)
{
- for (j = 0; j < i; j++)
- if (flag_ira_algorithm != IRA_ALGORITHM_PRIORITY
- && reg_classes_intersect_p ((enum reg_class) 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);
- if (! hard_reg_set_empty_p (temp_hard_regset))
- ira_reg_class_cover[ira_reg_class_cover_size++] = (enum reg_class) cl;
+ if (hard_reg_set_empty_p (temp_hard_regset))
+ continue;
+ ira_allocno_classes[ira_allocno_classes_num++] = (enum reg_class) cl;
}
ira_important_classes_num = 0;
for (cl = 0; cl < N_REG_CLASSES; cl++)
@@ -813,100 +995,82 @@ setup_cover_and_important_classes (void)
if (! hard_reg_set_empty_p (temp_hard_regset))
{
set_p = false;
- for (j = 0; j < ira_reg_class_cover_size; j++)
+ for (j = 0; j < ira_allocno_classes_num; 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]]);
+ reg_class_contents[ira_allocno_classes[j]]);
AND_COMPL_HARD_REG_SET (temp_hard_regset2, no_unit_alloc_regs);
- if ((enum reg_class) cl == ira_reg_class_cover[j]
- || hard_reg_set_equal_p (temp_hard_regset,
- temp_hard_regset2))
+ if ((enum reg_class) cl == ira_allocno_classes[j])
break;
else if (hard_reg_set_subset_p (temp_hard_regset,
temp_hard_regset2))
set_p = true;
}
- if (set_p && j >= ira_reg_class_cover_size)
+ if (set_p && j >= ira_allocno_classes_num)
ira_important_classes[ira_important_classes_num++]
= (enum reg_class) cl;
}
}
- for (j = 0; j < ira_reg_class_cover_size; j++)
+ for (j = 0; j < ira_allocno_classes_num; j++)
ira_important_classes[ira_important_classes_num++]
- = ira_reg_class_cover[j];
+ = ira_allocno_classes[j];
+ for (cl = 0; cl < N_REG_CLASSES; cl++)
+ {
+ ira_reg_allocno_class_p[cl] = false;
+ ira_reg_pressure_class_p[cl] = false;
+ }
+ for (j = 0; j < ira_allocno_classes_num; j++)
+ ira_reg_allocno_class_p[ira_allocno_classes[j]] = true;
+ setup_pressure_classes ();
}
-/* Map of all register classes to corresponding cover class containing
- the given class. If given class is not a subset of a cover class,
- we translate it into the cheapest cover class. */
-enum reg_class ira_class_translate[N_REG_CLASSES];
+/* Map of all register classes to corresponding allocno classes
+ containing the given class. If given class is not a subset of an
+ allocno class, we translate it into the cheapest allocno class. */
+enum reg_class ira_allocno_class_translate[N_REG_CLASSES];
+
+/* Map of all register classes to corresponding pressure classes
+ containing the given class. If given class is not a subset of an
+ pressure class, we translate it into the cheapest pressure class. */
+extern enum reg_class ira_pressure_class_translate[N_REG_CLASSES];
-/* Set up array IRA_CLASS_TRANSLATE. */
+/* Setup translation in CLASS_TRANSLATE of all classes into a class
+ given by array CLASSES of length CLASSES_NUM. */
static void
-setup_class_translate (void)
+setup_class_translate_array (enum reg_class *class_translate,
+ int classes_num, enum reg_class *classes)
{
int cl, mode;
- enum reg_class cover_class, best_class, *cl_ptr;
+ enum reg_class aclass, best_class, *cl_ptr;
int i, cost, min_cost, best_cost;
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;
+ class_translate[cl] = NO_REGS;
- 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++)
+ for (i = 0; i < classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- 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 ();
- }
-#endif
- }
- ira_class_translate[cover_class] = cover_class;
- }
- /* For classes which are not fully covered by a cover class (in
- other words covered by more one cover class), use the cheapest
- cover class. */
+ aclass = classes[i];
+ for (cl_ptr = &alloc_reg_class_subclasses[aclass][0];
+ (cl = *cl_ptr) != LIM_REG_CLASSES;
+ cl_ptr++)
+ if (class_translate[cl] == NO_REGS)
+ class_translate[cl] = aclass;
+ class_translate[aclass] = aclass;
+ }
+ /* For classes which are not fully covered by one of given classes
+ (in other words covered by more one given class), use the
+ cheapest class. */
for (cl = 0; cl < N_REG_CLASSES; cl++)
{
- if (cl == NO_REGS || ira_class_translate[cl] != NO_REGS)
+ if (cl == NO_REGS || class_translate[cl] != NO_REGS)
continue;
best_class = NO_REGS;
best_cost = INT_MAX;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
+ aclass = classes[i];
COPY_HARD_REG_SET (temp_hard_regset,
- reg_class_contents[cover_class]);
+ reg_class_contents[aclass]);
AND_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))
@@ -921,18 +1085,29 @@ setup_class_translate (void)
}
if (best_class == NO_REGS || best_cost > min_cost)
{
- best_class = cover_class;
+ best_class = aclass;
best_cost = min_cost;
}
}
}
- ira_class_translate[cl] = best_class;
+ class_translate[cl] = best_class;
}
}
-/* Order numbers of cover classes in original target cover class
- array, -1 for non-cover classes. */
-static int cover_class_order[N_REG_CLASSES];
+/* Set up array IRA_ALLOCNO_CLASS_TRANSLATE and
+ IRA_PRESSURE_CLASS_TRANSLATE. */
+static void
+setup_class_translate (void)
+{
+ setup_class_translate_array (ira_allocno_class_translate,
+ ira_allocno_classes_num, ira_allocno_classes);
+ setup_class_translate_array (ira_pressure_class_translate,
+ ira_pressure_classes_num, ira_pressure_classes);
+}
+
+/* Order numbers of allocno classes in original target allocno class
+ array, -1 for non-allocno classes. */
+static int allocno_class_order[N_REG_CLASSES];
/* The function used to sort the important classes. */
static int
@@ -940,17 +1115,18 @@ comp_reg_classes_func (const void *v1p,
{
enum reg_class cl1 = *(const enum reg_class *) v1p;
enum reg_class cl2 = *(const enum reg_class *) v2p;
+ enum reg_class tcl1, tcl2;
int diff;
- cl1 = ira_class_translate[cl1];
- cl2 = ira_class_translate[cl2];
- if (cl1 != NO_REGS && cl2 != NO_REGS
- && (diff = cover_class_order[cl1] - cover_class_order[cl2]) != 0)
+ tcl1 = ira_allocno_class_translate[cl1];
+ tcl2 = ira_allocno_class_translate[cl2];
+ if (tcl1 != NO_REGS && tcl2 != NO_REGS
+ && (diff = allocno_class_order[tcl1] - allocno_class_order[tcl2]) != 0)
return diff;
return (int) cl1 - (int) cl2;
}
-/* Reorder important classes according to the order of their cover
+/* Reorder important classes according to the order of their allocno
classes. Set up array ira_important_class_nums too. */
static void
reorder_important_classes (void)
@@ -958,9 +1134,9 @@ reorder_important_classes (void)
int i;
for (i = 0; i < N_REG_CLASSES; i++)
- cover_class_order[i] = -1;
- for (i = 0; i < ira_reg_class_cover_size; i++)
- cover_class_order[ira_reg_class_cover[i]] = i;
+ allocno_class_order[i] = -1;
+ for (i = 0; i < ira_allocno_classes_num; i++)
+ allocno_class_order[ira_allocno_classes[i]] = i;
qsort (ira_important_classes, ira_important_classes_num,
sizeof (enum reg_class), comp_reg_classes_func);
for (i = 0; i < ira_important_classes_num; i++)
@@ -986,14 +1162,15 @@ bool ira_reg_classes_intersect_p[N_REG_C
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
+/* The biggest (smallest) important class inside of (covering) union
+ of the two classes (that is calculated taking only hard registers
+ available for allocation into account). If the both classes
contain no hard registers available for allocation, the value is
- calculated by taking all hard-registers including fixed ones into
+ calculated with taking all hard-registers including fixed ones into
account. In other words, the value is the corresponding
- reg_class_subunion value. */
-enum reg_class ira_reg_class_union[N_REG_CLASSES][N_REG_CLASSES];
+ reg_class_subunion (reg_class_superunion) value. */
+enum reg_class ira_reg_class_subunion[N_REG_CLASSES][N_REG_CLASSES];
+enum reg_class ira_reg_class_superunion[N_REG_CLASSES][N_REG_CLASSES];
/* Set up the above reg class relations. */
static void
@@ -1029,7 +1206,8 @@ setup_reg_class_relations (void)
(enum reg_class) cl3))
ira_reg_class_intersect[cl1][cl2] = (enum reg_class) cl3;
}
- ira_reg_class_union[cl1][cl2] = reg_class_subunion[cl1][cl2];
+ ira_reg_class_subunion[cl1][cl2] = reg_class_subunion[cl1][cl2];
+ ira_reg_class_superunion[cl1][cl2] = reg_class_superunion[cl1][cl2];
continue;
}
ira_reg_classes_intersect_p[cl1][cl2]
@@ -1045,7 +1223,8 @@ setup_reg_class_relations (void)
*p++ = (enum reg_class) cl2;
*p = LIM_REG_CLASSES;
}
- ira_reg_class_union[cl1][cl2] = NO_REGS;
+ ira_reg_class_subunion[cl1][cl2] = NO_REGS;
+ ira_reg_class_superunion[cl1][cl2] = NO_REGS;
COPY_HARD_REG_SET (intersection_set, reg_class_contents[cl1]);
AND_HARD_REG_SET (intersection_set, reg_class_contents[cl2]);
AND_COMPL_HARD_REG_SET (intersection_set, no_unit_alloc_regs);
@@ -1068,68 +1247,102 @@ setup_reg_class_relations (void)
/* Ignore unavailable hard registers and prefer
smallest class for debugging purposes. */
|| (hard_reg_set_equal_p (temp_hard_regset, temp_set2)
- && hard_reg_set_subset_p
- (reg_class_contents[cl3],
- reg_class_contents
- [(int) ira_reg_class_intersect[cl1][cl2]])))
+ && (cl3 == GENERAL_REGS
+ || (ira_reg_class_intersect[cl1][cl2] != GENERAL_REGS
+ && hard_reg_set_subset_p
+ (reg_class_contents[cl3],
+ reg_class_contents
+ [(int) ira_reg_class_intersect[cl1][cl2]])))))
ira_reg_class_intersect[cl1][cl2] = (enum reg_class) cl3;
}
if (hard_reg_set_subset_p (temp_hard_regset, union_set))
{
COPY_HARD_REG_SET
(temp_set2,
- reg_class_contents[(int) ira_reg_class_union[cl1][cl2]]);
+ reg_class_contents[(int) ira_reg_class_subunion[cl1][cl2]]);
AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
- if (ira_reg_class_union[cl1][cl2] == NO_REGS
+ if (ira_reg_class_subunion[cl1][cl2] == NO_REGS
|| (hard_reg_set_subset_p (temp_set2, temp_hard_regset)
+
+ && (! hard_reg_set_equal_p (temp_set2,
+ temp_hard_regset)
+ || cl3 == GENERAL_REGS
+ /* Ignore unavailable hard registers and
+ prefer smallest class for debugging
+ purposes. */
+ || (ira_reg_class_subunion[cl1][cl2] != GENERAL_REGS
+ && hard_reg_set_subset_p
+ (reg_class_contents[cl3],
+ reg_class_contents
+ [(int) ira_reg_class_subunion[cl1][cl2]])))))
+ ira_reg_class_subunion[cl1][cl2] = (enum reg_class) cl3;
+ }
+ if (hard_reg_set_subset_p (union_set, temp_hard_regset))
+ {
+ COPY_HARD_REG_SET
+ (temp_set2,
+ reg_class_contents[(int) ira_reg_class_superunion[cl1][cl2]]);
+ AND_COMPL_HARD_REG_SET (temp_set2, no_unit_alloc_regs);
+ if (ira_reg_class_superunion[cl1][cl2] == NO_REGS
+ || (hard_reg_set_subset_p (temp_hard_regset, temp_set2)
&& (! hard_reg_set_equal_p (temp_set2,
temp_hard_regset)
+ || cl3 == GENERAL_REGS
/* Ignore unavailable hard registers and
prefer smallest class for debugging
purposes. */
- || hard_reg_set_subset_p
- (reg_class_contents[cl3],
- reg_class_contents
- [(int) ira_reg_class_union[cl1][cl2]]))))
- ira_reg_class_union[cl1][cl2] = (enum reg_class) cl3;
+ || (ira_reg_class_superunion[cl1][cl2] != GENERAL_REGS
+ && hard_reg_set_subset_p
+ (reg_class_contents[cl3],
+ reg_class_contents
+ [(int) ira_reg_class_superunion[cl1][cl2]])))))
+ ira_reg_class_superunion[cl1][cl2] = (enum reg_class) cl3;
}
}
}
}
}
-/* Output all cover classes and the translation map into file F. */
+/* Output all possible allocno classes and the translation map into
+ file F. */
static void
-print_class_cover (FILE *f)
+print_classes (FILE *f, bool pressure_p)
{
+ int classes_num = (pressure_p
+ ? ira_pressure_classes_num : ira_allocno_classes_num);
+ enum reg_class *classes = (pressure_p
+ ? ira_pressure_classes : ira_allocno_classes);
+ enum reg_class *class_translate = (pressure_p
+ ? ira_pressure_class_translate
+ : ira_allocno_class_translate);
static const char *const reg_class_names[] = REG_CLASS_NAMES;
int i;
- fprintf (f, "Class cover:\n");
- for (i = 0; i < ira_reg_class_cover_size; i++)
- fprintf (f, " %s", reg_class_names[ira_reg_class_cover[i]]);
+ fprintf (f, "%s classes:\n", pressure_p ? "Pressure" : "Allocno");
+ for (i = 0; i < classes_num; i++)
+ fprintf (f, " %s", reg_class_names[classes[i]]);
fprintf (f, "\nClass translation:\n");
for (i = 0; i < N_REG_CLASSES; i++)
fprintf (f, " %s -> %s\n", reg_class_names[i],
- reg_class_names[ira_class_translate[i]]);
+ reg_class_names[class_translate[i]]);
}
-/* Output all cover classes and the translation map into
- stderr. */
+/* Output all possible allocno and translation classes and the
+ translation maps into stderr. */
void
-ira_debug_class_cover (void)
+ira_debug_allocno_classes (void)
{
- print_class_cover (stderr);
+ print_classes (stderr, false);
+ print_classes (stderr, true);
}
-/* Set up different arrays concerning class subsets, cover and
+/* Set up different arrays concerning class subsets, allocno and
important classes. */
static void
-find_reg_class_closure (void)
+find_reg_classes (void)
{
- setup_reg_subclasses ();
- setup_cover_and_important_classes ();
+ setup_allocno_and_important_classes ();
setup_class_translate ();
reorder_important_classes ();
setup_reg_class_relations ();
@@ -1137,27 +1350,27 @@ find_reg_class_closure (void)
\f
-/* Map: hard register number -> cover class it belongs to. If the
+/* Map: hard register number -> allocno class it belongs to. If the
corresponding class is NO_REGS, the hard register is not available
for allocation. */
-enum reg_class ira_hard_regno_cover_class[FIRST_PSEUDO_REGISTER];
+enum reg_class ira_hard_regno_allocno_class[FIRST_PSEUDO_REGISTER];
/* Set up the array above. */
static void
-setup_hard_regno_cover_class (void)
+setup_hard_regno_aclass (void)
{
int i, j;
enum reg_class cl;
for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
{
- ira_hard_regno_cover_class[i] = NO_REGS;
- for (j = 0; j < ira_reg_class_cover_size; j++)
+ ira_hard_regno_allocno_class[i] = NO_REGS;
+ for (j = 0; j < ira_allocno_classes_num; j++)
{
- cl = ira_reg_class_cover[j];
+ cl = ira_allocno_classes[j];
if (ira_class_hard_reg_index[cl][i] >= 0)
{
- ira_hard_regno_cover_class[i] = cl;
+ ira_hard_regno_allocno_class[i] = cl;
break;
}
}
@@ -1167,28 +1380,31 @@ setup_hard_regno_cover_class (void)
\f
-/* Map: register class x machine mode -> number of hard registers of
- given class needed to store value of given mode. If the number is
- different, the size will be negative. */
-int ira_reg_class_nregs[N_REG_CLASSES][MAX_MACHINE_MODE];
-
-/* Maximal value of the previous array elements. */
-int ira_max_nregs;
+/* Maps: register class x machine mode -> maximal/minimal number of
+ hard registers of given class needed to store value of given
+ mode. */
+int ira_reg_class_max_nregs[N_REG_CLASSES][MAX_MACHINE_MODE];
+int ira_reg_class_min_nregs[N_REG_CLASSES][MAX_MACHINE_MODE];
-/* Form IRA_REG_CLASS_NREGS map. */
+/* Form IRA_REG_CLASS_MAX_NREGS and IRA_REG_CLASS_MIN_NREGS maps. */
static void
setup_reg_class_nregs (void)
{
- int cl, m;
+ int i, cl, cl2, m;
- ira_max_nregs = -1;
- for (cl = 0; cl < N_REG_CLASSES; cl++)
for (m = 0; m < MAX_MACHINE_MODE; m++)
{
- ira_reg_class_nregs[cl][m] = CLASS_MAX_NREGS ((enum reg_class) cl,
- (enum machine_mode) m);
- if (ira_max_nregs < ira_reg_class_nregs[cl][m])
- ira_max_nregs = ira_reg_class_nregs[cl][m];
+ for (cl = 0; cl < N_REG_CLASSES; cl++)
+ ira_reg_class_max_nregs[cl][m]
+ = ira_reg_class_min_nregs[cl][m]
+ = CLASS_MAX_NREGS ((enum reg_class) cl, (enum machine_mode) m);
+ for (cl = 0; cl < N_REG_CLASSES; cl++)
+ for (i = 0;
+ (cl2 = alloc_reg_class_subclasses[cl][i]) != LIM_REG_CLASSES;
+ i++)
+ if (ira_reg_class_min_nregs[cl2][m]
+ < ira_reg_class_min_nregs[cl][m])
+ ira_reg_class_min_nregs[cl][m] = ira_reg_class_min_nregs[cl2][m];
}
}
@@ -1197,50 +1413,106 @@ setup_reg_class_nregs (void)
/* Array whose values are hard regset of hard registers available for
the allocation of given register class whose HARD_REGNO_MODE_OK
values for given mode are zero. */
-HARD_REG_SET prohibited_class_mode_regs[N_REG_CLASSES][NUM_MACHINE_MODES];
+HARD_REG_SET ira_prohibited_class_mode_regs[N_REG_CLASSES][NUM_MACHINE_MODES];
-/* Set up PROHIBITED_CLASS_MODE_REGS. */
+/* Set up IRA_PROHIBITED_CLASS_MODE_REGS. */
static void
setup_prohibited_class_mode_regs (void)
{
- int i, j, k, hard_regno;
- enum reg_class cl;
+ int j, k, hard_regno, cl;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--)
{
- cl = ira_reg_class_cover[i];
for (j = 0; j < NUM_MACHINE_MODES; j++)
{
- CLEAR_HARD_REG_SET (prohibited_class_mode_regs[cl][j]);
+ CLEAR_HARD_REG_SET (ira_prohibited_class_mode_regs[cl][j]);
for (k = ira_class_hard_regs_num[cl] - 1; k >= 0; k--)
{
hard_regno = ira_class_hard_regs[cl][k];
if (! HARD_REGNO_MODE_OK (hard_regno, (enum machine_mode) j))
- SET_HARD_REG_BIT (prohibited_class_mode_regs[cl][j],
+ SET_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
hard_regno);
}
}
}
}
+/* Clarify IRA_PROHIBITED_CLASS_MODE_REGS by excluding hard registers
+ spanning from one register pressure class to another one. It is
+ called after defining the pressure classes. */
+static void
+clarify_prohibited_class_mode_regs (void)
+{
+ int j, k, hard_regno, cl, pclass, nregs;
+
+ for (cl = (int) N_REG_CLASSES - 1; cl >= 0; cl--)
+ for (j = 0; j < NUM_MACHINE_MODES; j++)
+ for (k = ira_class_hard_regs_num[cl] - 1; k >= 0; k--)
+ {
+ hard_regno = ira_class_hard_regs[cl][k];
+ if (TEST_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j], hard_regno))
+ continue;
+ nregs = hard_regno_nregs[hard_regno][j];
+ pclass = ira_pressure_class_translate[REGNO_REG_CLASS (hard_regno)];
+ for (nregs-- ;nregs >= 0; nregs--)
+ if (((enum reg_class) pclass
+ != ira_pressure_class_translate[REGNO_REG_CLASS
+ (hard_regno + nregs)]))
+ {
+ SET_HARD_REG_BIT (ira_prohibited_class_mode_regs[cl][j],
+ hard_regno);
+ break;
+ }
+ }
+}
+
\f
/* Allocate and initialize IRA_REGISTER_MOVE_COST,
- IRA_MAY_MOVE_IN_COST, and IRA_MAY_MOVE_OUT_COST for MODE if it is
- not done yet. */
+ IRA_MAX_REGISTER_MOVE_COST, IRA_MAY_MOVE_IN_COST,
+ IRA_MAY_MOVE_OUT_COST, IRA_MAX_MAY_MOVE_IN_COST, and
+ IRA_MAX_MAY_MOVE_OUT_COST for MODE if it is not done yet. */
void
ira_init_register_move_cost (enum machine_mode mode)
{
- int cl1, cl2;
+ int cl1, cl2, cl3;
ira_assert (ira_register_move_cost[mode] == NULL
+ && ira_max_register_move_cost[mode] == NULL
&& ira_may_move_in_cost[mode] == NULL
- && ira_may_move_out_cost[mode] == NULL);
+ && ira_may_move_out_cost[mode] == NULL
+ && ira_max_may_move_in_cost[mode] == NULL
+ && ira_max_may_move_out_cost[mode] == NULL);
if (move_cost[mode] == NULL)
init_move_cost (mode);
ira_register_move_cost[mode] = move_cost[mode];
/* Don't use ira_allocate because the tables exist out of scope of a
IRA call. */
+ ira_max_register_move_cost[mode]
+ = (move_table *) xmalloc (sizeof (move_table) * N_REG_CLASSES);
+ memcpy (ira_max_register_move_cost[mode], ira_register_move_cost[mode],
+ sizeof (move_table) * N_REG_CLASSES);
+ for (cl1 = 0; cl1 < N_REG_CLASSES; cl1++)
+ {
+ COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl1]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+ if (hard_reg_set_empty_p (temp_hard_regset))
+ continue;
+ for (cl2 = 0; cl2 < N_REG_CLASSES; cl2++)
+ if (hard_reg_set_subset_p (reg_class_contents[cl1],
+ reg_class_contents[cl2]))
+ for (cl3 = 0; cl3 < N_REG_CLASSES; cl3++)
+ {
+ if (ira_max_register_move_cost[mode][cl2][cl3]
+ < ira_register_move_cost[mode][cl1][cl3])
+ ira_max_register_move_cost[mode][cl2][cl3]
+ = ira_register_move_cost[mode][cl1][cl3];
+ if (ira_max_register_move_cost[mode][cl3][cl2]
+ < ira_register_move_cost[mode][cl3][cl1])
+ ira_max_register_move_cost[mode][cl3][cl2]
+ = ira_register_move_cost[mode][cl3][cl1];
+ }
+ }
ira_may_move_in_cost[mode]
= (move_table *) xmalloc (sizeof (move_table) * N_REG_CLASSES);
memcpy (ira_may_move_in_cost[mode], may_move_in_cost[mode],
@@ -1249,14 +1521,36 @@ ira_init_register_move_cost (enum machin
= (move_table *) xmalloc (sizeof (move_table) * N_REG_CLASSES);
memcpy (ira_may_move_out_cost[mode], may_move_out_cost[mode],
sizeof (move_table) * N_REG_CLASSES);
+ ira_max_may_move_in_cost[mode]
+ = (move_table *) xmalloc (sizeof (move_table) * N_REG_CLASSES);
+ memcpy (ira_max_may_move_in_cost[mode], ira_max_register_move_cost[mode],
+ sizeof (move_table) * N_REG_CLASSES);
+ ira_max_may_move_out_cost[mode]
+ = (move_table *) xmalloc (sizeof (move_table) * N_REG_CLASSES);
+ memcpy (ira_max_may_move_out_cost[mode], ira_max_register_move_cost[mode],
+ sizeof (move_table) * N_REG_CLASSES);
for (cl1 = 0; cl1 < N_REG_CLASSES; cl1++)
{
for (cl2 = 0; cl2 < N_REG_CLASSES; cl2++)
{
+ COPY_HARD_REG_SET (temp_hard_regset, reg_class_contents[cl2]);
+ AND_COMPL_HARD_REG_SET (temp_hard_regset, no_unit_alloc_regs);
+ if (hard_reg_set_empty_p (temp_hard_regset))
+ continue;
if (ira_class_subset_p[cl1][cl2])
ira_may_move_in_cost[mode][cl1][cl2] = 0;
if (ira_class_subset_p[cl2][cl1])
ira_may_move_out_cost[mode][cl1][cl2] = 0;
+ if (ira_class_subset_p[cl1][cl2])
+ ira_max_may_move_in_cost[mode][cl1][cl2] = 0;
+ if (ira_class_subset_p[cl2][cl1])
+ ira_max_may_move_out_cost[mode][cl1][cl2] = 0;
+ ira_register_move_cost[mode][cl1][cl2]
+ = ira_max_register_move_cost[mode][cl1][cl2];
+ ira_may_move_in_cost[mode][cl1][cl2]
+ = ira_max_may_move_in_cost[mode][cl1][cl2];
+ ira_may_move_out_cost[mode][cl1][cl2]
+ = ira_max_may_move_out_cost[mode][cl1][cl2];
}
}
}
@@ -1274,14 +1568,18 @@ ira_init_once (void)
for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
{
ira_register_move_cost[mode] = NULL;
+ ira_max_register_move_cost[mode] = NULL;
ira_may_move_in_cost[mode] = NULL;
ira_may_move_out_cost[mode] = NULL;
+ ira_max_may_move_in_cost[mode] = NULL;
+ ira_max_may_move_out_cost[mode] = NULL;
}
ira_init_costs_once ();
}
-/* Free ira_register_move_cost, ira_may_move_in_cost, and
- ira_may_move_out_cost for each mode. */
+/* Free ira_max_register_move_cost, ira_may_move_in_cost,
+ ira_may_move_out_cost, ira_max_may_move_in_cost, and
+ ira_max_may_move_out_cost for each mode. */
static void
free_register_move_costs (void)
{
@@ -1289,13 +1587,22 @@ free_register_move_costs (void)
for (mode = 0; mode < MAX_MACHINE_MODE; mode++)
{
+ if (ira_max_register_move_cost[mode] != NULL)
+ free (ira_max_register_move_cost[mode]);
if (ira_may_move_in_cost[mode] != NULL)
free (ira_may_move_in_cost[mode]);
if (ira_may_move_out_cost[mode] != NULL)
free (ira_may_move_out_cost[mode]);
+ if (ira_max_may_move_in_cost[mode] != NULL)
+ free (ira_max_may_move_in_cost[mode]);
+ if (ira_max_may_move_out_cost[mode] != NULL)
+ free (ira_max_may_move_out_cost[mode]);
ira_register_move_cost[mode] = NULL;
+ ira_max_register_move_cost[mode] = NULL;
ira_may_move_in_cost[mode] = NULL;
ira_may_move_out_cost[mode] = NULL;
+ ira_max_may_move_in_cost[mode] = NULL;
+ ira_max_may_move_out_cost[mode] = NULL;
}
}
@@ -1308,10 +1615,11 @@ ira_init (void)
setup_reg_mode_hard_regset ();
setup_alloc_regs (flag_omit_frame_pointer != 0);
setup_class_subset_and_memory_move_costs ();
- find_reg_class_closure ();
- setup_hard_regno_cover_class ();
setup_reg_class_nregs ();
setup_prohibited_class_mode_regs ();
+ find_reg_classes ();
+ clarify_prohibited_class_mode_regs ();
+ setup_hard_regno_aclass ();
ira_init_costs ();
}
@@ -1638,7 +1946,7 @@ setup_reg_renumber (void)
ALLOCNO_ASSIGNED_P (a) = true;
ira_free_allocno_updated_costs (a);
hard_regno = ALLOCNO_HARD_REGNO (a);
- regno = (int) REGNO (ALLOCNO_REG (a));
+ regno = ALLOCNO_REGNO (a);
reg_renumber[regno] = (hard_regno < 0 ? -1 : hard_regno);
if (hard_regno >= 0 && ALLOCNO_CALLS_CROSSED_NUM (a) != 0
&& ! ira_hard_reg_not_in_set_p (hard_regno, ALLOCNO_MODE (a),
@@ -1678,11 +1986,11 @@ setup_allocno_assignment_flags (void)
ALLOCNO_ASSIGNED_P (a) = (hard_regno >= 0
|| ALLOCNO_MEM_OPTIMIZED_DEST_P (a)
|| (ALLOCNO_MEMORY_COST (a)
- - ALLOCNO_COVER_CLASS_COST (a)) < 0);
+ - ALLOCNO_CLASS_COST (a)) < 0);
ira_assert (hard_regno < 0
|| ! ira_hard_reg_not_in_set_p (hard_regno, ALLOCNO_MODE (a),
reg_class_contents
- [ALLOCNO_COVER_CLASS (a)]));
+ [ALLOCNO_CLASS (a)]));
}
}
@@ -1702,7 +2010,7 @@ calculate_allocation_cost (void)
ira_assert (hard_regno < 0
|| ! ira_hard_reg_not_in_set_p
(hard_regno, ALLOCNO_MODE (a),
- reg_class_contents[ALLOCNO_COVER_CLASS (a)]));
+ reg_class_contents[ALLOCNO_CLASS (a)]));
if (hard_regno < 0)
{
cost = ALLOCNO_MEMORY_COST (a);
@@ -1712,12 +2020,12 @@ calculate_allocation_cost (void)
{
cost = (ALLOCNO_HARD_REG_COSTS (a)
[ira_class_hard_reg_index
- [ALLOCNO_COVER_CLASS (a)][hard_regno]]);
+ [ALLOCNO_CLASS (a)][hard_regno]]);
ira_reg_cost += cost;
}
else
{
- cost = ALLOCNO_COVER_CLASS_COST (a);
+ cost = ALLOCNO_CLASS_COST (a);
ira_reg_cost += cost;
}
ira_overall_cost += cost;
@@ -1869,7 +2177,7 @@ setup_preferred_alternate_classes_for_ne
ira_assert (i != old_regno);
setup_reg_classes (i, reg_preferred_class (old_regno),
reg_alternate_class (old_regno),
- reg_cover_class (old_regno));
+ reg_allocno_class (old_regno));
if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL)
fprintf (ira_dump_file,
" New r%d: setting preferred %s, alternative %s\n",
@@ -1899,12 +2207,12 @@ static bool
too_high_register_pressure_p (void)
{
int i;
- enum reg_class cover_class;
+ enum reg_class pclass;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- cover_class = ira_reg_class_cover[i];
- if (ira_loop_tree_root->reg_pressure[cover_class] > 10000)
+ pclass = ira_pressure_classes[i];
+ if (ira_loop_tree_root->reg_pressure[pclass] > 10000)
return true;
}
return false;
@@ -2112,9 +2420,10 @@ equiv_init_movable_p (rtx x, int regno)
return 0;
case REG:
- return (reg_equiv[REGNO (x)].loop_depth >= reg_equiv[regno].loop_depth
- && reg_equiv[REGNO (x)].replace)
- || (REG_BASIC_BLOCK (REGNO (x)) < NUM_FIXED_BLOCKS && ! rtx_varies_p (x, 0));
+ return ((reg_equiv[REGNO (x)].loop_depth >= reg_equiv[regno].loop_depth
+ && reg_equiv[REGNO (x)].replace)
+ || (REG_BASIC_BLOCK (REGNO (x)) < NUM_FIXED_BLOCKS
+ && ! rtx_varies_p (x, 0)));
case UNSPEC_VOLATILE:
return 0;
@@ -2147,7 +2456,8 @@ equiv_init_movable_p (rtx x, int regno)
return 1;
}
-/* TRUE if X uses any registers for which reg_equiv[REGNO].replace is true. */
+/* TRUE if X uses any registers for which reg_equiv[REGNO].replace is
+ true. */
static int
contains_replace_regs (rtx x)
{
@@ -2295,7 +2605,8 @@ memref_used_between_p (rtx memref, rtx s
assignment - a SET, CLOBBER or REG_INC note. It is currently not used,
but needs to be there because this function is called from note_stores. */
static void
-no_equiv (rtx reg, const_rtx store ATTRIBUTE_UNUSED, void *data ATTRIBUTE_UNUSED)
+no_equiv (rtx reg, const_rtx store ATTRIBUTE_UNUSED,
+ void *data ATTRIBUTE_UNUSED)
{
int regno;
rtx list;
@@ -2340,12 +2651,13 @@ adjust_cleared_regs (rtx loc, const_rtx
static int recorded_label_ref;
/* Find registers that are equivalent to a single value throughout the
- compilation (either because they can be referenced in memory or are set once
- from a single constant). Lower their priority for a register.
-
- If such a register is only referenced once, try substituting its value
- into the using insn. If it succeeds, we can eliminate the register
- completely.
+ compilation (either because they can be referenced in memory or are
+ set once from a single constant). Lower their priority for a
+ register.
+
+ If such a register is only referenced once, try substituting its
+ value into the using insn. If it succeeds, we can eliminate the
+ register completely.
Initialize the REG_EQUIV_INIT array of initializing insns.
Index: sched-deps.c
===================================================================
--- sched-deps.c (revision 161709)
+++ sched-deps.c (working copy)
@@ -1827,10 +1827,10 @@ mark_insn_pseudo_birth (rtx insn, int re
enum reg_class cl;
gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
- cl = sched_regno_cover_class[regno];
+ cl = sched_regno_pressure_class[regno];
if (cl != NO_REGS)
{
- incr = ira_reg_class_nregs[cl][PSEUDO_REGNO_MODE (regno)];
+ incr = ira_reg_class_max_nregs[cl][PSEUDO_REGNO_MODE (regno)];
if (clobber_p)
{
new_incr = reg_pressure_info[cl].clobber_increase + incr;
@@ -1867,7 +1867,7 @@ mark_insn_hard_regno_birth (rtx insn, in
gcc_assert (regno < FIRST_PSEUDO_REGISTER);
if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
{
- cl = sched_regno_cover_class[regno];
+ cl = sched_regno_pressure_class[regno];
if (cl != NO_REGS)
{
if (clobber_p)
@@ -1928,10 +1928,10 @@ mark_pseudo_death (int regno)
enum reg_class cl;
gcc_assert (regno >= FIRST_PSEUDO_REGISTER);
- cl = sched_regno_cover_class[regno];
+ cl = sched_regno_pressure_class[regno];
if (cl != NO_REGS)
{
- incr = ira_reg_class_nregs[cl][PSEUDO_REGNO_MODE (regno)];
+ incr = ira_reg_class_max_nregs[cl][PSEUDO_REGNO_MODE (regno)];
reg_pressure_info[cl].change -= incr;
}
}
@@ -1949,7 +1949,7 @@ mark_hard_regno_death (int regno, int nr
gcc_assert (regno < FIRST_PSEUDO_REGISTER);
if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno))
{
- cl = sched_regno_cover_class[regno];
+ cl = sched_regno_pressure_class[regno];
if (cl != NO_REGS)
reg_pressure_info[cl].change -= 1;
}
@@ -2010,9 +2010,9 @@ setup_insn_reg_pressure_info (rtx insn)
if (! INSN_P (insn))
return;
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- cl = ira_reg_class_cover[i];
+ cl = ira_pressure_classes[i];
reg_pressure_info[cl].clobber_increase = 0;
reg_pressure_info[cl].set_increase = 0;
reg_pressure_info[cl].unused_set_increase = 0;
@@ -2033,14 +2033,14 @@ setup_insn_reg_pressure_info (rtx insn)
if (REG_NOTE_KIND (link) == REG_DEAD)
mark_reg_death (XEXP (link, 0));
- len = sizeof (struct reg_pressure_data) * ira_reg_class_cover_size;
+ len = sizeof (struct reg_pressure_data) * ira_pressure_classes_num;
pressure_info
= INSN_REG_PRESSURE (insn) = (struct reg_pressure_data *) xmalloc (len);
- INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_reg_class_cover_size
+ INSN_MAX_REG_PRESSURE (insn) = (int *) xcalloc (ira_pressure_classes_num
* sizeof (int), 1);
- for (i = 0; i < ira_reg_class_cover_size; i++)
+ for (i = 0; i < ira_pressure_classes_num; i++)
{
- cl = ira_reg_class_cover[i];
+ cl = ira_pressure_classes[i];
pressure_info[i].clobber_increase
= reg_pressure_info[cl].clobber_increase;
pressure_info[i].set_increase = reg_pressure_info[cl].set_increase;
Index: ira.h
===================================================================
--- ira.h (revision 161709)
+++ ira.h (working copy)
@@ -1,6 +1,6 @@
/* Communication between the Integrated Register Allocator (IRA) and
the rest of the compiler.
- Copyright (C) 2006, 2007, 2008, 2009
+ Copyright (C) 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Vladimir Makarov <vmakarov@redhat.com>.
@@ -24,31 +24,46 @@ along with GCC; see the file COPYING3.
allocation for given classes. */
extern int ira_available_class_regs[N_REG_CLASSES];
-/* Map: hard register number -> cover class it belongs to. If the
+/* Map: hard register number -> allocno class it belongs to. If the
corresponding class is NO_REGS, the hard register is not available
for allocation. */
-extern enum reg_class ira_hard_regno_cover_class[FIRST_PSEUDO_REGISTER];
+extern enum reg_class ira_hard_regno_allocno_class[FIRST_PSEUDO_REGISTER];
-/* Number of cover classes. Cover classes is non-intersected register
- classes containing all hard-registers available for the
- allocation. */
-extern int ira_reg_class_cover_size;
-
-/* The array containing cover classes (see also comments for macro
- IRA_COVER_CLASSES). Only first IRA_REG_CLASS_COVER_SIZE elements are
- used for this. */
-extern enum reg_class ira_reg_class_cover[N_REG_CLASSES];
-
-/* Map of all register classes to corresponding cover class containing
- the given class. If given class is not a subset of a cover class,
- we translate it into the cheapest cover class. */
-extern enum reg_class ira_class_translate[N_REG_CLASSES];
-
-/* Map: register class x machine mode -> number of hard registers of
- given class needed to store value of given mode. If the number for
- some hard-registers of the register class is different, the size
- will be negative. */
-extern int ira_reg_class_nregs[N_REG_CLASSES][MAX_MACHINE_MODE];
+/* Number of allocno classes. Allocno classes are register classes
+ which can be used for allocations of allocnos. */
+extern int ira_allocno_classes_num;
+
+/* The array containing allocno classes. Only first
+ IRA_ALLOCNO_CLASSES_NUM elements are used for this. */
+extern enum reg_class ira_allocno_classes[N_REG_CLASSES];
+
+/* Map of all register classes to corresponding allocno classes
+ containing the given class. If given class is not a subset of an
+ allocno class, we translate it into the cheapest allocno class. */
+extern enum reg_class ira_allocno_class_translate[N_REG_CLASSES];
+
+/* Number of pressure classes. Pressure classes are register classes
+ for which we calculate register pressure. */
+extern int ira_pressure_classes_num;
+
+/* The array containing pressure classes. Only first
+ IRA_PRESSURE_CLASSES_NUM elements are used for this. */
+extern enum reg_class ira_pressure_classes[N_REG_CLASSES];
+
+/* Map of all register classes to corresponding pressure classes
+ containing the given class. If given class is not a subset of an
+ pressure class, we translate it into the cheapest pressure class. */
+extern enum reg_class ira_pressure_class_translate[N_REG_CLASSES];
+
+/* Bigest pressure register class containing stack registers. NO_REGS
+ if there are no stack registers. */
+extern enum reg_class ira_stack_reg_pressure_class;
+
+/* Maps: register class x machine mode -> maximal/minimal number of
+ hard registers of given class needed to store value of given
+ mode. */
+extern int ira_reg_class_max_nregs[N_REG_CLASSES][MAX_MACHINE_MODE];
+extern int ira_reg_class_min_nregs[N_REG_CLASSES][MAX_MACHINE_MODE];
/* Function specific hard registers can not be used for the register
allocation. */
Index: ira-costs.c
===================================================================
--- ira-costs.c (revision 161709)
+++ ira-costs.c (working copy)
@@ -1,5 +1,5 @@
/* IRA hard register and memory cost calculation for allocnos or pseudos.
- Copyright (C) 2006, 2007, 2008, 2009
+ Copyright (C) 2006, 2007, 2008, 2009, 2010
Free Software Foundation, Inc.
Contributed by Vladimir Makarov <vmakarov@redhat.com>.
@@ -62,8 +62,7 @@ struct costs
{
int mem_cost;
/* Costs for register classes start here. We process only some
- register classes (cover classes on the 1st cost calculation
- iteration and important classes on the 2nd iteration). */
+ allocno classes. */
int cost[1];
};
@@ -121,8 +120,8 @@ static enum reg_class *pref;
/* Allocated buffers for pref. */
static enum reg_class *pref_buffer;
-/* Record cover register class of each allocno with the same regno. */
-static enum reg_class *regno_cover_class;
+/* Record allocno class of each allocno with the same regno. */
+static enum reg_class *regno_aclass;
/* Record cost gains for not allocating a register with an invariant
equivalence. */
@@ -176,7 +175,8 @@ copy_cost (rtx x, enum machine_mode mode
{
if (!move_cost[mode])
init_move_cost (mode);
- return (sri.extra_cost + move_cost[mode][REGNO_REG_CLASS (REGNO (x))][rclass]);
+ return (sri.extra_cost
+ + move_cost[mode][REGNO_REG_CLASS (REGNO (x))][rclass]);
}
else
/* If this is a constant, we may eventually want to call rtx_cost
@@ -343,12 +343,10 @@ record_reg_classes (int n_alts, int n_op
? ira_memory_move_cost[mode][classes[i]][1] : 0)
- allows_mem[i]) * frequency;
- /* If we have assigned a class to this allocno in our
- first pass, add a cost to this alternative
- corresponding to what we would add if this allocno
- were not in the appropriate class. We could use
- cover class here but it is less accurate
- approximation. */
+ /* If we have assigned a class to this allocno in
+ our first pass, add a cost to this alternative
+ corresponding to what we would add if this
+ allocno were not in the appropriate class. */
if (pref)
{
enum reg_class pref_class = pref[COST_INDEX (REGNO (op))];
@@ -411,7 +409,7 @@ record_reg_classes (int n_alts, int n_op
to be allocated to a register that can be the
base of an address, i.e. BASE_REG_CLASS. */
classes[i]
- = ira_reg_class_union[classes[i]]
+ = ira_reg_class_subunion[classes[i]]
[base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
break;
@@ -497,12 +495,12 @@ record_reg_classes (int n_alts, int n_op
win = 1;
insn_allows_mem[i] = allows_mem[i] = 1;
case 'r':
- classes[i] = ira_reg_class_union[classes[i]][GENERAL_REGS];
+ classes[i] = ira_reg_class_subunion[classes[i]][GENERAL_REGS];
break;
default:
if (REG_CLASS_FROM_CONSTRAINT (c, p) != NO_REGS)
- classes[i] = ira_reg_class_union[classes[i]]
+ classes[i] = ira_reg_class_subunion[classes[i]]
[REG_CLASS_FROM_CONSTRAINT (c, p)];
#ifdef EXTRA_CONSTRAINT_STR
else if (EXTRA_CONSTRAINT_STR (op, c, p))
@@ -526,7 +524,7 @@ record_reg_classes (int n_alts, int n_op
that can be the base of an address,
i.e. BASE_REG_CLASS. */
classes[i]
- = ira_reg_class_union[classes[i]]
+ = ira_reg_class_subunion[classes[i]]
[base_reg_class (VOIDmode, ADDRESS, SCRATCH)];
}
#endif
@@ -584,12 +582,10 @@ record_reg_classes (int n_alts, int n_op
+ (recog_data.operand_type[i] != OP_OUT
? ira_memory_move_cost[mode][classes[i]][1] : 0)
- allows_mem[i]) * frequency;
- /* If we have assigned a class to this allocno in our
- first pass, add a cost to this alternative
- corresponding to what we would add if this allocno
- were not in the appropriate class. We could use
- cover class here but it is less accurate
- approximation. */
+ /* If we have assigned a class to this allocno in
+ our first pass, add a cost to this alternative
+ corresponding to what we would add if this
+ allocno were not in the appropriate class. */
if (pref)
{
enum reg_class pref_class = pref[COST_INDEX (REGNO (op))];
@@ -910,7 +906,7 @@ record_address_regs (enum machine_mode m
{
struct costs *pp;
enum reg_class i;
- int k;
+ int k, add_cost;
if (REGNO (x) < FIRST_PSEUDO_REGISTER)
break;
@@ -918,12 +914,19 @@ record_address_regs (enum machine_mode m
if (allocno_p)
ALLOCNO_BAD_SPILL_P (ira_curr_regno_allocno_map[REGNO (x)]) = true;
pp = COSTS (costs, COST_INDEX (REGNO (x)));
- pp->mem_cost += (ira_memory_move_cost[Pmode][rclass][1] * scale) / 2;
+ add_cost = (ira_memory_move_cost[Pmode][rclass][1] * scale) / 2;
+ if (INT_MAX - add_cost < pp->mem_cost)
+ pp->mem_cost = INT_MAX;
+ else
+ pp->mem_cost += add_cost;
for (k = 0; k < cost_classes_num; k++)
{
i = cost_classes[k];
- pp->cost[k]
- += (ira_get_may_move_cost (Pmode, i, rclass, true) * scale) / 2;
+ add_cost = (ira_get_may_move_cost (Pmode, i, rclass, true) * scale) / 2;
+ if (INT_MAX - add_cost < pp->cost[k])
+ pp->cost[k] = INT_MAX;
+ else
+ pp->cost[k] += add_cost;
}
}
break;
@@ -1057,10 +1060,21 @@ scan_one_insn (rtx insn)
int regno = REGNO (recog_data.operand[i]);
struct costs *p = COSTS (costs, COST_INDEX (regno));
struct costs *q = op_costs[i];
+ int add_cost;
- p->mem_cost += q->mem_cost;
+ add_cost = q->mem_cost;
+ if (add_cost > 0 && INT_MAX - add_cost < p->mem_cost)
+ p->mem_cost = INT_MAX;
+ else
+ p->mem_cost += add_cost;
for (k = 0; k < cost_classes_num; k++)
- p->cost[k] += q->cost[k];
+ {
+ add_cost = q->cost[k];
+ if (add_cost > 0 && INT_MAX - add_cost < p->cost[k])
+ p->cost[k] = INT_MAX;
+ else
+ p->cost[k] += add_cost;
+ }
}
return insn;
@@ -1111,7 +1125,11 @@ print_allocno_costs (FILE *f)
fprintf (f, ",%d", COSTS (total_allocno_costs, i)->cost[k]);
}
}
- fprintf (f, " MEM:%i\n", COSTS (costs, i)->mem_cost);
+ fprintf (f, " MEM:%i", COSTS (costs, i)->mem_cost);
+ if (flag_ira_region == IRA_REGION_ALL
+ || flag_ira_region == IRA_REGION_MIXED)
+ fprintf (f, ",%d", COSTS (total_allocno_costs, i)->mem_cost);
+ fprintf (f, "\n");
}
}
@@ -1126,7 +1144,7 @@ print_pseudo_costs (FILE *f)
fprintf (f, "\n");
for (regno = max_reg_num () - 1; regno >= FIRST_PSEUDO_REGISTER; regno--)
{
- if (regno_reg_rtx[regno] == NULL_RTX)
+ if (REG_N_REFS (regno) <= 0)
continue;
fprintf (f, " r%d costs:", regno);
for (k = 0; k < cost_classes_num; k++)
@@ -1175,7 +1193,7 @@ process_bb_node_for_costs (ira_loop_tree
}
/* Find costs of register classes and memory for allocnos or pseudos
- and their best costs. Set up preferred, alternative and cover
+ and their best costs. Set up preferred, alternative and allocno
classes for pseudos. */
static void
find_costs_and_classes (FILE *dump_file)
@@ -1213,9 +1231,6 @@ find_costs_and_classes (FILE *dump_file)
if ((!allocno_p || internal_flag_ira_verbose > 0) && dump_file)
fprintf (dump_file,
"\nPass %i for finding pseudo/allocno costs\n\n", pass);
- /* We could use only cover classes. Unfortunately it does not
- work well for some targets where some subclass of cover class
- is costly and wrong cover class is chosen. */
for (i = 0; i < N_REG_CLASSES; i++)
cost_class_nums[i] = -1;
for (cost_classes_num = 0;
@@ -1262,7 +1277,7 @@ find_costs_and_classes (FILE *dump_file)
for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--)
{
ira_allocno_t a, parent_a;
- int rclass, a_num, parent_a_num;
+ int rclass, a_num, parent_a_num, add_cost;
ira_loop_tree_node_t parent;
int best_cost, allocno_cost;
enum reg_class best, alt_class;
@@ -1304,14 +1319,41 @@ find_costs_and_classes (FILE *dump_file)
tree. */
parent_a_num = ALLOCNO_NUM (parent_a);
for (k = 0; k < cost_classes_num; k++)
- COSTS (total_allocno_costs, parent_a_num)->cost[k]
- += COSTS (total_allocno_costs, a_num)->cost[k];
- COSTS (total_allocno_costs, parent_a_num)->mem_cost
- += COSTS (total_allocno_costs, a_num)->mem_cost;
+ {
+ add_cost
+ = COSTS (total_allocno_costs, a_num)->cost[k];
+ if (add_cost > 0 && INT_MAX - add_cost
+ < COSTS (total_allocno_costs, parent_a_num)->cost[k])
+ COSTS (total_allocno_costs, parent_a_num)->cost[k]
+ = INT_MAX;
+ else
+ COSTS (total_allocno_costs, parent_a_num)->cost[k]
+ += add_cost;
+ }
+ add_cost = COSTS (total_allocno_costs, a_num)->mem_cost;
+ if (add_cost > 0
+ && (INT_MAX - add_cost
+ < COSTS (total_allocno_costs,
+ parent_a_num)->mem_cost))
+ COSTS (total_allocno_costs, parent_a_num)->mem_cost
+ = INT_MAX;
+ else
+ COSTS (total_allocno_costs, parent_a_num)->mem_cost
+ += add_cost;
}
for (k = 0; k < cost_classes_num; k++)
- temp_costs->cost[k] += COSTS (costs, a_num)->cost[k];
- temp_costs->mem_cost += COSTS (costs, a_num)->mem_cost;
+ {
+ add_cost = COSTS (costs, a_num)->cost[k];
+ if (add_cost > 0 && INT_MAX - add_cost < temp_costs->cost[k])
+ temp_costs->cost[k] = INT_MAX;
+ else
+ temp_costs->cost[k] += add_cost;
+ }
+ add_cost = COSTS (costs, a_num)->mem_cost;
+ if (add_cost && INT_MAX - add_cost < temp_costs->mem_cost)
+ temp_costs->mem_cost = INT_MAX;
+ else
+ temp_costs->mem_cost += add_cost;
#ifdef FORBIDDEN_INC_DEC_CLASSES
if (in_inc_dec[a_num])
inc_dec_p = true;
@@ -1353,38 +1395,38 @@ find_costs_and_classes (FILE *dump_file)
best = (enum reg_class) rclass;
}
else if (temp_costs->cost[k] == best_cost)
- best = ira_reg_class_union[best][rclass];
+ best = ira_reg_class_subunion[best][rclass];
if (pass == flag_expensive_optimizations
&& temp_costs->cost[k] < temp_costs->mem_cost
&& (reg_class_size[reg_class_subunion[alt_class][rclass]]
> reg_class_size[alt_class]))
alt_class = reg_class_subunion[alt_class][rclass];
}
- alt_class = ira_class_translate[alt_class];
+ alt_class = ira_allocno_class_translate[alt_class];
if (best_cost > temp_costs->mem_cost)
- regno_cover_class[i] = NO_REGS;
- else if (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY)
- /* Make the common class the biggest class of best and
- alt_class. */
- regno_cover_class[i] = alt_class == NO_REGS ? best : alt_class;
+ regno_aclass[i] = NO_REGS;
else
- /* Make the common class a cover class. Remember all
- allocnos with the same regno should have the same cover
- class. */
- regno_cover_class[i] = ira_class_translate[best];
+ {
+ /* Make the common class the biggest class of best and
+ alt_class. */
+ regno_aclass[i]
+ = ira_reg_class_superunion[best][alt_class];
+ ira_assert (regno_aclass[i] != NO_REGS
+ && ira_reg_allocno_class_p[regno_aclass[i]]);
+ }
if (pass == flag_expensive_optimizations)
{
if (best_cost > temp_costs->mem_cost)
best = alt_class = NO_REGS;
else if (best == alt_class)
alt_class = NO_REGS;
- setup_reg_classes (i, best, alt_class, regno_cover_class[i]);
+ setup_reg_classes (i, best, alt_class, regno_aclass[i]);
if ((!allocno_p || internal_flag_ira_verbose > 2)
&& dump_file != NULL)
fprintf (dump_file,
- " r%d: preferred %s, alternative %s, cover %s\n",
+ " r%d: preferred %s, alternative %s, allocno %s\n",
i, reg_class_names[best], reg_class_names[alt_class],
- reg_class_names[regno_cover_class[i]]);
+ reg_class_names[regno_aclass[i]]);
}
if (! allocno_p)
{
@@ -1396,7 +1438,7 @@ find_costs_and_classes (FILE *dump_file)
a = ALLOCNO_NEXT_REGNO_ALLOCNO (a))
{
a_num = ALLOCNO_NUM (a);
- if (regno_cover_class[i] == NO_REGS)
+ if (regno_aclass[i] == NO_REGS)
best = NO_REGS;
else
{
@@ -1408,7 +1450,7 @@ find_costs_and_classes (FILE *dump_file)
for (k = 0; k < cost_classes_num; k++)
{
rclass = cost_classes[k];
- if (! ira_class_subset_p[rclass][regno_cover_class[i]])
+ if (! ira_class_subset_p[rclass][regno_aclass[i]])
continue;
/* Ignore classes that are too small for this
operand or invalid for an operand that was
@@ -1434,15 +1476,13 @@ find_costs_and_classes (FILE *dump_file)
else if (COSTS (total_allocno_costs, a_num)->cost[k]
== best_cost)
{
- best = ira_reg_class_union[best][rclass];
+ best = ira_reg_class_subunion[best][rclass];
allocno_cost
= MAX (allocno_cost, COSTS (costs, a_num)->cost[k]);
}
}
- ALLOCNO_COVER_CLASS_COST (a) = allocno_cost;
+ ALLOCNO_CLASS_COST (a) = allocno_cost;
}
- ira_assert (flag_ira_algorithm == IRA_ALGORITHM_PRIORITY
- || ira_class_translate[best] == regno_cover_class[i]);
if (internal_flag_ira_verbose > 2 && dump_file != NULL
&& (pass == 0 || pref[a_num] != best))
{
@@ -1452,9 +1492,9 @@ find_costs_and_classes (FILE *dump_file)
else
fprintf (dump_file, "l%d",
ALLOCNO_LOOP_TREE_NODE (a)->loop->num);
- fprintf (dump_file, ") best %s, cover %s\n",
+ fprintf (dump_file, ") best %s, allocno %s\n",
reg_class_names[best],
- reg_class_names[regno_cover_class[i]]);
+ reg_class_names[regno_aclass[i]]);
}
pref[a_num] = best;
}
@@ -1477,8 +1517,8 @@ find_costs_and_classes (FILE *dump_file)
\f
/* Process moves involving hard regs to modify allocno hard register
- costs. We can do this only after determining allocno cover class.
- If a hard register forms a register class, than moves with the hard
+ costs. We can do this only after determining allocno class. If a
+ hard register forms a register class, than moves with the hard
register are already taken into account in class costs for the
allocno. */
static void
@@ -1527,7 +1567,7 @@ process_bb_node_for_hard_reg_moves (ira_
}
else
continue;
- rclass = ALLOCNO_COVER_CLASS (a);
+ rclass = ALLOCNO_CLASS (a);
if (! TEST_HARD_REG_BIT (reg_class_contents[rclass], hard_regno))
continue;
i = ira_class_hard_reg_index[rclass][hard_regno];
@@ -1539,25 +1579,25 @@ process_bb_node_for_hard_reg_moves (ira_
= (to_p ? ira_get_register_move_cost (mode, hard_reg_class, rclass)
: ira_get_register_move_cost (mode, rclass, hard_reg_class)) * freq;
ira_allocate_and_set_costs (&ALLOCNO_HARD_REG_COSTS (a), rclass,
- ALLOCNO_COVER_CLASS_COST (a));
+ ALLOCNO_CLASS_COST (a));
ira_allocate_and_set_costs (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a),
rclass, 0);
ALLOCNO_HARD_REG_COSTS (a)[i] -= cost;
ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[i] -= cost;
- ALLOCNO_COVER_CLASS_COST (a) = MIN (ALLOCNO_COVER_CLASS_COST (a),
- ALLOCNO_HARD_REG_COSTS (a)[i]);
+ ALLOCNO_CLASS_COST (a) = MIN (ALLOCNO_CLASS_COST (a),
+ ALLOCNO_HARD_REG_COSTS (a)[i]);
}
}
/* After we find hard register and memory costs for allocnos, define
- its cover class and modify hard register cost because insns moving
+ its class and modify hard register cost because insns moving
allocno to/from hard registers. */
static void
-setup_allocno_cover_class_and_costs (void)
+setup_allocno_class_and_costs (void)
{
- int i, j, n, regno, num;
+ int i, j, n, hard_regno, num;
int *reg_costs;
- enum reg_class cover_class, rclass;
+ enum reg_class aclass, rclass;
ira_allocno_t a;
ira_allocno_iterator ai;
@@ -1565,35 +1605,30 @@ setup_allocno_cover_class_and_costs (voi
FOR_EACH_ALLOCNO (a, ai)
{
i = ALLOCNO_NUM (a);
- cover_class = regno_cover_class[ALLOCNO_REGNO (a)];
- ira_assert (pref[i] == NO_REGS || cover_class != NO_REGS);
+ aclass = regno_aclass[ALLOCNO_REGNO (a)];
+ ira_assert (pref[i] == NO_REGS || aclass != NO_REGS);
ALLOCNO_MEMORY_COST (a) = COSTS (costs, i)->mem_cost;
- ira_set_allocno_cover_class (a, cover_class);
- if (cover_class == NO_REGS)
+ ira_set_allocno_class (a, aclass);
+ if (aclass == NO_REGS)
continue;
- ALLOCNO_AVAILABLE_REGS_NUM (a) = ira_available_class_regs[cover_class];
- if (optimize && ALLOCNO_COVER_CLASS (a) != pref[i])
+ if (optimize && ALLOCNO_CLASS (a) != pref[i])
{
- n = ira_class_hard_regs_num[cover_class];
+ n = ira_class_hard_regs_num[aclass];
ALLOCNO_HARD_REG_COSTS (a)
- = reg_costs = ira_allocate_cost_vector (cover_class);
+ = reg_costs = ira_allocate_cost_vector (aclass);
for (j = n - 1; j >= 0; j--)
{
- regno = ira_class_hard_regs[cover_class][j];
- if (TEST_HARD_REG_BIT (reg_class_contents[pref[i]], regno))
- reg_costs[j] = ALLOCNO_COVER_CLASS_COST (a);
+ hard_regno = ira_class_hard_regs[aclass][j];
+ if (TEST_HARD_REG_BIT (reg_class_contents[pref[i]], hard_regno))
+ reg_costs[j] = ALLOCNO_CLASS_COST (a);
else
{
- rclass = REGNO_REG_CLASS (regno);
+ rclass = REGNO_REG_CLASS (hard_regno);
num = cost_class_nums[rclass];
if (num < 0)
{
- /* The hard register class is not a cover class or a
- class not fully inside in a cover class -- use
- the allocno cover class. */
- ira_assert (ira_hard_regno_cover_class[regno]
- == cover_class);
- num = cost_class_nums[cover_class];
+ num = cost_class_nums[aclass];
+ ira_assert (num >= 0);
}
reg_costs[j] = COSTS (costs, i)->cost[num];
}
@@ -1658,7 +1693,8 @@ ira_init_costs (void)
free_ira_costs ();
max_struct_costs_size
= sizeof (struct costs) + sizeof (int) * (ira_important_classes_num - 1);
- /* Don't use ira_allocate because vectors live through several IRA calls. */
+ /* Don't use ira_allocate because vectors live through several IRA
+ calls. */
init_cost = (struct costs *) xmalloc (max_struct_costs_size);
init_cost->mem_cost = 1000000;
for (i = 0; i < ira_important_classes_num; i++)
@@ -1690,12 +1726,10 @@ init_costs (void)
init_subregs_of_mode ();
costs = (struct costs *) ira_allocate (max_struct_costs_size
* cost_elements_num);
- pref_buffer
- = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
- * cost_elements_num);
- regno_cover_class
- = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
- * max_reg_num ());
+ pref_buffer = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
+ * cost_elements_num);
+ regno_aclass = (enum reg_class *) ira_allocate (sizeof (enum reg_class)
+ * max_reg_num ());
regno_equiv_gains = (int *) ira_allocate (sizeof (int) * max_reg_num ());
memset (regno_equiv_gains, 0, sizeof (int) * max_reg_num ());
}
@@ -1706,13 +1740,13 @@ static void
finish_costs (void)
{
ira_free (regno_equiv_gains);
- ira_free (regno_cover_class);
+ ira_free (regno_aclass);
ira_free (pref_buffer);
ira_free (costs);
}
-/* Entry function which defines cover class, memory and hard register
- costs for each allocno. */
+/* Entry function which defines register class, memory and hard
+ register costs for each allocno. */
void
ira_costs (void)
{
@@ -1723,7 +1757,7 @@ ira_costs (void)
* ira_allocnos_num);
calculate_elim_costs_all_insns ();
find_costs_and_classes (ira_dump_file);
- setup_allocno_cover_class_and_costs ();
+ setup_allocno_class_and_costs ();
finish_costs ();
ira_free (total_allocno_costs);
}
@@ -1747,32 +1781,35 @@ ira_set_pseudo_classes (FILE *dump_file)
function calls. This is called only when we found all intersected
calls during building allocno live ranges. */
void
-ira_tune_allocno_costs_and_cover_classes (void)
+ira_tune_allocno_costs (void)
{
int j, n, regno;
int cost, min_cost, *reg_costs;
- enum reg_class cover_class, rclass;
+ enum reg_class aclass, rclass;
enum machine_mode mode;
ira_allocno_t a;
ira_allocno_iterator ai;
FOR_EACH_ALLOCNO (a, ai)
{
- cover_class = ALLOCNO_COVER_CLASS (a);
- if (cover_class == NO_REGS)
+ aclass = ALLOCNO_CLASS (a);
+ if (aclass == NO_REGS)
continue;
mode = ALLOCNO_MODE (a);
- n = ira_class_hard_regs_num[cover_class];
+ n = ira_class_hard_regs_num[aclass];
min_cost = INT_MAX;
if (ALLOCNO_CALLS_CROSSED_NUM (a) != 0)
{
ira_allocate_and_set_costs
- (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
- ALLOCNO_COVER_CLASS_COST (a));
+ (&ALLOCNO_HARD_REG_COSTS (a), aclass,
+ ALLOCNO_CLASS_COST (a));
reg_costs = ALLOCNO_HARD_REG_COSTS (a);
for (j = n - 1; j >= 0; j--)
{
- regno = ira_class_hard_regs[cover_class][j];
+ regno = ira_class_hard_regs[aclass][j];
+ if (! ira_hard_reg_not_in_set_p (regno, mode,
+ ALLOCNO_CONFLICT_HARD_REGS (a)))
+ continue;
rclass = REGNO_REG_CLASS (regno);
cost = 0;
if (! ira_hard_reg_not_in_set_p (regno, mode, call_used_reg_set)
@@ -1786,13 +1823,16 @@ ira_tune_allocno_costs_and_cover_classes
* ALLOCNO_FREQ (a)
* IRA_HARD_REGNO_ADD_COST_MULTIPLIER (regno) / 2);
#endif
- reg_costs[j] += cost;
+ if (INT_MAX - cost < reg_costs[j])
+ reg_costs[j] = INT_MAX;
+ else
+ reg_costs[j] += cost;
if (min_cost > reg_costs[j])
min_cost = reg_costs[j];
}
}
if (min_cost != INT_MAX)
- ALLOCNO_COVER_CLASS_COST (a) = min_cost;
+ ALLOCNO_CLASS_COST (a) = min_cost;
/* Some targets allow pseudos to be allocated to unaligned
sequences of hard registers. However, selecting an unaligned
@@ -1802,18 +1842,17 @@ ira_tune_allocno_costs_and_cover_classes
{
int nregs, index;
- if ((nregs = ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)]) > 1)
+ if ((nregs = ira_reg_class_max_nregs[aclass][ALLOCNO_MODE (a)]) > 1)
{
ira_allocate_and_set_costs
- (&ALLOCNO_HARD_REG_COSTS (a), cover_class,
- ALLOCNO_COVER_CLASS_COST (a));
+ (&ALLOCNO_HARD_REG_COSTS (a), aclass, ALLOCNO_CLASS_COST (a));
reg_costs = ALLOCNO_HARD_REG_COSTS (a);
for (j = n - 1; j >= 0; j--)
{
if (j % nregs != 0)
{
- regno = ira_non_ordered_class_hard_regs[cover_class][j];
- index = ira_class_hard_reg_index[cover_class][regno];
+ regno = ira_non_ordered_class_hard_regs[aclass][j];
+ index = ira_class_hard_reg_index[aclass][regno];
ira_assert (index != -1);
reg_costs[index] += ALLOCNO_FREQ (a);
}
Index: rtl.h
===================================================================
--- rtl.h (revision 161709)
+++ rtl.h (working copy)
@@ -1934,7 +1934,7 @@ extern const char *decode_asm_operands (
extern enum reg_class reg_preferred_class (int);
extern enum reg_class reg_alternate_class (int);
-extern enum reg_class reg_cover_class (int);
+extern enum reg_class reg_allocno_class (int);
extern void setup_reg_classes (int, enum reg_class, enum reg_class,
enum reg_class);
Index: sched-int.h
===================================================================
--- sched-int.h (revision 161709)
+++ sched-int.h (working copy)
@@ -653,9 +653,9 @@ extern struct haifa_sched_info *current_
up. */
extern bool sched_pressure_p;
-/* Map regno -> its cover class. The map defined only when
+/* Map regno -> its pressure class. The map defined only when
SCHED_PRESSURE_P is true. */
-extern enum reg_class *sched_regno_cover_class;
+extern enum reg_class *sched_regno_pressure_class;
/* Indexed by INSN_UID, the collection of all data associated with
a single instruction. */
@@ -707,7 +707,7 @@ struct _haifa_deps_insn_data
#define INCREASE_BITS 8
/* The structure describes how the corresponding insn increases the
- register pressure for each cover class. */
+ register pressure for each pressure class. */
struct reg_pressure_data
{
/* Pressure increase for given class because of clobber. */
@@ -736,7 +736,7 @@ struct reg_use_data
};
/* The following structure describes used sets of registers by insns.
- Registers are pseudos whose cover class is not NO_REGS or hard
+ Registers are pseudos whose pressure class is not NO_REGS or hard
registers available for allocations. */
struct reg_set_data
{
@@ -804,7 +804,7 @@ struct _haifa_insn_data
struct reg_pressure_data *reg_pressure;
/* The following array contains maximal reg pressure between last
scheduled insn and given insn. There is an element for each
- cover class of pseudos referenced in insns. This info updated
+ pressure class of pseudos referenced in insns. This info updated
after scheduling each insn for each insn between the two
mentioned insns. */
int *max_reg_pressure;
Index: reginfo.c
===================================================================
--- reginfo.c (revision 161709)
+++ reginfo.c (working copy)
@@ -1,7 +1,7 @@
/* Compute different info about registers.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996
1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- 2009 Free Software Foundation, Inc.
+ 2009, 2010 Free Software Foundation, Inc.
This file is part of GCC.
@@ -914,9 +914,9 @@ struct reg_pref
union of most major pair of classes, that generality is not required. */
char altclass;
- /* coverclass is a register class that IRA uses for allocating
+ /* allocnoclass is a register class that IRA uses for allocating
the pseudo. */
- char coverclass;
+ char allocnoclass;
};
/* Record preferences of each pseudo. This is available after RA is
@@ -949,12 +949,12 @@ reg_alternate_class (int regno)
/* Return the reg_class which is used by IRA for its allocation. */
enum reg_class
-reg_cover_class (int regno)
+reg_allocno_class (int regno)
{
if (reg_pref == 0)
return NO_REGS;
- return (enum reg_class) reg_pref[regno].coverclass;
+ return (enum reg_class) reg_pref[regno].allocnoclass;
}
\f
@@ -1051,18 +1051,18 @@ struct rtl_opt_pass pass_reginfo_init =
\f
/* Set up preferred, alternate, and cover classes for REGNO as
- PREFCLASS, ALTCLASS, and COVERCLASS. */
+ PREFCLASS, ALTCLASS, and ALLOCNOCLASS. */
void
setup_reg_classes (int regno,
enum reg_class prefclass, enum reg_class altclass,
- enum reg_class coverclass)
+ enum reg_class allocnoclass)
{
if (reg_pref == NULL)
return;
gcc_assert (reg_info_size == max_reg_num ());
reg_pref[regno].prefclass = prefclass;
reg_pref[regno].altclass = altclass;
- reg_pref[regno].coverclass = coverclass;
+ reg_pref[regno].allocnoclass = allocnoclass;
}
\f
Index: Makefile.in
===================================================================
--- Makefile.in (revision 161709)
+++ Makefile.in (working copy)
@@ -3327,7 +3327,7 @@ ira-conflicts.o: ira-conflicts.c $(CONFI
ira-color.o: ira-color.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(TARGET_H) $(RTL_H) $(REGS_H) hard-reg-set.h $(FLAGS_H) \
$(EXPR_H) $(BASIC_BLOCK_H) $(TOPLEV_H) $(TM_P_H) reload.h $(PARAMS_H) \
- $(DF_H) $(SPLAY_TREE_H) $(IRA_INT_H)
+ $(DF_H) $(IRA_INT_H)
ira-emit.o: ira-emit.c $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) \
$(REGS_H) $(RTL_H) $(TM_P_H) $(TARGET_H) $(FLAGS_H) hard-reg-set.h \
$(BASIC_BLOCK_H) $(EXPR_H) $(RECOG_H) $(PARAMS_H) $(TIMEVAR_H) \
Index: config/alpha/alpha.h
===================================================================
--- config/alpha/alpha.h (revision 161709)
+++ config/alpha/alpha.h (working copy)
@@ -548,19 +548,6 @@ enum reg_class {
{0x00000000, 0x7fffffff}, /* FLOAT_REGS */ \
{0xffffffff, 0xffffffff} }
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, FLOAT_REGS, LIM_REG_CLASSES \
-}
-
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
Index: config/frv/frv.h
===================================================================
--- config/frv/frv.h (revision 161709)
+++ config/frv/frv.h (working copy)
@@ -1155,21 +1155,6 @@ enum reg_class
{ 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0x1fff}, /* ALL_REGS */\
}
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GPR_REGS, FPR_REGS, ACC_REGS, ICR_REGS, FCR_REGS, ICC_REGS, FCC_REGS, \
- ACCG_REGS, SPR_REGS, \
- LIM_REG_CLASSES \
-}
-
/* A C expression whose value is a register class containing hard register
REGNO. In general there is more than one such class; choose a class which
is "minimal", meaning that no smaller class also contains the register. */
Index: config/s390/s390.h
===================================================================
--- config/s390/s390.h (revision 161709)
+++ config/s390/s390.h (working copy)
@@ -490,19 +490,6 @@ enum reg_class
{ 0xffffffff, 0x0000003f }, /* ALL_REGS */ \
}
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, FP_REGS, CC_REGS, ACCESS_REGS, LIM_REG_CLASSES \
-}
-
/* In some case register allocation order is not enough for IRA to
generate a good code. The following macro (if defined) increases
cost of REGNO for a pseudo approximately by pseudo usage frequency
Index: config/spu/spu.h
===================================================================
--- config/spu/spu.h (revision 161709)
+++ config/spu/spu.h (working copy)
@@ -199,9 +199,6 @@ enum reg_class {
LIM_REG_CLASSES
};
-/* SPU is simple, it really only has one class of registers. */
-#define IRA_COVER_CLASSES { GENERAL_REGS, LIM_REG_CLASSES }
-
#define N_REG_CLASSES (int) LIM_REG_CLASSES
#define REG_CLASS_NAMES \
Index: config/sparc/sparc.h
===================================================================
--- config/sparc/sparc.h (revision 161709)
+++ config/sparc/sparc.h (working copy)
@@ -1077,19 +1077,6 @@ extern enum reg_class sparc_regno_reg_cl
#define REGNO_REG_CLASS(REGNO) sparc_regno_reg_class[(REGNO)]
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, EXTRA_FP_REGS, FPCC_REGS, LIM_REG_CLASSES \
-}
-
/* Defines invalid mode changes. Borrowed from pa64-regs.h.
SImode loads to floating-point registers are not zero-extended.
Index: config/mep/mep.h
===================================================================
--- config/mep/mep.h (revision 161709)
+++ config/mep/mep.h (working copy)
@@ -417,8 +417,6 @@ enum reg_class
#define REGNO_REG_CLASS(REGNO) mep_regno_reg_class (REGNO)
-#define IRA_COVER_CLASSES { GENERAL_REGS, CONTROL_REGS, CR_REGS, CCR_REGS, LIM_REG_CLASSES }
-
#define BASE_REG_CLASS GENERAL_REGS
#define INDEX_REG_CLASS GENERAL_REGS
Index: config/m32r/m32r.h
===================================================================
--- config/m32r/m32r.h (revision 161709)
+++ config/m32r/m32r.h (working copy)
@@ -624,11 +624,6 @@ enum reg_class
NO_REGS, CARRY_REG, ACCUM_REGS, GENERAL_REGS, ALL_REGS, LIM_REG_CLASSES
};
-#define IRA_COVER_CLASSES \
-{ \
- ACCUM_REGS, GENERAL_REGS, LIM_REG_CLASSES \
-}
-
#define N_REG_CLASSES ((int) LIM_REG_CLASSES)
/* Give names of register classes as strings for dump file. */
Index: config/rx/rx.h
===================================================================
--- config/rx/rx.h (revision 161709)
+++ config/rx/rx.h (working copy)
@@ -192,11 +192,6 @@ enum reg_class
{ 0x0000ffff } /* All registers. */ \
}
-#define IRA_COVER_CLASSES \
- { \
- GR_REGS, LIM_REG_CLASSES \
- }
-
#define SMALL_REGISTER_CLASSES 0
#define N_REG_CLASSES (int) LIM_REG_CLASSES
#define CLASS_MAX_NREGS(CLASS, MODE) ((GET_MODE_SIZE (MODE) \
Index: config/i386/i386.h
===================================================================
--- config/i386/i386.h (revision 161709)
+++ config/i386/i386.h (working copy)
@@ -879,9 +879,6 @@ enum target_cpu_default
|| ((MODE) == DFmode && (!TARGET_SSE2 || !TARGET_SSE_MATH)) \
|| (MODE) == XFmode)
-/* Cover class containing the stack registers. */
-#define STACK_REG_COVER_CLASS FLOAT_REGS
-
/* Number of actual hardware registers.
The hardware registers are assigned numbers for the compiler
from 0 to just below FIRST_PSEUDO_REGISTER.
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c (revision 161709)
+++ config/i386/i386.c (working copy)
@@ -25290,22 +25290,6 @@ ix86_free_from_memory (enum machine_mode
}
}
-/* Implement TARGET_IRA_COVER_CLASSES. If -mfpmath=sse, we prefer
- SSE_REGS to FLOAT_REGS if their costs for a pseudo are the
- same. */
-static const reg_class_t *
-i386_ira_cover_classes (void)
-{
- static const reg_class_t sse_fpmath_classes[] = {
- GENERAL_REGS, SSE_REGS, MMX_REGS, FLOAT_REGS, LIM_REG_CLASSES
- };
- static const reg_class_t no_sse_fpmath_classes[] = {
- GENERAL_REGS, FLOAT_REGS, MMX_REGS, SSE_REGS, LIM_REG_CLASSES
- };
-
- return TARGET_SSE_MATH ? sse_fpmath_classes : no_sse_fpmath_classes;
-}
-
/* Put float CONST_DOUBLE in the constant pool instead of fp regs.
QImode must go into class Q_REGS.
Narrow ALL_REGS to GENERAL_REGS. This supports allowing movsf and
@@ -30992,9 +30976,6 @@ ix86_enum_va_list (int idx, const char *
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P ix86_legitimate_address_p
-#undef TARGET_IRA_COVER_CLASSES
-#define TARGET_IRA_COVER_CLASSES i386_ira_cover_classes
-
#undef TARGET_FRAME_POINTER_REQUIRED
#define TARGET_FRAME_POINTER_REQUIRED ix86_frame_pointer_required
Index: config/sh/sh.h
===================================================================
--- config/sh/sh.h (revision 161709)
+++ config/sh/sh.h (working copy)
@@ -1195,20 +1195,6 @@ enum reg_class
extern enum reg_class regno_reg_class[FIRST_PSEUDO_REGISTER];
#define REGNO_REG_CLASS(REGNO) regno_reg_class[(REGNO)]
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, FP_REGS, PR_REGS, T_REGS, MAC_REGS, TARGET_REGS, \
- FPUL_REGS, LIM_REG_CLASSES \
-}
-
/* When this hook returns true for MODE, the compiler allows
registers explicitly used in the rtl to be used as spill registers
but prevents the compiler from extending the lifetime of these
Index: config/avr/avr.h
===================================================================
--- config/avr/avr.h (revision 161709)
+++ config/avr/avr.h (working copy)
@@ -300,19 +300,6 @@ enum reg_class {
#define REGNO_REG_CLASS(R) avr_regno_reg_class(R)
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, LIM_REG_CLASSES \
-}
-
#define BASE_REG_CLASS (reload_completed ? BASE_POINTER_REGS : POINTER_REGS)
#define INDEX_REG_CLASS NO_REGS
Index: config/crx/crx.h
===================================================================
--- config/crx/crx.h (revision 161709)
+++ config/crx/crx.h (working copy)
@@ -183,19 +183,6 @@ enum reg_class
#define N_REG_CLASSES (int) LIM_REG_CLASSES
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, LIM_REG_CLASSES \
-}
-
#define REG_CLASS_NAMES \
{ \
"NO_REGS", \
Index: config/xtensa/xtensa.h
===================================================================
--- config/xtensa/xtensa.h (revision 161709)
+++ config/xtensa/xtensa.h (working copy)
@@ -459,11 +459,6 @@ enum reg_class
{ 0xffffffff, 0x0000000f } /* all registers */ \
}
-#define IRA_COVER_CLASSES \
-{ \
- BR_REGS, FP_REGS, ACC_REG, AR_REGS, LIM_REG_CLASSES \
-}
-
/* A C expression whose value is a register class containing hard
register REGNO. In general there is more that one such class;
choose a class which is "minimal", meaning that no smaller class
Index: config/stormy16/stormy16.h
===================================================================
--- config/stormy16/stormy16.h (revision 161709)
+++ config/stormy16/stormy16.h (working copy)
@@ -174,11 +174,6 @@ enum reg_class
#define N_REG_CLASSES ((int) LIM_REG_CLASSES)
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, LIM_REG_CLASSES \
-}
-
#define REG_CLASS_NAMES \
{ \
"NO_REGS", \
Index: config/fr30/fr30.h
===================================================================
--- config/fr30/fr30.h (revision 161709)
+++ config/fr30/fr30.h (working copy)
@@ -282,11 +282,6 @@ enum reg_class
#define GENERAL_REGS REAL_REGS
#define N_REG_CLASSES ((int) LIM_REG_CLASSES)
-#define IRA_COVER_CLASSES \
-{ \
- REAL_REGS, MULTIPLY_64_REG, LIM_REG_CLASSES \
-}
-
/* An initializer containing the names of the register classes as C string
constants. These names are used in writing some of the debugging dumps. */
#define REG_CLASS_NAMES \
Index: config/moxie/moxie.h
===================================================================
--- config/moxie/moxie.h (revision 161709)
+++ config/moxie/moxie.h (working copy)
@@ -133,15 +133,6 @@ enum reg_class
};
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-#define IRA_COVER_CLASSES { GENERAL_REGS, LIM_REG_CLASSES }
-
#define REG_CLASS_CONTENTS \
{ { 0x00000000 }, /* Empty */ \
{ 0x0003FFFF }, /* $fp, $sp, $r0 to $r13, ?fp */ \
Index: config/cris/cris.h
===================================================================
--- config/cris/cris.h (revision 161709)
+++ config/cris/cris.h (working copy)
@@ -583,8 +583,6 @@ enum reg_class
#define INDEX_REG_CLASS GENERAL_REGS
-#define IRA_COVER_CLASSES { GENERAL_REGS, SPECIAL_REGS, LIM_REG_CLASSES }
-
#define REG_CLASS_FROM_LETTER(C) \
( \
(C) == 'a' ? ACR_REGS : \
Index: config/iq2000/iq2000.h
===================================================================
--- config/iq2000/iq2000.h (revision 161709)
+++ config/iq2000/iq2000.h (working copy)
@@ -202,11 +202,6 @@ enum reg_class
#define N_REG_CLASSES (int) LIM_REG_CLASSES
-#define IRA_COVER_CLASSES \
-{ \
- GR_REGS, LIM_REG_CLASSES \
-}
-
#define REG_CLASS_NAMES \
{ \
"NO_REGS", \
Index: config/mn10300/mn10300.h
===================================================================
--- config/mn10300/mn10300.h (revision 161709)
+++ config/mn10300/mn10300.h (working copy)
@@ -303,19 +303,6 @@ enum reg_class {
{ 0xffffffff, 0x3ffff } /* ALL_REGS */ \
}
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, FP_REGS, LIM_REG_CLASSES \
-}
-
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
Index: config/ia64/ia64.h
===================================================================
--- config/ia64/ia64.h (revision 161709)
+++ config/ia64/ia64.h (working copy)
@@ -808,19 +808,6 @@ enum reg_class
0xFFFFFFFF, 0xFFFFFFFF, 0x3FFF }, \
}
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- PR_REGS, BR_REGS, AR_M_REGS, AR_I_REGS, GR_REGS, FR_REGS, LIM_REG_CLASSES \
-}
-
/* A C expression whose value is a register class containing hard register
REGNO. In general there is more than one such class; choose a class which
is "minimal", meaning that no smaller class also contains the register. */
Index: config/m68k/m68k.h
===================================================================
--- config/m68k/m68k.h (revision 161709)
+++ config/m68k/m68k.h (working copy)
@@ -517,10 +517,6 @@ extern enum reg_class regno_reg_class[];
#define REGISTER_MOVE_COST(MODE, CLASS1, CLASS2) \
((((CLASS1) == FP_REGS) != ((CLASS2) == FP_REGS)) ? 4 : 2)
-#define IRA_COVER_CLASSES \
-{ \
- ALL_REGS, LIM_REG_CLASSES \
-}
\f
/* Stack layout; function entry, exit and calling. */
Index: config/rs6000/rs6000.c
===================================================================
--- config/rs6000/rs6000.c (revision 161709)
+++ config/rs6000/rs6000.c (working copy)
@@ -1244,8 +1244,6 @@ static reg_class_t rs6000_secondary_relo
enum machine_mode,
struct secondary_reload_info *);
-static const reg_class_t *rs6000_ira_cover_classes (void);
-
const int INSN_NOT_AVAILABLE = -1;
static enum machine_mode rs6000_eh_return_filter_mode (void);
static bool rs6000_can_eliminate (const int, const int);
@@ -1615,9 +1613,6 @@ static const struct attribute_spec rs600
#undef TARGET_SECONDARY_RELOAD
#define TARGET_SECONDARY_RELOAD rs6000_secondary_reload
-#undef TARGET_IRA_COVER_CLASSES
-#define TARGET_IRA_COVER_CLASSES rs6000_ira_cover_classes
-
#undef TARGET_LEGITIMATE_ADDRESS_P
#define TARGET_LEGITIMATE_ADDRESS_P rs6000_legitimate_address_p
@@ -14128,26 +14123,6 @@ rs6000_secondary_reload_inner (rtx reg,
return;
}
-/* Target hook to return the cover classes for Integrated Register Allocator.
- Cover classes is a set of non-intersected register classes covering all hard
- registers used for register allocation purpose. Any move between two
- registers of a cover class should be cheaper than load or store of the
- registers. The value is array of register classes with LIM_REG_CLASSES used
- as the end marker.
-
- We need two IRA_COVER_CLASSES, one for pre-VSX, and the other for VSX to
- account for the Altivec and Floating registers being subsets of the VSX
- register set under VSX, but distinct register sets on pre-VSX machines. */
-
-static const reg_class_t *
-rs6000_ira_cover_classes (void)
-{
- static const reg_class_t cover_pre_vsx[] = IRA_COVER_CLASSES_PRE_VSX;
- static const reg_class_t cover_vsx[] = IRA_COVER_CLASSES_VSX;
-
- return (TARGET_VSX) ? cover_vsx : cover_pre_vsx;
-}
-
/* Allocate a 64-bit stack slot to be used for copying SDmode
values through if this function has any SDmode references. */
Index: config/rs6000/rs6000.h
===================================================================
--- config/rs6000/rs6000.h (revision 161709)
+++ config/rs6000/rs6000.h (working copy)
@@ -1347,34 +1347,6 @@ enum reg_class
{ 0xffffffff, 0xffffffff, 0xffffffff, 0x0003ffff } /* ALL_REGS */ \
}
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker.
-
- We need two IRA_COVER_CLASSES, one for pre-VSX, and the other for VSX to
- account for the Altivec and Floating registers being subsets of the VSX
- register set. */
-
-#define IRA_COVER_CLASSES_PRE_VSX \
-{ \
- GENERAL_REGS, SPECIAL_REGS, FLOAT_REGS, ALTIVEC_REGS, /* VSX_REGS, */ \
- /* VRSAVE_REGS,*/ VSCR_REGS, SPE_ACC_REGS, SPEFSCR_REGS, \
- /* MQ_REGS, LINK_REGS, CTR_REGS, */ \
- CR_REGS, CA_REGS, LIM_REG_CLASSES \
-}
-
-#define IRA_COVER_CLASSES_VSX \
-{ \
- GENERAL_REGS, SPECIAL_REGS, /* FLOAT_REGS, ALTIVEC_REGS, */ VSX_REGS, \
- /* VRSAVE_REGS,*/ VSCR_REGS, SPE_ACC_REGS, SPEFSCR_REGS, \
- /* MQ_REGS, LINK_REGS, CTR_REGS, */ \
- CR_REGS, CA_REGS, LIM_REG_CLASSES \
-}
-
/* The same information, inverted:
Return the class number of the smallest class containing
reg number REGNO. This could be a conditional expression
Index: config/picochip/picochip.h
===================================================================
--- config/picochip/picochip.h (revision 161709)
+++ config/picochip/picochip.h (working copy)
@@ -300,19 +300,6 @@ enum reg_class
#define N_REG_CLASSES (int) LIM_REG_CLASSES
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GR_REGS, LIM_REG_CLASSES \
-}
-
/* The names of the register classes */
#define REG_CLASS_NAMES \
Index: config/mcore/mcore.h
===================================================================
--- config/mcore/mcore.h (revision 161709)
+++ config/mcore/mcore.h (working copy)
@@ -366,11 +366,6 @@ enum reg_class
#define N_REG_CLASSES (int) LIM_REG_CLASSES
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, C_REGS, LIM_REG_CLASSES \
-}
-
/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
Index: config/score/score.h
===================================================================
--- config/score/score.h (revision 161709)
+++ config/score/score.h (working copy)
@@ -440,18 +440,6 @@ enum reg_class
also contains the register. */
#define REGNO_REG_CLASS(REGNO) score_reg_class (REGNO)
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-#define IRA_COVER_CLASSES \
-{ \
- G32_REGS, CE_REGS, SP_REGS, LIM_REG_CLASSES \
-}
-
/* A macro whose definition is the name of the class to which a
valid base register must belong. A base register is one used in
an address which is the register value plus a displacement. */
Index: config/arm/arm.h
===================================================================
--- config/arm/arm.h (revision 161709)
+++ config/arm/arm.h (working copy)
@@ -1222,20 +1222,6 @@ enum reg_class
or could index an array. */
#define REGNO_REG_CLASS(REGNO) arm_regno_class (REGNO)
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, FPA_REGS, CIRRUS_REGS, VFP_REGS, IWMMXT_GR_REGS, IWMMXT_REGS,\
- LIM_REG_CLASSES \
-}
-
/* FPA registers can't do subreg as all values are reformatted to internal
precision. VFP registers may only be accessed in the mode they
were set. */
Index: config/pa/pa32-regs.h
===================================================================
--- config/pa/pa32-regs.h (revision 161709)
+++ config/pa/pa32-regs.h (working copy)
@@ -311,19 +311,6 @@ enum reg_class { NO_REGS, R1_REGS, GENER
{0x00000000, 0x00000000, 0x01000000}, /* SHIFT_REGS */ \
{0xfffffffe, 0xffffffff, 0x01ffffff}} /* ALL_REGS */
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, FP_REGS, SHIFT_REGS, LIM_REG_CLASSES \
-}
-
/* Defines invalid mode changes. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
Index: config/pa/pa64-regs.h
===================================================================
--- config/pa/pa64-regs.h (revision 161709)
+++ config/pa/pa64-regs.h (working copy)
@@ -242,19 +242,6 @@ enum reg_class { NO_REGS, R1_REGS, GENER
{0x00000000, 0x10000000}, /* SHIFT_REGS */ \
{0xfffffffe, 0x1fffffff}} /* ALL_REGS */
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, FP_REGS, SHIFT_REGS, LIM_REG_CLASSES \
-}
-
/* Defines invalid mode changes. */
#define CANNOT_CHANGE_MODE_CLASS(FROM, TO, CLASS) \
Index: config/mips/mips.c
===================================================================
--- config/mips/mips.c (revision 161709)
+++ config/mips/mips.c (working copy)
@@ -10927,29 +10927,6 @@ mips_register_move_cost (enum machine_mo
return 0;
}
-/* Implement TARGET_IRA_COVER_CLASSES. */
-
-static const reg_class_t *
-mips_ira_cover_classes (void)
-{
- static const reg_class_t acc_classes[] = {
- GR_AND_ACC_REGS, FP_REGS, COP0_REGS, COP2_REGS, COP3_REGS,
- ST_REGS, LIM_REG_CLASSES
- };
- static const reg_class_t no_acc_classes[] = {
- GR_REGS, FP_REGS, COP0_REGS, COP2_REGS, COP3_REGS,
- ST_REGS, LIM_REG_CLASSES
- };
-
- /* Don't allow the register allocators to use LO and HI in MIPS16 mode,
- which has no MTLO or MTHI instructions. Also, using GR_AND_ACC_REGS
- as a cover class only works well when we keep per-register costs.
- Using it when not optimizing can cause us to think accumulators
- have the same cost as GPRs in cases where GPRs are actually much
- cheaper. */
- return TARGET_MIPS16 || !optimize ? no_acc_classes : acc_classes;
-}
-
/* Return the register class required for a secondary register when
copying between one of the registers in RCLASS and value X, which
has mode MODE. X is the source of the move if IN_P, otherwise it
@@ -16453,9 +16430,6 @@ void mips_function_profiler (FILE *file)
#undef TARGET_DWARF_REGISTER_SPAN
#define TARGET_DWARF_REGISTER_SPAN mips_dwarf_register_span
-#undef TARGET_IRA_COVER_CLASSES
-#define TARGET_IRA_COVER_CLASSES mips_ira_cover_classes
-
#undef TARGET_ASM_FINAL_POSTSCAN_INSN
#define TARGET_ASM_FINAL_POSTSCAN_INSN mips_final_postscan_insn
Index: config/vax/vax.h
===================================================================
--- config/vax/vax.h (revision 161709)
+++ config/vax/vax.h (working copy)
@@ -228,15 +228,6 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_
#define REG_CLASS_NAMES \
{ "NO_REGS", "ALL_REGS" }
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-#define IRA_COVER_CLASSES { ALL_REGS, LIM_REG_CLASSES }
-
/* Return the maximum number of consecutive registers
needed to represent mode MODE in a register of class CLASS. */
#define CLASS_MAX_NREGS(CLASS, MODE) \
Index: config/h8300/h8300.h
===================================================================
--- config/h8300/h8300.h (revision 161709)
+++ config/h8300/h8300.h (working copy)
@@ -360,19 +360,6 @@ enum reg_class {
{ "NO_REGS", "COUNTER_REGS", "SOURCE_REGS", "DESTINATION_REGS", \
"GENERAL_REGS", "MAC_REGS", "ALL_REGS", "LIM_REGS" }
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, MAC_REGS, LIM_REG_CLASSES \
-}
-
/* Define which registers fit in which classes.
This is an initializer for a vector of HARD_REG_SET
of length N_REG_CLASSES. */
Index: config/v850/v850.h
===================================================================
--- config/v850/v850.h (revision 161709)
+++ config/v850/v850.h (working copy)
@@ -318,11 +318,6 @@ enum reg_class
#define N_REG_CLASSES (int) LIM_REG_CLASSES
-#define IRA_COVER_CLASSES \
-{ \
- GENERAL_REGS, LIM_REG_CLASSES \
-}
-
/* Give names of register classes as strings for dump file. */
#define REG_CLASS_NAMES \
Index: config/bfin/bfin.h
===================================================================
--- config/bfin/bfin.h (revision 161709)
+++ config/bfin/bfin.h (working copy)
@@ -743,19 +743,6 @@ enum reg_class
: (REGNO) >= REG_RETS ? PROLOGUE_REGS \
: NO_REGS)
-/* The following macro defines cover classes for Integrated Register
- Allocator. Cover classes is a set of non-intersected register
- classes covering all hard registers used for register allocation
- purpose. Any move between two registers of a cover class should be
- cheaper than load or store of the registers. The macro value is
- array of register classes with LIM_REG_CLASSES used as the end
- marker. */
-
-#define IRA_COVER_CLASSES \
-{ \
- MOST_REGS, AREGS, CCREGS, LIM_REG_CLASSES \
-}
-
/* When this hook returns true for MODE, the compiler allows
registers explicitly used in the rtl to be used as spill registers
but prevents the compiler from extending the lifetime of these
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: IRA improvements 1/4
2010-07-07 13:32 IRA improvements 1/4 Vladimir Makarov
@ 2010-07-07 20:27 ` Bernd Schmidt
2010-07-07 20:35 ` Vladimir Makarov
2010-07-26 14:17 ` Joseph S. Myers
` (2 subsequent siblings)
3 siblings, 1 reply; 8+ messages in thread
From: Bernd Schmidt @ 2010-07-07 20:27 UTC (permalink / raw)
To: Vladimir Makarov; +Cc: gcc-patches, Jeffrey Law
On 07/07/2010 03:31 PM, Vladimir Makarov wrote:
> The patch removes -fira-coalesce because it is really hard to
> implement it with the new dynamically calculated allocno classes.
> The patch uses also new spilling algorithms because of the same reason.
> Removing -fira-coalesce is not a big deal because it is not used and
> its most functionality is implemented by IRA preferencing technique.
coalesce_allocnos is still present. Is this only used for sharing stack
slots now?
Bernd
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: IRA improvements 1/4
2010-07-07 20:27 ` Bernd Schmidt
@ 2010-07-07 20:35 ` Vladimir Makarov
0 siblings, 0 replies; 8+ messages in thread
From: Vladimir Makarov @ 2010-07-07 20:35 UTC (permalink / raw)
To: Bernd Schmidt; +Cc: gcc-patches, Jeffrey Law
Bernd Schmidt wrote:
> On 07/07/2010 03:31 PM, Vladimir Makarov wrote:
>
>> The patch removes -fira-coalesce because it is really hard to
>> implement it with the new dynamically calculated allocno classes.
>> The patch uses also new spilling algorithms because of the same reason.
>> Removing -fira-coalesce is not a big deal because it is not used and
>> its most functionality is implemented by IRA preferencing technique.
>>
>
> coalesce_allocnos is still present. Is this only used for sharing stack
> slots now?
>
>
Yes. It is used only for stack slots.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: IRA improvements 1/4
2010-07-07 13:32 IRA improvements 1/4 Vladimir Makarov
2010-07-07 20:27 ` Bernd Schmidt
@ 2010-07-26 14:17 ` Joseph S. Myers
2010-08-02 19:22 ` Jeff Law
2010-08-03 17:01 ` Jeff Law
3 siblings, 0 replies; 8+ messages in thread
From: Joseph S. Myers @ 2010-07-26 14:17 UTC (permalink / raw)
To: Vladimir Makarov; +Cc: gcc-patches, Jeffrey Law
On Wed, 7 Jul 2010, Vladimir Makarov wrote:
> * doc/tm.texi: Remove TARGET_IRA_COVER_CLASSES and
> IRA_COVER_CLASSES.
When target macros or hooks are removed, they should be added to the lists
of poisoned macros in system.h to help ensure people update ports when
moving them to newer versions of GCC.
--
Joseph S. Myers
joseph@codesourcery.com
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: IRA improvements 1/4
2010-07-07 13:32 IRA improvements 1/4 Vladimir Makarov
2010-07-07 20:27 ` Bernd Schmidt
2010-07-26 14:17 ` Joseph S. Myers
@ 2010-08-02 19:22 ` Jeff Law
2010-08-03 20:00 ` Vladimir Makarov
2010-08-03 17:01 ` Jeff Law
3 siblings, 1 reply; 8+ messages in thread
From: Jeff Law @ 2010-08-02 19:22 UTC (permalink / raw)
To: Vladimir Makarov; +Cc: gcc-patches
On 07/07/10 07:31, Vladimir Makarov wrote:
> This patch removes cover classes. The cover classes were introduced
> because classical graph coloring algorithms work on on intersected
> registers classes. As our experience shows defining cover classes can
> create a lot of performance problems for some targets and as
> consequence few targets have to use less powerful priority coloring
> algorithm instead of Preston-Briggs graph coloring algorithm.
>
> So removing cover classes makes GCC more portable. But the major
> idea for the patch is to not only make GCC profitable but to improve
> performance too.
>
> Irregular register file architectures (like x86) force to use
> smaller register classes (not just GENERAL_REGS) because other
> registers might be not profitable. Taking this requirement into
> account in more adequate way (than just available register number)
> could improve quality of graph coloring RA. Regular register file
> architectures also need this because some registers are not available
> in some parts of the code (e.g. registers used for argument passing)
> or not profitable (e.g. call clobbered registers).
>
> The patch makes graph coloring works on dynamically calculated classes
> (which is just a hard reg set) of registers profitable for given
> allocno. More correctly, the approximation of such classes used which
> forms a tree of such classes. Here is a simple x86 example to get the
> idea of the change. Let pseudo P conflicts with 7 other pseudos
> P1-P7. P and P7 can use any general register (it means that they are
> profitable too), P1-P6 can use only AX. In the old version of IRA P is
> not trivially colorable. With this patch, P is trivially colorable
> because the algorithm can easily figure out that the impact of P1-P6
> on P is just 1 registers (not 6 as IRA before the patch).
>
> The patch also permits to use registers from different old cover
> classes. For example, if we have pseudo which is only used for moving
> value from one memory location to another one, we could use general or
> floating point registers on most architectures. In the previous
> version of IRA, only general registers were used for such case because
> general and floating registers usually belonged to different cover
> classes.
>
> The patch removes -fira-coalesce because it is really hard to
> implement it with the new dynamically calculated allocno classes.
> The patch uses also new spilling algorithms because of the same reason.
> Removing -fira-coalesce is not a big deal because it is not used and
> its most functionality is implemented by IRA preferencing technique.
>
> The code for new trivial colorability test is still fast but it
> slower than the previous one. Code for cost calculation needs to
> process more classes too (like FLOAT_INT_REGS). That slows down RA
> significantly because the test and cost calculation are critical parts
> of IRA. A lot of work was done to speed up other parts of IRA to
> compensate this slow down. The subsequent patches are devoted to
> speeding other parts of IRA.
>
> Is the patch ok to commit the patch to the trunk?
>
I'm not through the entire patch, but thought I'd go ahead and pass
along a few questions/comments.
I notice that you removed the splay tree code in push_allocno_to_stack
and friends, presumably the compile-time problems we had when there was
a huge number of uncolorable allocnos isn't a problem anymore?
In allocnos_have_intersected_live_ranges_p, if the two allocnos are the
same you return false. Shouldn't it return true?
You might consider submitting removal of -fira-coalesce and the CB
coloring support separately. The former is clearly on its way out and I
believe the latter out to be as well.
ira_remove_allocno_copy_from_list can probably be eliminated as a
separate patch as I don't think it's used at all on the trunk.
There'll be more...
jeff
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: IRA improvements 1/4
2010-07-07 13:32 IRA improvements 1/4 Vladimir Makarov
` (2 preceding siblings ...)
2010-08-02 19:22 ` Jeff Law
@ 2010-08-03 17:01 ` Jeff Law
2010-08-03 20:01 ` Vladimir Makarov
3 siblings, 1 reply; 8+ messages in thread
From: Jeff Law @ 2010-08-03 17:01 UTC (permalink / raw)
To: Vladimir Makarov; +Cc: gcc-patches
On 07/07/10 07:31, Vladimir Makarov wrote:
> This patch removes cover classes. The cover classes were introduced
> because classical graph coloring algorithms work on on intersected
> registers classes. As our experience shows defining cover classes can
> create a lot of performance problems for some targets and as
> consequence few targets have to use less powerful priority coloring
> algorithm instead of Preston-Briggs graph coloring algorithm.
>
> So removing cover classes makes GCC more portable. But the major
> idea for the patch is to not only make GCC profitable but to improve
> performance too.
>
> Irregular register file architectures (like x86) force to use
> smaller register classes (not just GENERAL_REGS) because other
> registers might be not profitable. Taking this requirement into
> account in more adequate way (than just available register number)
> could improve quality of graph coloring RA. Regular register file
> architectures also need this because some registers are not available
> in some parts of the code (e.g. registers used for argument passing)
> or not profitable (e.g. call clobbered registers).
>
> The patch makes graph coloring works on dynamically calculated classes
> (which is just a hard reg set) of registers profitable for given
> allocno. More correctly, the approximation of such classes used which
> forms a tree of such classes. Here is a simple x86 example to get the
> idea of the change. Let pseudo P conflicts with 7 other pseudos
> P1-P7. P and P7 can use any general register (it means that they are
> profitable too), P1-P6 can use only AX. In the old version of IRA P is
> not trivially colorable. With this patch, P is trivially colorable
> because the algorithm can easily figure out that the impact of P1-P6
> on P is just 1 registers (not 6 as IRA before the patch).
>
> The patch also permits to use registers from different old cover
> classes. For example, if we have pseudo which is only used for moving
> value from one memory location to another one, we could use general or
> floating point registers on most architectures. In the previous
> version of IRA, only general registers were used for such case because
> general and floating registers usually belonged to different cover
> classes.
>
> The patch removes -fira-coalesce because it is really hard to
> implement it with the new dynamically calculated allocno classes.
> The patch uses also new spilling algorithms because of the same reason.
> Removing -fira-coalesce is not a big deal because it is not used and
> its most functionality is implemented by IRA preferencing technique.
>
> The code for new trivial colorability test is still fast but it
> slower than the previous one. Code for cost calculation needs to
> process more classes too (like FLOAT_INT_REGS). That slows down RA
> significantly because the test and cost calculation are critical parts
> of IRA. A lot of work was done to speed up other parts of IRA to
> compensate this slow down. The subsequent patches are devoted to
> speeding other parts of IRA.
>
>
A few more comments:
Overall it looks reasonable -- I'm going to largely trust you on the
algorithmic & implementation issues since you know IRA better than
anyone else. I haven't looked, but you probably should be listed as
the RA maintainer.
I don't recall anything which describes the forest of allocno hard regs.
In setup_allocno_and_important_classes you have this code:
+ else if (i == GENERAL_REGS)
+ /* Prefer general regs. For i386 example, it means that
+ we prefer GENERAL_REGS over INDEX_REGS or LEGACY_REGS
+ (all of them consists of the same available hard
+ registers). */
+ classes[j] = (enum reg_class) i;
Do we really want to treat GENERAL_REGS special here? ISTM we need some
kind of rule for which register class to select when presented with
multiple register classes with the same effective contents. Even if it
doesn't make any changes in the generated code, it does affect dumps.
I don't understand why improve_allocation is necessary -- shouldn't the
overall algorithm already be attempting to reduce the overall allocation
cost? If not a more concrete description of the situations this
function improves would really help.
I'd like to see the compile-time improvements as well as hunks I
identified yesterday go in first, then another looksie at the removal of
cover-class patch. If that's going to create a huge amount of work for
you, let me know and we'll look at other ways to stage in the changes.
jeff
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: IRA improvements 1/4
2010-08-02 19:22 ` Jeff Law
@ 2010-08-03 20:00 ` Vladimir Makarov
0 siblings, 0 replies; 8+ messages in thread
From: Vladimir Makarov @ 2010-08-03 20:00 UTC (permalink / raw)
To: Jeff Law; +Cc: gcc-patches
On 08/02/2010 03:21 PM, Jeff Law wrote:
> On 07/07/10 07:31, Vladimir Makarov wrote:
>> This patch removes cover classes. The cover classes were introduced
>> because classical graph coloring algorithms work on on intersected
>> registers classes. As our experience shows defining cover classes can
>> create a lot of performance problems for some targets and as
>> consequence few targets have to use less powerful priority coloring
>> algorithm instead of Preston-Briggs graph coloring algorithm.
>>
>> So removing cover classes makes GCC more portable. But the major
>> idea for the patch is to not only make GCC profitable but to improve
>> performance too.
>>
>> Irregular register file architectures (like x86) force to use
>> smaller register classes (not just GENERAL_REGS) because other
>> registers might be not profitable. Taking this requirement into
>> account in more adequate way (than just available register number)
>> could improve quality of graph coloring RA. Regular register file
>> architectures also need this because some registers are not available
>> in some parts of the code (e.g. registers used for argument passing)
>> or not profitable (e.g. call clobbered registers).
>>
>> The patch makes graph coloring works on dynamically calculated classes
>> (which is just a hard reg set) of registers profitable for given
>> allocno. More correctly, the approximation of such classes used which
>> forms a tree of such classes. Here is a simple x86 example to get the
>> idea of the change. Let pseudo P conflicts with 7 other pseudos
>> P1-P7. P and P7 can use any general register (it means that they are
>> profitable too), P1-P6 can use only AX. In the old version of IRA P is
>> not trivially colorable. With this patch, P is trivially colorable
>> because the algorithm can easily figure out that the impact of P1-P6
>> on P is just 1 registers (not 6 as IRA before the patch).
>>
>> The patch also permits to use registers from different old cover
>> classes. For example, if we have pseudo which is only used for moving
>> value from one memory location to another one, we could use general or
>> floating point registers on most architectures. In the previous
>> version of IRA, only general registers were used for such case because
>> general and floating registers usually belonged to different cover
>> classes.
>>
>> The patch removes -fira-coalesce because it is really hard to
>> implement it with the new dynamically calculated allocno classes.
>> The patch uses also new spilling algorithms because of the same reason.
>> Removing -fira-coalesce is not a big deal because it is not used and
>> its most functionality is implemented by IRA preferencing technique.
>>
>> The code for new trivial colorability test is still fast but it
>> slower than the previous one. Code for cost calculation needs to
>> process more classes too (like FLOAT_INT_REGS). That slows down RA
>> significantly because the test and cost calculation are critical parts
>> of IRA. A lot of work was done to speed up other parts of IRA to
>> compensate this slow down. The subsequent patches are devoted to
>> speeding other parts of IRA.
>>
>> Is the patch ok to commit the patch to the trunk?
>>
> I'm not through the entire patch, but thought I'd go ahead and pass
> along a few questions/comments.
>
>
> I notice that you removed the splay tree code in push_allocno_to_stack
> and friends, presumably the compile-time problems we had when there
> was a huge number of uncolorable allocnos isn't a problem anymore?
>
Yes, there will be no problem with a huge number of uncolorable
allocnos. Spilling priorities will be static. Allocnos will be
reordered just once.
> In allocnos_have_intersected_live_ranges_p, if the two allocnos are
> the same you return false. Shouldn't it return true?
>
No. This name (and pseudos_have_intersected_live_ranges_p) has a
misleading name. It probably should be called as
allocnos_conflict_by_live_ranges_p. I'll change the names.
> You might consider submitting removal of -fira-coalesce and the CB
> coloring support separately. The former is clearly on its way out and
> I believe the latter out to be as well.
>
Ok.
> ira_remove_allocno_copy_from_list can probably be eliminated as a
> separate patch as I don't think it's used at all on the trunk.
>
Ok. I overlooked to remove the function when I rewrote IRA IR
flattening for gcc 4.4. Since then it is not used.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: IRA improvements 1/4
2010-08-03 17:01 ` Jeff Law
@ 2010-08-03 20:01 ` Vladimir Makarov
0 siblings, 0 replies; 8+ messages in thread
From: Vladimir Makarov @ 2010-08-03 20:01 UTC (permalink / raw)
To: Jeffrey Law; +Cc: gcc-patches
On 08/03/2010 01:00 PM, Jeff Law wrote:
> On 07/07/10 07:31, Vladimir Makarov wrote:
>>
>> The code for new trivial colorability test is still fast but it
>> slower than the previous one. Code for cost calculation needs to
>> process more classes too (like FLOAT_INT_REGS). That slows down RA
>> significantly because the test and cost calculation are critical parts
>> of IRA. A lot of work was done to speed up other parts of IRA to
>> compensate this slow down. The subsequent patches are devoted to
>> speeding other parts of IRA.
>>
>>
> A few more comments:
>
> Overall it looks reasonable -- I'm going to largely trust you on the
> algorithmic & implementation issues since you know IRA better than
> anyone else. I haven't looked, but you probably should be listed as
> the RA maintainer.
>
> I don't recall anything which describes the forest of allocno hard regs.
>
The general IRA overview is described at the top of ira.c. There is a
description of forest of allocno hard regs in a paragraph about allocno
classes.
> In setup_allocno_and_important_classes you have this code:
>
> + else if (i == GENERAL_REGS)
> + /* Prefer general regs. For i386 example, it means that
> + we prefer GENERAL_REGS over INDEX_REGS or LEGACY_REGS
> + (all of them consists of the same available hard
> + registers). */
> + classes[j] = (enum reg_class) i;
>
> Do we really want to treat GENERAL_REGS special here? ISTM we need
> some kind of rule for which register class to select when presented
> with multiple register classes with the same effective contents. Even
> if it doesn't make any changes in the generated code, it does affect
> dumps.
>
GENERAL_REGS is already special register class and every target has it.
The problem is in that target specific code for move/ld/st costs are
usually defined for GENERAL_REGS and sometimes overlooked for other
register classes. What I added is probably the simplest solution.
The problem could be solved if every target specific code returns right
costs for every possible (combination of) register classes. Another
solution would be yours. I'll figure out what should be done for your
proposal. But in any case, I'd like to do it after the patch goes to
the trunk.
> I don't understand why improve_allocation is necessary -- shouldn't
> the overall algorithm already be attempting to reduce the overall
> allocation cost? If not a more concrete description of the situations
> this function improves would really help.
>
IRA uses heuristic algorithms. It is just additional heuristic to
improve RA. As one example when it improves the code (there are other
situations too), let us consider such situation
...
push A1 as potential spilling
...
push A2 as potential spilling
...
pop A2 and assign hard reg (optimistic coloring)
...
pop A1 and assign memory because no available hard regs
...
A1 conflicts with more other allocnos therefore has lower priority but
its cost (of memory usage) is bigger A2 one. Improve_allocation can
spill A2 in some situations and assign its register to A1 improving the
overall allocation cost.
> I'd like to see the compile-time improvements as well as hunks I
> identified yesterday go in first, then another looksie at the removal
> of cover-class patch. If that's going to create a huge amount of work
> for you, let me know and we'll look at other ways to stage in the
> changes.
>
>
I am still in process of the resolution of conflicts with Bernd's and
Richard Sandiford's patches. All your proposed changes (as other people
who wrote me) will be added to the branch after that and I'll resubmit
the patches again after that.
Thanks for reviewing my code, Jeff. It is really helpful.
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2010-08-03 20:01 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-07-07 13:32 IRA improvements 1/4 Vladimir Makarov
2010-07-07 20:27 ` Bernd Schmidt
2010-07-07 20:35 ` Vladimir Makarov
2010-07-26 14:17 ` Joseph S. Myers
2010-08-02 19:22 ` Jeff Law
2010-08-03 20:00 ` Vladimir Makarov
2010-08-03 17:01 ` Jeff Law
2010-08-03 20:01 ` Vladimir Makarov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).