From bd5a2c67cfd636b6c78f213c8ee6dac62323eff9 Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Thu, 26 Oct 2017 16:53:43 +0000 Subject: [PATCH] Add wider_subreg_mode helper functions This patch adds helper functions that say which of the two modes involved in a subreg is the larger, preferring the outer mode in the event of a tie. It also converts IRA and reload to track modes instead of byte sizes, since this is slightly more convenient when variable-sized modes are added later. 2017-10-26 Richard Sandiford Alan Hayward David Sherwood gcc/ * rtl.h (wider_subreg_mode): New function. * ira.h (ira_sort_regnos_for_alter_reg): Take a machine_mode * rather than an unsigned int *. * ira-color.c (regno_max_ref_width): Replace with... (regno_max_ref_mode): ...this new variable. (coalesced_pseudo_reg_slot_compare): Update accordingly. Use wider_subreg_mode. (ira_sort_regnos_for_alter_reg): Likewise. Take a machine_mode * rather than an unsigned int *. * lra-constraints.c (uses_hard_regs_p): Use wider_subreg_mode. (process_alt_operands): Likewise. (invariant_p): Likewise. * lra-spills.c (assign_mem_slot): Likewise. (add_pseudo_to_slot): Likewise. * lra.c (collect_non_operand_hard_regs): Likewise. (add_regs_to_insn_regno_info): Likewise. * reload1.c (regno_max_ref_width): Replace with... (regno_max_ref_mode): ...this new variable. (reload): Update accordingly. Update call to ira_sort_regnos_for_alter_reg. (alter_reg): Update to use regno_max_ref_mode. Call wider_subreg_mode. (init_eliminable_invariants): Update to use regno_max_ref_mode. (scan_paradoxical_subregs): Likewise. Co-Authored-By: Alan Hayward Co-Authored-By: David Sherwood From-SVN: r254115 --- gcc/ChangeLog | 28 ++++++++++++++++++++++++++++ gcc/ira-color.c | 30 +++++++++++++++++------------- gcc/ira.h | 2 +- gcc/lra-constraints.c | 10 +++------- gcc/lra-spills.c | 9 +++------ gcc/lra.c | 6 ++---- gcc/reload1.c | 32 +++++++++++++++++--------------- gcc/rtl.h | 18 ++++++++++++++++++ 8 files changed, 89 insertions(+), 46 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 81e5bba..4312ac2 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,31 @@ +2017-10-26 Richard Sandiford + Alan Hayward + David Sherwood + + * rtl.h (wider_subreg_mode): New function. + * ira.h (ira_sort_regnos_for_alter_reg): Take a machine_mode * + rather than an unsigned int *. + * ira-color.c (regno_max_ref_width): Replace with... + (regno_max_ref_mode): ...this new variable. + (coalesced_pseudo_reg_slot_compare): Update accordingly. + Use wider_subreg_mode. + (ira_sort_regnos_for_alter_reg): Likewise. Take a machine_mode * + rather than an unsigned int *. + * lra-constraints.c (uses_hard_regs_p): Use wider_subreg_mode. + (process_alt_operands): Likewise. + (invariant_p): Likewise. + * lra-spills.c (assign_mem_slot): Likewise. + (add_pseudo_to_slot): Likewise. + * lra.c (collect_non_operand_hard_regs): Likewise. + (add_regs_to_insn_regno_info): Likewise. + * reload1.c (regno_max_ref_width): Replace with... + (regno_max_ref_mode): ...this new variable. + (reload): Update accordingly. Update call to + ira_sort_regnos_for_alter_reg. + (alter_reg): Update to use regno_max_ref_mode. Call wider_subreg_mode. + (init_eliminable_invariants): Update to use regno_max_ref_mode. + (scan_paradoxical_subregs): Likewise. + 2017-10-26 Wilco Dijkstra * config/aarch64/aarch64.h (EXIT_IGNORE_STACK): Set if alloca is used. diff --git a/gcc/ira-color.c b/gcc/ira-color.c index 31a4a80..240eb48 100644 --- a/gcc/ira-color.c +++ b/gcc/ira-color.c @@ -3908,7 +3908,7 @@ coalesced_pseudo_reg_freq_compare (const void *v1p, const void *v2p) /* Widest width in which each pseudo reg is referred to (via subreg). It is used for sorting pseudo registers. */ -static unsigned int *regno_max_ref_width; +static machine_mode *regno_max_ref_mode; /* Sort pseudos according their slot numbers (putting ones with smaller numbers first, or last when the frame pointer is not @@ -3921,7 +3921,7 @@ coalesced_pseudo_reg_slot_compare (const void *v1p, const void *v2p) ira_allocno_t a1 = ira_regno_allocno_map[regno1]; ira_allocno_t a2 = ira_regno_allocno_map[regno2]; int diff, slot_num1, slot_num2; - int total_size1, total_size2; + machine_mode mode1, mode2; if (a1 == NULL || ALLOCNO_HARD_REGNO (a1) >= 0) { @@ -3936,11 +3936,11 @@ coalesced_pseudo_reg_slot_compare (const void *v1p, const void *v2p) if ((diff = slot_num1 - slot_num2) != 0) return (frame_pointer_needed || (!FRAME_GROWS_DOWNWARD) == STACK_GROWS_DOWNWARD ? diff : -diff); - total_size1 = MAX (PSEUDO_REGNO_BYTES (regno1), - regno_max_ref_width[regno1]); - total_size2 = MAX (PSEUDO_REGNO_BYTES (regno2), - regno_max_ref_width[regno2]); - if ((diff = total_size2 - total_size1) != 0) + mode1 = wider_subreg_mode (PSEUDO_REGNO_MODE (regno1), + regno_max_ref_mode[regno1]); + mode2 = wider_subreg_mode (PSEUDO_REGNO_MODE (regno2), + regno_max_ref_mode[regno2]); + if ((diff = GET_MODE_SIZE (mode2) - GET_MODE_SIZE (mode1)) != 0) return diff; return regno1 - regno2; } @@ -4144,7 +4144,7 @@ coalesce_spill_slots (ira_allocno_t *spilled_coalesced_allocnos, int num) reload. */ void ira_sort_regnos_for_alter_reg (int *pseudo_regnos, int n, - unsigned int *reg_max_ref_width) + machine_mode *reg_max_ref_mode) { int max_regno = max_reg_num (); int i, regno, num, slot_num; @@ -4225,10 +4225,14 @@ ira_sort_regnos_for_alter_reg (int *pseudo_regnos, int n, ira_assert (ALLOCNO_HARD_REGNO (a) < 0); ALLOCNO_HARD_REGNO (a) = -slot_num; if (internal_flag_ira_verbose > 3 && ira_dump_file != NULL) - fprintf (ira_dump_file, " a%dr%d(%d,%d)", - ALLOCNO_NUM (a), ALLOCNO_REGNO (a), ALLOCNO_FREQ (a), - MAX (PSEUDO_REGNO_BYTES (ALLOCNO_REGNO (a)), - reg_max_ref_width[ALLOCNO_REGNO (a)])); + { + machine_mode mode = wider_subreg_mode + (PSEUDO_REGNO_MODE (ALLOCNO_REGNO (a)), + reg_max_ref_mode[ALLOCNO_REGNO (a)]); + fprintf (ira_dump_file, " a%dr%d(%d,%d)", + ALLOCNO_NUM (a), ALLOCNO_REGNO (a), ALLOCNO_FREQ (a), + GET_MODE_SIZE (mode)); + } if (a == allocno) break; @@ -4239,7 +4243,7 @@ ira_sort_regnos_for_alter_reg (int *pseudo_regnos, int n, ira_spilled_reg_stack_slots_num = slot_num - 1; ira_free (spilled_coalesced_allocnos); /* Sort regnos according the slot numbers. */ - regno_max_ref_width = reg_max_ref_width; + regno_max_ref_mode = reg_max_ref_mode; qsort (pseudo_regnos, n, sizeof (int), coalesced_pseudo_reg_slot_compare); FOR_EACH_ALLOCNO (a, ai) ALLOCNO_ADD_DATA (a) = NULL; diff --git a/gcc/ira.h b/gcc/ira.h index 69021c4..fba2ca5 100644 --- a/gcc/ira.h +++ b/gcc/ira.h @@ -195,7 +195,7 @@ extern void ira_set_pseudo_classes (bool, FILE *); extern void ira_expand_reg_equiv (void); extern void ira_update_equiv_info_by_shuffle_insn (int, int, rtx_insn *); -extern void ira_sort_regnos_for_alter_reg (int *, int, unsigned int *); +extern void ira_sort_regnos_for_alter_reg (int *, int, machine_mode *); extern void ira_mark_allocation_change (int); extern void ira_mark_memory_move_deletion (int, int); extern bool ira_reassign_pseudos (int *, int, HARD_REG_SET, HARD_REG_SET *, diff --git a/gcc/lra-constraints.c b/gcc/lra-constraints.c index c3bbfd7..a423f06 100644 --- a/gcc/lra-constraints.c +++ b/gcc/lra-constraints.c @@ -1772,10 +1772,9 @@ uses_hard_regs_p (rtx x, HARD_REG_SET set) mode = GET_MODE (x); if (code == SUBREG) { + mode = wider_subreg_mode (x); x = SUBREG_REG (x); code = GET_CODE (x); - if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (mode)) - mode = GET_MODE (x); } if (REG_P (x)) @@ -1953,10 +1952,8 @@ process_alt_operands (int only_alternative) biggest_mode[nop] = GET_MODE (op); if (GET_CODE (op) == SUBREG) { + biggest_mode[nop] = wider_subreg_mode (op); operand_reg[nop] = reg = SUBREG_REG (op); - if (GET_MODE_SIZE (biggest_mode[nop]) - < GET_MODE_SIZE (GET_MODE (reg))) - biggest_mode[nop] = GET_MODE (reg); } if (! REG_P (reg)) operand_reg[nop] = NULL_RTX; @@ -5659,8 +5656,7 @@ invariant_p (const_rtx x) { x = SUBREG_REG (x); code = GET_CODE (x); - if (GET_MODE_SIZE (GET_MODE (x)) > GET_MODE_SIZE (mode)) - mode = GET_MODE (x); + mode = wider_subreg_mode (mode, GET_MODE (x)); } if (MEM_P (x)) diff --git a/gcc/lra-spills.c b/gcc/lra-spills.c index 5997b1e..9abcda4 100644 --- a/gcc/lra-spills.c +++ b/gcc/lra-spills.c @@ -134,8 +134,7 @@ assign_mem_slot (int i) machine_mode mode = GET_MODE (regno_reg_rtx[i]); HOST_WIDE_INT inherent_size = PSEUDO_REGNO_BYTES (i); machine_mode wider_mode - = (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (lra_reg_info[i].biggest_mode) - ? mode : lra_reg_info[i].biggest_mode); + = wider_subreg_mode (mode, lra_reg_info[i].biggest_mode); HOST_WIDE_INT total_size = GET_MODE_SIZE (wider_mode); HOST_WIDE_INT adjust = 0; @@ -312,10 +311,8 @@ add_pseudo_to_slot (int regno, int slot_num) and a total size which provides room for paradoxical subregs. We need to make sure the size and alignment of the slot are sufficient for both. */ - machine_mode mode = (GET_MODE_SIZE (PSEUDO_REGNO_MODE (regno)) - >= GET_MODE_SIZE (lra_reg_info[regno].biggest_mode) - ? PSEUDO_REGNO_MODE (regno) - : lra_reg_info[regno].biggest_mode); + machine_mode mode = wider_subreg_mode (PSEUDO_REGNO_MODE (regno), + lra_reg_info[regno].biggest_mode); unsigned int align = spill_slot_alignment (mode); slots[slot_num].align = MAX (slots[slot_num].align, align); slots[slot_num].size = MAX (slots[slot_num].size, GET_MODE_SIZE (mode)); diff --git a/gcc/lra.c b/gcc/lra.c index 04acf88..66fbfd5 100644 --- a/gcc/lra.c +++ b/gcc/lra.c @@ -832,12 +832,11 @@ collect_non_operand_hard_regs (rtx *x, lra_insn_recog_data_t data, subreg_p = false; if (code == SUBREG) { + mode = wider_subreg_mode (op); if (read_modify_subreg_p (op)) subreg_p = true; op = SUBREG_REG (op); code = GET_CODE (op); - if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (op))) - mode = GET_MODE (op); } if (REG_P (op)) { @@ -1425,12 +1424,11 @@ add_regs_to_insn_regno_info (lra_insn_recog_data_t data, rtx x, int uid, subreg_p = false; if (GET_CODE (x) == SUBREG) { + mode = wider_subreg_mode (x); if (read_modify_subreg_p (x)) subreg_p = true; x = SUBREG_REG (x); code = GET_CODE (x); - if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (GET_MODE (x))) - mode = GET_MODE (x); } if (REG_P (x)) { diff --git a/gcc/reload1.c b/gcc/reload1.c index e2ee2fe..e15bd8a 100644 --- a/gcc/reload1.c +++ b/gcc/reload1.c @@ -97,8 +97,8 @@ static regset_head reg_has_output_reload; in the current insn. */ static HARD_REG_SET reg_is_output_reload; -/* Widest width in which each pseudo reg is referred to (via subreg). */ -static unsigned int *reg_max_ref_width; +/* Widest mode in which each pseudo reg is referred to (via subreg). */ +static machine_mode *reg_max_ref_mode; /* Vector to remember old contents of reg_renumber before spilling. */ static short *reg_old_renumber; @@ -830,7 +830,7 @@ reload (rtx_insn *first, int global) if (ira_conflicts_p) /* Ask IRA to order pseudo-registers for better stack slot sharing. */ - ira_sort_regnos_for_alter_reg (temp_pseudo_reg_arr, n, reg_max_ref_width); + ira_sort_regnos_for_alter_reg (temp_pseudo_reg_arr, n, reg_max_ref_mode); for (i = 0; i < n; i++) alter_reg (temp_pseudo_reg_arr[i], -1, false); @@ -1252,7 +1252,7 @@ reload (rtx_insn *first, int global) /* Indicate that we no longer have known memory locations or constants. */ free_reg_equiv (); - free (reg_max_ref_width); + free (reg_max_ref_mode); free (reg_old_renumber); free (pseudo_previous_regs); free (pseudo_forbidden_regs); @@ -2142,8 +2142,9 @@ alter_reg (int i, int from_reg, bool dont_share_p) machine_mode mode = GET_MODE (regno_reg_rtx[i]); unsigned int inherent_size = PSEUDO_REGNO_BYTES (i); unsigned int inherent_align = GET_MODE_ALIGNMENT (mode); - unsigned int total_size = MAX (inherent_size, reg_max_ref_width[i]); - unsigned int min_align = reg_max_ref_width[i] * BITS_PER_UNIT; + machine_mode wider_mode = wider_subreg_mode (mode, reg_max_ref_mode[i]); + unsigned int total_size = GET_MODE_SIZE (wider_mode); + unsigned int min_align = GET_MODE_BITSIZE (reg_max_ref_mode[i]); int adjust = 0; something_was_spilled = true; @@ -4083,9 +4084,9 @@ init_eliminable_invariants (rtx_insn *first, bool do_subregs) grow_reg_equivs (); if (do_subregs) - reg_max_ref_width = XCNEWVEC (unsigned int, max_regno); + reg_max_ref_mode = XCNEWVEC (machine_mode, max_regno); else - reg_max_ref_width = NULL; + reg_max_ref_mode = NULL; num_eliminable_invariants = 0; @@ -4404,7 +4405,7 @@ finish_spills (int global) return something_changed; } -/* Find all paradoxical subregs within X and update reg_max_ref_width. */ +/* Find all paradoxical subregs within X and update reg_max_ref_mode. */ static void scan_paradoxical_subregs (rtx x) @@ -4427,13 +4428,14 @@ scan_paradoxical_subregs (rtx x) return; case SUBREG: - if (REG_P (SUBREG_REG (x)) - && (GET_MODE_SIZE (GET_MODE (x)) - > reg_max_ref_width[REGNO (SUBREG_REG (x))])) + if (REG_P (SUBREG_REG (x))) { - reg_max_ref_width[REGNO (SUBREG_REG (x))] - = GET_MODE_SIZE (GET_MODE (x)); - mark_home_live_1 (REGNO (SUBREG_REG (x)), GET_MODE (x)); + unsigned int regno = REGNO (SUBREG_REG (x)); + if (partial_subreg_p (reg_max_ref_mode[regno], GET_MODE (x))) + { + reg_max_ref_mode[regno] = GET_MODE (x); + mark_home_live_1 (regno, GET_MODE (x)); + } } return; diff --git a/gcc/rtl.h b/gcc/rtl.h index f854550..8e82f04 100644 --- a/gcc/rtl.h +++ b/gcc/rtl.h @@ -2877,6 +2877,24 @@ subreg_lowpart_offset (machine_mode outermode, machine_mode innermode) GET_MODE_SIZE (innermode)); } +/* Given that a subreg has outer mode OUTERMODE and inner mode INNERMODE, + return the mode that is big enough to hold both the outer and inner + values. Prefer the outer mode in the event of a tie. */ + +inline machine_mode +wider_subreg_mode (machine_mode outermode, machine_mode innermode) +{ + return partial_subreg_p (outermode, innermode) ? innermode : outermode; +} + +/* Likewise for subreg X. */ + +inline machine_mode +wider_subreg_mode (const_rtx x) +{ + return wider_subreg_mode (GET_MODE (x), GET_MODE (SUBREG_REG (x))); +} + extern unsigned int subreg_size_highpart_offset (unsigned int, unsigned int); /* Return the SUBREG_BYTE for an OUTERMODE highpart of an INNERMODE value. */ -- 2.7.4