public inbox for gcc-help@gcc.gnu.org
 help / color / mirror / Atom feed
* Any way to locally apply no-strict-alias?
@ 2008-10-09 12:40 John Fine
  2008-10-09 12:48 ` Andrew Haley
  0 siblings, 1 reply; 9+ messages in thread
From: John Fine @ 2008-10-09 12:40 UTC (permalink / raw)
  To: gcc-help

I have a very large module, which contains a few places where a pointer 
is cast based on a templated data type.

Typically a pointer is created using a templated type, then copied as a 
void*, then used as the templated type.  In one of those places, the 
optimizer removes the copy step, which is correct behavior for the 
optimizer under strict aliasing, but of course incorrect for the program.

Because of the way the templating fits in, it would be very hard to 
either make a correct union for the pointer, or do the copy using the 
correct type.

Creating, copying and using the pointer are coded in different sub 
projects in code templated on different things, but all of which might 
be brought together by inlining (so the optimizer can do this damage).

If I compile the whole module with no-strict-alias it runs correctly, 
but the generated code is 3% bigger and I think runs significantly 
slower (I can only approximate how fast the broken code runs).

It would be great to have some attribute one could define on a pointer 
to say that pointer violates strict aliasing.  The pointers described 
above are actually used through another layer of pointer, which is 
declared as a void**.  In concept the code looks like:

Datatype* a;
void** x = malloc ...
(Datatype*&)(x[n]) = a;
void** y = malloc ...
y[n] = x[n];
Datatype* b;
b = (Datatype*&)(y[n]);

So if there were a way to put an attribute on x and y to say they 
violate strict aliasing, that would be a perfect solution.

Alternately, if violation of strict aliasing could be applied to inline 
function definitions, that might be reasonable (hopefully just applying 
to the operations inside that function, not to the whole function into 
which it gets inlined).

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Any way to locally apply no-strict-alias?
  2008-10-09 12:40 Any way to locally apply no-strict-alias? John Fine
@ 2008-10-09 12:48 ` Andrew Haley
  2008-10-09 14:09   ` John Fine
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Haley @ 2008-10-09 12:48 UTC (permalink / raw)
  To: John Fine; +Cc: gcc-help

John Fine wrote:
> I have a very large module, which contains a few places where a pointer
> is cast based on a templated data type.
> 
> Typically a pointer is created using a templated type, then copied as a
> void*, then used as the templated type.  In one of those places, the
> optimizer removes the copy step, which is correct behavior for the
> optimizer under strict aliasing, but of course incorrect for the program.

I don't really get this.

You are allowed to take a pointer, copy it as a void *, and copy it
back to the same type and dereference it.  If the compiler removes
the copy step, then the compiler is broken.  If your code accesses
the object via an incompatible type, then your code is broken.

Confused,
Andrew.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Any way to locally apply no-strict-alias?
  2008-10-09 12:48 ` Andrew Haley
@ 2008-10-09 14:09   ` John Fine
  2008-10-09 16:58     ` Andrew Haley
  0 siblings, 1 reply; 9+ messages in thread
From: John Fine @ 2008-10-09 14:09 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc-help

Andrew Haley wrote:
> You are allowed to take a pointer, copy it as a void *, and copy it
> back to the same type and dereference it.  If the compiler removes
> the copy step, then the compiler is broken.  If your code accesses
> the object via an incompatible type, then your code is broken.
>
>   

I think the difference between that and what I'm doing is the extra 
level of indirection.

I write a Datatype* indirectly through a Datatype**.  Then I read a 
void* indirectly through a void** that happens to be the same pointer as 
that Datatype**.
Next I do the reverse (write through void** to read through Datatype**).

You're saying I can copy a Datatype* to a void* then back to a Datatype* 
and use it.  That wouldn't be a violation of strict aliasing, because it 
never dereferences two different type pointers to the same address.

I know my code is "broken".  I didn't write it and I have no practical 
way to rewrite it.  I'm looking for a local work around to the problem.

I've looked at the generated assembler code and the copy step is 
optimized out when compiled without -fno-strict-alias and isn't 
optimized out when compiled with -fno-strict-alias.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Any way to locally apply no-strict-alias?
  2008-10-09 14:09   ` John Fine
@ 2008-10-09 16:58     ` Andrew Haley
  2008-10-09 17:30       ` John Fine
  0 siblings, 1 reply; 9+ messages in thread
From: Andrew Haley @ 2008-10-09 16:58 UTC (permalink / raw)
  To: John Fine; +Cc: gcc-help

John Fine wrote:
> Andrew Haley wrote:
>> You are allowed to take a pointer, copy it as a void *, and copy it
>> back to the same type and dereference it.  If the compiler removes
>> the copy step, then the compiler is broken.  If your code accesses
>> the object via an incompatible type, then your code is broken.
> 
> I think the difference between that and what I'm doing is the extra
> level of indirection.
> 
> I write a Datatype* indirectly through a Datatype**.  Then I read a
> void* indirectly through a void** that happens to be the same pointer as
> that Datatype**.
> Next I do the reverse (write through void** to read through Datatype**).

By my reckoning this should still work.  Writing through the void**
will be fine.  Casting &(void*) to Datatype** is the bit that won't
work.  But you don't need to do that...

> You're saying I can copy a Datatype* to a void* then back to a Datatype*
> and use it.  That wouldn't be a violation of strict aliasing, because it
> never dereferences two different type pointers to the same address.

OK, I now understand.

> I know my code is "broken".  I didn't write it and I have no practical
> way to rewrite it.  I'm looking for a local work around to the problem.
> 
> I've looked at the generated assembler code and the copy step is
> optimized out when compiled without -fno-strict-alias and isn't
> optimized out when compiled with -fno-strict-alias.

OK, but you still haven't said what "the copy step" is.

We obviously don't want to start having a no-strict-alias attribute for
pointers.  I think it's pointless because it would only apply to new
code, and the whole point of no-strict-alias is to make old code work.

Andrew.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Any way to locally apply no-strict-alias?
  2008-10-09 16:58     ` Andrew Haley
@ 2008-10-09 17:30       ` John Fine
  2008-10-09 17:39         ` Andrew Haley
  0 siblings, 1 reply; 9+ messages in thread
From: John Fine @ 2008-10-09 17:30 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc-help

Andrew Haley wrote:
>
> We obviously don't want to start having a no-strict-alias attribute for
> pointers.  I think it's pointless because it would only apply to new
> code, and the whole point of no-strict-alias is to make old code work.
>
>
>   
I sure disagree with that.

How about making old code repairable.

It would be a monster task to rewrite old code to not need the problem 
casts.  It is a much more reasonable task to find all the pointers that 
are used with problem casts.  If you could just tack some attribute onto 
the declaration of each such pointer, you could take a giant application 
you don't even understand and repair it for this issue in under a day.

I think I've tricked the compiler into generating working code.  I don't 
think my correction is correct (I think I just confused the optimizer).  
But I don't know enough about the exact rules of aliasing to be sure.

I made a union of void* and int*.  And my basic pointer now points to 
that union instead of being void**.

Then I never use the int* member of the union.  What used to directly 
use the void** now uses the void* member of the union.  What used to use 
the Datatye** cast of the void** now uses a Datatype** cast of the 
address of the void* member of the union.  That still means I'm casting 
a void** to a Datatype**, but it seems to have changed the compiler's 
understanding of it.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Any way to locally apply no-strict-alias?
  2008-10-09 17:30       ` John Fine
@ 2008-10-09 17:39         ` Andrew Haley
  2008-10-09 18:13           ` John Fine
  2008-10-09 19:34           ` John Breitenbach
  0 siblings, 2 replies; 9+ messages in thread
From: Andrew Haley @ 2008-10-09 17:39 UTC (permalink / raw)
  To: John Fine; +Cc: gcc-help

John Fine wrote:
> Andrew Haley wrote:
>>
>> We obviously don't want to start having a no-strict-alias attribute for
>> pointers.  I think it's pointless because it would only apply to new
>> code, and the whole point of no-strict-alias is to make old code work.
> 
> I sure disagree with that.
> 
> How about making old code repairable.
> 
> It would be a monster task to rewrite old code to not need the problem
> casts.

The hard part IME is finding the bad casts.  Once you've done that it's
not so awfully hard to convert pointer casts to use unions instead.
Adding a no-strict-alias attribute solves the easy part, leaving the
hard part.

> It is a much more reasonable task to find all the pointers that
> are used with problem casts.  If you could just tack some attribute onto
> the declaration of each such pointer, you could take a giant application
> you don't even understand and repair it for this issue in under a day.
> 
> I think I've tricked the compiler into generating working code.  I don't
> think my correction is correct (I think I just confused the optimizer). 
> But I don't know enough about the exact rules of aliasing to be sure.
> 
> I made a union of void* and int*.  And my basic pointer now points to
> that union instead of being void**.

> Then I never use the int* member of the union.  What used to directly
> use the void** now uses the void* member of the union.  What used to use
> the Datatye** cast of the void** now uses a Datatype** cast of the
> address of the void* member of the union.  That still means I'm casting
> a void** to a Datatype**, but it seems to have changed the compiler's
> understanding of it.

Why not make it a union of Datatype* and void*  ?
Then you wouldn't need to cast at all.

Andrew.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Any way to locally apply no-strict-alias?
  2008-10-09 17:39         ` Andrew Haley
@ 2008-10-09 18:13           ` John Fine
  2008-10-09 19:34           ` John Breitenbach
  1 sibling, 0 replies; 9+ messages in thread
From: John Fine @ 2008-10-09 18:13 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc-help

Andrew Haley wrote:
> Why not make it a union of Datatype* and void*  ?
> Then you wouldn't need to cast at all.
>
>   
Datatype is a template argument that is known at the time the casts are 
instantiated but can't be known nor even used as a template argument at 
the time the pointer (that was void** and now is my_union*) is 
instantiated, nor at the point that the copying is done.

1) Allocate (using malloc for some stupid reason) a my_union[] at a 
point where Datatype can't be known.
2) Fill that array with nulls
3) In code where Datatype is a template argument, pass various 
Datatype*& from within that array to several routines which overwrite 
some of those nulls.
4) Steps 1 and 2 for a different my_union[] (again can't know Datatype)
5) In other code that can't know Datatype, copy some void*'s from the 
first array to the second.  The optimizer discarded this code before my 
change.
6) In code where Datatype is a template argument, pass Datatype*const& 
from within the second array to several routines which use those 
Datatype*'s.

Under strict aliasing, the void*'s copied in step 5 are never used, and 
everything that touches the second array across its entire lifetime is 
inlined into one place, so the compiler knows those void*'s are never used.
The Datatype*'s that exist at the same address as those void*'s are used.

Datatype is never int.  The union tells the compiler that an int* exists 
at the same address as the void*.  Even though the compiler inlines 
enough code to see the int* is never used, somehow this defeats the 
optimization.


^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Any way to locally apply no-strict-alias?
  2008-10-09 17:39         ` Andrew Haley
  2008-10-09 18:13           ` John Fine
@ 2008-10-09 19:34           ` John Breitenbach
  2008-10-09 20:06             ` John Fine
  1 sibling, 1 reply; 9+ messages in thread
From: John Breitenbach @ 2008-10-09 19:34 UTC (permalink / raw)
  To: Andrew Haley; +Cc: gcc-help

Have you considered __attribute__ ((__may_alias__)) on the variable 
declaration?  I've used this on a structure
declaration which, coincidently, may alias another structure ... solved 
my problem when upgrading from gcc 2.95 to 3.4.

^ permalink raw reply	[flat|nested] 9+ messages in thread

* Re: Any way to locally apply no-strict-alias?
  2008-10-09 19:34           ` John Breitenbach
@ 2008-10-09 20:06             ` John Fine
  0 siblings, 0 replies; 9+ messages in thread
From: John Fine @ 2008-10-09 20:06 UTC (permalink / raw)
  To: John Breitenbach; +Cc: Andrew Haley, gcc-help

John Breitenbach wrote:
> Have you considered __attribute__ ((__may_alias__)) on the variable 
> declaration?  I've used this on a structure
> declaration which, coincidently, may alias another structure ... 
> solved my problem when upgrading from gcc 2.95 to 3.4.
>
Thanks.  I looked through all the variable attributes and function 
attributes (both C and C++)  in the 4.1.2 documentation.  I didn't 
notice (until the google search of __may_alias__ I just did) that there 
are also type attributes (section 5.32 of the documentation).

I'll need to experiment a bit to see if that makes a cleaner solution to 
the problem and to see what the correct syntax would be.

If I understand the documentation, I could

typedef void* __attribute__((__may_alias__)) alias_ptr;


Then, after alias_ptr* x = malloc ..., I can mix accesses to 
(Datatype*&)(x[n]) and x[n] without breaking aliasing rules?

after void** x = malloc ..., I can't mix accesses to (Datatype*&)(x[n]) 
and x[n], because the thing pointed to by a void** (unlike the thing 
pointed to by a void*) is subject to the aliasing rules.

^ permalink raw reply	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2008-10-09 20:06 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-10-09 12:40 Any way to locally apply no-strict-alias? John Fine
2008-10-09 12:48 ` Andrew Haley
2008-10-09 14:09   ` John Fine
2008-10-09 16:58     ` Andrew Haley
2008-10-09 17:30       ` John Fine
2008-10-09 17:39         ` Andrew Haley
2008-10-09 18:13           ` John Fine
2008-10-09 19:34           ` John Breitenbach
2008-10-09 20:06             ` John Fine

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).