GCC Status Report (2004-03-09)
Jakub Jelinek
jakub@redhat.com
Thu Apr 1 14:33:00 GMT 2004
On Thu, Apr 01, 2004 at 03:55:11PM +0200, Eric Botcazou wrote:
> > I tested the patches overnight on {i386,x86_64,ia64,ppc,ppc64,s390,s390x}.
> > There was one regression, particularly 20030408-1.c on IA-64 at -O1 and
> > above. test2(), test3() and test4() abort ().
>
> That's what I suspected: reverting the fix for PR opt/8634 is not safe
> because the problem for this PR doesn't come from the double-store.
Even without reverting it the problem is there.
> The safe solution appears to be the blockage only, but then we would emit it
> even if the aggregate is const.
True, but not at the place we are emitting it ATM.
ATM the blockage is between clearing and storing of the individual non-zero
fields in the initializer, while for 20030408-1.c or 20040401-1.c to work
on IA-64, the blockage needs to be in between the last store to the (partially)
const object and the rest of the function.
The 20040401-1.c problem is that all stores are done with /u and then
__builtin_memcpy is expanded by move_by_pieces. As X is not
RTX_UNCHANGING_P as whole, but only some individual fields, move_by_pieces
is called with:
to: (mem/s:BLK (reg/f:DI 356) [3 buffer+0 S10 A128])
from: (mem/s:BLK (reg/f:DI 335 virtual-stack-vars) [2 X+0 S10 A128])
len: 10, align: 64, endp: 0.
Note no RTX_UNCHANGING_P on from.
You can see this on both stock gcc-3_4-branch and with your patch.
Clearly we don't guarantee that some memory location which is written
by /u is never actually read with non-/u MEM. At which point all /u stores
are potential bugs.
extern void abort (void);
struct foo {
const char a, b;
char c;
};
int main ()
{
struct foo X = { a : 'A', b : 'B', c : 'C' };
char buffer[3];
__builtin_memcpy (buffer, &X, 3);
if (buffer[0] != 'A' || buffer[1] != 'B' || buffer[2] != 'C')
abort ();
return 0;
}
generates:
X.a = 'A' // /u store
X.b = 'B' // /u store
X.c = 'C'
tmp = *(short *)&X // non-/u read
*(short *)buffer = tmp
tmp = *(short *)&X.c // non-/u read
buffer[2] = tmp
at rtl level. Is there anything that ensures non-/u read comes after /u
store?
Jakub
More information about the Gcc-patches
mailing list