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]

[Committed] store_bit_field: Handle paradoxical subregs properly


Hi Roger,

> On Wed, 19 Apr 2006, Andreas Krebbel wrote:
> > However gcc creates wrong code for it without:
> > http://gcc.gnu.org/ml/gcc-patches/2006-03/msg01793.html
> 
> Ahh, sorry for the chicken and egg situation.  I was wondering why
> it was taking a while to commit your change after the approval,
> but I'd forgotten about the patch interdependency on s390/s390x.
No problem. The delay was caused by one week vacation on my side.

> The first patch, the one cited above, is also OK for mainline, but
> now that the ICE is resolved it would be nice to add an execution
> test to the testsuite to confirm that the code generation problem is
> fixed and doesn't regress in future.  A suitable execution test
> case is pre-approved, though you should post it to this list when
> you commit it.
Ok. I've committed the attached patch.

Bootstrapped on i686, s390 and s390x.

Bye,

-Andreas-

2006-04-25  Andreas Krebbel  <krebbel1@de.ibm.com>

	* expmed.c (store_bit_field): Handle paradoxical subregs on big endian
	machines.

2006-04-25  Andreas Krebbel  <krebbel1@de.ibm.com>

	* gcc.dg/20060425-1.c: New testcase.


Index: gcc/expmed.c
===================================================================
*** gcc/expmed.c.orig	2006-03-12 19:44:58.000000000 +0100
--- gcc/expmed.c	2006-04-25 09:35:50.000000000 +0200
*************** store_bit_field (rtx str_rtx, unsigned H
*** 363,369 ****
  	 meaningful at a much higher level; when structures are copied
  	 between memory and regs, the higher-numbered regs
  	 always get higher addresses.  */
!       bitnum += SUBREG_BYTE (op0) * BITS_PER_UNIT;
        op0 = SUBREG_REG (op0);
      }
  
--- 363,387 ----
  	 meaningful at a much higher level; when structures are copied
  	 between memory and regs, the higher-numbered regs
  	 always get higher addresses.  */
!       int inner_mode_size = GET_MODE_SIZE (GET_MODE (SUBREG_REG (op0)));
!       int outer_mode_size = GET_MODE_SIZE (GET_MODE (op0));
!       
!       byte_offset = 0;
! 
!       /* Paradoxical subregs need special handling on big endian machines.  */
!       if (SUBREG_BYTE (op0) == 0 && inner_mode_size < outer_mode_size)
! 	{
! 	  int difference = inner_mode_size - outer_mode_size;
! 
! 	  if (WORDS_BIG_ENDIAN)
! 	    byte_offset += (difference / UNITS_PER_WORD) * UNITS_PER_WORD;
! 	  if (BYTES_BIG_ENDIAN)
! 	    byte_offset += difference % UNITS_PER_WORD;
! 	}
!       else
! 	byte_offset = SUBREG_BYTE (op0);
! 
!       bitnum += byte_offset * BITS_PER_UNIT;
        op0 = SUBREG_REG (op0);
      }
  
Index: gcc/testsuite/gcc.dg/20060425-1.c
===================================================================
*** /dev/null	1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.dg/20060425-1.c	2006-04-25 10:04:14.000000000 +0200
***************
*** 0 ****
--- 1,38 ----
+ /* { dg-do run } */
+ /* { dg-options "-O1" } */
+ 
+ /* This failed because if conversion didn't handle insv patterns properly.  */
+ 
+ void abort (void);
+ 
+ union y
+ {
+   int a;
+   unsigned short b;
+ };
+ 
+ void __attribute__ ((noinline))
+ bar (unsigned short u, union y v)
+ {
+   if (u != 1)
+     abort ();
+ }
+ 
+ void __attribute__ ((noinline))
+ foo (int check)
+ {
+   union y x;
+ 
+   if (check != 0)
+     x.b = 1;
+   else
+     x.b = 2;
+   bar (x.b, x);
+ }
+ 
+ int
+ main ()
+ {
+   foo (1);
+   return 0;
+ }


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