> It's pretty hard to say anything conclusive about an incomplete example, Unfortunately I failed to create a small example illustrating this optimization. > but the use of reinterpret_cast and -fstrict-aliasing obviously suggests > an aliasing violation. > > Perhaps you could explain why this is not an aliasing violation? > I am pretty sure that this cast violate strict aliasing rules because we try to treat value of type GlobalObject* as a value of type byte*. And then we treat a value of type byte* as a value of type Object**. Neither of this types are compatible as far as I understand. 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. > (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. I would like to understand what exactly compiler proved in this case. -- Vyacheslav Egorov On Fri, Oct 1, 2010 at 5:45 PM, Ian Lance Taylor <iant@xxxxxxxxxx> wrote: > Vyacheslav Egorov <vegorov@xxxxxxxxxxxx> writes: > >> I am experiencing the following problem when compiling V8[1] with gcc >> 4.5.1 with -O1 -fstrict-aliasing enabled: for some reason GCC removes >> one of the stores to memory. >> >> Store removal happens in the method Genesis::HookUpGlobalProxy [2] >> >> void Genesis::HookUpGlobalProxy(Handle<GlobalObject> inner_global, >> Handle<JSGlobalProxy> global_proxy) { >> // ... >> inner_global->set_global_context(*global_context()); >> // ... >> } >> >> GCC inlines method GlobalObject::set_global_context, which is defined >> through macroses ACCESSORS[3] and WRITE_FIELD[4] >> >> void GlobalObject::set_global_context(Context* value, WriteBarrierMode mode) { >> WRITE_FIELD(this, offset, value); >> CONDITIONAL_WRITE_BARRIER(this, offset, mode); >> } >> >> #define FIELD_ADDR(p, offset) \ >> (reinterpret_cast<byte*>(p) + offset - kHeapObjectTag) >> >> #define WRITE_FIELD(p, offset, value) \ >> (*reinterpret_cast<Object**>(FIELD_ADDR(p, offset)) = value) >> >> and removes memory store which should be generated from WRITE_FIELD. >> >> I am trying to figure out why GCC decides that this memory store can >> be safely removed. > > It's pretty hard to say anything conclusive about an incomplete example, > but the use of reinterpret_cast and -fstrict-aliasing obviously suggests > an aliasing violation. > > Perhaps you could explain why this is not an aliasing violation? > > (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.) > > Ian >