[spu, committed] Fix latent wrong-code generation bug

Ulrich Weigand uweigand@de.ibm.com
Mon Feb 9 14:45:00 GMT 2009


Hello,

spu.c:array_to_constant sometimes builds an incorrect constant value,
leading to wrong code generation.  The problem is that in this code:

       val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
       val <<= 32;
       val |= (arr[4] << 24) | (arr[5] << 16) | (arr[6] << 8) | arr[7];

even though "arr" is of type unsigned char [], the subexpression gets
promoted to (signed) "int".  Therefore, if arr[4] happens to have its
high bit set, this is further sign-extended to HOST_WIDE_INT, overwriting
the high word of "val".

The patch below fixes this by rewriting the code as a loop, similar to
other locations in array_to_constant.

Note that I was unable to find any case where this is actually exercised
on mainline GCC, so it is really a latent issue.  (We do have a case 
where the problem is exposed, in a patched tree.)

Tested with no regressions on spu-elf.  Approved off-line by Trevor,
committed to mainline.

Bye,
Ulrich


ChangeLog:

	* config/spu/spu.c (array_to_constant): Fix (latent) wrong-code
	generation due to implicit sign extension.


Index: gcc/config/spu/spu.c
===================================================================
*** gcc/config/spu/spu.c	(revision 143924)
--- gcc/config/spu/spu.c	(working copy)
*************** array_to_constant (enum machine_mode mod
*** 4722,4730 ****
      }
    if (mode == DFmode)
      {
!       val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
!       val <<= 32;
!       val |= (arr[4] << 24) | (arr[5] << 16) | (arr[6] << 8) | arr[7];
        return hwint_to_const_double (DFmode, val);
      }
  
--- 4722,4729 ----
      }
    if (mode == DFmode)
      {
!       for (i = 0, val = 0; i < 8; i++)
! 	val = (val << 8) | arr[i];
        return hwint_to_const_double (DFmode, val);
      }
  
-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com



More information about the Gcc-patches mailing list