Commit bd5a2c67 by Richard Sandiford Committed by Richard Sandiford

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  <richard.sandiford@linaro.org>
	    Alan Hayward  <alan.hayward@arm.com>
	    David Sherwood  <david.sherwood@arm.com>

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 <alan.hayward@arm.com>
Co-Authored-By: David Sherwood <david.sherwood@arm.com>

From-SVN: r254115
parent 204d2c03
2017-10-26 Richard Sandiford <richard.sandiford@linaro.org>
Alan Hayward <alan.hayward@arm.com>
David Sherwood <david.sherwood@arm.com>
* 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 <wdijkstr@arm.com>
* config/aarch64/aarch64.h (EXIT_IGNORE_STACK): Set if alloca is used.
......@@ -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;
......
......@@ -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 *,
......
......@@ -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))
......
......@@ -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));
......
......@@ -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))
{
......
......@@ -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;
......
......@@ -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. */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment