aboutsummaryrefslogtreecommitdiff
path: root/gcc/ira.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@linaro.org>2017-12-20 12:54:17 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2017-12-20 12:54:17 +0000
commit9dcf1f868c048e20c72df7ee5d378625d1e77bc8 (patch)
treefbb848314cbe3951097d2ceaad0c9faa22cb53f6 /gcc/ira.c
parent7f679e470b6255bcf495b8200d66acfed1e975a3 (diff)
downloadgcc-9dcf1f868c048e20c72df7ee5d378625d1e77bc8.zip
gcc-9dcf1f868c048e20c72df7ee5d378625d1e77bc8.tar.gz
gcc-9dcf1f868c048e20c72df7ee5d378625d1e77bc8.tar.bz2
poly_int: ira subreg liveness tracking
Normmaly the IRA-reload interface tries to track the liveness of individual bytes of an allocno if the allocno is sometimes written to as a SUBREG. This isn't possible for variable-sized allocnos, but it doesn't matter because targets with variable-sized registers should use LRA instead. This patch adds a get_subreg_tracking_sizes function for deciding whether it is possible to model a partial read or write. Later patches make it return false if anything is variable. 2017-12-20 Richard Sandiford <richard.sandiford@linaro.org> Alan Hayward <alan.hayward@arm.com> David Sherwood <david.sherwood@arm.com> gcc/ * ira.c (get_subreg_tracking_sizes): New function. (init_live_subregs): Take an integer size rather than a register. (build_insn_chain): Use get_subreg_tracking_sizes. Update calls to init_live_subregs. Co-Authored-By: Alan Hayward <alan.hayward@arm.com> Co-Authored-By: David Sherwood <david.sherwood@arm.com> From-SVN: r255881
Diffstat (limited to 'gcc/ira.c')
-rw-r--r--gcc/ira.c60
1 files changed, 40 insertions, 20 deletions
diff --git a/gcc/ira.c b/gcc/ira.c
index 79837da..1397254 100644
--- a/gcc/ira.c
+++ b/gcc/ira.c
@@ -4037,16 +4037,27 @@ pseudo_for_reload_consideration_p (int regno)
return (reg_renumber[regno] >= 0 || ira_conflicts_p);
}
-/* Init LIVE_SUBREGS[ALLOCNUM] and LIVE_SUBREGS_USED[ALLOCNUM] using
- REG to the number of nregs, and INIT_VALUE to get the
- initialization. ALLOCNUM need not be the regno of REG. */
+/* Return true if we can track the individual bytes of subreg X.
+ When returning true, set *OUTER_SIZE to the number of bytes in
+ X itself, *INNER_SIZE to the number of bytes in the inner register
+ and *START to the offset of the first byte. */
+static bool
+get_subreg_tracking_sizes (rtx x, HOST_WIDE_INT *outer_size,
+ HOST_WIDE_INT *inner_size, HOST_WIDE_INT *start)
+{
+ rtx reg = regno_reg_rtx[REGNO (SUBREG_REG (x))];
+ *outer_size = GET_MODE_SIZE (GET_MODE (x));
+ *inner_size = GET_MODE_SIZE (GET_MODE (reg));
+ *start = SUBREG_BYTE (x);
+ return true;
+}
+
+/* Init LIVE_SUBREGS[ALLOCNUM] and LIVE_SUBREGS_USED[ALLOCNUM] for
+ a register with SIZE bytes, making the register live if INIT_VALUE. */
static void
init_live_subregs (bool init_value, sbitmap *live_subregs,
- bitmap live_subregs_used, int allocnum, rtx reg)
+ bitmap live_subregs_used, int allocnum, int size)
{
- unsigned int regno = REGNO (SUBREG_REG (reg));
- int size = GET_MODE_SIZE (GET_MODE (regno_reg_rtx[regno]));
-
gcc_assert (size > 0);
/* Been there, done that. */
@@ -4155,19 +4166,26 @@ build_insn_chain (void)
&& (!DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)))
{
rtx reg = DF_REF_REG (def);
-
- /* We can model subregs, but not if they are
- wrapped in ZERO_EXTRACTS. */
+ HOST_WIDE_INT outer_size, inner_size, start;
+
+ /* We can usually track the liveness of individual
+ bytes within a subreg. The only exceptions are
+ subregs wrapped in ZERO_EXTRACTs and subregs whose
+ size is not known; in those cases we need to be
+ conservative and treat the definition as a partial
+ definition of the full register rather than a full
+ definition of a specific part of the register. */
if (GET_CODE (reg) == SUBREG
- && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT))
+ && !DF_REF_FLAGS_IS_SET (def, DF_REF_ZERO_EXTRACT)
+ && get_subreg_tracking_sizes (reg, &outer_size,
+ &inner_size, &start))
{
- unsigned int start = SUBREG_BYTE (reg);
- unsigned int last = start
- + GET_MODE_SIZE (GET_MODE (reg));
+ HOST_WIDE_INT last = start + outer_size;
init_live_subregs
(bitmap_bit_p (live_relevant_regs, regno),
- live_subregs, live_subregs_used, regno, reg);
+ live_subregs, live_subregs_used, regno,
+ inner_size);
if (!DF_REF_FLAGS_IS_SET
(def, DF_REF_STRICT_LOW_PART))
@@ -4252,18 +4270,20 @@ build_insn_chain (void)
if (regno < FIRST_PSEUDO_REGISTER
|| pseudo_for_reload_consideration_p (regno))
{
+ HOST_WIDE_INT outer_size, inner_size, start;
if (GET_CODE (reg) == SUBREG
&& !DF_REF_FLAGS_IS_SET (use,
DF_REF_SIGN_EXTRACT
- | DF_REF_ZERO_EXTRACT))
+ | DF_REF_ZERO_EXTRACT)
+ && get_subreg_tracking_sizes (reg, &outer_size,
+ &inner_size, &start))
{
- unsigned int start = SUBREG_BYTE (reg);
- unsigned int last = start
- + GET_MODE_SIZE (GET_MODE (reg));
+ HOST_WIDE_INT last = start + outer_size;
init_live_subregs
(bitmap_bit_p (live_relevant_regs, regno),
- live_subregs, live_subregs_used, regno, reg);
+ live_subregs, live_subregs_used, regno,
+ inner_size);
/* Ignore the paradoxical bits. */
if (last > SBITMAP_SIZE (live_subregs[regno]))