[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