From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from smtpbgeu2.qq.com (smtpbgeu2.qq.com [18.194.254.142]) by sourceware.org (Postfix) with ESMTPS id 662013858D1E for ; Wed, 8 Nov 2023 03:47:51 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 662013858D1E Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=rivai.ai Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=rivai.ai ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 662013858D1E Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=18.194.254.142 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699415276; cv=none; b=Ih2wxvzL/GClni2xZ05753RNf3B4CUcgPdfjgppg3Q7TlnDONfFLJeh1AV8z3GgynqMMo9fjvwOam3WiHCvSCl/i7oMThByBcBC3oGCmCB8l8BGrC6+rRoNZ7AIwoRZRNgKG3ZXJs5yJXVenVwqOOWV9OnD0k7fdWxtgciC0mws= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1699415276; c=relaxed/simple; bh=v4W3E55FgFNEGH9jr3lAVGsI9hJFqA5zXEbiQkqL1Zs=; h=From:To:Subject:Date:Message-Id:MIME-Version; b=LoyBzh4w4tnXRF6tpwAoU1uQEB0KJ3GcuZ6JaCoGVJslp7fNKJzYPCJcGGfmrhM1naTnvAyrGkdBCH4dEE8YEciNC6XtGjpYN5p7R8idwrQJVNpbTU1v0liMz4LGrWMS0YJe8xhx0ItB3NiD5ZLjmEFX2mlD9PFj6q9WsOQQPJw= ARC-Authentication-Results: i=1; server2.sourceware.org X-QQ-mid: bizesmtp81t1699415264tkfnfoog Received: from rios-cad121.hadoop.rioslab.org ( [58.60.1.9]) by bizesmtp.qq.com (ESMTP) with id ; Wed, 08 Nov 2023 11:47:44 +0800 (CST) X-QQ-SSF: 01400000000000C0F000000A0000000 X-QQ-FEAT: 90EFqYDyPxBc3KQ/9XgGnDhIoC+1rKpcuLonAkuhR+5nbRq0jsPVEe948hUy7 c8x3Ybckbge4ELbL9eFh3wWnOPAHF+DmMc5BsB9YIXFlZ/s6ZxTlquuUoq9w4zlBEb7CUau pdJP9neM3kRHma1QaWerdgUbD7XlZKwncwgk3kG9Xk/x7T58vEIeqZpU6gqKiIHk+XjvnLW WA1TQCjCFin0CvRljZ/u1D13/2jFXaxtb/YBIixaXDsyH5ACmbPWgy3ouDk2oeLp079veOA ZKsp+b4fY1tq8KmsGz02q7oswY7Q/cZ9XcHUto10UXK2jYAtb+Fb+z5FwtidwDrvZIB2ym5 GIO6zJAk9iI1TcUmo6MKMOoPpFdvbeqdhkCz90fGvk5vo1PYdtJasPKuu2CJA== X-QQ-GoodBg: 2 X-BIZMAIL-ID: 17222830383864493665 From: Lehua Ding To: gcc-patches@gcc.gnu.org Cc: vmakarov@redhat.com, richard.sandiford@arm.com, juzhe.zhong@rivai.ai, lehua.ding@rivai.ai Subject: [PATCH 1/7] ira: Refactor the handling of register conflicts to make it more general Date: Wed, 8 Nov 2023 11:47:34 +0800 Message-Id: <20231108034740.834590-2-lehua.ding@rivai.ai> X-Mailer: git-send-email 2.36.3 In-Reply-To: <20231108034740.834590-1-lehua.ding@rivai.ai> References: <20231108034740.834590-1-lehua.ding@rivai.ai> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-QQ-SENDSIZE: 520 Feedback-ID: bizesmtp:rivai.ai:qybglogicsvrgz:qybglogicsvrgz6a-0 X-Spam-Status: No, score=-11.5 required=5.0 tests=BAYES_00,GIT_PATCH_0,KAM_DMARC_STATUS,RCVD_IN_DNSWL_NONE,RCVD_IN_MSPIKE_H3,RCVD_IN_MSPIKE_WL,SPF_PASS,TXREP,T_SCC_BODY_TEXT_LINE,T_SPF_HELO_TEMPERROR,URIBL_SBL_A autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: This patch does not make any functional changes. It mainly refactor two parts: 1. The ira_allocno's objects field is expanded to an scalable array, and multi-word pseduo registers are split and tracked only when necessary. 2. Since the objects array has been expanded, there will be more subreg objects that pass through later, rather than the previous fixed two. Therefore, it is necessary to modify the detection of whether two objects conflict, and the check method is to pull back the registers occupied by the object to the first register of the allocno for judgment. gcc/ChangeLog: * hard-reg-set.h (struct HARD_REG_SET): Add operator>>. * ira-build.cc (init_object_start_and_nregs): New func. (find_object): Ditto. (ira_create_allocno): Adjust. (ira_set_allocno_class): Set subreg info. (ira_create_allocno_objects): Adjust. (init_regs_with_subreg): Collect access in subreg. (ira_build): Call init_regs_with_subreg (ira_destroy): Clear regs_with_subreg * ira-color.cc (setup_profitable_hard_regs): Adjust. (get_conflict_and_start_profitable_regs): Adjust. (check_hard_reg_p): Adjust. (assign_hard_reg): Adjust. (improve_allocation): Adjust. * ira-int.h (struct ira_object): Adjust fields. (struct ira_allocno): Adjust objects filed. (ALLOCNO_NUM_OBJECTS): Adjust. (ALLOCNO_UNIT_SIZE): New. (ALLOCNO_TRACK_SUBREG_P): New. (ALLOCNO_NREGS): New. (OBJECT_SIZE): New. (OBJECT_OFFSET): New. (OBJECT_START): New. (OBJECT_NREGS): New. (find_object): New. (has_subreg_object_p): New. (get_full_object): New. * ira.cc (check_allocation): Adjust. --- gcc/hard-reg-set.h | 33 +++++++ gcc/ira-build.cc | 106 +++++++++++++++++++- gcc/ira-color.cc | 234 ++++++++++++++++++++++++++++++--------------- gcc/ira-int.h | 45 ++++++++- gcc/ira.cc | 52 ++++------ 5 files changed, 349 insertions(+), 121 deletions(-) diff --git a/gcc/hard-reg-set.h b/gcc/hard-reg-set.h index b0bb9bce074..760eadba186 100644 --- a/gcc/hard-reg-set.h +++ b/gcc/hard-reg-set.h @@ -113,6 +113,39 @@ struct HARD_REG_SET return !operator== (other); } + HARD_REG_SET + operator>> (unsigned int shift_amount) const + { + if (shift_amount == 0) + return *this; + + HARD_REG_SET res; + unsigned int total_bits = sizeof (HARD_REG_ELT_TYPE) * 8; + if (shift_amount >= total_bits) + { + unsigned int n_elt = shift_amount % total_bits; + shift_amount -= n_elt * total_bits; + for (unsigned int i = 0; i < ARRAY_SIZE (elts) - n_elt - 1; i += 1) + res.elts[i] = elts[i + n_elt]; + /* clear upper n_elt elements. */ + for (unsigned int i = 0; i < n_elt; i += 1) + res.elts[ARRAY_SIZE (elts) - 1 - i] = 0; + } + + if (shift_amount > 0) + { + /* The left bits of an element be shifted. */ + HARD_REG_ELT_TYPE left = 0; + /* Total bits of an element. */ + for (int i = ARRAY_SIZE (elts); i >= 0; --i) + { + res.elts[i] = (elts[i] >> shift_amount) | left; + left = elts[i] << (total_bits - shift_amount); + } + } + return res; + } + HARD_REG_ELT_TYPE elts[HARD_REG_SET_LONGS]; }; typedef const HARD_REG_SET &const_hard_reg_set; diff --git a/gcc/ira-build.cc b/gcc/ira-build.cc index 93e46033170..07aba27c1c9 100644 --- a/gcc/ira-build.cc +++ b/gcc/ira-build.cc @@ -440,6 +440,40 @@ initiate_allocnos (void) memset (ira_regno_allocno_map, 0, max_reg_num () * sizeof (ira_allocno_t)); } +/* Update OBJ's start and nregs field according A and OBJ info. */ +static void +init_object_start_and_nregs (ira_allocno_t a, ira_object_t obj) +{ + enum reg_class aclass = ALLOCNO_CLASS (a); + gcc_assert (aclass != NO_REGS); + + machine_mode mode = ALLOCNO_MODE (a); + int nregs = ira_reg_class_max_nregs[aclass][mode]; + if (ALLOCNO_TRACK_SUBREG_P (a)) + { + poly_int64 end = OBJECT_OFFSET (obj) + OBJECT_SIZE (obj); + for (int i = 0; i < nregs; i += 1) + { + poly_int64 right = ALLOCNO_UNIT_SIZE (a) * (i + 1); + if (OBJECT_START (obj) < 0 && maybe_lt (OBJECT_OFFSET (obj), right)) + { + OBJECT_START (obj) = i; + } + if (OBJECT_NREGS (obj) < 0 && maybe_le (end, right)) + { + OBJECT_NREGS (obj) = i + 1 - OBJECT_START (obj); + break; + } + } + gcc_assert (OBJECT_START (obj) >= 0 && OBJECT_NREGS (obj) > 0); + } + else + { + OBJECT_START (obj) = 0; + OBJECT_NREGS (obj) = nregs; + } +} + /* Create and return an object corresponding to a new allocno A. */ static ira_object_t ira_create_object (ira_allocno_t a, int subword) @@ -460,15 +494,36 @@ ira_create_object (ira_allocno_t a, int subword) OBJECT_MIN (obj) = INT_MAX; OBJECT_MAX (obj) = -1; OBJECT_LIVE_RANGES (obj) = NULL; + OBJECT_SIZE (obj) = UNITS_PER_WORD; + OBJECT_OFFSET (obj) = subword * UNITS_PER_WORD; + OBJECT_START (obj) = -1; + OBJECT_NREGS (obj) = -1; ira_object_id_map_vec.safe_push (obj); ira_object_id_map = ira_object_id_map_vec.address (); ira_objects_num = ira_object_id_map_vec.length (); + if (aclass != NO_REGS) + init_object_start_and_nregs (a, obj); + + a->objects.push_back (obj); + return obj; } +/* Return the object in allocno A which match START & NREGS. */ +ira_object_t +find_object (ira_allocno_t a, int start, int nregs) +{ + for (ira_object_t obj : a->objects) + { + if (OBJECT_START (obj) == start && OBJECT_NREGS (obj) == nregs) + return obj; + } + return NULL; +} + /* Create and return the allocno corresponding to REGNO in LOOP_TREE_NODE. Add the allocno to the list of allocnos with the same regno if CAP_P is FALSE. */ @@ -525,7 +580,8 @@ ira_create_allocno (int regno, bool cap_p, ALLOCNO_MEMORY_COST (a) = 0; ALLOCNO_UPDATED_MEMORY_COST (a) = 0; ALLOCNO_EXCESS_PRESSURE_POINTS_NUM (a) = 0; - ALLOCNO_NUM_OBJECTS (a) = 0; + ALLOCNO_UNIT_SIZE (a) = 0; + ALLOCNO_TRACK_SUBREG_P (a) = false; ALLOCNO_ADD_DATA (a) = NULL; allocno_vec.safe_push (a); @@ -535,6 +591,9 @@ ira_create_allocno (int regno, bool cap_p, return a; } +/* Record the regs referenced by subreg. */ +static bitmap_head regs_with_subreg; + /* Set up register class for A and update its conflict hard registers. */ void @@ -549,6 +608,19 @@ ira_set_allocno_class (ira_allocno_t a, enum reg_class aclass) OBJECT_CONFLICT_HARD_REGS (obj) |= ~reg_class_contents[aclass]; OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) |= ~reg_class_contents[aclass]; } + + if (aclass == NO_REGS) + return; + /* SET the unit_size of one register. */ + machine_mode mode = ALLOCNO_MODE (a); + int nregs = ira_reg_class_max_nregs[aclass][mode]; + if (nregs == 2 && maybe_eq (GET_MODE_SIZE (mode), nregs * UNITS_PER_WORD) + && bitmap_bit_p (®s_with_subreg, ALLOCNO_REGNO (a))) + { + ALLOCNO_UNIT_SIZE (a) = UNITS_PER_WORD; + ALLOCNO_TRACK_SUBREG_P (a) = true; + return; + } } /* Determine the number of objects we should associate with allocno A @@ -561,12 +633,12 @@ ira_create_allocno_objects (ira_allocno_t a) int n = ira_reg_class_max_nregs[aclass][mode]; int i; - if (n != 2 || maybe_ne (GET_MODE_SIZE (mode), n * UNITS_PER_WORD)) + if (n != 2 || maybe_ne (GET_MODE_SIZE (mode), n * UNITS_PER_WORD) + || !bitmap_bit_p (®s_with_subreg, ALLOCNO_REGNO (a))) n = 1; - ALLOCNO_NUM_OBJECTS (a) = n; for (i = 0; i < n; i++) - ALLOCNO_OBJECT (a, i) = ira_create_object (a, i); + ira_create_object (a, i); } /* For each allocno, set ALLOCNO_NUM_OBJECTS and create the @@ -3460,6 +3532,30 @@ update_conflict_hard_reg_costs (void) } } +/* Traverse all instructions to determine which ones have access through subreg. + */ +static void +init_regs_with_subreg () +{ + bitmap_initialize (®s_with_subreg, ®_obstack); + basic_block bb; + rtx_insn *insn; + df_ref def, use; + FOR_ALL_BB_FN (bb, cfun) + FOR_BB_INSNS (bb, insn) + { + if (!NONDEBUG_INSN_P (insn)) + continue; + df_insn_info *insn_info = DF_INSN_INFO_GET (insn); + FOR_EACH_INSN_INFO_DEF (def, insn_info) + if (DF_REF_FLAGS (def) & (DF_REF_PARTIAL | DF_REF_SUBREG)) + bitmap_set_bit (®s_with_subreg, DF_REF_REGNO (def)); + FOR_EACH_INSN_INFO_USE (use, insn_info) + if (DF_REF_FLAGS (use) & (DF_REF_PARTIAL | DF_REF_SUBREG)) + bitmap_set_bit (®s_with_subreg, DF_REF_REGNO (use)); + } +} + /* Create a internal representation (IR) for IRA (allocnos, copies, loop tree nodes). The function returns TRUE if we generate loop structure (besides nodes representing all function and the basic @@ -3475,6 +3571,7 @@ ira_build (void) initiate_allocnos (); initiate_prefs (); initiate_copies (); + init_regs_with_subreg (); create_loop_tree_nodes (); form_loop_tree (); create_allocnos (); @@ -3565,4 +3662,5 @@ ira_destroy (void) finish_allocnos (); finish_cost_vectors (); ira_finish_allocno_live_ranges (); + bitmap_clear (®s_with_subreg); } diff --git a/gcc/ira-color.cc b/gcc/ira-color.cc index f2e8ea34152..6af8318e5f5 100644 --- a/gcc/ira-color.cc +++ b/gcc/ira-color.cc @@ -1031,7 +1031,7 @@ static void setup_profitable_hard_regs (void) { unsigned int i; - int j, k, nobj, hard_regno, nregs, class_size; + int j, k, nobj, hard_regno, class_size; ira_allocno_t a; bitmap_iterator bi; enum reg_class aclass; @@ -1076,7 +1076,6 @@ setup_profitable_hard_regs (void) || (hard_regno = ALLOCNO_HARD_REGNO (a)) < 0) continue; mode = ALLOCNO_MODE (a); - nregs = hard_regno_nregs (hard_regno, mode); nobj = ALLOCNO_NUM_OBJECTS (a); for (k = 0; k < nobj; k++) { @@ -1088,24 +1087,39 @@ setup_profitable_hard_regs (void) { ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj); - /* We can process the conflict allocno repeatedly with - the same result. */ - if (nregs == nobj && nregs > 1) + if (!has_subreg_object_p (a)) { - int num = OBJECT_SUBWORD (conflict_obj); - - if (REG_WORDS_BIG_ENDIAN) - CLEAR_HARD_REG_BIT - (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs, - hard_regno + nobj - num - 1); - else - CLEAR_HARD_REG_BIT - (ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs, - hard_regno + num); + ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs + &= ~ira_reg_mode_hard_regset[hard_regno][mode]; + continue; + } + + /* Clear all hard regs occupied by obj. */ + if (REG_WORDS_BIG_ENDIAN) + { + int start_regno + = hard_regno + ALLOCNO_NREGS (a) - 1 - OBJECT_START (obj); + for (int i = 0; i < OBJECT_NREGS (obj); i += 1) + { + int regno = start_regno - i; + if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER) + CLEAR_HARD_REG_BIT ( + ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs, + regno); + } } else - ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs - &= ~ira_reg_mode_hard_regset[hard_regno][mode]; + { + int start_regno = hard_regno + OBJECT_START (obj); + for (int i = 0; i < OBJECT_NREGS (obj); i += 1) + { + int regno = start_regno + i; + if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER) + CLEAR_HARD_REG_BIT ( + ALLOCNO_COLOR_DATA (conflict_a)->profitable_hard_regs, + regno); + } + } } } } @@ -1677,18 +1691,25 @@ update_conflict_hard_regno_costs (int *costs, enum reg_class aclass, aligned. */ static inline void get_conflict_and_start_profitable_regs (ira_allocno_t a, bool retry_p, - HARD_REG_SET *conflict_regs, + HARD_REG_SET *start_conflict_regs, HARD_REG_SET *start_profitable_regs) { int i, nwords; ira_object_t obj; nwords = ALLOCNO_NUM_OBJECTS (a); - for (i = 0; i < nwords; i++) - { - obj = ALLOCNO_OBJECT (a, i); - conflict_regs[i] = OBJECT_TOTAL_CONFLICT_HARD_REGS (obj); - } + CLEAR_HARD_REG_SET (*start_conflict_regs); + if (has_subreg_object_p (a)) + for (i = 0; i < nwords; i++) + { + obj = ALLOCNO_OBJECT (a, i); + for (int j = 0; j < OBJECT_NREGS (obj); j += 1) + *start_conflict_regs |= OBJECT_TOTAL_CONFLICT_HARD_REGS (obj) + >> (OBJECT_START (obj) + j); + } + else + *start_conflict_regs + = OBJECT_TOTAL_CONFLICT_HARD_REGS (get_full_object (a)); if (retry_p) *start_profitable_regs = (reg_class_contents[ALLOCNO_CLASS (a)] @@ -1702,9 +1723,9 @@ get_conflict_and_start_profitable_regs (ira_allocno_t a, bool retry_p, PROFITABLE_REGS and whose objects have CONFLICT_REGS. */ static inline bool check_hard_reg_p (ira_allocno_t a, int hard_regno, - HARD_REG_SET *conflict_regs, HARD_REG_SET profitable_regs) + HARD_REG_SET start_conflict_regs, + HARD_REG_SET profitable_regs) { - int j, nwords, nregs; enum reg_class aclass; machine_mode mode; @@ -1716,28 +1737,17 @@ check_hard_reg_p (ira_allocno_t a, int hard_regno, /* Checking only profitable hard regs. */ if (! TEST_HARD_REG_BIT (profitable_regs, hard_regno)) return false; - nregs = hard_regno_nregs (hard_regno, mode); - nwords = ALLOCNO_NUM_OBJECTS (a); - for (j = 0; j < nregs; j++) + + if (has_subreg_object_p (a)) + return !TEST_HARD_REG_BIT (start_conflict_regs, hard_regno); + else { - int k; - int set_to_test_start = 0, set_to_test_end = nwords; - - if (nregs == nwords) - { - if (REG_WORDS_BIG_ENDIAN) - set_to_test_start = nwords - j - 1; - else - set_to_test_start = j; - set_to_test_end = set_to_test_start + 1; - } - for (k = set_to_test_start; k < set_to_test_end; k++) - if (TEST_HARD_REG_BIT (conflict_regs[k], hard_regno + j)) - break; - if (k != set_to_test_end) - break; + int nregs = hard_regno_nregs (hard_regno, mode); + for (int i = 0; i < nregs; i += 1) + if (TEST_HARD_REG_BIT (start_conflict_regs, hard_regno + i)) + return false; + return true; } - return j == nregs; } /* Return number of registers needed to be saved and restored at @@ -1945,7 +1955,7 @@ spill_soft_conflicts (ira_allocno_t a, bitmap allocnos_to_spill, static bool assign_hard_reg (ira_allocno_t a, bool retry_p) { - HARD_REG_SET conflicting_regs[2], profitable_hard_regs; + HARD_REG_SET start_conflicting_regs, profitable_hard_regs; int i, j, hard_regno, best_hard_regno, class_size; int cost, mem_cost, min_cost, full_cost, min_full_cost, nwords, word; int *a_costs; @@ -1962,8 +1972,7 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) HARD_REG_SET soft_conflict_regs = {}; ira_assert (! ALLOCNO_ASSIGNED_P (a)); - get_conflict_and_start_profitable_regs (a, retry_p, - conflicting_regs, + get_conflict_and_start_profitable_regs (a, retry_p, &start_conflicting_regs, &profitable_hard_regs); aclass = ALLOCNO_CLASS (a); class_size = ira_class_hard_regs_num[aclass]; @@ -2041,7 +2050,6 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) (hard_regno, ALLOCNO_MODE (conflict_a), reg_class_contents[aclass]))) { - int n_objects = ALLOCNO_NUM_OBJECTS (conflict_a); int conflict_nregs; mode = ALLOCNO_MODE (conflict_a); @@ -2076,24 +2084,95 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) note_conflict (r); } } + else if (has_subreg_object_p (a)) + { + /* Set start_conflicting_regs if that cause obj and + conflict_obj overlap. the overlap position: + +--------------+ + | conflict_obj | + +--------------+ + + +-----------+ +-----------+ + | obj | ... | obj | + +-----------+ +-----------+ + + Point: A B C + + the hard regs from A to C point will cause overlap. + For REG_WORDS_BIG_ENDIAN: + A = hard_regno + ALLOCNO_NREGS (conflict_a) - 1 + - OBJECT_START (conflict_obj) + - OBJECT_NREGS (obj) + 1 + C = A + OBJECT_NREGS (obj) + + OBJECT_NREGS (conflict_obj) - 2 + For !REG_WORDS_BIG_ENDIAN: + A = hard_regno + OBJECT_START (conflict_obj) + - OBJECT_NREGS (obj) + 1 + C = A + OBJECT_NREGS (obj) + + OBJECT_NREGS (conflict_obj) - 2 + */ + int start_regno; + int conflict_allocno_nregs, conflict_object_nregs, + conflict_object_start; + if (has_subreg_object_p (conflict_a)) + { + conflict_allocno_nregs = ALLOCNO_NREGS (conflict_a); + conflict_object_nregs = OBJECT_NREGS (conflict_obj); + conflict_object_start = OBJECT_START (conflict_obj); + } + else + { + conflict_allocno_nregs = conflict_object_nregs + = hard_regno_nregs (hard_regno, mode); + conflict_object_start = 0; + } + if (REG_WORDS_BIG_ENDIAN) + { + int A = hard_regno + conflict_allocno_nregs - 1 + - conflict_object_start - OBJECT_NREGS (obj) + + 1; + start_regno = A + OBJECT_NREGS (obj) - 1 + + OBJECT_START (obj) - ALLOCNO_NREGS (a) + + 1; + } + else + { + int A = hard_regno + conflict_object_start + - OBJECT_NREGS (obj) + 1; + start_regno = A - OBJECT_START (obj); + } + + for (int i = 0; + i <= OBJECT_NREGS (obj) + conflict_object_nregs - 2; + i += 1) + { + int regno = start_regno + i; + if (regno >= 0 && regno < FIRST_PSEUDO_REGISTER) + SET_HARD_REG_BIT (start_conflicting_regs, regno); + } + if (hard_reg_set_subset_p (profitable_hard_regs, + start_conflicting_regs)) + goto fail; + } else { - if (conflict_nregs == n_objects && conflict_nregs > 1) + if (has_subreg_object_p (conflict_a)) { - int num = OBJECT_SUBWORD (conflict_obj); - - if (REG_WORDS_BIG_ENDIAN) - SET_HARD_REG_BIT (conflicting_regs[word], - hard_regno + n_objects - num - 1); - else - SET_HARD_REG_BIT (conflicting_regs[word], - hard_regno + num); + int start_hard_regno + = REG_WORDS_BIG_ENDIAN + ? hard_regno + ALLOCNO_NREGS (conflict_a) + - OBJECT_START (conflict_obj) + : hard_regno + OBJECT_START (conflict_obj); + for (int i = 0; i < OBJECT_NREGS (conflict_obj); + i += 1) + SET_HARD_REG_BIT (start_conflicting_regs, + start_hard_regno + i); } else - conflicting_regs[word] + start_conflicting_regs |= ira_reg_mode_hard_regset[hard_regno][mode]; if (hard_reg_set_subset_p (profitable_hard_regs, - conflicting_regs[word])) + start_conflicting_regs)) goto fail; } } @@ -2160,8 +2239,8 @@ assign_hard_reg (ira_allocno_t a, bool retry_p) && FIRST_STACK_REG <= hard_regno && hard_regno <= LAST_STACK_REG) continue; #endif - if (! check_hard_reg_p (a, hard_regno, - conflicting_regs, profitable_hard_regs)) + if (!check_hard_reg_p (a, hard_regno, start_conflicting_regs, + profitable_hard_regs)) continue; cost = costs[i]; full_cost = full_costs[i]; @@ -3154,7 +3233,7 @@ improve_allocation (void) machine_mode mode; int *allocno_costs; int costs[FIRST_PSEUDO_REGISTER]; - HARD_REG_SET conflicting_regs[2], profitable_hard_regs; + HARD_REG_SET start_conflicting_regs, profitable_hard_regs; ira_allocno_t a; bitmap_iterator bi; int saved_nregs; @@ -3193,7 +3272,7 @@ improve_allocation (void) - allocno_copy_cost_saving (a, hregno)); try_p = false; get_conflict_and_start_profitable_regs (a, false, - conflicting_regs, + &start_conflicting_regs, &profitable_hard_regs); class_size = ira_class_hard_regs_num[aclass]; mode = ALLOCNO_MODE (a); @@ -3202,8 +3281,8 @@ improve_allocation (void) for (j = 0; j < class_size; j++) { hregno = ira_class_hard_regs[aclass][j]; - if (! check_hard_reg_p (a, hregno, - conflicting_regs, profitable_hard_regs)) + if (!check_hard_reg_p (a, hregno, start_conflicting_regs, + profitable_hard_regs)) continue; ira_assert (ira_class_hard_reg_index[aclass][hregno] == j); k = allocno_costs == NULL ? 0 : j; @@ -3287,16 +3366,15 @@ improve_allocation (void) } conflict_nregs = hard_regno_nregs (conflict_hregno, ALLOCNO_MODE (conflict_a)); - auto note_conflict = [&](int r) - { - if (check_hard_reg_p (a, r, - conflicting_regs, profitable_hard_regs)) - { - if (spill_a) - SET_HARD_REG_BIT (soft_conflict_regs, r); - costs[r] += spill_cost; - } - }; + auto note_conflict = [&] (int r) { + if (check_hard_reg_p (a, r, start_conflicting_regs, + profitable_hard_regs)) + { + if (spill_a) + SET_HARD_REG_BIT (soft_conflict_regs, r); + costs[r] += spill_cost; + } + }; for (r = conflict_hregno; r >= 0 && (int) end_hard_regno (mode, r) > conflict_hregno; r--) @@ -3314,8 +3392,8 @@ improve_allocation (void) for (j = 0; j < class_size; j++) { hregno = ira_class_hard_regs[aclass][j]; - if (check_hard_reg_p (a, hregno, - conflicting_regs, profitable_hard_regs) + if (check_hard_reg_p (a, hregno, start_conflicting_regs, + profitable_hard_regs) && min_cost > costs[hregno]) { best = hregno; diff --git a/gcc/ira-int.h b/gcc/ira-int.h index 0685e1f4e8d..b6281d3df6d 100644 --- a/gcc/ira-int.h +++ b/gcc/ira-int.h @@ -23,6 +23,7 @@ along with GCC; see the file COPYING3. If not see #include "recog.h" #include "function-abi.h" +#include /* To provide consistency in naming, all IRA external variables, functions, common typedefs start with prefix ira_. */ @@ -240,6 +241,13 @@ struct ira_object Zero means the lowest-order subword (or the entire allocno in case it is not being tracked in subwords). */ int subword; + /* Reprensent OBJECT occupied [start, start + nregs) registers of it's + ALLOCNO. */ + int start, nregs; + /* Reprensent the size and offset of current object, use to track subreg + range, For full reg, the size is GET_MODE_SIZE (ALLOCNO_MODE (allocno)), + offset is 0. */ + poly_int64 size, offset; /* Allocated size of the conflicts array. */ unsigned int conflicts_array_size; /* A unique number for every instance of this structure, which is used @@ -295,6 +303,11 @@ struct ira_allocno reload (at this point pseudo-register has only one allocno) which did not get stack slot yet. */ signed int hard_regno : 16; + /* Unit size of one register that allocate for the allocno. Only use to + compute the start and nregs of subreg which be tracked. */ + poly_int64 unit_size; + /* Flag means need track subreg live range for the allocno. */ + bool track_subreg_p; /* A bitmask of the ABIs used by calls that occur while the allocno is live. */ unsigned int crossed_calls_abis : NUM_ABI_IDS; @@ -353,8 +366,6 @@ struct ira_allocno register class living at the point than number of hard-registers of the class available for the allocation. */ int excess_pressure_points_num; - /* The number of objects tracked in the following array. */ - int num_objects; /* Accumulated frequency of calls which given allocno intersects. */ int call_freq; @@ -387,8 +398,8 @@ struct ira_allocno /* An array of structures describing conflict information and live ranges for each object associated with the allocno. There may be more than one such object in cases where the allocno represents a - multi-word register. */ - ira_object_t objects[2]; + multi-hardreg pesudo. */ + std::vector objects; /* Registers clobbered by intersected calls. */ HARD_REG_SET crossed_calls_clobbered_regs; /* Array of usage costs (accumulated and the one updated during @@ -468,8 +479,12 @@ struct ira_allocno #define ALLOCNO_EXCESS_PRESSURE_POINTS_NUM(A) \ ((A)->excess_pressure_points_num) #define ALLOCNO_OBJECT(A,N) ((A)->objects[N]) -#define ALLOCNO_NUM_OBJECTS(A) ((A)->num_objects) +#define ALLOCNO_NUM_OBJECTS(A) ((int) (A)->objects.size ()) #define ALLOCNO_ADD_DATA(A) ((A)->add_data) +#define ALLOCNO_UNIT_SIZE(A) ((A)->unit_size) +#define ALLOCNO_TRACK_SUBREG_P(A) ((A)->track_subreg_p) +#define ALLOCNO_NREGS(A) \ + (ira_reg_class_max_nregs[ALLOCNO_CLASS (A)][ALLOCNO_MODE (A)]) /* Typedef for pointer to the subsequent structure. */ typedef struct ira_emit_data *ira_emit_data_t; @@ -511,6 +526,8 @@ allocno_emit_reg (ira_allocno_t a) } #define OBJECT_ALLOCNO(O) ((O)->allocno) +#define OBJECT_SIZE(O) ((O)->size) +#define OBJECT_OFFSET(O) ((O)->offset) #define OBJECT_SUBWORD(O) ((O)->subword) #define OBJECT_CONFLICT_ARRAY(O) ((O)->conflicts_array) #define OBJECT_CONFLICT_VEC(O) ((ira_object_t *)(O)->conflicts_array) @@ -524,6 +541,8 @@ allocno_emit_reg (ira_allocno_t a) #define OBJECT_MAX(O) ((O)->max) #define OBJECT_CONFLICT_ID(O) ((O)->id) #define OBJECT_LIVE_RANGES(O) ((O)->live_ranges) +#define OBJECT_START(O) ((O)->start) +#define OBJECT_NREGS(O) ((O)->nregs) /* Map regno -> allocnos with given regno (see comments for allocno member `next_regno_allocno'). */ @@ -1041,6 +1060,8 @@ extern void ira_free_cost_vector (int *, reg_class_t); extern void ira_flattening (int, int); extern bool ira_build (void); extern void ira_destroy (void); +extern ira_object_t +find_object (ira_allocno_t, int, int); /* ira-costs.cc */ extern void ira_init_costs_once (void); @@ -1708,4 +1729,18 @@ ira_caller_save_loop_spill_p (ira_allocno_t a, ira_allocno_t subloop_a, return call_cost && call_cost >= spill_cost; } +/* Return true if allocno A has subreg object. */ +inline bool +has_subreg_object_p (ira_allocno_t a) +{ + return ALLOCNO_NUM_OBJECTS (a) > 1; +} + +/* Return the full object of allocno A. */ +inline ira_object_t +get_full_object (ira_allocno_t a) +{ + return find_object (a, 0, ALLOCNO_NREGS (a)); +} + #endif /* GCC_IRA_INT_H */ diff --git a/gcc/ira.cc b/gcc/ira.cc index d7530f01380..2fa6e0e5c94 100644 --- a/gcc/ira.cc +++ b/gcc/ira.cc @@ -2623,7 +2623,7 @@ static void check_allocation (void) { ira_allocno_t a; - int hard_regno, nregs, conflict_nregs; + int hard_regno; ira_allocno_iterator ai; FOR_EACH_ALLOCNO (a, ai) @@ -2634,28 +2634,18 @@ check_allocation (void) if (ALLOCNO_CAP_MEMBER (a) != NULL || (hard_regno = ALLOCNO_HARD_REGNO (a)) < 0) continue; - nregs = hard_regno_nregs (hard_regno, ALLOCNO_MODE (a)); - if (nregs == 1) - /* We allocated a single hard register. */ - n = 1; - else if (n > 1) - /* We allocated multiple hard registers, and we will test - conflicts in a granularity of single hard regs. */ - nregs = 1; for (i = 0; i < n; i++) { ira_object_t obj = ALLOCNO_OBJECT (a, i); ira_object_t conflict_obj; ira_object_conflict_iterator oci; - int this_regno = hard_regno; - if (n > 1) - { - if (REG_WORDS_BIG_ENDIAN) - this_regno += n - i - 1; - else - this_regno += i; - } + int this_regno; + if (REG_WORDS_BIG_ENDIAN) + this_regno = hard_regno + ALLOCNO_NREGS (a) - 1 - OBJECT_START (obj) + - OBJECT_NREGS (obj) + 1; + else + this_regno = hard_regno + OBJECT_START (obj); FOR_EACH_OBJECT_CONFLICT (obj, conflict_obj, oci) { ira_allocno_t conflict_a = OBJECT_ALLOCNO (conflict_obj); @@ -2665,24 +2655,18 @@ check_allocation (void) if (ira_soft_conflict (a, conflict_a)) continue; - conflict_nregs = hard_regno_nregs (conflict_hard_regno, - ALLOCNO_MODE (conflict_a)); - - if (ALLOCNO_NUM_OBJECTS (conflict_a) > 1 - && conflict_nregs == ALLOCNO_NUM_OBJECTS (conflict_a)) - { - if (REG_WORDS_BIG_ENDIAN) - conflict_hard_regno += (ALLOCNO_NUM_OBJECTS (conflict_a) - - OBJECT_SUBWORD (conflict_obj) - 1); - else - conflict_hard_regno += OBJECT_SUBWORD (conflict_obj); - conflict_nregs = 1; - } + if (REG_WORDS_BIG_ENDIAN) + conflict_hard_regno = conflict_hard_regno + + ALLOCNO_NREGS (conflict_a) - 1 + - OBJECT_START (conflict_obj) + - OBJECT_NREGS (conflict_obj) + 1; + else + conflict_hard_regno + = conflict_hard_regno + OBJECT_START (conflict_obj); - if ((conflict_hard_regno <= this_regno - && this_regno < conflict_hard_regno + conflict_nregs) - || (this_regno <= conflict_hard_regno - && conflict_hard_regno < this_regno + nregs)) + if (!(this_regno + OBJECT_NREGS (obj) <= conflict_hard_regno + || conflict_hard_regno + OBJECT_NREGS (conflict_obj) + <= this_regno)) { fprintf (stderr, "bad allocation for %d and %d\n", ALLOCNO_REGNO (a), ALLOCNO_REGNO (conflict_a)); -- 2.36.3