Optimization bug in GCC V1.32 on BIG_ENDIAN machines

Jon Olson olson at modular.UUCP
Sun Jan 22 14:36:26 AEST 1989


I am sending out this GCC bug-report out to a couple likely
newsgroups since I have no luck reaching the gcc-bug account
of gcc-bug at prep.ai.mit.edu.  Hopefully someone will see this
who knows to forward to its appropriate destination.

I tracked down a rather annoying bug in GCC V1.32 on SUNOS 4.0
the other day.  The small test program below demonstrates this
bug:

struct TEST
  {
  unsigned char c;
  unsigned short s;
  int i;
  } r1, r2, r3;

main()
  {
  foo( &r1, 1, 2, 3 );
  printf( "c = %d, s = %d, i = %d\n", r1.c, r1.s, r1.i );
  }

foo( p, i1, i2, i3 )
struct TEST *p;
int i1, i2, i3;
  {
  p->c = i1;   /* Here, GCC generates moveb a6@(12),a0@ */
  p->s = i2;
  p->i = i3;
  }

After a bit of digging I found the problem lied in some missing
logic in `combine.c' with respect to big-endian machines.  During
optimization, this code forgot to add in the extra 3-bytes required
to extract the low byte of `i1' instead of the high byte.  Below
are the context diffs for the change I made to fix the bug.  Maybe
somebody should go through GCC carefully to make sure that there
are no other such big-endian machine problems???

*** combine.c.save	Sat Jan 21 20:45:51 1989
--- combine.c	Sat Jan 21 21:02:39 1989
***************
*** 878,891 ****
  	 paradoxical case where gen_lowpart_for_combine makes them.  */
        if (SUBREG_REG (x) == to
  	  && GET_CODE (to) == MEM)
! 	{
  	  if (!undobuf.storage)
  	    undobuf.storage = (char *) oballoc (0);
  	  /* Note if the plus_constant doesn't make a valid address
  	     then this combination won't be accepted.  */
  	  return gen_rtx (MEM, GET_MODE (x),
! 			  plus_constant (XEXP (to, 0),
! 					 SUBREG_WORD (x) * UNITS_PER_WORD));
  	}
        break;
  
--- 878,895 ----
  	 paradoxical case where gen_lowpart_for_combine makes them.  */
        if (SUBREG_REG (x) == to
  	  && GET_CODE (to) == MEM)
! 	{/****** JPO: Fixed this for BIG-ENDIAN machines*****/
! 	register int offset = SUBREG_WORD (x) * UNITS_PER_WORD;
! #ifdef BYTES_BIG_ENDIAN
! 	offset -= (min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (x)))
! 		   - min (UNITS_PER_WORD, GET_MODE_SIZE (GET_MODE (to))));
! #endif
  	  if (!undobuf.storage)
  	    undobuf.storage = (char *) oballoc (0);
  	  /* Note if the plus_constant doesn't make a valid address
  	     then this combination won't be accepted.  */
  	  return gen_rtx (MEM, GET_MODE (x),
! 			  plus_constant (XEXP (to, 0), offset));
  	}
        break;
  



More information about the Comp.lang.c mailing list