summaryrefslogtreecommitdiff
path: root/gcc/ira-costs.c
diff options
context:
space:
mode:
authorvmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2011-03-27 23:16:35 +0000
committervmakarov <vmakarov@138bc75d-0d04-0410-961f-82ee72b054a4>2011-03-27 23:16:35 +0000
commit284914859842aefe10bf7e92f4157a841e97deac (patch)
treeab75249e0724a39c82bc4c52637b7593afc63580 /gcc/ira-costs.c
parent5f239f1387c82100c270c389cda7f8a536144034 (diff)
downloadgcc-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.c874
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);
}