diff options
author | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-03-27 23:16:35 +0000 |
---|---|---|
committer | vmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-03-27 23:16:35 +0000 |
commit | 284914859842aefe10bf7e92f4157a841e97deac (patch) | |
tree | ab75249e0724a39c82bc4c52637b7593afc63580 /gcc/ira-costs.c | |
parent | 5f239f1387c82100c270c389cda7f8a536144034 (diff) | |
download | gcc-284914859842aefe10bf7e92f4157a841e97deac.tar.gz |
2011-03-27 Vladimir Makarov <vmakarov@redhat.com>
* regmove.c (regmove_optimize): Move ira_set_pseudo_classes call
after regstat_init_n_sets_and_refs.
* ira.c: Add more comments at the top.
(setup_stack_reg_pressure_class, setup_pressure_classes):
Add comments how we compute the register pressure classes.
(setup_allocno_and_important_classes): Add more comments.
(setup_class_translate_array, reorder_important_classes)
(setup_reg_class_relations): Add comments.
* ira-emit.c: Add 2011 to the Copyright line. Add comments at the
start of the file.
* ira-color.c: Add 2011 to the Copyright line.
(assign_hard_reg): Add more comments.
(improve_allocation): Ditto.
* ira-costs.c: Add 2011 to the Copyright line.
(setup_cost_classes, setup_regno_cost_classes_by_aclass): Add more
comments.
(setup_regno_cost_classes_by_mode): Ditto.
Initial patches from ira-improv branch:
2010-08-13 Vladimir Makarov <vmakarov@redhat.com>
* ira-build.c: (ira_create_object): Remove initialization of
OBJECT_PROFITABLE_HARD_REGS. Initialize OBJECT_ADD_DATA.
(ira_create_allocno): Remove initialization of
ALLOCNO_MEM_OPTIMIZED_DEST, ALLOCNO_MEM_OPTIMIZED_DEST_P,
ALLOCNO_SOMEWHERE_RENAMED_P, ALLOCNO_CHILD_RENAMED_P,
ALLOCNO_IN_GRAPH_P, ALLOCNO_MAY_BE_SPILLED_P, ALLOCNO_COLORABLE_P,
ALLOCNO_NEXT_BUCKET_ALLOCNO, ALLOCNO_PREV_BUCKET_ALLOCNO,
ALLOCNO_FIRST_COALESCED_ALLOCNO, ALLOCNO_NEXT_COALESCED_ALLOCNO.
Initialize ALLOCNO_ADD_DATA.
(copy_info_to_removed_store_destinations): Use ALLOCNO_EMIT_DATA
and allocno_emit_reg instead of ALLOCNO_MEM_OPTIMIZED_DEST_P and
ALLOCNO_REG.
(ira_flattening): Ditto. Use ALLOCNO_EMIT_DATA instead of
ALLOCNO_MEM_OPTIMIZED_DEST and ALLOCNO_SOMEWHERE_RENAMED_P.
* ira.c (ira_reallocate): Remove.
(setup_pressure_classes): Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost instead of ira_get_register_move_cost.
(setup_allocno_assignment_flags): Use ALLOCNO_EMIT_DATA.
(ira): Call ira_initiate_emit_data and ira_finish_emit_data.
* ira-color.c: Use ALLOCNO_COLOR_DATA instead of
ALLOCNO_IN_GRAPH_P, ALLOCNO_MAY_BE_SPILLED_P, ALLOCNO_COLORABLE_P,
ALLOCNO_AVAILABLE_REGS_NUM, ALLOCNO_NEXT_BUCKET_ALLOCNO,
ALLOCNO_PREV_BUCKET_ALLOCNO. ALLOCNO_TEMP. Use OBJECT_COLOR_DATA
instead of OBJECT_PROFITABLE_HARD_REGS, OBJECT_HARD_REGS_NODE,
OBJECT_HARD_REGS_SUBNODES_START, OBJECT_HARD_REGS_SUBNODES_NUM.
Fix formatting.
(object_hard_regs_t, object_hard_regs_node_t): Move from
ira-int.h.
(struct object_hard_regs, struct object_hard_regs_node): Ditto.
(struct allocno_color_data): New.
(allocno_color_data_t): New typedef.
(allocno_color_data): New definition.
(ALLOCNO_COLOR_DATA): New macro.
(struct object_color_data): New.
(object_color_data_t): New typedef.
(object_color_data): New definition.
(OBJECT_COLOR_DATA): New macro.
(update_copy_costs, calculate_allocno_spill_cost): Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost instead of ira_get_register_move_cost.
(move_spill_restore, update_curr_costs): Ditto.
(allocno_spill_priority): Make it inline.
(color_pass): Allocate and free allocno_color_dat and
object_color_data.
(struct coalesce_data, coalesce_data_t): New.
(allocno_coalesce_data): New definition.
(ALLOCNO_COALESCE_DATA): New macro.
(merge_allocnos, coalesced_allocno_conflict_p): Use
ALLOCNO_COALESCED_DATA instead of ALLOCNO_FIRST_COALESCED_ALLOCNO,
ALLOCNO_NEXT_COALESCED_ALLOCNO, ALLOCNO_TEMP.
(coalesce_allocnos): Ditto.
(setup_coalesced_allocno_costs_and_nums): Ditto.
(collect_spilled_coalesced_allocnos): Ditto.
(slot_coalesced_allocno_live_ranges_intersect_p): Ditto.
(setup_slot_coalesced_allocno_live_ranges): Ditto.
(coalesce_spill_slots): Ditto.
(ira_sort_regnos_for_alter_reg): Ditto. Allocate, initialize and
free allocno_coalesce_data.
* ira-conflicts.c: Fix formatting.
(process_regs_for_copy): Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost instead of ira_get_register_move_cost.
(build_object_conflicts): Optimize.
* ira-costs.c (record_reg_classes): Optimize. Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost, ira_may_move_in_cost, and
ira_may_move_out_cost instead of ira_get_register_move_cost and
ira_get_may_move_cost.
(record_address_regs): Ditto.
(scan_one_insn): Optimize.
(find_costs_and_classes): Optimize.
(process_bb_node_for_hard_reg_moves): Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost instead of ira_get_register_move_cost.
* ira-emit.c: Use allocno_emit_reg, ALLOCNO_EMIT_DATA instead of
ALLOCNO_REG, ALLOCNO_CHILD_RENAMED_P, ALLOCNO_MEM_OPTIMIZED_DEST,
ALLOCNO_MEM_OPTIMIZED_DEST_P, and ALLOCNO_SOMEWHERE_RENAMED_P.
(ira_allocno_emit_data, void_p, new_allocno_emit_data_vec): New
definitions.
(ira_initiate_emit_data, ira_finish_emit_data)
(create_new_allocno): New functions.
(modify_move_list): Call create_new_alloc instead of
ira_create_allocno.
(emit_move_list): Call ira_init_register_move_cost_if_necessary.
Use ira_register_move_cost instead of ira_get_register_move_cost.
* ira-int.h: Fix some comments.
(object_hard_regs_t, object_hard_regs_node_t): Move
to ira-color.c.
(struct object_hard_regs, struct object_hard_regs_node):
Ditto.
(struct ira_object): Remove profitable_hard_regs, hard_regs_node,
hard_regs_subnodes_start, hard_regs_subnodes_num. Add new member
add_data.
(struct ira_allocno): Make mode and aclass a bitfield. Move other
bitfield after mode. Make hard_regno a short int. Make
hard_regno short. Remove first_coalesced_allocno and
next_coalesced_allocno. Move mem_optimized_dest_p,
somewhere_renamed_p, child_renamed_p, reg, and mem_optimized_dest
into struct ira_emit_data. Remove in_graph_p, may_be_spilled_p,
available_regs_num, next_bucket_allocno, prev_bucket_allocno,
temp, colorable_p. Add new member add_data.
(ALLOCNO_IN_GRAPH_P, ALLOCNO_MAY_BE_SPILLED_P): Remove.
(ALLOCNO_COLORABLE_P, ALLOCNO_AVAILABLE_REGS_NUM): Remove.
(ALLOCNO_NEXT_BUCKET_ALLOCNO, ALLOCNO_PREV_BUCKET_ALLOCNO): Remove.
(ALLOCNO_TEMP, ALLOCNO_FIRST_COALESCED_ALLOCNO): Remove.
(ALLOCNO_NEXT_COALESCED_ALLOCNO): Remove.
(ALLOCNO_ADD_DATA): New macro.
(ira_emit_data_t): New typedef.
(struct ira_emit_data): New. Move mem_optimized_dest_p,
somewhere_renamed_p, child_renamed_p, reg, mem_optimized_dest
from struct ira_allocno.
(ALLOCNO_EMIT_DATA): New macro.
(ira_allocno_emit_data, allocno_emit_reg): New.
(ALLOCNO_PROFITABLE_HARD_REGS, OBJECT_HARD_REGS_NODE): Remove.
(OBJECT_HARD_REGS_SUBNODES_STAR, OBJECT_HARD_REGS_SUBNODES_NUM):
Remove.
(OBJECT_ADD_DATA): New macro.
(ira_reallocate): Remove.
(ira_initiate_emit_data, ira_finish_emit_data): New.
(ira_get_register_move_cost, ira_get_may_move_cost): Remove.
(ira_init_register_move_cost_if_necessary): New.
(ira_object_conflict_iter_next): Merge into
ira_object_conflict_iter_cond.
(FOR_EACH_OBJECT_CONFLICT): Don't use
ira_object_conflict_iter_next.
* ira-live.c: (process_single_reg_class_operands): Call
ira_init_register_move_cost_if_necessary. Use
ira_register_move_cost instead of ira_get_register_move_cost.
2010-08-13 Vladimir Makarov <vmakarov@redhat.com>
* ira-int.h (struct target_ira_int): Remove x_cost_classes.
* ira-costs.c: Fix formatting.
(cost_classes, cost_classes_num): Remove.
(struct cost_classes, cost_classes_t, const_cost_classes_t): New.
(regno_cost_classes, cost_classes_hash, cost_classes_eq): New.
(cost_classes_del, cost_classes_htab): New.
(cost_classes_aclass_cache, cost_classes_mode_cache): New.
(initiate_regno_cost_classes, setup_cost_classes): New.
(setup_regno_cost_classes_by_aclass): New.
(setup_regno_cost_classes_by_mode, finish_regno_cost_classes):
New.
(record_reg_classes): Use regno_cost_classes instead of
cost_classes. Move checking opposite operand up.
(record_address_regs): Use regno_cost_classes
instead of cost_classes.
(scan_one_insn): Ditto. Use always general register.
(print_allocno_costs): Use regno_cost_classes instead of
cost_classes.
(print_pseudo_costs): Ditto. Use Reg_N_REFS.
(find_costs_and_classes): Set up cost classes for each registers.
Use also their mode for this. Use regno_cost_classes instead of
cost_classes.
(setup_allocno_class_and_costs): Use regno_cost_classes instead of
cost_classes.
(free_ira_costs, ira_init_costs): Don't use cost_classes.
(ira_costs, ira_set_pseudo_classes): Call
initiate_regno_cost_classes and finish_regno_cost_classes.
2010-10-04 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.
* 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. Fix
formatting.
* 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.
(object_hard_regs_t, object_hard_regs_node_t): New typedefs.
(struct object_hard_regs, struct object_hard_regs_node): New.
(struct ira_object): New members profitable_hard_regs,
hard_regs_node, hard_regs_subnodes_start, hard_regs_subnodes_num.
(struct ira_allocno): Rename cover_class to aclass. 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.
(ALLOCNO_SPLAY_REMOVED_P, ALLOCNO_LEFT_CONFLICTS_SIZE): Remove.
(ALLOCNO_COLORABLE_P): New macro.
(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.
(OBJECT_...): Rename parameter C to O.
(OBJECT_PROFITABLE_HARD_REGS): New macro.
(OBJECT_HARD_REGS_NODE, OBJECT_HARD_REGS_SUBNODES_START)
(OBJECT_HARD_REGS_SUBNODES_NUM): New macros.
(struct target_ira_int): New members x_ira_max_memory_move_cost,
x_ira_max_register_move_cost, x_ira_max_may_move_in_cost,
x_ira_max_may_move_out_cost, x_ira_reg_allocno_class_p,
x_ira_reg_pressure_class_p, x_ira_important_class_nums,
x_ira_reg_class_superunion. Rename x_prohibited_class_mode_reg to
x_ira_prohibited_class_mode_reg. Rename x_ira_reg_class_union to
x_ira_reg_class_subunion.
(ira_max_memory_move_cost, ira_max_register_move_cost)
(ira_max_may_move_in_cost, ira_max_may_move_out_cost)
(ira_reg_allocno_class_p, ira_reg_pressure_class_p)
(ira_important_class_nums, ira_reg_class_superunion): New macros.
(prohibited_class_mode_regs): Rename to
ira_prohibited_class_mode_regs.
(ira_reg_class_union): Rename to ira_reg_class_subunion.
(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_object_conflict_iter_init, ira_object_conflict_iter_cond)
(ira_object_conflict_iter_next): Fix comments.
(ira_hard_reg_set_intersection_p, hard_reg_set_size): New
functions.
(ira_allocate_and_set_costs, ira_allocate_and_copy_costs): Rename
cover_class to aclass.
(ira_allocate_and_accumulate_costs): Ditto.
(ira_allocate_and_set_or_copy_costs): Ditto.
* 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. Fix formatting.
(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.
(object_hard_regs_vec, object_hard_regs_htab, node_check_tick):
New definitions.
(hard_regs_roots, hard_regs_node_vec): Ditto.
(object_hard_regs_hash, object_hard_regs_eq, find_hard_regs): Ditto.
(insert_hard_regs, init_object_hard_regs, add_object_hard_regs): Ditto.
(finish_object_hard_regs, object_hard_regs_compare): Ditto.
(create_new_object_hard_regs_node): Ditto.
(add_new_object_hard_regs_node_to_forest): Ditto.
(add_object_hard_regs_to_forest, collect_object_hard_regs_cover):
Ditto.
(setup_object_hard_regs_nodes_parent, first_common_ancestor_node):
Ditto.
(print_hard_reg_set, print_hard_regs_subforest): Ditto.
(print_hard_regs_forest, ira_debug_hard_regs_forest): Ditto.
(remove_unused_object_hard_regs_nodes): Ditto.
(enumerate_object_hard_regs_nodes): Ditto.
(object_hard_regs_nodes_num, object_hard_regs_nodes): Ditto.
(object_hard_regs_subnode_t): Ditto.
(struct object_hard_regs_subnode): Ditto.
(object_hard_regs_subnodes, object_hard_regs_subnode_index): Ditto.
(setup_object_hard_regs_subnode_index): Ditto.
(get_object_hard_regs_subnodes_num): Ditto.
(form_object_hard_regs_nodes_forest): Ditto.
(finish_object_hard_regs_nodes_tree): Ditto.
(finish_object_hard_regs_nodes_forest): Ditto.
(allocnos_have_intersected_live_ranges_p): Rename to
allocnos_conflict_by_live_ranges_p. Move before
copy_freq_compare_func.
(pseudos_have_intersected_live_ranges_p): Rename to
conflict_by_live_ranges_p. Move before copy_freq_compare_func.
(setup_left_conflict_sizes_p, update_left_conflict_sizes_p): Ditto.
(empty_profitable_hard_regs, setup_profitable_hard_regs): Ditto.
(update_copy_costs): Remove assert. Skip cost update if the hard
reg does not belong the class.
(assign_hard_reg): Process only profitable hard regs.
(uncolorable_allocnos_num): Make it scalar.
(allocno_spill_priority): Use ALLOCNO_EXCESS_PRESSURE_POINTS_NUM
and ira_reg_class_max_nregs instead of ALLOCNO_LEFT_CONFLICTS_SIZE
and ira_reg_class_max_nregs.
(bucket_allocno_compare_func): Check frequency first.
(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): 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. Don't
build and use splay tree. Choose first allocno in uncolorable
allocno bucket to spill. Remove setting spill cost.
(all_conflicting_hard_regs): Remove.
(setup_allocno_available_regs_num): 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.
(improve_allocation): New.
(color_allocnos): Call setup_profitable_hard_regs,
form_object_hard_regs_nodes_forest, improve_allocation,
finish_object_hard_regs_nodes_forest. Setup spill cost.
(print_loop_title): Use pressure classes.
(color_allocnso): Ditto.
(do_coloring): Remove allocation and freeing splay_tree_node_pool
and allocnos_for_spilling.
(ira_sort_regnos_for_alter_reg): 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. Fix
formatting.
(update_allocno_pressure_excess_length): Use pressure classes.
(inc_register_pressure, dec_register_pressure): Check for pressure
class.
(mark_pseudo_regno_live, mark_pseudo_regno_subword_live): Use
pressure class. Use ira_reg_class_nregs instead of
ira_reg_class_max_nregs.
(mark_pseudo_regno_dead, mark_pseudo_regno_subword_dead): Ditto.
(mark_hard_reg_live, 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. Fix formatting.
(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. Fix formatting.
(ira_create_object): Initiate OBJECT_PROFITABLE_HARD_REGS.
(ira_create_allocno): Remove initialization of
ALLOCNO_SPLAY_REMOVED_P, ALLOCNO_LEFT_CONFLICT_SIZE. Initialize
ALLOCNO_COLORABLE_P.
(ira_set_allocno_cover_class): Rename to ira_set_allocno_class.
Update conflict regs for the objects.
(create_cap_allocno): 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.
(low_pressure_loop_node_p): Use pressure classes.
(object_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. Fix formatting.
(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.
(move_loop_invariants): Initialize and finalize regstat.
* ira.c: Remove mentioning cover classes from the file. Add
comments about coloring without cover classes. Use ALLOCNO_CLASS
instead of ALLOCNO_COVER_CLASS. Fix formatting.
(alloc_reg_class_subclasses, setup_reg_subclasses): Move it before
setup_class_subset_and_memory_move_costs.
(setup_stack_reg_pressure_class, setup_pressure_classes): New.
(setup_cover_and_important_classes): Rename to
setup_allocno_and_important_classes.
(setup_class_translate_array): New.
(setup_class_translate): Call it for allocno and pressure classes.
(cover_class_order): Rename to allocno_class_order.
(comp_reg_classes_func): Use ira_allocno_class_translate instead
of ira_class_translate.
(reorder_important_classes): Set up ira_important_class_nums.
(setup_reg_class_relations): Set up ira_reg_class_superunion.
(print_class_cover): Rename to print_classes. Add parameter.
(ira_debug_class_cover): Rename to ira_debug_allocno_classes.
Print pressure classes too.
(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.
(ira_reg_class_nregs): Rename to ira_reg_class_max_nregs.
(setup_prohibited_class_mode_regs): Use
ira_prohibited_class_mode_regs instead of
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_prohibited_class_mode_regs.
Call clarify_prohibited_class_mode_regs.
(ira_no_alloc_reg): Remove.
(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_no_alloc_reg): Remove external.
(struct target_ira): Rename x_ira_hard_regno_cover_class,
x_ira_reg_class_cover_size, x_ira_reg_class_cover, and
x_ira_class_translate to x_ira_hard_regno_allocno_class,
x_ira_allocno_classes_num, x_ira_allocno_classes, and
x_ira_allocno_class_translate. Add x_ira_pressure_classes_num,
x_ira_pressure_classes, x_ira_pressure_class_translate, and
x_ira_stack_reg_pressure_class. Rename x_ira_reg_class_nregs to
x_ira_reg_class_max_nregs. Add x_ira_reg_class_min_nregs and
x_ira_no_alloc_regs.
(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): New definitions.
(ira_pressure_class_translate, ira_stack_reg_pressure_class): Ditto.
(ira_reg_class_nregs): Rename to ira_reg_class_max_nregs.
(ira_reg_class_min_nregs, ira_stack_reg_pressure_class): New
(ira_no_alloc_regs): New.
* 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
by processing objects. Use ira_reg_class_max_nregs instead of
ira_reg_class_nregs.
* 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/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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@171583 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/ira-costs.c')
-rw-r--r-- | gcc/ira-costs.c | 874 |
1 files changed, 613 insertions, 261 deletions
diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 6db5bf29b52..4a3083a65ab 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -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]; }; @@ -77,8 +76,6 @@ struct costs (this_target_ira_int->x_op_costs) #define this_op_costs \ (this_target_ira_int->x_this_op_costs) -#define cost_classes \ - (this_target_ira_int->x_cost_classes) /* Costs of each class for each allocno or pseudo. */ static struct costs *costs; @@ -86,13 +83,6 @@ static struct costs *costs; /* Accumulated costs of each class for each allocno. */ static struct costs *total_allocno_costs; -/* The size of the previous array. */ -static int cost_classes_num; - -/* Map: cost class -> order number (they start with 0) of the cost - class. The order number is negative for non-cost classes. */ -static int cost_class_nums[N_REG_CLASSES]; - /* It is the current size of struct costs. */ static int struct_costs_size; @@ -102,8 +92,8 @@ static int struct_costs_size; ((struct costs *) ((char *) (arr) + (num) * struct_costs_size)) /* Return index in COSTS when processing reg with REGNO. */ -#define COST_INDEX(regno) (allocno_p \ - ? ALLOCNO_NUM (ira_curr_regno_allocno_map[regno]) \ +#define COST_INDEX(regno) (allocno_p \ + ? ALLOCNO_NUM (ira_curr_regno_allocno_map[regno]) \ : (int) regno) /* Record register class preferences of each allocno or pseudo. Null @@ -114,8 +104,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. */ @@ -126,6 +116,204 @@ static int frequency; +/* Info about reg classes whose costs are calculated for a pseudo. */ +struct cost_classes +{ + /* Number of the cost classes in the subsequent array. */ + int num; + /* Container of the cost classes. */ + enum reg_class classes[N_REG_CLASSES]; + /* Map reg class -> index of the reg class in the previous array. + -1 if it is not a cost classe. */ + int index[N_REG_CLASSES]; + /* Map hard regno index of first class in array CLASSES containing + the hard regno, -1 otherwise. */ + int hard_regno_index[FIRST_PSEUDO_REGISTER]; +}; + +/* Types of pointers to the structure above. */ +typedef struct cost_classes *cost_classes_t; +typedef const struct cost_classes *const_cost_classes_t; + +/* Info about cost classes for each pseudo. */ +static cost_classes_t *regno_cost_classes; + +/* Returns hash value for cost classes info V. */ +static hashval_t +cost_classes_hash (const void *v) +{ + const_cost_classes_t hv = (const_cost_classes_t) v; + + return iterative_hash (&hv->classes, sizeof (enum reg_class) * hv->num, 0); +} + +/* Compares cost classes info V1 and V2. */ +static int +cost_classes_eq (const void *v1, const void *v2) +{ + const_cost_classes_t hv1 = (const_cost_classes_t) v1; + const_cost_classes_t hv2 = (const_cost_classes_t) v2; + + return hv1->num == hv2->num && memcmp (hv1->classes, hv2->classes, + sizeof (enum reg_class) * hv1->num); +} + +/* Delete cost classes info V from the hash table. */ +static void +cost_classes_del (void *v) +{ + ira_free (v); +} + +/* Hash table of unique cost classes. */ +static htab_t cost_classes_htab; + +/* Map allocno class -> cost classes for pseudo of given allocno + class. */ +static cost_classes_t cost_classes_aclass_cache[N_REG_CLASSES]; + +/* Map mode -> cost classes for pseudo of give mode. */ +static cost_classes_t cost_classes_mode_cache[MAX_MACHINE_MODE]; + +/* Initialize info about the cost classes for each pseudo. */ +static void +initiate_regno_cost_classes (void) +{ + int size = sizeof (cost_classes_t) * max_reg_num (); + + regno_cost_classes = (cost_classes_t *) ira_allocate (size); + memset (regno_cost_classes, 0, size); + memset (cost_classes_aclass_cache, 0, + sizeof (cost_classes_t) * N_REG_CLASSES); + memset (cost_classes_mode_cache, 0, + sizeof (cost_classes_t) * MAX_MACHINE_MODE); + cost_classes_htab + = htab_create (200, cost_classes_hash, cost_classes_eq, cost_classes_del); +} + +/* Create new cost classes from cost classes FROM and set up members + index and hard_regno_index. Return the new classes. The function + implements some common code of two functions + setup_regno_cost_classes_by_aclass and + setup_regno_cost_classes_by_mode. */ +static cost_classes_t +setup_cost_classes (cost_classes_t from) +{ + cost_classes_t classes_ptr; + enum reg_class cl; + int i, j, hard_regno; + + classes_ptr = (cost_classes_t) ira_allocate (sizeof (struct cost_classes)); + classes_ptr->num = from->num; + for (i = 0; i < N_REG_CLASSES; i++) + classes_ptr->index[i] = -1; + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) + classes_ptr->hard_regno_index[i] = -1; + for (i = 0; i < from->num; i++) + { + cl = classes_ptr->classes[i] = from->classes[i]; + classes_ptr->index[cl] = i; + for (j = ira_class_hard_regs_num[cl] - 1; j >= 0; j--) + { + hard_regno = ira_class_hard_regs[cl][j]; + if (classes_ptr->hard_regno_index[hard_regno] < 0) + classes_ptr->hard_regno_index[hard_regno] = i; + } + } + return classes_ptr; +} + +/* Setup cost classes for pseudo REGNO whose allocno class is ACLASS. + This function is used when we know an initial approximation of + allocno class of the pseudo already, e.g. on the second iteration + of class cost calculation or after class cost calculation in + register-pressure sensitive insn scheduling or register-pressure + sensitive loop-invariant motion. */ +static void +setup_regno_cost_classes_by_aclass (int regno, enum reg_class aclass) +{ + static struct cost_classes classes; + cost_classes_t classes_ptr; + enum reg_class cl; + int i; + PTR *slot; + HARD_REG_SET temp, temp2; + + if ((classes_ptr = cost_classes_aclass_cache[aclass]) == NULL) + { + COPY_HARD_REG_SET (temp, reg_class_contents[aclass]); + AND_COMPL_HARD_REG_SET (temp, ira_no_alloc_regs); + classes.num = 0; + for (i = 0; i < ira_important_classes_num; i++) + { + cl = ira_important_classes[i]; + COPY_HARD_REG_SET (temp2, reg_class_contents[cl]); + AND_COMPL_HARD_REG_SET (temp2, ira_no_alloc_regs); + if (! ira_reg_pressure_class_p[cl] + && hard_reg_set_subset_p (temp2, temp) && cl != aclass) + continue; + classes.classes[classes.num++] = cl; + } + slot = htab_find_slot (cost_classes_htab, &classes, INSERT); + if (*slot == NULL) + { + classes_ptr = setup_cost_classes (&classes); + *slot = classes_ptr; + } + classes_ptr = cost_classes_aclass_cache[aclass] = (cost_classes_t) *slot; + } + regno_cost_classes[regno] = classes_ptr; +} + +/* Setup cost classes for pseudo REGNO with MODE. Usage of MODE can + decrease number of cost classes for the pseudo, if hard registers + of some important classes can not hold a value of MODE. So the + pseudo can not get hard register of some important classes and cost + calculation for such important classes is only waisting CPU + time. */ +static void +setup_regno_cost_classes_by_mode (int regno, enum machine_mode mode) +{ + static struct cost_classes classes; + cost_classes_t classes_ptr; + enum reg_class cl; + int i; + PTR *slot; + HARD_REG_SET temp; + + if ((classes_ptr = cost_classes_mode_cache[mode]) == NULL) + { + classes.num = 0; + for (i = 0; i < ira_important_classes_num; i++) + { + cl = ira_important_classes[i]; + COPY_HARD_REG_SET (temp, ira_prohibited_class_mode_regs[cl][mode]); + IOR_HARD_REG_SET (temp, ira_no_alloc_regs); + if (hard_reg_set_subset_p (reg_class_contents[cl], temp)) + continue; + classes.classes[classes.num++] = cl; + } + slot = htab_find_slot (cost_classes_htab, &classes, INSERT); + if (*slot == NULL) + { + classes_ptr = setup_cost_classes (&classes); + *slot = classes_ptr; + } + cost_classes_mode_cache[mode] = (cost_classes_t) *slot; + } + regno_cost_classes[regno] = classes_ptr; +} + +/* Finilize info about the cost classes for each pseudo. */ +static void +finish_regno_cost_classes (void) +{ + ira_free (regno_cost_classes); + htab_delete (cost_classes_htab); +} + + + /* Compute the cost of loading X into (if TO_P is TRUE) or from (if TO_P is FALSE) a register of class RCLASS in mode MODE. X must not be a pseudo register. */ @@ -313,53 +501,78 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, Moreover, if we cannot tie them, this alternative needs to do a copy, which is one insn. */ struct costs *pp = this_op_costs[i]; - - for (k = 0; k < cost_classes_num; k++) + int *pp_costs = pp->cost; + cost_classes_t cost_classes_ptr + = regno_cost_classes[REGNO (op)]; + enum reg_class *cost_classes = cost_classes_ptr->classes; + bool in_p = recog_data.operand_type[i] != OP_OUT; + bool out_p = recog_data.operand_type[i] != OP_IN; + enum reg_class op_class = classes[i]; + move_table *move_in_cost, *move_out_cost; + + ira_init_register_move_cost_if_necessary (mode); + if (! in_p) { - rclass = cost_classes[k]; - pp->cost[k] - = (((recog_data.operand_type[i] != OP_OUT - ? ira_get_may_move_cost (mode, rclass, - classes[i], true) : 0) - + (recog_data.operand_type[i] != OP_IN - ? ira_get_may_move_cost (mode, classes[i], - rclass, false) : 0)) - * frequency); + ira_assert (out_p); + move_out_cost = ira_may_move_out_cost[mode]; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + rclass = cost_classes[k]; + pp_costs[k] + = move_out_cost[op_class][rclass] * frequency; + } + } + else if (! out_p) + { + ira_assert (in_p); + move_in_cost = ira_may_move_in_cost[mode]; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + rclass = cost_classes[k]; + pp_costs[k] + = move_in_cost[rclass][op_class] * frequency; + } + } + else + { + move_in_cost = ira_may_move_in_cost[mode]; + move_out_cost = ira_may_move_out_cost[mode]; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + rclass = cost_classes[k]; + pp_costs[k] = ((move_in_cost[rclass][op_class] + + move_out_cost[op_class][rclass]) + * frequency); + } } /* If the alternative actually allows memory, make things a bit cheaper since we won't need an extra insn to load it. */ pp->mem_cost - = ((recog_data.operand_type[i] != OP_IN - ? ira_memory_move_cost[mode][classes[i]][0] : 0) - + (recog_data.operand_type[i] != OP_OUT - ? ira_memory_move_cost[mode][classes[i]][1] : 0) + = ((out_p ? ira_memory_move_cost[mode][op_class][0] : 0) + + (in_p ? ira_memory_move_cost[mode][op_class][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))]; if (pref_class == NO_REGS) alt_cost - += ((recog_data.operand_type[i] != OP_IN - ? ira_memory_move_cost[mode][classes[i]][0] - : 0) - + (recog_data.operand_type[i] != OP_OUT - ? ira_memory_move_cost[mode][classes[i]][1] + += ((out_p + ? ira_memory_move_cost[mode][op_class][0] : 0) + + (in_p + ? ira_memory_move_cost[mode][op_class][1] : 0)); else if (ira_reg_class_intersect - [pref_class][classes[i]] == NO_REGS) - alt_cost += ira_get_register_move_cost (mode, - pref_class, - classes[i]); + [pref_class][op_class] == NO_REGS) + alt_cost + += ira_register_move_cost[mode][pref_class][op_class]; } if (REGNO (ops[i]) != REGNO (ops[j]) && ! find_reg_note (insn, REG_DEAD, op)) @@ -405,7 +618,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, 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; @@ -491,12 +704,12 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, 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)) @@ -520,7 +733,7 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, 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 @@ -554,53 +767,77 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, } else { + unsigned int regno = REGNO (op); struct costs *pp = this_op_costs[i]; - - for (k = 0; k < cost_classes_num; k++) + int *pp_costs = pp->cost; + cost_classes_t cost_classes_ptr = regno_cost_classes[regno]; + enum reg_class *cost_classes = cost_classes_ptr->classes; + bool in_p = recog_data.operand_type[i] != OP_OUT; + bool out_p = recog_data.operand_type[i] != OP_IN; + enum reg_class op_class = classes[i]; + move_table *move_in_cost, *move_out_cost; + + ira_init_register_move_cost_if_necessary (mode); + if (! in_p) { - rclass = cost_classes[k]; - pp->cost[k] - = (((recog_data.operand_type[i] != OP_OUT - ? ira_get_may_move_cost (mode, rclass, - classes[i], true) : 0) - + (recog_data.operand_type[i] != OP_IN - ? ira_get_may_move_cost (mode, classes[i], - rclass, false) : 0)) - * frequency); + ira_assert (out_p); + move_out_cost = ira_may_move_out_cost[mode]; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + rclass = cost_classes[k]; + pp_costs[k] + = move_out_cost[op_class][rclass] * frequency; + } + } + else if (! out_p) + { + ira_assert (in_p); + move_in_cost = ira_may_move_in_cost[mode]; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + rclass = cost_classes[k]; + pp_costs[k] + = move_in_cost[rclass][op_class] * frequency; + } + } + else + { + move_in_cost = ira_may_move_in_cost[mode]; + move_out_cost = ira_may_move_out_cost[mode]; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + rclass = cost_classes[k]; + pp_costs[k] = ((move_in_cost[rclass][op_class] + + move_out_cost[op_class][rclass]) + * frequency); + } } /* If the alternative actually allows memory, make things a bit cheaper since we won't need an extra insn to load it. */ pp->mem_cost - = ((recog_data.operand_type[i] != OP_IN - ? ira_memory_move_cost[mode][classes[i]][0] : 0) - + (recog_data.operand_type[i] != OP_OUT - ? ira_memory_move_cost[mode][classes[i]][1] : 0) + = ((out_p ? ira_memory_move_cost[mode][op_class][0] : 0) + + (in_p ? ira_memory_move_cost[mode][op_class][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))]; if (pref_class == NO_REGS) alt_cost - += ((recog_data.operand_type[i] != OP_IN - ? ira_memory_move_cost[mode][classes[i]][0] - : 0) - + (recog_data.operand_type[i] != OP_OUT - ? ira_memory_move_cost[mode][classes[i]][1] + += ((out_p + ? ira_memory_move_cost[mode][op_class][0] : 0) + + (in_p + ? ira_memory_move_cost[mode][op_class][1] : 0)); - else if (ira_reg_class_intersect[pref_class][classes[i]] + else if (ira_reg_class_intersect[pref_class][op_class] == NO_REGS) - alt_cost += ira_get_register_move_cost (mode, - pref_class, - classes[i]); + alt_cost += ira_register_move_cost[mode][pref_class][op_class]; } } } @@ -643,14 +880,17 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, if (REG_P (ops[i]) && REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER) { struct costs *pp = op_costs[i], *qq = this_op_costs[i]; + int *pp_costs = pp->cost, *qq_costs = qq->cost; int scale = 1 + (recog_data.operand_type[i] == OP_INOUT); + cost_classes_t cost_classes_ptr + = regno_cost_classes[REGNO (ops[i])]; pp->mem_cost = MIN (pp->mem_cost, (qq->mem_cost + op_cost_add) * scale); - for (k = 0; k < cost_classes_num; k++) - pp->cost[k] - = MIN (pp->cost[k], (qq->cost[k] + op_cost_add) * scale); + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + pp_costs[k] + = MIN (pp_costs[k], (qq_costs[k] + op_cost_add) * scale); } } @@ -686,37 +926,40 @@ record_reg_classes (int n_alts, int n_ops, rtx *ops, && REG_P (ops[0]) && REG_P (ops[1]) && find_regno_note (insn, REG_DEAD, REGNO (ops[1]))) for (i = 0; i <= 1; i++) - if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER) + if (REGNO (ops[i]) >= FIRST_PSEUDO_REGISTER + && REGNO (ops[!i]) < FIRST_PSEUDO_REGISTER) { - unsigned int regno = REGNO (ops[!i]); + unsigned int regno = REGNO (ops[i]); + unsigned int other_regno = REGNO (ops[!i]); enum machine_mode mode = GET_MODE (ops[!i]); + cost_classes_t cost_classes_ptr = regno_cost_classes[regno]; + enum reg_class *cost_classes = cost_classes_ptr->classes; enum reg_class rclass; - unsigned int nr; + int nr; - if (regno < FIRST_PSEUDO_REGISTER) - for (k = 0; k < cost_classes_num; k++) - { - rclass = cost_classes[k]; - if (TEST_HARD_REG_BIT (reg_class_contents[rclass], regno) - && (reg_class_size[rclass] - == (unsigned) CLASS_MAX_NREGS (rclass, mode))) - { - if (reg_class_size[rclass] == 1) - op_costs[i]->cost[k] = -frequency; - else - { - for (nr = 0; - nr < (unsigned) hard_regno_nregs[regno][mode]; - nr++) - if (! TEST_HARD_REG_BIT (reg_class_contents[rclass], - regno + nr)) - break; - - if (nr == (unsigned) hard_regno_nregs[regno][mode]) - op_costs[i]->cost[k] = -frequency; - } - } - } + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + rclass = cost_classes[k]; + if (TEST_HARD_REG_BIT (reg_class_contents[rclass], other_regno) + && (reg_class_size[rclass] + == (unsigned) CLASS_MAX_NREGS (rclass, mode))) + { + if (reg_class_size[rclass] == 1) + op_costs[i]->cost[k] = -frequency; + else + { + for (nr = 0; + nr < hard_regno_nregs[other_regno][mode]; + nr++) + if (! TEST_HARD_REG_BIT (reg_class_contents[rclass], + other_regno + nr)) + break; + + if (nr == hard_regno_nregs[other_regno][mode]) + op_costs[i]->cost[k] = -frequency; + } + } + } } } @@ -903,21 +1146,38 @@ record_address_regs (enum machine_mode mode, rtx x, int context, case REG: { struct costs *pp; + int *pp_costs; enum reg_class i; - int k; + int k, regno, add_cost; + cost_classes_t cost_classes_ptr; + enum reg_class *cost_classes; + move_table *move_in_cost; if (REGNO (x) < FIRST_PSEUDO_REGISTER) break; + regno = REGNO (x); 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; - for (k = 0; k < cost_classes_num; k++) + ALLOCNO_BAD_SPILL_P (ira_curr_regno_allocno_map[regno]) = true; + pp = COSTS (costs, COST_INDEX (regno)); + 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; + cost_classes_ptr = regno_cost_classes[regno]; + cost_classes = cost_classes_ptr->classes; + pp_costs = pp->cost; + ira_init_register_move_cost_if_necessary (Pmode); + move_in_cost = ira_may_move_in_cost[Pmode]; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) { i = cost_classes[k]; - pp->cost[k] - += (ira_get_may_move_cost (Pmode, i, rclass, true) * scale) / 2; + add_cost = (move_in_cost[i][rclass] * scale) / 2; + if (INT_MAX - add_cost < pp_costs[k]) + pp_costs[k] = INT_MAX; + else + pp_costs[k] += add_cost; } } break; @@ -972,7 +1232,7 @@ record_operand_costs (rtx insn, enum reg_class *pref) record_address_regs (VOIDmode, recog_data.operand[i], 0, ADDRESS, SCRATCH, frequency * 2); } - + /* Check for commutative in a separate loop so everything will have been initialized. We must do this even if one operand is a constant--see addsi3 in m68k.md. */ @@ -1041,8 +1301,6 @@ scan_one_insn (rtx insn) rtx reg = SET_DEST (set); int num = COST_INDEX (REGNO (reg)); - if (pref) - cl = pref[num]; COSTS (costs, num)->mem_cost -= ira_memory_move_cost[GET_MODE (reg)][cl][1] * frequency; record_address_regs (GET_MODE (SET_SRC (set)), XEXP (SET_SRC (set), 0), @@ -1061,13 +1319,28 @@ 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 *p_costs = p->cost, *q_costs = q->cost; + cost_classes_t cost_classes_ptr = regno_cost_classes[regno]; + int add_cost; /* If the already accounted for the memory "cost" above, don't do so again. */ if (!counted_mem) - p->mem_cost += q->mem_cost; - for (k = 0; k < cost_classes_num; k++) - p->cost[k] += q->cost[k]; + { + 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 = cost_classes_ptr->num - 1; k >= 0; k--) + { + add_cost = q_costs[k]; + if (add_cost > 0 && INT_MAX - add_cost < p_costs[k]) + p_costs[k] = INT_MAX; + else + p_costs[k] += add_cost; + } } return insn; @@ -1090,6 +1363,8 @@ print_allocno_costs (FILE *f) int i, rclass; basic_block bb; int regno = ALLOCNO_REGNO (a); + cost_classes_t cost_classes_ptr = regno_cost_classes[regno]; + enum reg_class *cost_classes = cost_classes_ptr->classes; i = ALLOCNO_NUM (a); fprintf (f, " a%d(r%d,", i, regno); @@ -1098,7 +1373,7 @@ print_allocno_costs (FILE *f) else fprintf (f, "l%d", ALLOCNO_LOOP_TREE_NODE (a)->loop->num); fprintf (f, ") costs:"); - for (k = 0; k < cost_classes_num; k++) + for (k = 0; k < cost_classes_ptr->num; k++) { rclass = cost_classes[k]; if (contains_reg_of_mode[rclass][PSEUDO_REGNO_MODE (regno)] @@ -1117,7 +1392,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"); } } @@ -1127,15 +1406,19 @@ print_pseudo_costs (FILE *f) { int regno, k; int rclass; + cost_classes_t cost_classes_ptr; + enum reg_class *cost_classes; ira_assert (! allocno_p); 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; + cost_classes_ptr = regno_cost_classes[regno]; + cost_classes = cost_classes_ptr->classes; fprintf (f, " r%d costs:", regno); - for (k = 0; k < cost_classes_num; k++) + for (k = 0; k < cost_classes_ptr->num; k++) { rclass = cost_classes[k]; if (contains_reg_of_mode[rclass][PSEUDO_REGNO_MODE (regno)] @@ -1180,31 +1463,54 @@ process_bb_node_for_costs (ira_loop_tree_node_t loop_tree_node) } /* 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) { - int i, k, start; + int i, k, start, max_cost_classes_num; int pass; basic_block bb; + enum reg_class *regno_best_class; init_recog (); #ifdef FORBIDDEN_INC_DEC_CLASSES in_inc_dec = ira_allocate (sizeof (bool) * cost_elements_num); #endif /* FORBIDDEN_INC_DEC_CLASSES */ - pref = NULL; - start = 0; - if (!resize_reg_info () && allocno_p && pseudo_classes_defined_p) + regno_best_class + = (enum reg_class *) ira_allocate (max_reg_num () + * sizeof (enum reg_class)); + for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--) + regno_best_class[i] = NO_REGS; + if (!resize_reg_info () && allocno_p + && pseudo_classes_defined_p && flag_expensive_optimizations) { ira_allocno_t a; ira_allocno_iterator ai; pref = pref_buffer; + max_cost_classes_num = 1; FOR_EACH_ALLOCNO (a, ai) - pref[ALLOCNO_NUM (a)] = reg_preferred_class (ALLOCNO_REGNO (a)); - if (flag_expensive_optimizations) - start = 1; + { + pref[ALLOCNO_NUM (a)] = reg_preferred_class (ALLOCNO_REGNO (a)); + setup_regno_cost_classes_by_aclass + (ALLOCNO_REGNO (a), pref[ALLOCNO_NUM (a)]); + max_cost_classes_num + = MAX (max_cost_classes_num, + regno_cost_classes[ALLOCNO_REGNO (a)]->num); + } + start = 1; + } + else + { + pref = NULL; + max_cost_classes_num = ira_important_classes_num; + for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--) + if (regno_reg_rtx[i] != NULL_RTX) + setup_regno_cost_classes_by_mode (i, PSEUDO_REGNO_MODE (i)); + else + setup_regno_cost_classes_by_aclass (i, ALL_REGS); + start = 0; } if (allocno_p) /* Clear the flag for the next compiled function. */ @@ -1218,22 +1524,20 @@ 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; - cost_classes_num < ira_important_classes_num; - cost_classes_num++) + + if (pass != start) { - cost_classes[cost_classes_num] - = ira_important_classes[cost_classes_num]; - cost_class_nums[cost_classes[cost_classes_num]] - = cost_classes_num; + max_cost_classes_num = 1; + for (i = max_reg_num () - 1; i >= FIRST_PSEUDO_REGISTER; i--) + { + setup_regno_cost_classes_by_aclass (i, regno_best_class[i]); + max_cost_classes_num + = MAX (max_cost_classes_num, regno_cost_classes[i]->num); + } } + struct_costs_size - = sizeof (struct costs) + sizeof (int) * (cost_classes_num - 1); + = sizeof (struct costs) + sizeof (int) * (max_cost_classes_num - 1); /* Zero out our accumulation of the cost of each class for each allocno. */ memset (costs, 0, cost_elements_num * struct_costs_size); @@ -1267,13 +1571,17 @@ 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; #ifdef FORBIDDEN_INC_DEC_CLASSES int inc_dec_p = false; #endif + cost_classes_t cost_classes_ptr = regno_cost_classes[i]; + enum reg_class *cost_classes = cost_classes_ptr->classes; + int *i_costs = temp_costs->cost; + int i_mem_cost; int equiv_savings = regno_equiv_gains[i]; if (! allocno_p) @@ -1284,17 +1592,21 @@ find_costs_and_classes (FILE *dump_file) inc_dec_p = in_inc_dec[i]; #endif memcpy (temp_costs, COSTS (costs, i), struct_costs_size); + i_mem_cost = temp_costs->mem_cost; } else { if (ira_regno_allocno_map[i] == NULL) continue; memset (temp_costs, 0, struct_costs_size); + i_mem_cost = 0; /* Find cost of all allocnos with the same regno. */ for (a = ira_regno_allocno_map[i]; a != NULL; a = ALLOCNO_NEXT_REGNO_ALLOCNO (a)) { + int *a_costs, *p_costs; + a_num = ALLOCNO_NUM (a); if ((flag_ira_region == IRA_REGION_ALL || flag_ira_region == IRA_REGION_MIXED) @@ -1308,15 +1620,42 @@ find_costs_and_classes (FILE *dump_file) /* Propagate costs to upper levels in the region 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; + a_costs = COSTS (total_allocno_costs, a_num)->cost; + p_costs = COSTS (total_allocno_costs, parent_a_num)->cost; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + add_cost = a_costs[k]; + if (add_cost > 0 && INT_MAX - add_cost < p_costs[k]) + p_costs[k] = INT_MAX; + else + p_costs[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; + a_costs = COSTS (costs, a_num)->cost; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + { + add_cost = a_costs[k]; + if (add_cost > 0 && INT_MAX - add_cost < i_costs[k]) + i_costs[k] = INT_MAX; + else + i_costs[k] += add_cost; + } + add_cost = COSTS (costs, a_num)->mem_cost; + if (add_cost && INT_MAX - add_cost < i_mem_cost) + i_mem_cost = INT_MAX; + else + i_mem_cost += add_cost; #ifdef FORBIDDEN_INC_DEC_CLASSES if (in_inc_dec[a_num]) inc_dec_p = true; @@ -1328,8 +1667,8 @@ find_costs_and_classes (FILE *dump_file) else if (equiv_savings > 0) { temp_costs->mem_cost = 0; - for (k = 0; k < cost_classes_num; k++) - temp_costs->cost[k] += equiv_savings; + for (k = cost_classes_ptr->num - 1; k >= 0; k--) + i_costs[k] += equiv_savings; } best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1; @@ -1337,7 +1676,7 @@ find_costs_and_classes (FILE *dump_file) alt_class = NO_REGS; /* Find best common class for all allocnos with the same regno. */ - for (k = 0; k < cost_classes_num; k++) + for (k = 0; k < cost_classes_ptr->num; k++) { rclass = cost_classes[k]; /* Ignore classes that are too small for this operand or @@ -1351,48 +1690,49 @@ find_costs_and_classes (FILE *dump_file) #endif ) continue; - if (temp_costs->cost[k] < best_cost) + if (i_costs[k] < best_cost) { - best_cost = temp_costs->cost[k]; + best_cost = i_costs[k]; best = (enum reg_class) rclass; } - else if (temp_costs->cost[k] == best_cost) - best = ira_reg_class_union[best][rclass]; + else if (i_costs[k] == best_cost) + best = ira_reg_class_subunion[best][rclass]; if (pass == flag_expensive_optimizations - && temp_costs->cost[k] < temp_costs->mem_cost + && i_costs[k] < i_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]; - 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; + alt_class = ira_allocno_class_translate[alt_class]; + if (best_cost > i_mem_cost) + 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) + if (best_cost > i_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]]); } + regno_best_class[i] = best; if (! allocno_p) { - pref[i] = best_cost > temp_costs->mem_cost ? NO_REGS : best; + pref[i] = best_cost > i_mem_cost ? NO_REGS : best; continue; } for (a = ira_regno_allocno_map[i]; @@ -1400,19 +1740,22 @@ 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 { + int *total_a_costs = COSTS (total_allocno_costs, a_num)->cost; + int *a_costs = COSTS (costs, a_num)->cost; + /* Finding best class which is subset of the common class. */ best_cost = (1 << (HOST_BITS_PER_INT - 2)) - 1; allocno_cost = best_cost; best = ALL_REGS; - for (k = 0; k < cost_classes_num; k++) + for (k = 0; k < cost_classes_ptr->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 @@ -1426,26 +1769,20 @@ find_costs_and_classes (FILE *dump_file) #endif ) ; - else if (COSTS (total_allocno_costs, a_num)->cost[k] - < best_cost) + else if (total_a_costs[k] < best_cost) { - best_cost - = COSTS (total_allocno_costs, a_num)->cost[k]; - allocno_cost = COSTS (costs, a_num)->cost[k]; + best_cost = total_a_costs[k]; + allocno_cost = a_costs[k]; best = (enum reg_class) rclass; } - else if (COSTS (total_allocno_costs, a_num)->cost[k] - == best_cost) + else if (total_a_costs[k] == best_cost) { - best = ira_reg_class_union[best][rclass]; - allocno_cost - = MAX (allocno_cost, COSTS (costs, a_num)->cost[k]); + best = ira_reg_class_subunion[best][rclass]; + allocno_cost = MAX (allocno_cost, a_costs[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)) { @@ -1455,14 +1792,14 @@ 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; } } - + if (internal_flag_ira_verbose > 4 && dump_file) { if (allocno_p) @@ -1472,6 +1809,7 @@ find_costs_and_classes (FILE *dump_file) fprintf (dump_file,"\n"); } } + ira_free (regno_best_class); #ifdef FORBIDDEN_INC_DEC_CLASSES ira_free (in_inc_dec); #endif @@ -1480,8 +1818,8 @@ find_costs_and_classes (FILE *dump_file) /* 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 @@ -1530,7 +1868,7 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node) } 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]; @@ -1538,65 +1876,64 @@ process_bb_node_for_hard_reg_moves (ira_loop_tree_node_t loop_tree_node) continue; mode = ALLOCNO_MODE (a); hard_reg_class = REGNO_REG_CLASS (hard_regno); + ira_init_register_move_cost_if_necessary (mode); cost - = (to_p ? ira_get_register_move_cost (mode, hard_reg_class, rclass) - : ira_get_register_move_cost (mode, rclass, hard_reg_class)) * freq; + = (to_p ? ira_register_move_cost[mode][hard_reg_class][rclass] + : ira_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_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, regno, 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; + cost_classes_t cost_classes_ptr; ira_assert (allocno_p); 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); + regno = ALLOCNO_REGNO (a); + aclass = regno_aclass[regno]; + cost_classes_ptr = regno_cost_classes[regno]; + 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); - num = cost_class_nums[rclass]; + rclass = REGNO_REG_CLASS (hard_regno); + num = cost_classes_ptr->index[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_classes_ptr->hard_regno_index[hard_regno]; + ira_assert (num >= 0); } reg_costs[j] = COSTS (costs, i)->cost[num]; } @@ -1623,7 +1960,6 @@ ira_init_costs_once (void) this_op_costs[i] = NULL; } temp_costs = NULL; - cost_classes = NULL; } /* Free allocated temporary cost vectors. */ @@ -1646,9 +1982,6 @@ free_ira_costs (void) if (temp_costs != NULL) free (temp_costs); temp_costs = NULL; - if (cost_classes != NULL) - free (cost_classes); - cost_classes = NULL; } /* This is called each time register related information is @@ -1661,7 +1994,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++) @@ -1672,8 +2006,6 @@ ira_init_costs (void) this_op_costs[i] = (struct costs *) xmalloc (max_struct_costs_size); } temp_costs = (struct costs *) xmalloc (max_struct_costs_size); - cost_classes = (enum reg_class *) xmalloc (sizeof (enum reg_class) - * ira_important_classes_num); } /* Function called once at the end of compiler work. */ @@ -1693,12 +2025,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 ()); } @@ -1710,13 +2040,13 @@ finish_costs (void) { finish_subregs_of_mode (); 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) { @@ -1725,9 +2055,11 @@ ira_costs (void) init_costs (); total_allocno_costs = (struct costs *) ira_allocate (max_struct_costs_size * ira_allocnos_num); + initiate_regno_cost_classes (); calculate_elim_costs_all_insns (); find_costs_and_classes (ira_dump_file); - setup_allocno_cover_class_and_costs (); + setup_allocno_class_and_costs (); + finish_regno_cost_classes (); finish_costs (); ira_free (total_allocno_costs); } @@ -1740,7 +2072,9 @@ ira_set_pseudo_classes (FILE *dump_file) internal_flag_ira_verbose = flag_ira_verbose; cost_elements_num = max_reg_num (); init_costs (); + initiate_regno_cost_classes (); find_costs_and_classes (dump_file); + finish_regno_cost_classes (); pseudo_classes_defined_p = true; finish_costs (); } @@ -1751,32 +2085,48 @@ 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; + ira_allocno_object_iterator oi; + ira_object_t obj; + bool skip_p; 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]; + skip_p = false; + FOR_EACH_ALLOCNO_OBJECT (a, obj, oi) + { + if (! ira_hard_reg_not_in_set_p (regno, mode, + OBJECT_CONFLICT_HARD_REGS + (obj))) + { + skip_p = true; + break; + } + } + if (skip_p) + continue; rclass = REGNO_REG_CLASS (regno); cost = 0; if (! ira_hard_reg_not_in_set_p (regno, mode, call_used_reg_set) @@ -1790,33 +2140,35 @@ ira_tune_allocno_costs_and_cover_classes (void) * 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 sequence can unnecessarily restrict later allocations. So increase the cost of unaligned hard regs to encourage the use of aligned hard regs. */ { - const int nregs = ira_reg_class_nregs[cover_class][ALLOCNO_MODE (a)]; + const int nregs = ira_reg_class_max_nregs[aclass][ALLOCNO_MODE (a)]; if (nregs > 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--) { - regno = ira_non_ordered_class_hard_regs[cover_class][j]; + regno = ira_non_ordered_class_hard_regs[aclass][j]; if ((regno % nregs) != 0) { - int index = ira_class_hard_reg_index[cover_class][regno]; + int index = ira_class_hard_reg_index[aclass][regno]; ira_assert (index != -1); reg_costs[index] += ALLOCNO_FREQ (a); } |