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