Re: movmemm pattern

2010-10-26 Thread Joseph S. Myers
On Mon, 25 Oct 2010, Richard Guenther wrote:

 Because the int * could point to unaligned data and there is no access
 that would prove otherwise (memcpy accepts any alignment).

As previously discussed, in ISO C storing a pointer in a particular 
pointer type or converting to / through that type implies it is properly 
aligned for that type.

Actually using that information could be risky - glibc headers assume that 
they can use unaligned accesses on non-strict-alignment targets, for 
example (it's possible some of that is in macros that are only used for 
old GCC versions, but that would need checking) which runs into problems 
if GCC uses the alignment information to decide to use vector 
instructions which really do have strict alignment requirements.

-- 
Joseph S. Myers
jos...@codesourcery.com


Re: movmemm pattern

2010-10-26 Thread Paul Koning

On Oct 25, 2010, at 9:28 PM, Dave Korn wrote:

 On 26/10/2010 01:53, Paul Koning wrote:
 On Oct 25, 2010, at 3:44 PM, Richard Guenther wrote:
 
 On Mon, Oct 25, 2010 at 11:26 AM, Paul Koning paul_kon...@dell.com
 wrote:
 Question on movmemm:
 
 Given
 
 extern int *i, *j; void foo (void) { memcpy (i, j, 10); }
 
 I would expect to see argument 4 (the shared alignment) to be
 sizeof(int) since both argument are pointers to int.  What I get
 instead is 1.  Why is that?
 Because the int * could point to unaligned data and there is no access 
 that would prove otherwise (memcpy accepts any alignment).
 
 Ok, but if I do a load on an int*,
 
  I think that is what Richard meant by an access that would prove otherwise.
 
 I get an aligned load, not an unaligned
 load, so in all those other cases there *is* an assumption that an int*
 contains a properly aligned address.
 
  This is a bit like GCC optimising away a null-pointer check if it knows
 you've already dereferenced the pointer.  Either you've already crashed by
 then, or it doesn't matter.
 
  What happens if you dereference i and j before the memcpy in foo?  Do you
 then get int-sized shared alignment in movmemM?
 
 extern int *i, *j; void foo (void) { *i; *j; memcpy (i, j, 10); }

That doesn't make any difference; I still get alignment 1.

paul




Re: movmemm pattern

2010-10-26 Thread Dave Korn
On 26/10/2010 17:16, Paul Koning wrote:
 On Oct 25, 2010, at 9:28 PM, Dave Korn wrote:
 
 On 26/10/2010 01:53, Paul Koning wrote:
 On Oct 25, 2010, at 3:44 PM, Richard Guenther wrote:

 On Mon, Oct 25, 2010 at 11:26 AM, Paul Koning paul_kon...@dell.com
 wrote:
 Question on movmemm:

 Given

 extern int *i, *j; void foo (void) { memcpy (i, j, 10); }

 I would expect to see argument 4 (the shared alignment) to be
 sizeof(int) since both argument are pointers to int.  What I get
 instead is 1.  Why is that?
 Because the int * could point to unaligned data and there is no access 
 that would prove otherwise (memcpy accepts any alignment).
 Ok, but if I do a load on an int*,
  I think that is what Richard meant by an access that would prove 
 otherwise.

 I get an aligned load, not an unaligned
 load, so in all those other cases there *is* an assumption that an int*
 contains a properly aligned address.
  This is a bit like GCC optimising away a null-pointer check if it knows
 you've already dereferenced the pointer.  Either you've already crashed by
 then, or it doesn't matter.

  What happens if you dereference i and j before the memcpy in foo?  Do you
 then get int-sized shared alignment in movmemM?

 extern int *i, *j; void foo (void) { *i; *j; memcpy (i, j, 10); }
 
 That doesn't make any difference; I still get alignment 1.
 

  That sounds like a missed optimisation opportunity to me, but maybe there's
some reason the compiler can't infer a larger alignment.  (Or maybe the reads
got discarded, you might need volatile to avoid that?)

cheers,
  DaveK



Re: movmemm pattern

2010-10-26 Thread Paul Koning

On Oct 26, 2010, at 1:27 PM, Dave Korn wrote:

 On 26/10/2010 17:16, Paul Koning wrote:
 On Oct 25, 2010, at 9:28 PM, Dave Korn wrote:
 ...
 
 What happens if you dereference i and j before the memcpy in foo?  Do you
 then get int-sized shared alignment in movmemM?
 
 extern int *i, *j; void foo (void) { *i; *j; memcpy (i, j, 10); }
 
 That doesn't make any difference; I still get alignment 1.
 
 
  That sounds like a missed optimisation opportunity to me, but maybe there's
 some reason the compiler can't infer a larger alignment.  (Or maybe the reads
 got discarded, you might need volatile to avoid that?)

No, they weren't discarded, I can see them in the output assembler code.  
Actually, I wrote *i = 20; *j = 10; 

paul




Re: movmemm pattern

2010-10-26 Thread Richard Guenther
On Tue, Oct 26, 2010 at 1:12 PM, Paul Koning paul_kon...@dell.com wrote:

 On Oct 26, 2010, at 1:27 PM, Dave Korn wrote:

 On 26/10/2010 17:16, Paul Koning wrote:
 On Oct 25, 2010, at 9:28 PM, Dave Korn wrote:
 ...

 What happens if you dereference i and j before the memcpy in foo?  Do you
 then get int-sized shared alignment in movmemM?

 extern int *i, *j; void foo (void) { *i; *j; memcpy (i, j, 10); }

 That doesn't make any difference; I still get alignment 1.


  That sounds like a missed optimisation opportunity to me, but maybe there's
 some reason the compiler can't infer a larger alignment.  (Or maybe the reads
 got discarded, you might need volatile to avoid that?)

 No, they weren't discarded, I can see them in the output assembler code.  
 Actually, I wrote *i = 20; *j = 10;

Alignment propagation (bit-CCP) doesn't (yet) exploit information from
such a load (on x86 it couldn't - that architecture can handle unaligned
loads just fine).

Richard.

        paul





Re: movmemm pattern

2010-10-25 Thread Richard Guenther
On Mon, Oct 25, 2010 at 11:26 AM, Paul Koning paul_kon...@dell.com wrote:
 Question on movmemm:

 Given

 extern int *i, *j;
 void foo (void) { memcpy (i, j, 10); }

 I would expect to see argument 4 (the shared alignment) to be sizeof(int) 
 since both argument are pointers to int.  What I get instead is 1.  Why is 
 that?

Because the int * could point to unaligned data and there is no access
that would prove otherwise (memcpy accepts any alignment).

Richard.

 If I have

 extern int i[10], j[10];

 then I do get larger alignment as expected.

        paul




Re: movmemm pattern

2010-10-25 Thread Paul Koning

On Oct 25, 2010, at 3:44 PM, Richard Guenther wrote:

 On Mon, Oct 25, 2010 at 11:26 AM, Paul Koning paul_kon...@dell.com wrote:
 Question on movmemm:
 
 Given
 
 extern int *i, *j;
 void foo (void) { memcpy (i, j, 10); }
 
 I would expect to see argument 4 (the shared alignment) to be sizeof(int) 
 since both argument are pointers to int.  What I get instead is 1.  Why is 
 that?
 
 Because the int * could point to unaligned data and there is no access
 that would prove otherwise (memcpy accepts any alignment).

Ok, but if I do a load on an int*, I get an aligned load, not an unaligned 
load, so in all those other cases there *is* an assumption that an int* 
contains a properly aligned address.  

paul



Re: movmemm pattern

2010-10-25 Thread Dave Korn
On 26/10/2010 01:53, Paul Koning wrote:
 On Oct 25, 2010, at 3:44 PM, Richard Guenther wrote:
 
 On Mon, Oct 25, 2010 at 11:26 AM, Paul Koning paul_kon...@dell.com
 wrote:
 Question on movmemm:
 
 Given
 
 extern int *i, *j; void foo (void) { memcpy (i, j, 10); }
 
 I would expect to see argument 4 (the shared alignment) to be
 sizeof(int) since both argument are pointers to int.  What I get
 instead is 1.  Why is that?
 Because the int * could point to unaligned data and there is no access 
 that would prove otherwise (memcpy accepts any alignment).
 
 Ok, but if I do a load on an int*,

  I think that is what Richard meant by an access that would prove otherwise.

 I get an aligned load, not an unaligned
 load, so in all those other cases there *is* an assumption that an int*
 contains a properly aligned address.

  This is a bit like GCC optimising away a null-pointer check if it knows
you've already dereferenced the pointer.  Either you've already crashed by
then, or it doesn't matter.

  What happens if you dereference i and j before the memcpy in foo?  Do you
then get int-sized shared alignment in movmemM?

extern int *i, *j; void foo (void) { *i; *j; memcpy (i, j, 10); }

cheers,
  DaveK