From patchwork Fri Jun 18 14:05:21 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernd Schmidt X-Patchwork-Id: 56184 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id 074D31007D5 for ; Sat, 19 Jun 2010 00:05:53 +1000 (EST) Received: (qmail 32687 invoked by alias); 18 Jun 2010 14:05:47 -0000 Received: (qmail 32263 invoked by uid 22791); 18 Jun 2010 14:05:42 -0000 X-SWARE-Spam-Status: No, hits=-1.9 required=5.0 tests=AWL, BAYES_00, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mail.codesourcery.com (HELO mail.codesourcery.com) (38.113.113.100) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Fri, 18 Jun 2010 14:05:29 +0000 Received: (qmail 30490 invoked from network); 18 Jun 2010 14:05:27 -0000 Received: from unknown (HELO ?84.152.216.85?) (bernds@127.0.0.2) by mail.codesourcery.com with ESMTPA; 18 Jun 2010 14:05:27 -0000 Message-ID: <4C1B7D21.6020607@codesourcery.com> Date: Fri, 18 Jun 2010 14:05:21 +0000 From: Bernd Schmidt User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100604 Thunderbird/3.0.4 MIME-Version: 1.0 To: GCC Patches Subject: Patch 2/9: Split up and reorganize some functions References: <4C1B7BC0.7010803@codesourcery.com> In-Reply-To: <4C1B7BC0.7010803@codesourcery.com> Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org This creates a few helper functions by breaking them out of larger ones. In part, this is to make the code easier to read and should be a stand-alone improvement, but mostly it is motivated by subsequent patches which will modify the behaviour of the new functions. In ira-lives.c, there is a slightly more involved restructuring of the: Functions to mark registers live or dead are split up into versions for pseudos and hard registers. set_allocno_live and clear_allocno_live get the more descriptive names inc_register_pressure and dec_register_pressure; all code that isn't related to tracking pressure is moved into other functions. This allows us to further reduce code duplication by reusing these functions in mark_hard_reg_live and mark_hard_reg_dead. I've also fixed up some confusion about when to clear allocno_saved_at_call. Note that there is a small change in behaviour: in inc/dec_register_pressure, we no longer recompute nregs as we iterate through the classes. I think it's more correct this way, and I haven't seen any difference in code generation. * ira-build.c (merge_hard_reg_conflicts): New function. (create_cap_allocno, copy_info_to_removed_store_destinations, propagate_some_info_from_allocno, propagate_allocno_info): Use it. (move_allocno_live_ranges, copy_allocno_live_ranges): New functions. (remove_unnecessary_allocnos, remove_low_level_allocnos) copy_nifo_to_removed_store_destination): Use them. * ira-lives.c (make_hard_regno_born): New function, split out of make_regno_born. (make_allocno_born): Likewise. (make_hard_regno_dead): New function, split out of make_regno_dead. (make_allocno_dead): Likewise. (inc_register_pressure): New function, split out of set_allocno_live. (dec_register_pressure): New function, split out of clear_allocno_live. (mark_pseudo_regno_live): New function, split out of mark_reg_live. (mark_hard_reg_live): Likewise. Use inc_register_pressure. (mark_pseudo_regno_dead): New function, split out of mark_reg_dead. (mark_hard_reg_dead): Likewise. Use dec_register_pressure. (make_pseudo_conflict): Use mark_pseudo_regno_dead and mark_pseudo_regno_live. (process_bb_node_lives): Use mark_pseudo_regno_live, make_hard_regno_born and make_allocno_dead. (make_regno_born, make_regno_dead, mark_reg_live, mark_reg_dead, set_allocno_live, clear_allocno_live): Delete functions. (Index: gcc/ira-build.c =================================================================== --- gcc.orig/ira-build.c +++ gcc/ira-build.c @@ -504,6 +504,25 @@ ira_set_allocno_cover_class (ira_allocno reg_class_contents[cover_class]); } +/* Merge hard register conflicts from allocno FROM into allocno TO. If + TOTAL_ONLY is true, we ignore ALLOCNO_CONFLICT_HARD_REGS. */ +static void +merge_hard_reg_conflicts (ira_allocno_t from, ira_allocno_t to, + bool total_only) +{ + if (!total_only) + IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (to), + ALLOCNO_CONFLICT_HARD_REGS (from)); + IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (to), + ALLOCNO_TOTAL_CONFLICT_HARD_REGS (from)); +#ifdef STACK_REGS + if (!total_only && ALLOCNO_NO_STACK_REG_P (from)) + ALLOCNO_NO_STACK_REG_P (to) = true; + if (ALLOCNO_TOTAL_NO_STACK_REG_P (from)) + ALLOCNO_TOTAL_NO_STACK_REG_P (to) = true; +#endif +} + /* Return TRUE if the conflict vector with NUM elements is more profitable than conflict bit vector for A. */ bool @@ -781,15 +800,8 @@ create_cap_allocno (ira_allocno_t a) ALLOCNO_NREFS (cap) = ALLOCNO_NREFS (a); ALLOCNO_FREQ (cap) = ALLOCNO_FREQ (a); ALLOCNO_CALL_FREQ (cap) = ALLOCNO_CALL_FREQ (a); - IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (cap), - ALLOCNO_CONFLICT_HARD_REGS (a)); - IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (cap), - ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a)); + merge_hard_reg_conflicts (a, cap, false); ALLOCNO_CALLS_CROSSED_NUM (cap) = ALLOCNO_CALLS_CROSSED_NUM (a); -#ifdef STACK_REGS - ALLOCNO_NO_STACK_REG_P (cap) = ALLOCNO_NO_STACK_REG_P (a); - ALLOCNO_TOTAL_NO_STACK_REG_P (cap) = ALLOCNO_TOTAL_NO_STACK_REG_P (a); -#endif if (internal_flag_ira_verbose > 2 && ira_dump_file != NULL) { fprintf (ira_dump_file, " Creating cap "); @@ -1603,12 +1615,7 @@ propagate_allocno_info (void) ALLOCNO_NREFS (parent_a) += ALLOCNO_NREFS (a); ALLOCNO_FREQ (parent_a) += ALLOCNO_FREQ (a); ALLOCNO_CALL_FREQ (parent_a) += ALLOCNO_CALL_FREQ (a); -#ifdef STACK_REGS - if (ALLOCNO_TOTAL_NO_STACK_REG_P (a)) - ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true; -#endif - IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a), - ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a)); + merge_hard_reg_conflicts (a, parent_a, true); ALLOCNO_CALLS_CROSSED_NUM (parent_a) += ALLOCNO_CALLS_CROSSED_NUM (a); ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (parent_a) @@ -1657,6 +1664,46 @@ change_allocno_in_range_list (allocno_li r->allocno = a; } +/* Move all live ranges associated with allocno A to allocno OTHER_A. */ +static void +move_allocno_live_ranges (ira_allocno_t from, ira_allocno_t to) +{ + allocno_live_range_t lr = ALLOCNO_LIVE_RANGES (from); + + if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL) + { + fprintf (ira_dump_file, + " Moving ranges of a%dr%d to a%dr%d: ", + ALLOCNO_NUM (from), ALLOCNO_REGNO (from), + ALLOCNO_NUM (to), ALLOCNO_REGNO (to)); + ira_print_live_range_list (ira_dump_file, lr); + } + change_allocno_in_range_list (lr, to); + ALLOCNO_LIVE_RANGES (to) + = ira_merge_allocno_live_ranges (lr, ALLOCNO_LIVE_RANGES (to)); + ALLOCNO_LIVE_RANGES (from) = NULL; +} + +/* Copy all live ranges associated with allocno A to allocno OTHER_A. */ +static void +copy_allocno_live_ranges (ira_allocno_t from, ira_allocno_t to) +{ + allocno_live_range_t lr = ALLOCNO_LIVE_RANGES (from); + + if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL) + { + fprintf (ira_dump_file, + " Copying ranges of a%dr%d to a%dr%d: ", + ALLOCNO_NUM (from), ALLOCNO_REGNO (from), + ALLOCNO_NUM (to), ALLOCNO_REGNO (to)); + ira_print_live_range_list (ira_dump_file, lr); + } + lr = ira_copy_allocno_live_range_list (lr); + change_allocno_in_range_list (lr, to); + ALLOCNO_LIVE_RANGES (to) + = ira_merge_allocno_live_ranges (lr, ALLOCNO_LIVE_RANGES (to)); +} + /* Return TRUE if NODE represents a loop with low register pressure. */ static bool @@ -1890,26 +1937,15 @@ propagate_some_info_from_allocno (ira_al { enum reg_class cover_class; - IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), - ALLOCNO_CONFLICT_HARD_REGS (from_a)); -#ifdef STACK_REGS - if (ALLOCNO_NO_STACK_REG_P (from_a)) - ALLOCNO_NO_STACK_REG_P (a) = true; -#endif + merge_hard_reg_conflicts (from_a, a, false); ALLOCNO_NREFS (a) += ALLOCNO_NREFS (from_a); ALLOCNO_FREQ (a) += ALLOCNO_FREQ (from_a); ALLOCNO_CALL_FREQ (a) += ALLOCNO_CALL_FREQ (from_a); - IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), - ALLOCNO_TOTAL_CONFLICT_HARD_REGS (from_a)); ALLOCNO_CALLS_CROSSED_NUM (a) += ALLOCNO_CALLS_CROSSED_NUM (from_a); ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) += ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (from_a); if (! ALLOCNO_BAD_SPILL_P (from_a)) ALLOCNO_BAD_SPILL_P (a) = false; -#ifdef STACK_REGS - if (ALLOCNO_TOTAL_NO_STACK_REG_P (from_a)) - ALLOCNO_TOTAL_NO_STACK_REG_P (a) = true; -#endif cover_class = ALLOCNO_COVER_CLASS (from_a); ira_assert (cover_class == ALLOCNO_COVER_CLASS (a)); ira_allocate_and_accumulate_costs (&ALLOCNO_HARD_REG_COSTS (a), cover_class, @@ -1930,7 +1966,6 @@ remove_unnecessary_allocnos (void) bool merged_p, rebuild_p; ira_allocno_t a, prev_a, next_a, parent_a; ira_loop_tree_node_t a_node, parent; - allocno_live_range_t r; merged_p = false; regno_allocnos = NULL; @@ -1971,13 +2006,8 @@ remove_unnecessary_allocnos (void) ira_regno_allocno_map[regno] = next_a; else ALLOCNO_NEXT_REGNO_ALLOCNO (prev_a) = next_a; - r = ALLOCNO_LIVE_RANGES (a); - change_allocno_in_range_list (r, parent_a); - ALLOCNO_LIVE_RANGES (parent_a) - = ira_merge_allocno_live_ranges - (r, ALLOCNO_LIVE_RANGES (parent_a)); + move_allocno_live_ranges (a, parent_a); merged_p = true; - ALLOCNO_LIVE_RANGES (a) = NULL; propagate_some_info_from_allocno (parent_a, a); /* Remove it from the corresponding regno allocno map to avoid info propagation of subsequent @@ -2011,7 +2041,6 @@ remove_low_level_allocnos (void) bool merged_p, propagate_p; ira_allocno_t a, top_a; ira_loop_tree_node_t a_node, parent; - allocno_live_range_t r; ira_allocno_iterator ai; merged_p = false; @@ -2030,12 +2059,8 @@ remove_low_level_allocnos (void) propagate_p = a_node->parent->regno_allocno_map[regno] == NULL; /* Remove the allocno and update info of allocno in the upper region. */ - r = ALLOCNO_LIVE_RANGES (a); - change_allocno_in_range_list (r, top_a); - ALLOCNO_LIVE_RANGES (top_a) - = ira_merge_allocno_live_ranges (r, ALLOCNO_LIVE_RANGES (top_a)); + move_allocno_live_ranges (a, top_a); merged_p = true; - ALLOCNO_LIVE_RANGES (a) = NULL; if (propagate_p) propagate_some_info_from_allocno (top_a, a); } @@ -2402,7 +2427,6 @@ copy_info_to_removed_store_destinations ira_allocno_t a; ira_allocno_t parent_a = NULL; ira_loop_tree_node_t parent; - allocno_live_range_t r; bool merged_p; merged_p = false; @@ -2425,26 +2449,8 @@ copy_info_to_removed_store_destinations break; if (parent == NULL || parent_a == NULL) continue; - if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL) - { - fprintf - (ira_dump_file, - " Coping ranges of a%dr%d to a%dr%d: ", - ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)), - ALLOCNO_NUM (parent_a), REGNO (ALLOCNO_REG (parent_a))); - ira_print_live_range_list (ira_dump_file, - ALLOCNO_LIVE_RANGES (a)); - } - r = ira_copy_allocno_live_range_list (ALLOCNO_LIVE_RANGES (a)); - change_allocno_in_range_list (r, parent_a); - ALLOCNO_LIVE_RANGES (parent_a) - = ira_merge_allocno_live_ranges (r, ALLOCNO_LIVE_RANGES (parent_a)); - IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a), - ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a)); -#ifdef STACK_REGS - if (ALLOCNO_TOTAL_NO_STACK_REG_P (a)) - ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true; -#endif + copy_allocno_live_ranges (a, parent_a); + merge_hard_reg_conflicts (a, parent_a, true); ALLOCNO_CALL_FREQ (parent_a) += ALLOCNO_CALL_FREQ (a); ALLOCNO_CALLS_CROSSED_NUM (parent_a) += ALLOCNO_CALLS_CROSSED_NUM (a); @@ -2522,28 +2528,9 @@ ira_flattening (int max_regno_before_emi mem_dest_p = true; if (REGNO (ALLOCNO_REG (a)) == REGNO (ALLOCNO_REG (parent_a))) { - IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (parent_a), - ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a)); -#ifdef STACK_REGS - if (ALLOCNO_TOTAL_NO_STACK_REG_P (a)) - ALLOCNO_TOTAL_NO_STACK_REG_P (parent_a) = true; -#endif - if (internal_flag_ira_verbose > 4 && ira_dump_file != NULL) - { - fprintf (ira_dump_file, - " Moving ranges of a%dr%d to a%dr%d: ", - ALLOCNO_NUM (a), REGNO (ALLOCNO_REG (a)), - ALLOCNO_NUM (parent_a), - REGNO (ALLOCNO_REG (parent_a))); - ira_print_live_range_list (ira_dump_file, - ALLOCNO_LIVE_RANGES (a)); - } - change_allocno_in_range_list (ALLOCNO_LIVE_RANGES (a), parent_a); - ALLOCNO_LIVE_RANGES (parent_a) - = ira_merge_allocno_live_ranges - (ALLOCNO_LIVE_RANGES (a), ALLOCNO_LIVE_RANGES (parent_a)); + merge_hard_reg_conflicts (a, parent_a, true); + move_allocno_live_ranges (a, parent_a); merged_p = true; - ALLOCNO_LIVE_RANGES (a) = NULL; ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a) = (ALLOCNO_MEM_OPTIMIZED_DEST_P (parent_a) || ALLOCNO_MEM_OPTIMIZED_DEST_P (a)); Index: gcc/ira-lives.c =================================================================== --- gcc.orig/ira-lives.c +++ gcc/ira-lives.c @@ -81,33 +81,44 @@ 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 - necessary. */ +/* Record the birth of hard register REGNO, updating hard_regs_live + and hard reg conflict information for living allocno. */ static void -make_regno_born (int regno) +make_hard_regno_born (int regno) { unsigned int i; - ira_allocno_t a; - allocno_live_range_t p; - if (regno < FIRST_PSEUDO_REGISTER) + SET_HARD_REG_BIT (hard_regs_live, regno); + EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i) { - SET_HARD_REG_BIT (hard_regs_live, regno); - EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i) - { - SET_HARD_REG_BIT (ALLOCNO_CONFLICT_HARD_REGS (ira_allocnos[i]), - regno); - SET_HARD_REG_BIT (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (ira_allocnos[i]), - regno); - } - return; + SET_HARD_REG_BIT (ALLOCNO_CONFLICT_HARD_REGS (ira_allocnos[i]), + regno); + SET_HARD_REG_BIT (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (ira_allocnos[i]), + regno); } - a = ira_curr_regno_allocno_map[regno]; - if (a == NULL) - return; - if ((p = ALLOCNO_LIVE_RANGES (a)) == NULL +} + +/* Process the death of hard register REGNO. This updates + hard_regs_live. */ +static void +make_hard_regno_dead (int regno) +{ + CLEAR_HARD_REG_BIT (hard_regs_live, regno); +} + +/* Record the birth of allocno A, starting a new live range for + it if necessary, and updating hard reg conflict information. We also + record it in allocnos_live. */ +static void +make_allocno_born (ira_allocno_t a) +{ + allocno_live_range_t p = ALLOCNO_LIVE_RANGES (a); + + sparseset_set_bit (allocnos_live, ALLOCNO_NUM (a)); + IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), hard_regs_live); + IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), hard_regs_live); + + if (p == NULL || (p->finish != curr_point && p->finish + 1 != curr_point)) ALLOCNO_LIVE_RANGES (a) = ira_create_allocno_live_range (a, curr_point, -1, @@ -137,56 +148,39 @@ update_allocno_pressure_excess_length (i } } -/* Process the death of register REGNO. This updates hard_regs_live - or finishes the current live range for the allocno corresponding to - REGNO. */ +/* Process the death of allocno A. This finishes the current live + range for it. */ static void -make_regno_dead (int regno) +make_allocno_dead (ira_allocno_t a) { - ira_allocno_t a; allocno_live_range_t p; - if (regno < FIRST_PSEUDO_REGISTER) - { - CLEAR_HARD_REG_BIT (hard_regs_live, regno); - return; - } - a = ira_curr_regno_allocno_map[regno]; - if (a == NULL) - return; p = ALLOCNO_LIVE_RANGES (a); ira_assert (p != NULL); p->finish = curr_point; update_allocno_pressure_excess_length (a); + sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a)); } /* The current register pressures for each cover class for the current basic block. */ static int curr_reg_pressure[N_REG_CLASSES]; -/* Mark allocno A as currently living and update current register - pressure, maximal register pressure for the current BB, start point - of the register pressure excess, and conflicting hard registers of - A. */ +/* Record that register pressure for COVER_CLASS increased by N + registers. Update the current register pressure, maximal register + pressure for the current BB and the start point of the register + pressure excess. */ static void -set_allocno_live (ira_allocno_t a) +inc_register_pressure (enum reg_class cover_class, int n) { int i; - enum reg_class cover_class, cl; + enum reg_class cl; - /* 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)); - IOR_HARD_REG_SET (ALLOCNO_CONFLICT_HARD_REGS (a), hard_regs_live); - IOR_HARD_REG_SET (ALLOCNO_TOTAL_CONFLICT_HARD_REGS (a), hard_regs_live); - cover_class = ALLOCNO_COVER_CLASS (a); for (i = 0; (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; i++) { - curr_reg_pressure[cl] += ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; + curr_reg_pressure[cl] += n; if (high_pressure_start_point[cl] < 0 && (curr_reg_pressure[cl] > ira_available_class_regs[cl])) high_pressure_start_point[cl] = curr_point; @@ -195,110 +189,87 @@ set_allocno_live (ira_allocno_t a) } } -/* Mark allocno A as currently not living and update current register - pressure, start point of the register pressure excess, and register - pressure excess length for living allocnos. */ +/* Record that register pressure for COVER_CLASS has decreased by + NREGS registers; update current register pressure, start point of + the register pressure excess, and register pressure excess length + for living allocnos. */ + static void -clear_allocno_live (ira_allocno_t a) +dec_register_pressure (enum reg_class cover_class, int nregs) { int i; unsigned int j; - enum reg_class cover_class, cl; - bool set_p; + enum reg_class cl; + bool set_p = false; - /* Invalidate because it is referenced. */ - allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; - if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) + for (i = 0; + (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; + i++) { - cover_class = ALLOCNO_COVER_CLASS (a); - set_p = false; + curr_reg_pressure[cl] -= nregs; + ira_assert (curr_reg_pressure[cl] >= 0); + if (high_pressure_start_point[cl] >= 0 + && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) + set_p = true; + } + if (set_p) + { + EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j) + update_allocno_pressure_excess_length (ira_allocnos[j]); for (i = 0; (cl = ira_reg_class_super_classes[cover_class][i]) != LIM_REG_CLASSES; i++) - { - curr_reg_pressure[cl] -= ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; - ira_assert (curr_reg_pressure[cl] >= 0); - if (high_pressure_start_point[cl] >= 0 - && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) - set_p = true; - } - if (set_p) - { - EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j) - update_allocno_pressure_excess_length (ira_allocnos[j]); - for (i = 0; - (cl = ira_reg_class_super_classes[cover_class][i]) - != LIM_REG_CLASSES; - i++) - if (high_pressure_start_point[cl] >= 0 - && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) - high_pressure_start_point[cl] = -1; - - } + if (high_pressure_start_point[cl] >= 0 + && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) + high_pressure_start_point[cl] = -1; } - sparseset_clear_bit (allocnos_live, ALLOCNO_NUM (a)); } -/* Mark the register REG as live. Store a 1 in hard_regs_live or - allocnos_live for this register or the corresponding allocno, - record how many consecutive hardware registers it actually - needs. */ +/* Mark the pseudo register REGNO as live. Update all information about + live ranges and register pressure. */ static void -mark_reg_live (rtx reg) +mark_pseudo_regno_live (int regno) { - int i, regno; + ira_allocno_t a = ira_curr_regno_allocno_map[regno]; + enum reg_class cl; + int nregs; - gcc_assert (REG_P (reg)); - regno = REGNO (reg); + if (a == NULL) + return; - if (regno >= FIRST_PSEUDO_REGISTER) - { - ira_allocno_t a = ira_curr_regno_allocno_map[regno]; + /* Invalidate because it is referenced. */ + allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; - if (a != NULL) - { - if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) - { - /* Invalidate because it is referenced. */ - allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; - return; - } - set_allocno_live (a); - } - make_regno_born (regno); - } - else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) + if (sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) + return; + + cl = ALLOCNO_COVER_CLASS (a); + nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; + inc_register_pressure (cl, nregs); + make_allocno_born (a); +} + +/* Mark the hard register REG as live. Store a 1 in hard_regs_live + for this register, record how many consecutive hardware registers + it actually needs. */ +static void +mark_hard_reg_live (rtx reg) +{ + int regno = REGNO (reg); + + if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) { int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; - enum reg_class cover_class, cl; while (regno < last) { if (! TEST_HARD_REG_BIT (hard_regs_live, regno) && ! TEST_HARD_REG_BIT (eliminable_regset, regno)) { - cover_class = ira_hard_regno_cover_class[regno]; - for (i = 0; - (cl = ira_reg_class_super_classes[cover_class][i]) - != LIM_REG_CLASSES; - i++) - { - curr_reg_pressure[cl]++; - if (high_pressure_start_point[cl] < 0 - && (curr_reg_pressure[cl] - > ira_available_class_regs[cl])) - high_pressure_start_point[cl] = curr_point; - } - make_regno_born (regno); - for (i = 0; - (cl = ira_reg_class_super_classes[cover_class][i]) - != LIM_REG_CLASSES; - i++) - { - if (curr_bb_node->reg_pressure[cl] < curr_reg_pressure[cl]) - curr_bb_node->reg_pressure[cl] = curr_reg_pressure[cl]; - } + enum reg_class cover_class = ira_hard_regno_cover_class[regno]; + inc_register_pressure (cover_class, 1); + make_hard_regno_born (regno); } regno++; } @@ -314,74 +285,55 @@ mark_ref_live (df_ref ref) reg = DF_REF_REG (ref); if (GET_CODE (reg) == SUBREG) reg = SUBREG_REG (reg); - mark_reg_live (reg); + if (REGNO (reg) >= FIRST_PSEUDO_REGISTER) + mark_pseudo_regno_live (REGNO (reg)); + else + mark_hard_reg_live (reg); } -/* Mark the register REG as dead. Store a 0 in hard_regs_live or - allocnos_live for the register. */ +/* Mark the pseudo register REGNO as dead. Update all information about + live ranges and register pressure. */ static void -mark_reg_dead (rtx reg) +mark_pseudo_regno_dead (int regno) { - int regno; + ira_allocno_t a = ira_curr_regno_allocno_map[regno]; + enum reg_class cl; + int nregs; - gcc_assert (REG_P (reg)); - regno = REGNO (reg); + if (a == NULL) + return; - if (regno >= FIRST_PSEUDO_REGISTER) - { - ira_allocno_t a = ira_curr_regno_allocno_map[regno]; + /* Invalidate because it is referenced. */ + allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; - if (a != NULL) - { - if (! sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) - { - /* Invalidate because it is referenced. */ - allocno_saved_at_call[ALLOCNO_NUM (a)] = 0; - return; - } - clear_allocno_live (a); - } - make_regno_dead (regno); - } - else if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) + if (! sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))) + return; + + cl = ALLOCNO_COVER_CLASS (a); + nregs = ira_reg_class_nregs[cl][ALLOCNO_MODE (a)]; + dec_register_pressure (cl, nregs); + + make_allocno_dead (a); +} + +/* Mark the hard register REG as dead. Store a 0 in hard_regs_live + for the register. */ +static void +mark_hard_reg_dead (rtx reg) +{ + int regno = REGNO (reg); + + if (! TEST_HARD_REG_BIT (ira_no_alloc_regs, regno)) { - int i; - unsigned int j; int last = regno + hard_regno_nregs[regno][GET_MODE (reg)]; - enum reg_class cover_class, cl; - bool set_p; while (regno < last) { if (TEST_HARD_REG_BIT (hard_regs_live, regno)) { - set_p = false; - cover_class = ira_hard_regno_cover_class[regno]; - for (i = 0; - (cl = ira_reg_class_super_classes[cover_class][i]) - != LIM_REG_CLASSES; - i++) - { - curr_reg_pressure[cl]--; - if (high_pressure_start_point[cl] >= 0 - && curr_reg_pressure[cl] <= ira_available_class_regs[cl]) - set_p = true; - ira_assert (curr_reg_pressure[cl] >= 0); - } - if (set_p) - { - EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, j) - update_allocno_pressure_excess_length (ira_allocnos[j]); - for (i = 0; - (cl = ira_reg_class_super_classes[cover_class][i]) - != LIM_REG_CLASSES; - i++) - if (high_pressure_start_point[cl] >= 0 - && (curr_reg_pressure[cl] - <= ira_available_class_regs[cl])) - high_pressure_start_point[cl] = -1; - } - make_regno_dead (regno); + enum reg_class cover_class = ira_hard_regno_cover_class[regno]; + dec_register_pressure (cover_class, 1); + make_hard_regno_dead (regno); } regno++; } @@ -402,7 +354,10 @@ mark_ref_dead (df_ref def) reg = DF_REF_REG (def); if (GET_CODE (reg) == SUBREG) reg = SUBREG_REG (reg); - mark_reg_dead (reg); + if (REGNO (reg) >= FIRST_PSEUDO_REGISTER) + mark_pseudo_regno_dead (REGNO (reg)); + else + mark_hard_reg_dead (reg); } /* Make pseudo REG conflicting with pseudo DREG, if the 1st pseudo @@ -427,10 +382,10 @@ make_pseudo_conflict (rtx reg, enum reg_ if (advance_p) curr_point++; - mark_reg_live (reg); - mark_reg_live (dreg); - mark_reg_dead (reg); - mark_reg_dead (dreg); + mark_pseudo_regno_live (REGNO (reg)); + mark_pseudo_regno_live (REGNO (dreg)); + mark_pseudo_regno_dead (REGNO (reg)); + mark_pseudo_regno_dead (REGNO (dreg)); return false; } @@ -961,15 +916,7 @@ process_bb_node_lives (ira_loop_tree_nod } } EXECUTE_IF_SET_IN_BITMAP (reg_live_out, FIRST_PSEUDO_REGISTER, j, bi) - { - ira_allocno_t a = ira_curr_regno_allocno_map[j]; - - if (a == NULL) - continue; - ira_assert (! sparseset_bit_p (allocnos_live, ALLOCNO_NUM (a))); - set_allocno_live (a); - make_regno_born (j); - } + mark_pseudo_regno_live (j); freq = REG_FREQ_FROM_BB (bb); if (freq == 0) @@ -1137,7 +1084,7 @@ process_bb_node_lives (ira_loop_tree_nod unsigned int regno = EH_RETURN_DATA_REGNO (j); if (regno == INVALID_REGNUM) break; - make_regno_born (regno); + make_hard_regno_born (regno); } #endif @@ -1155,7 +1102,7 @@ process_bb_node_lives (ira_loop_tree_nod ALLOCNO_TOTAL_NO_STACK_REG_P (ira_allocnos[px]) = true; } for (px = FIRST_STACK_REG; px <= LAST_STACK_REG; px++) - make_regno_born (px); + make_hard_regno_born (px); #endif /* No need to record conflicts for call clobbered regs if we have nonlocal labels around, as we don't ever try to @@ -1163,13 +1110,11 @@ process_bb_node_lives (ira_loop_tree_nod if (!cfun->has_nonlocal_label && bb_has_abnormal_call_pred (bb)) for (px = 0; px < FIRST_PSEUDO_REGISTER; px++) if (call_used_regs[px]) - make_regno_born (px); + make_hard_regno_born (px); } EXECUTE_IF_SET_IN_SPARSESET (allocnos_live, i) - { - make_regno_dead (ALLOCNO_REGNO (ira_allocnos[i])); - } + make_allocno_dead (ira_allocnos[i]); curr_point++;