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.
Tested on aarch64-linux-gnu and x86_64-linux-gnu, and by checking
there was no change in the testsuite assembly output for at least
one target per CPU. OK to install?
Richard
2017-08-28 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.
Index: gcc/rtl.h
===
--- gcc/rtl.h 2017-08-28 09:23:51.181220876 +0100
+++ gcc/rtl.h 2017-08-28 09:23:56.230220860 +0100
@@ -2840,6 +2840,24 @@ subreg_lowpart_offset (machine_mode oute
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. */
Index: gcc/ira.h
===
--- gcc/ira.h 2017-08-28 09:22:51.676686496 +0100
+++ gcc/ira.h 2017-08-28 09:23:56.227520860 +0100
@@ -195,7 +195,7 @@ extern void ira_set_pseudo_classes (bool
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 *,
Index: gcc/ira-color.c
===
--- gcc/ira-color.c 2017-08-28 09:22:51.676686496 +0100
+++ gcc/ira-color.c 2017-08-28 09:23:56.226620860 +0100
@@ -3908,7 +3908,7 @@ coalesced_pseudo_reg_freq_compare (const
/* 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
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
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 (