poly_int: ira subreg liveness tracking
authorRichard Sandiford <richard.sandiford@linaro.org>
Wed, 20 Dec 2017 12:54:17 +0000 (12:54 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Wed, 20 Dec 2017 12:54:17 +0000 (12:54 +0000)
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

gcc/ChangeLog
gcc/ira.c

index 9f2d0657004a4fab2c3bb1ea13ef76ab55d9fc07..91f1927ff69d7ee462a657ce1ef3ff731ac81f94 100644 (file)
@@ -1,3 +1,12 @@
+2017-12-20  Richard Sandiford  <richard.sandiford@linaro.org>
+           Alan Hayward  <alan.hayward@arm.com>
+           David Sherwood  <david.sherwood@arm.com>
+
+       * 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.
+
 2017-12-20  Richard Sandiford  <richard.sandiford@linaro.org>
            Alan Hayward  <alan.hayward@arm.com>
            David Sherwood  <david.sherwood@arm.com>
index 79837da1db5142f5819d0d7ea53f215b4c2b1224..13972540a9cfa45f9fbe3662e7edd3ca7d6b1b90 100644 (file)
--- 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]))