[024/nnn] poly_int: ira subreg liveness tracking

Message ID 87zi8hpz8r.fsf@linaro.org
State New
Headers show
Series
  • [024/nnn] poly_int: ira subreg liveness tracking
Related show

Commit Message

Richard Sandiford Oct. 23, 2017, 5:09 p.m.
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-10-23  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.

Comments

Jeff Law Nov. 28, 2017, 8:30 p.m. | #1
On 10/23/2017 11:09 AM, Richard Sandiford wrote:
> 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-10-23  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.

OK.

Note this is starting to get close to the discussion around CLOBBER_HIGH
vs using a self set with a low subreg that we're having with Alan on
another thread in that liveness tracking of subregs of SVE regs could
potentially use some improvements.

When I quickly looked at the subreg handling in the df infrstructure my
first thought was that it might need some updating for SVE.  I can't
immediately call bits for poly_int/SVE in the patches to-date.  Have you
dug in there at all for the poly_int/SVE work?

Jeff
Richard Sandiford Dec. 5, 2017, 9:54 p.m. | #2
Jeff Law <law@redhat.com> writes:
> On 10/23/2017 11:09 AM, Richard Sandiford wrote:

>> 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-10-23  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.

> OK.

>

> Note this is starting to get close to the discussion around CLOBBER_HIGH

> vs using a self set with a low subreg that we're having with Alan on

> another thread in that liveness tracking of subregs of SVE regs could

> potentially use some improvements.

>

> When I quickly looked at the subreg handling in the df infrstructure my

> first thought was that it might need some updating for SVE.  I can't

> immediately call bits for poly_int/SVE in the patches to-date.  Have you

> dug in there at all for the poly_int/SVE work?


Yeah, although the subreg tracking in this patch is specific to reload,
I thought we had something similar for LRA.  I couldn't find anything
though, and the static type checking of poly_ints would have forced
the issue.

There is the DF_WORD_LR code, which tracks the liveness of words in a
double-word pseudo.  We didn't extend that to variable-length registers
for two reasons: (1) if we did need it, we'd want it for pseudos
that map to 3 or 4 registers, not just 2, so that LD[234] and ST[234]
are handled consistently; and (2) it's only used for DCE at the moment,
and it's rare for LD[234]/ST[234]s to be dead code.

Thanks,
Richard

Patch

Index: gcc/ira.c
===================================================================
--- gcc/ira.c	2017-10-23 17:11:43.647074065 +0100
+++ gcc/ira.c	2017-10-23 17:11:59.074107016 +0100
@@ -4040,16 +4040,27 @@  pseudo_for_reload_consideration_p (int r
   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.  */
@@ -4158,19 +4169,26 @@  build_insn_chain (void)
 			&& (!DF_REF_FLAGS_IS_SET (def, DF_REF_CONDITIONAL)))
 		      {
 			rtx reg = DF_REF_REG (def);
+			HOST_WIDE_INT outer_size, inner_size, start;
 
-			/* We can model subregs, but not if they are
-			   wrapped in ZERO_EXTRACTS.  */
+			/* 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))
@@ -4255,18 +4273,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]))