Re: gcc 4.5.1 -fstrict-aliasing and store removal

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> This example is also incomplete since result is not used.  I'll assume
> that it is returned from mk().

Correct. Sorry for the confusion.

> Therefore, the compiler knows that the assignments to p[0] and p[1] can not modify
> result.

I understand this part. I would understand if say compiler reordered
reads from result variable and stores to p[0] and p[1].
But I do not understand what allows compiler to consider these stores
as dead --- they have to modify _something_ in the memory to which p
points. In general compiler can't say anything about that location
especially if it sees only body of
init [lets consider non-inlined case to reduce amount of information
available to compiler]. Maybe init was called like:

uint32_t x[2];
init(reinterpret_cast<uint64_t*>(x), hi, lo);
use(x[0]);
use(x[1]);

Is it also a violation of strict aliasing rules? We load and store
values through uint32_t* pointers. But uint32_t* pointers are passed
around hidden as a pointer of incompatible type uint64_t*.

That is what happens in V8 all the time: we read and store values
through pointers of type Object** (each object in heap is essentially
an array of pointer to other objects), but we "hide" this Object**
pointers inside pointers of type Foo*, where Foo is some type with
nicely typed getters/setters which essentially cast this pointer to
Object** pointer.

--
Vyacheslav Egorov


On Fri, Oct 1, 2010 at 8:38 PM, Ian Lance Taylor <iant@xxxxxxxxxx> wrote:
> Vyacheslav Egorov <vegorov@xxxxxxxxxxxx> writes:
>
>> The question is why this conversions between incompatible pointer
>> types allows GCC to remove memory stores to some random memory
>> location it does not know anything about?
>>
>> In some article about strict aliasing I've read that compiler can
>> remove the following stores:
>>
>> inline void init (uint64_t* value, uint32_t hi, uint32_t lo) {
>>   uint32_t* p = reinterpret_cast<uint32_t>(value);
>>   p[0] = lo;  // can be optimized out when inlined to mk
>>   p[1] = hi;  // can be optimized out when inlined to mk
>> }
>>
>> uint64_t mk(uint32_t hi, uint32_t lo) {
>>   uint64_t result;
>>   init(&result, hi, lo);
>> }
>>
>> But I cannot clearly see why compiler can do that nor I can understand
>> why it would be beneficial to do so. And the main mystery for me here
>> is how to prevent compiler from doing such optimizations.
>
> This example is also incomplete since result is not used.  I'll assume
> that it is returned from mk().
>
> The C/C++ language standards say that a store via a pointer whose type
> is uint32_t* can not modify a value whose type is uint64_t.  Therefore,
> the compiler knows that the assignments to p[0] and p[1] can not modify
> result.  So it can just leave result unchanged.  Then it can see that
> the assignments to p[0] and p[1] are not used, and so they can be
> discarded.  Finally, result is uninitialized, so the compiler does not
> need to return any particular value.  The effect is that compiler can
> reduce mk() to a function which does absolutely nothing, and any caller
> will simply get whatever value happens to be stored in the return
> register when mk() is called.
>
>
>>> (When your program has an aliasing violation, gcc does unpredictable
>>> things.  There is little benefit to speculating about precisely why it
>>> did what it did.)
>>
>> Any optimization done by a compiler is always predictable [unless it
>> is bug in optimizer], because compiler has to prove that his
>> transformation is correct.
>
> You are right, of course.  When I say unpredictable I mean that the
> generated code will not follow any simple rules with respect to the
> invalid source code.
>
>> I would like to understand what exactly compiler proved in this case.
>
> Hope this helps.
>
> Ian
>



[Index of Archives]     [Linux C Programming]     [Linux Kernel]     [eCos]     [Fedora Development]     [Fedora Announce]     [Autoconf]     [The DWARVES Debugging Tools]     [Yosemite Campsites]     [Yosemite News]     [Linux GCC]

  Powered by Linux