Does anyone have a small example in which __attribute__((__may_alias__))
is necessary and sufficient to generate correct code?
It is a documented feature of gcc that, as documented, exactly fits the
situation I am trying to deal with (in a few places). So far as I
recall, I have never gotten it to work. If I see even one case where it
is necessary and sufficient, I might know what direction to modify my
own code (rather than try things blindly).
Andrew Haley wrote:
John Fine wrote:
Working code:
union { DAT* pp; std::size_t dummy; } no_strict_alias;
no_strict_alias.pp =foo();
reinterpret_cast<DAT_PTR*>(&no_strict_alias.pp)->bar(x);
No, this isn't guaranteed to work. Your data must be *declared* as
union no_strict_alias. Casting to a pointer to union no_strict_alias
isn't the same unless the only way you ever access your data is via
that cast.
I don't understand your objection. I certainly am worried this
construct will stop working in future versions of gcc (though not for
the reason you described). I'm getting pretty confident that it works
reliably for gcc 4.3.2 because it has fixed every case where I have
needed it.
When you said "Your data must be *declared* as union no_strict_alias."
were you talking about my example that you quoted?
In that example, the data obviously is declared with the union.
Or were you talking about the more complicated example I mentioned, but
you didn't quote even my description of that?
In general:
Problem: there is a specific write to an object, such that the optimizer
(after inlining) can see all possible reads from that object and none of
those possible reads are compatible data types with the write. So the
optimizer removes the write. (If the optimizer cannot see all possible
reads, it can't know none are compatible, so it can't remove the write.)
My correction is to do that specific write through one side of a union,
where the other side of that union is never used. That seems to cover
the full problem in gcc4.3.2
In my most complicated case, the creation of the object was distant,
where it was not practical to use the union nor possible for the
optimizer to infer anything about subsequent reads or writes. The
problem write was in a location where (with a lot of inlining) the
optimizer could see the subsequent destruction of the object and all
reads (there was only one) that occur before the destruction. That read
was impractical to change to use a union, so I discovered changing only
the write was enough.
You said "Casting to a pointer to union no_strict_alias isn't the same
unless the only way you ever access your data is via that cast".
That may be true for some future version of gcc. I'm not sure what to
do them. For now, I think the union works.
But if anyone knows of any case where this one sided union method fails,
please tell me.
The key distinguishing factor of this method is that all writes that the
optimizer might otherwise eliminate because of strict aliasing are
through the union.