https://gcc.gnu.org/bugzilla/show_bug.cgi?id=70526
--- Comment #20 from Richard Biener <rguenth at gcc dot gnu.org> --- (In reply to Jan de Mooij from comment #17) > Thank you for looking into this again. > > I don't understand comment 16 though: > > > _BUT_ here we access D.3125 both as Register (the store) > > and as its declared type TypedOrValueRegister (the load). > > So D.3125 is a TypedOrValueRegister right? TypedOrValueRegister is defined as > > class TypedOrValueRegister > { > MIRType type_; > AlignedStorage2<Register> typed; > ... > > So IIUC it's wrong to store to |typed| in the constructor, by doing this: > > *typed.addr() = reg; > > Why is that? Any suggestions on how to fix this on our end? No, it's valid to do that. What is not valid is to copy TypedOrValueRegister with a plain assignment (well, or the C++ FE is implementing that wrongly). In C language terms the analogy is when you write struct X { int type; char c[16]; }; float foo () { struct X x; x.type = 1; *(float *)x.c = 1.0; struct X y = x; return *(float *)y.c; } then the aggregate copy y = x is not using an effective type that aliases with the float store/load and thus it can be re-ordered with both the store and the load. I'd have to dive deep into the C++ standard to find the equivalent wording about how TBAA applies to class types (and the C++ notion of the type in effect when writing an aggregate assignment or a copy via a return by value or passing a parameter by value). It might be that the C++ standard writes the copying is done member-wise with accesses that have the member type as effective type for TBAA which would mean the C++ FE has to implement aggregate assignment differently. Note this applies to PODs mostly as non-PODs would invoke the copy constructor (where then the question is on the constraints of the default implementation done by GCC again). I'm going to backport the original fix and I think the new issue warrants a separate bug as it only affects GCC 6.