[Committed] PR25703

Roger Sayle roger@eyesopen.com
Thu Jan 26 03:02:00 GMT 2006


The following patch resolves PR25703 which is a wrong-code regression
on mainline caused by my recent patch to generalize the optimization
of merging constant bit-field assignments in combine.  Many thanks to
Eric Botcazou for analyzing some Ada ACATS failures and discovering
the problem was that I was assuming subreg_lowpart_p in more places
than I should.

The following patch has been tested on i686-pc-linux-gnu with a full
"make bootstrap", all default languages including Ada, and regression
tested with a top-level "make -k check" with no new failures.  Many
thanks also to Jan for reducing a C testcase, included below.

This patch has been committed to mainline as revision 110242.
Please let me know if there are any further problems.
My apologies for any inconvenience, the gnat build was broken
during the development of the patch, or I'd have noticed the
new acats failures.


2006-01-25  Roger Sayle  <roger@eyesopen.com>

	PR rtl-optimization/25703
	* combine.c (try_combine): Handle zero_extract and strict_low_part
	of non-lowpart SUBREGs for constant reg_subword_p set optimization.

2006-01-25  Jan Hubicka  <jh@suse.cz>
	    Roger Sayle  <roger@eyesopen.com>

	PR rtl-optimization/25703
	* gcc.target/i386/20060125-1.c: New test case.
	* gcc.target/i386/20060125-2.c: New test case.


Index: combine.c
===================================================================
*** combine.c	(revision 109912)
--- combine.c	(working copy)
*************** try_combine (rtx i3, rtx i2, rtx i1, int
*** 1951,1990 ****
        int offset = -1;
        int width = 0;

!       if (GET_CODE (dest) == STRICT_LOW_PART)
! 	{
! 	  width = GET_MODE_BITSIZE (GET_MODE (XEXP (dest, 0)));
! 	  offset = 0;
! 	}
!       else if (GET_CODE (dest) == ZERO_EXTRACT)
  	{
  	  if (GET_CODE (XEXP (dest, 1)) == CONST_INT
  	      && GET_CODE (XEXP (dest, 2)) == CONST_INT)
  	    {
  	      width = INTVAL (XEXP (dest, 1));
  	      offset = INTVAL (XEXP (dest, 2));
!
  	      if (BITS_BIG_ENDIAN)
! 		offset = GET_MODE_BITSIZE (GET_MODE (XEXP (dest, 0)))
! 			 - width - offset;
  	    }
  	}
!       else if (subreg_lowpart_p (dest))
  	{
  	  width = GET_MODE_BITSIZE (GET_MODE (dest));
  	  offset = 0;
  	}
!       /* ??? Preserve the original logic to handle setting the high word
! 	 of double-word pseudos, where inner is half the size of outer
! 	 but not the lowpart.  This could be generalized by handling
! 	 SUBREG_BYTE, WORDS_BIG_ENDIAN and BYTES_BIG_ENDIAN ourselves.
! 	 Unfortunately this logic is tricky to get right and probably
! 	 not worth the effort.  */
!       else if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (temp)))
! 	       == 2 * GET_MODE_BITSIZE (GET_MODE (dest)))
  	{
! 	  width = GET_MODE_BITSIZE (GET_MODE (dest));
! 	  offset = width;
  	}

        if (offset >= 0)
--- 1951,1988 ----
        int offset = -1;
        int width = 0;

!       if (GET_CODE (dest) == ZERO_EXTRACT)
  	{
  	  if (GET_CODE (XEXP (dest, 1)) == CONST_INT
  	      && GET_CODE (XEXP (dest, 2)) == CONST_INT)
  	    {
  	      width = INTVAL (XEXP (dest, 1));
  	      offset = INTVAL (XEXP (dest, 2));
! 	      dest = XEXP (dest, 0);
  	      if (BITS_BIG_ENDIAN)
! 		offset = GET_MODE_BITSIZE (GET_MODE (dest)) - width - offset;
  	    }
  	}
!       else
  	{
+ 	  if (GET_CODE (dest) == STRICT_LOW_PART)
+ 	    dest = XEXP (dest, 0);
  	  width = GET_MODE_BITSIZE (GET_MODE (dest));
  	  offset = 0;
  	}
!
!       if (offset >= 0)
  	{
! 	  /* If this is the low part, we're done.  */
! 	  if (subreg_lowpart_p (dest))
! 	    ;
! 	  /* Handle the case where inner is twice the size of outer.  */
! 	  else if (GET_MODE_BITSIZE (GET_MODE (SET_DEST (temp)))
! 		   == 2 * GET_MODE_BITSIZE (GET_MODE (dest)))
! 	    offset += GET_MODE_BITSIZE (GET_MODE (dest));
! 	  /* Otherwise give up for now.  */
! 	  else
! 	    offset = -1;
  	}

        if (offset >= 0)


/* PR rtl-optimization/25703 */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-O2 -mtune=i486" } */

extern void abort (void);

struct a
{
        int a;
        char b,c,d,e;
};

__attribute__ ((noinline))
__attribute__ ((regparm(1))) t(struct a a)
{
        if (a.a!=1 || a.b!=1 || a.c!=1)
                        abort();
}

int main()
{
        struct a a;
        a.c=1;
        a.a=1;
        a.b=1;
        t(a);
        return 0;
}


/* PR rtl-optimization/25703 */
/* { dg-do run { target i?86-*-* x86_64-*-* } } */
/* { dg-require-effective-target ilp32 } */
/* { dg-options "-O2 -mtune=pentiumpro" } */

extern void abort (void);

struct a
{
        int a;
        char b,c,d,e;
};

__attribute__ ((noinline))
__attribute__ ((regparm(1))) t(struct a a)
{
        if (a.a!=1 || a.b!=1 || a.c!=1)
                        abort();
}

int main()
{
        struct a a;
        a.c=1;
        a.a=1;
        a.b=1;
        t(a);
        return 0;
}

Roger
--



More information about the Gcc-patches mailing list