This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFA:] Fix PR rtl-optimization/17933: parallel set destinationsunhandled by dead_or_set_regno_p.


On Wed, 3 Nov 2004, Richard Henderson wrote:
> This can be restructured as
>
> static bool
> covers_regno_no_parallel_p (rtx dest, unsigned int test_regno)
> {
>   if (GET_CODE (dest) == SUBREG ...)
>     ...
>   if (!REG_P (dest))
>   ...
> }
>
> static bool
> covers_regno_p (rtx dest, unsigned int test_regno)
> {
>   if (GET_CODE (dest) == PARALLEL)
>     {
>       loop calling covers_regno_no_parallel_p.
>       return false;
>     }
>   else
>     return covers_regno_no_parallel_p (dest, test_regno);
> }
>
> which will avoid the recursion.
>
> Otherwise ok.

Yep, as alluded to by "it could be tweaked by breaking out code to a
separate function, but that would be less readable and premature at this
point." ;-)

Anyway, since you approve it with this change, so that's what it'll be.
Your directions are clear to the point that the updated patch is obvious,
so committed as such, after an additional bootstrap and check on
i686-pc-linux-gnu (FC2) and ia64-unknown-linux-gnu (RH E AS 3.0) (no ada
or fortran; hacked around the libunwind issue).  Same testsuite case.

gcc:
	PR rtl-optimization/17933
	* rtlanal.c (dead_or_set_regno_p): Break out common code to...
	(covers_regno_p): New function.  Handle SETs of PARALLEL,
	and defer the rest to...
	(covers_regno_no_parallel_p): New function.

Index: rtlanal.c
===================================================================
RCS file: /mnt/auto/localgcccvs/gcc/gcc/rtlanal.c,v
retrieving revision 1.203
diff -p -c -r1.203 rtlanal.c
*** rtlanal.c	10 Oct 2004 22:06:04 -0000	1.203
--- rtlanal.c	5 Nov 2004 22:40:46 -0000
*************** Software Foundation, 59 Temple Place - S
*** 41,46 ****
--- 41,48 ----
  /* Forward declarations */
  static int global_reg_mentioned_p_1 (rtx *, void *);
  static void set_of_1 (rtx, rtx, void *);
+ static bool covers_regno_p (rtx, unsigned int);
+ static bool covers_regno_no_parallel_p (rtx, unsigned int);
  static int rtx_referenced_p_1 (rtx *, void *);
  static int computed_jump_p_1 (rtx);
  static void parms_set (rtx, rtx, void *);
*************** dead_or_set_p (rtx insn, rtx x)
*** 1549,1561 ****
    return 1;
  }

  /* Utility function for dead_or_set_p to check an individual register.  Also
     called from flow.c.  */

  int
  dead_or_set_regno_p (rtx insn, unsigned int test_regno)
  {
-   unsigned int regno, endregno;
    rtx pattern;

    /* See if there is a death note for something that includes TEST_REGNO.  */
--- 1551,1614 ----
    return 1;
  }

+ /* Return TRUE iff DEST is a register or subreg of a register and
+    doesn't change the number of words of the inner register, and any
+    part of the register is TEST_REGNO.  */
+
+ static bool
+ covers_regno_no_parallel_p (rtx dest, unsigned int test_regno)
+ {
+   unsigned int regno, endregno;
+
+   if (GET_CODE (dest) == SUBREG
+       && (((GET_MODE_SIZE (GET_MODE (dest))
+ 	    + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
+ 	  == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
+ 	       + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
+     dest = SUBREG_REG (dest);
+
+   if (!REG_P (dest))
+     return false;
+
+   regno = REGNO (dest);
+   endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
+ 	      : regno + hard_regno_nregs[regno][GET_MODE (dest)]);
+   return (test_regno >= regno && test_regno < endregno);
+ }
+
+ /* Like covers_regno_no_parallel_p, but also handles PARALLELs where
+    any member matches the covers_regno_no_parallel_p criteria.  */
+
+ static bool
+ covers_regno_p (rtx dest, unsigned int test_regno)
+ {
+   if (GET_CODE (dest) == PARALLEL)
+     {
+       /* Some targets place small structures in registers for return
+ 	 values of functions, and those registers are wrapped in
+ 	 PARALLELs that we may see as the destination of a SET.  */
+       int i;
+
+       for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
+ 	{
+ 	  rtx inner = XEXP (XVECEXP (dest, 0, i), 0);
+ 	  if (inner != NULL_RTX
+ 	      && covers_regno_no_parallel_p (inner, test_regno))
+ 	    return true;
+ 	}
+
+       return false;
+     }
+   else
+     return covers_regno_no_parallel_p (dest, test_regno);
+ }
+
  /* Utility function for dead_or_set_p to check an individual register.  Also
     called from flow.c.  */

  int
  dead_or_set_regno_p (rtx insn, unsigned int test_regno)
  {
    rtx pattern;

    /* See if there is a death note for something that includes TEST_REGNO.  */
*************** dead_or_set_regno_p (rtx insn, unsigned
*** 1572,1599 ****
      pattern = COND_EXEC_CODE (pattern);

    if (GET_CODE (pattern) == SET)
!     {
!       rtx dest = SET_DEST (pattern);
!
!       /* A value is totally replaced if it is the destination or the
! 	 destination is a SUBREG of REGNO that does not change the number of
! 	 words in it.  */
!       if (GET_CODE (dest) == SUBREG
! 	  && (((GET_MODE_SIZE (GET_MODE (dest))
! 		+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)
! 	      == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
! 		   + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
! 	dest = SUBREG_REG (dest);
!
!       if (!REG_P (dest))
! 	return 0;
!
!       regno = REGNO (dest);
!       endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
! 		  : regno + hard_regno_nregs[regno][GET_MODE (dest)]);
!
!       return (test_regno >= regno && test_regno < endregno);
!     }
    else if (GET_CODE (pattern) == PARALLEL)
      {
        int i;
--- 1625,1631 ----
      pattern = COND_EXEC_CODE (pattern);

    if (GET_CODE (pattern) == SET)
!     return covers_regno_p (SET_DEST (pattern), test_regno);
    else if (GET_CODE (pattern) == PARALLEL)
      {
        int i;
*************** dead_or_set_regno_p (rtx insn, unsigned
*** 1605,1631 ****
  	  if (GET_CODE (body) == COND_EXEC)
  	    body = COND_EXEC_CODE (body);

! 	  if (GET_CODE (body) == SET || GET_CODE (body) == CLOBBER)
! 	    {
! 	      rtx dest = SET_DEST (body);
!
! 	      if (GET_CODE (dest) == SUBREG
! 		  && (((GET_MODE_SIZE (GET_MODE (dest))
! 			+ UNITS_PER_WORD - 1) / UNITS_PER_WORD)
! 		      == ((GET_MODE_SIZE (GET_MODE (SUBREG_REG (dest)))
! 			   + UNITS_PER_WORD - 1) / UNITS_PER_WORD)))
! 		dest = SUBREG_REG (dest);
!
! 	      if (!REG_P (dest))
! 		continue;
!
! 	      regno = REGNO (dest);
! 	      endregno = (regno >= FIRST_PSEUDO_REGISTER ? regno + 1
! 			  : regno + hard_regno_nregs[regno][GET_MODE (dest)]);
!
! 	      if (test_regno >= regno && test_regno < endregno)
! 		return 1;
! 	    }
  	}
      }

--- 1637,1645 ----
  	  if (GET_CODE (body) == COND_EXEC)
  	    body = COND_EXEC_CODE (body);

! 	  if ((GET_CODE (body) == SET || GET_CODE (body) == CLOBBER)
! 	      && covers_regno_p (SET_DEST (body), test_regno))
! 	    return 1;
  	}
      }


brgds, H-P


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]