diff options
-rw-r--r-- | gcc/ChangeLog | 38 | ||||
-rw-r--r-- | gcc/ira-build.c | 8 | ||||
-rw-r--r-- | gcc/ira-color.c | 67 | ||||
-rw-r--r-- | gcc/ira-conflicts.c | 25 | ||||
-rw-r--r-- | gcc/ira-costs.c | 3 | ||||
-rw-r--r-- | gcc/ira-int.h | 8 | ||||
-rw-r--r-- | gcc/ira-lives.c | 40 | ||||
-rw-r--r-- | gcc/ira.c | 5 |
8 files changed, 148 insertions, 46 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 666594f8b30..a683eca7e00 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,43 @@ 2008-10-27 Vladimir Makarov <vmakarov@redhat.com> + * ira-int.h (ira_allocno): Add member updated_cover_class_cost. + (ALLOCNO_UPDATED_COVER_CLASS_COST): New. + (ira_fast_allocation): Remove the prototype. + + * ira-color.c (update_copy_costs, allocno_cost_compare_func, + assign_hard_reg, calculate_allocno_spill_cost): Use updated costs. + (color_pass): Modify the updated costs. + (ira_color): Rename to color. Make it static. + (ira_fast_allocation): Rename to fast_allocation. Make it static. + (ira_color): New function. + + * ira-conflicts.c (process_regs_for_copy): Propagate hard reg cost + change. + + * ira-lives.c (last_call_num, allocno_saved_at_call): New + variables. + (set_allocno_live, clear_allocno_live, mark_ref_live, + mark_ref_dead): Invalidate corresponding element of + allocno_saved_at_call. + (process_bb_node_lives): Increment last_call_num. Setup + allocno_saved_at_call. Don't increase ALLOCNO_CALL_FREQ if the + allocno was already saved. + (ira_create_allocno_live_ranges): Initiate last_call_num and + allocno_saved_at_call. + + * ira-build.c (ira_create_allocno): Initiate + ALLOCNO_UPDATED_COVER_CLASS_COST. + (create_cap_allocno, propagate_allocno_info, + remove_unnecessary_allocnos): Remove setting updated costs. + (ira_flattening): Set up ALLOCNO_UPDATED_COVER_CLASS_COST. + + * ira.c (ira): Don't call ira_fast_allocation. + + * ira-costs.c (setup_allocno_cover_class_and_costs): Don't set up + updated costs. + +2008-10-27 Vladimir Makarov <vmakarov@redhat.com> + PR middle-end/37813 * ira-conflicts.c (process_regs_for_copy): Remove class subset check. diff --git a/gcc/ira-build.c b/gcc/ira-build.c index 68b54dfad25..8e92f8c1b3e 100644 --- a/gcc/ira-build.c +++ b/gcc/ira-build.c @@ -469,6 +469,7 @@ ira_create_allocno (int regno, bool cap_p, ira_loop_tree_node_t loop_tree_node) ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (a) = NULL; ALLOCNO_LEFT_CONFLICTS_NUM (a) = -1; ALLOCNO_COVER_CLASS (a) = NO_REGS; + ALLOCNO_UPDATED_COVER_CLASS_COST (a) = 0; ALLOCNO_COVER_CLASS_COST (a) = 0; ALLOCNO_MEMORY_COST (a) = 0; ALLOCNO_UPDATED_MEMORY_COST (a) = 0; @@ -769,7 +770,6 @@ create_cap_allocno (ira_allocno_t a) ALLOCNO_CAP (a) = cap; ALLOCNO_COVER_CLASS_COST (cap) = ALLOCNO_COVER_CLASS_COST (a); ALLOCNO_MEMORY_COST (cap) = ALLOCNO_MEMORY_COST (a); - ALLOCNO_UPDATED_MEMORY_COST (cap) = ALLOCNO_UPDATED_MEMORY_COST (a); ira_allocate_and_copy_costs (&ALLOCNO_HARD_REG_COSTS (cap), cover_class, ALLOCNO_HARD_REG_COSTS (a)); ira_allocate_and_copy_costs @@ -1509,8 +1509,6 @@ propagate_allocno_info (void) ALLOCNO_COVER_CLASS_COST (parent_a) += ALLOCNO_COVER_CLASS_COST (a); ALLOCNO_MEMORY_COST (parent_a) += ALLOCNO_MEMORY_COST (a); - ALLOCNO_UPDATED_MEMORY_COST (parent_a) - += ALLOCNO_UPDATED_MEMORY_COST (a); } } @@ -1789,8 +1787,6 @@ remove_unnecessary_allocnos (void) ALLOCNO_COVER_CLASS_COST (parent_a) += ALLOCNO_COVER_CLASS_COST (a); ALLOCNO_MEMORY_COST (parent_a) += ALLOCNO_MEMORY_COST (a); - ALLOCNO_UPDATED_MEMORY_COST (parent_a) - += ALLOCNO_UPDATED_MEMORY_COST (a); finish_allocno (a); } } @@ -2353,7 +2349,9 @@ ira_flattening (int max_regno_before_emit, int ira_max_point_before_emit) ALLOCNO_LOOP_TREE_NODE (a) = ira_loop_tree_root; ALLOCNO_REGNO (a) = REGNO (ALLOCNO_REG (a)); ALLOCNO_CAP (a) = NULL; + /* Restore updated costs for assignments from reload. */ ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a); + ALLOCNO_UPDATED_COVER_CLASS_COST (a) = ALLOCNO_COVER_CLASS_COST (a); if (! ALLOCNO_ASSIGNED_P (a)) ira_free_allocno_updated_costs (a); ira_assert (ALLOCNO_UPDATED_HARD_REG_COSTS (a) == NULL); diff --git a/gcc/ira-color.c b/gcc/ira-color.c index c972ba942a2..7a89c1b62eb 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -252,7 +252,7 @@ update_copy_costs (ira_allocno_t allocno, bool decr_p) ira_allocate_and_set_or_copy_costs (&ALLOCNO_UPDATED_HARD_REG_COSTS (another_allocno), cover_class, - ALLOCNO_COVER_CLASS_COST (another_allocno), + ALLOCNO_UPDATED_COVER_CLASS_COST (another_allocno), ALLOCNO_HARD_REG_COSTS (another_allocno)); ira_allocate_and_set_or_copy_costs (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (another_allocno), @@ -348,8 +348,8 @@ allocno_cost_compare_func (const void *v1p, const void *v2p) ira_allocno_t p2 = *(const ira_allocno_t *) v2p; int c1, c2; - c1 = ALLOCNO_UPDATED_MEMORY_COST (p1) - ALLOCNO_COVER_CLASS_COST (p1); - c2 = ALLOCNO_UPDATED_MEMORY_COST (p2) - ALLOCNO_COVER_CLASS_COST (p2); + c1 = ALLOCNO_UPDATED_MEMORY_COST (p1) - ALLOCNO_UPDATED_COVER_CLASS_COST (p1); + c2 = ALLOCNO_UPDATED_MEMORY_COST (p2) - ALLOCNO_UPDATED_COVER_CLASS_COST (p2); if (c1 - c2) return c1 - c2; @@ -426,7 +426,9 @@ assign_hard_reg (ira_allocno_t allocno, bool retry_p) #ifdef STACK_REGS no_stack_reg_p = no_stack_reg_p || ALLOCNO_TOTAL_NO_STACK_REG_P (a); #endif - for (cost = ALLOCNO_COVER_CLASS_COST (a), i = 0; i < class_size; i++) + for (cost = ALLOCNO_UPDATED_COVER_CLASS_COST (a), i = 0; + i < class_size; + i++) if (a_costs != NULL) { costs[i] += a_costs[i]; @@ -959,7 +961,7 @@ calculate_allocno_spill_cost (ira_allocno_t a) ira_loop_tree_node_t parent_node, loop_node; regno = ALLOCNO_REGNO (a); - cost = ALLOCNO_UPDATED_MEMORY_COST (a) - ALLOCNO_COVER_CLASS_COST (a); + cost = ALLOCNO_UPDATED_MEMORY_COST (a) - ALLOCNO_UPDATED_COVER_CLASS_COST (a); if (ALLOCNO_CAP (a) != NULL) return cost; loop_node = ALLOCNO_LOOP_TREE_NODE (a); @@ -1821,24 +1823,26 @@ color_pass (ira_loop_tree_node_t loop_tree_node) else { cover_class = ALLOCNO_COVER_CLASS (subloop_allocno); - ira_allocate_and_set_costs - (&ALLOCNO_HARD_REG_COSTS (subloop_allocno), cover_class, - ALLOCNO_COVER_CLASS_COST (subloop_allocno)); - ira_allocate_and_set_costs - (&ALLOCNO_CONFLICT_HARD_REG_COSTS (subloop_allocno), - cover_class, 0); cost = (ira_register_move_cost[mode][rclass][rclass] * (exit_freq + enter_freq)); - ALLOCNO_HARD_REG_COSTS (subloop_allocno)[index] -= cost; - ALLOCNO_CONFLICT_HARD_REG_COSTS (subloop_allocno)[index] + ira_allocate_and_set_or_copy_costs + (&ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno), cover_class, + ALLOCNO_UPDATED_COVER_CLASS_COST (subloop_allocno), + ALLOCNO_HARD_REG_COSTS (subloop_allocno)); + ira_allocate_and_set_or_copy_costs + (&ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (subloop_allocno), + cover_class, 0, + ALLOCNO_CONFLICT_HARD_REG_COSTS (subloop_allocno)); + ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index] -= cost; + ALLOCNO_UPDATED_CONFLICT_HARD_REG_COSTS (subloop_allocno)[index] -= cost; + if (ALLOCNO_UPDATED_COVER_CLASS_COST (subloop_allocno) + > ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index]) + ALLOCNO_UPDATED_COVER_CLASS_COST (subloop_allocno) + = ALLOCNO_UPDATED_HARD_REG_COSTS (subloop_allocno)[index]; ALLOCNO_UPDATED_MEMORY_COST (subloop_allocno) += (ira_memory_move_cost[mode][rclass][0] * enter_freq + ira_memory_move_cost[mode][rclass][1] * exit_freq); - if (ALLOCNO_COVER_CLASS_COST (subloop_allocno) - > ALLOCNO_HARD_REG_COSTS (subloop_allocno)[index]) - ALLOCNO_COVER_CLASS_COST (subloop_allocno) - = ALLOCNO_HARD_REG_COSTS (subloop_allocno)[index]; } } } @@ -3054,8 +3058,8 @@ ira_finish_assign (void) /* Entry function doing color-based register allocation. */ -void -ira_color (void) +static void +color (void) { allocno_stack_vec = VEC_alloc (ira_allocno_t, heap, ira_allocnos_num); removed_splay_allocno_vec @@ -3077,8 +3081,8 @@ ira_color (void) /* Do register allocation by not using allocno conflicts. It uses only allocno live ranges. The algorithm is close to Chow's priority coloring. */ -void -ira_fast_allocation (void) +static void +fast_allocation (void) { int i, j, k, num, class_size, hard_regno; #ifdef STACK_REGS @@ -3148,3 +3152,24 @@ ira_fast_allocation (void) if (internal_flag_ira_verbose > 1 && ira_dump_file != NULL) ira_print_disposition (ira_dump_file); } + + + +/* Entry function doing coloring. */ +void +ira_color (void) +{ + ira_allocno_t a; + ira_allocno_iterator ai; + + /* Setup updated costs. */ + FOR_EACH_ALLOCNO (a, ai) + { + ALLOCNO_UPDATED_MEMORY_COST (a) = ALLOCNO_MEMORY_COST (a); + ALLOCNO_UPDATED_COVER_CLASS_COST (a) = ALLOCNO_COVER_CLASS_COST (a); + } + if (optimize) + color (); + else + fast_allocation (); +} diff --git a/gcc/ira-conflicts.c b/gcc/ira-conflicts.c index 9bdc3e7252d..01ba907ab5d 100644 --- a/gcc/ira-conflicts.c +++ b/gcc/ira-conflicts.c @@ -337,6 +337,7 @@ process_regs_for_copy (rtx reg1, rtx reg2, rtx insn, int freq) enum reg_class rclass, cover_class; enum machine_mode mode; ira_copy_t cp; + ira_loop_tree_node_t parent; gcc_assert (REG_SUBREG_P (reg1) && REG_SUBREG_P (reg2)); only_regs_p = REG_P (reg1) && REG_P (reg2); @@ -386,13 +387,23 @@ process_regs_for_copy (rtx reg1, rtx reg2, rtx insn, int freq) cost = ira_register_move_cost[mode][cover_class][rclass] * freq; else cost = ira_register_move_cost[mode][rclass][cover_class] * freq; - ira_allocate_and_set_costs - (&ALLOCNO_HARD_REG_COSTS (a), cover_class, - ALLOCNO_COVER_CLASS_COST (a)); - ira_allocate_and_set_costs - (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), cover_class, 0); - ALLOCNO_HARD_REG_COSTS (a)[index] -= cost; - ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost; + for (;;) + { + ira_allocate_and_set_costs + (&ALLOCNO_HARD_REG_COSTS (a), cover_class, + ALLOCNO_COVER_CLASS_COST (a)); + ira_allocate_and_set_costs + (&ALLOCNO_CONFLICT_HARD_REG_COSTS (a), cover_class, 0); + ALLOCNO_HARD_REG_COSTS (a)[index] -= cost; + ALLOCNO_CONFLICT_HARD_REG_COSTS (a)[index] -= cost; + if (ALLOCNO_HARD_REG_COSTS (a)[index] < ALLOCNO_COVER_CLASS_COST (a)) + ALLOCNO_COVER_CLASS_COST (a) = ALLOCNO_HARD_REG_COSTS (a)[index]; + if (ALLOCNO_CAP (a) != NULL) + a = ALLOCNO_CAP (a); + else if ((parent = ALLOCNO_LOOP_TREE_NODE (a)->parent) == NULL + || (a = parent->regno_allocno_map[ALLOCNO_REGNO (a)]) == NULL) + break; + } return true; } diff --git a/gcc/ira-costs.c b/gcc/ira-costs.c index 82adf5dccb8..eade4da4d1c 100644 --- a/gcc/ira-costs.c +++ b/gcc/ira-costs.c @@ -1407,8 +1407,7 @@ setup_allocno_cover_class_and_costs (void) mode = ALLOCNO_MODE (a); cover_class = ira_class_translate[allocno_pref[i]]; ira_assert (allocno_pref[i] == NO_REGS || cover_class != NO_REGS); - ALLOCNO_MEMORY_COST (a) = ALLOCNO_UPDATED_MEMORY_COST (a) - = COSTS_OF_ALLOCNO (allocno_costs, i)->mem_cost; + ALLOCNO_MEMORY_COST (a) = COSTS_OF_ALLOCNO (allocno_costs, i)->mem_cost; ira_set_allocno_cover_class (a, cover_class); if (cover_class == NO_REGS) continue; diff --git a/gcc/ira-int.h b/gcc/ira-int.h index dafcfb7ec46..c72df3de77b 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -258,9 +258,9 @@ struct ira_allocno /* Register class which should be used for allocation for given allocno. NO_REGS means that we should use memory. */ enum reg_class cover_class; - /* Minimal accumulated cost of usage register of the cover class for - the allocno. */ - int cover_class_cost; + /* Minimal accumulated and updated costs of usage register of the + cover class for the allocno. */ + int cover_class_cost, updated_cover_class_cost; /* Minimal accumulated, and updated costs of memory for the allocno. At the allocation start, the original and updated costs are equal. The updated cost may be changed after finishing @@ -451,6 +451,7 @@ struct ira_allocno #define ALLOCNO_LEFT_CONFLICTS_NUM(A) ((A)->left_conflicts_num) #define ALLOCNO_COVER_CLASS(A) ((A)->cover_class) #define ALLOCNO_COVER_CLASS_COST(A) ((A)->cover_class_cost) +#define ALLOCNO_UPDATED_COVER_CLASS_COST(A) ((A)->updated_cover_class_cost) #define ALLOCNO_MEMORY_COST(A) ((A)->memory_cost) #define ALLOCNO_UPDATED_MEMORY_COST(A) ((A)->updated_memory_cost) #define ALLOCNO_EXCESS_PRESSURE_POINTS_NUM(A) ((A)->excess_pressure_points_num) @@ -902,7 +903,6 @@ extern void ira_reassign_conflict_allocnos (int); extern void ira_initiate_assign (void); extern void ira_finish_assign (void); extern void ira_color (void); -extern void ira_fast_allocation (void); /* ira-emit.c */ extern void ira_emit (bool); diff --git a/gcc/ira-lives.c b/gcc/ira-lives.c index c908ab71338..5573ce86a5e 100644 --- a/gcc/ira-lives.c +++ b/gcc/ira-lives.c @@ -75,6 +75,11 @@ static HARD_REG_SET hard_regs_live; /* The loop tree node corresponding to the current basic block. */ static ira_loop_tree_node_t curr_bb_node; +/* The number of the last processed call. */ +static int last_call_num; +/* The number of last call at which given allocno was saved. */ +static int *allocno_saved_at_call; + /* The function processing birth of register REGNO. It updates living hard regs and conflict hard regs for living allocnos or starts a new live range for the allocno corresponding to REGNO if it is @@ -163,6 +168,8 @@ set_allocno_live (ira_allocno_t a) int nregs; enum reg_class cover_class; + /* Invalidate because it is referenced. */ + allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) return; sparseset_set_bit (allocnos_live, ALLOCNO_NUM (a)); @@ -189,6 +196,8 @@ clear_allocno_live (ira_allocno_t a) unsigned int i; enum reg_class cover_class; + /* Invalidate because it is referenced. */ + allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) { cover_class = ALLOCNO_COVER_CLASS (a); @@ -228,7 +237,11 @@ mark_reg_live (rtx reg) if (a != NULL) { if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) - return; + { + /* Invalidate because it is referenced. */ + allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; + return; + } set_allocno_live (a); } make_regno_born (regno); @@ -293,7 +306,11 @@ mark_reg_dead (rtx reg) if (a != NULL) { if (! sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) - return; + { + /* Invalidate because it is referenced. */ + allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; + return; + } clear_allocno_live (a); } make_regno_dead (regno); @@ -820,6 +837,9 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) if (freq == 0) freq = 1; + /* Invalidate all allocno_saved_at_call entries. */ + last_call_num++; + /* Scan the code of this basic block, noting which allocnos and hard regs are born or die. @@ -901,12 +921,21 @@ process_bb_node_lives (ira_loop_tree_node_t loop_tree_node) if (call_p) { + last_call_num++; /* The current set of live allocnos are live across the call. */ EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i) { ira_allocno_t a = ira_allocnos[i]; - ALLOCNO_CALL_FREQ (a) += freq; + if (allocno_saved_at_call[i] != last_call_num) + /* Here we are mimicking caller-save.c behaviour + which does not save hard register at a call if + it was saved on previous call in the same basic + block and the hard register was not mentioned + between the two calls. */ + ALLOCNO_CALL_FREQ (a) += freq; + /* Mark it as saved at the next call. */ + allocno_saved_at_call[i] = last_call_num + 1; ALLOCNO_CALLS_CROSSED_NUM (a)++; /* Don't allocate allocnos that cross setjmps or any call, if this function receives a nonlocal @@ -1152,6 +1181,10 @@ ira_create_allocno_live_ranges (void) { allocnos_live = sparseset_alloc (ira_allocnos_num); curr_point = 0; + last_call_num = 0; + allocno_saved_at_call + = (int *) ira_allocate (ira_allocnos_num * sizeof (int)); + memset (allocno_saved_at_call, 0, ira_allocnos_num * sizeof (int)); ira_traverse_loop_tree (true, ira_loop_tree_root, NULL, process_bb_node_lives); ira_max_point = curr_point; @@ -1159,6 +1192,7 @@ ira_create_allocno_live_ranges (void) if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL) print_live_ranges (ira_dump_file); /* Clean up. */ + ira_free (allocno_saved_at_call); sparseset_free (allocnos_live); } diff --git a/gcc/ira.c b/gcc/ira.c index 30ef8c898c7..d0232f75a1e 100644 --- a/gcc/ira.c +++ b/gcc/ira.c @@ -1792,10 +1792,7 @@ ira (FILE *f) loops_p = ira_build (optimize && (flag_ira_algorithm == IRA_ALGORITHM_REGIONAL || flag_ira_algorithm == IRA_ALGORITHM_MIXED)); - if (optimize) - ira_color (); - else - ira_fast_allocation (); + ira_color (); ira_max_point_before_emit = ira_max_point; |