[Bug ipa/80899] [6/7/8 Regression] Devirtualization causes incorrect code generation with placement new in some cases
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80899 Jakub Jelinek changed: What|Removed |Added CC||jakub at gcc dot gnu.org --- Comment #7 from Jakub Jelinek --- Having placement new represented in the IL is something I've suggested several times (e.g. to be able to be more aggressive on TBAA in loops which don't contain any placement new), but Richard didn't like that.
[Bug ipa/80899] [6/7/8 Regression] Devirtualization causes incorrect code generation with placement new in some cases
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80899 --- Comment #6 from Jan Hubicka --- The problem here is that after gimplification we make no distinction between original pointer and pointer returned by placement new. If one can placement new different type to object into arbitrary field of structure, probably one can do it also for automatic and static variables. So we would need to anticipate dynamic type changes absolutely everywhere. This would more or less disable nonspeculative devirtualization completely because in most cases there is some function call between constructor and use of values which prevents us from proving that the value did not change. What we could do is to keep new operations represented in gimple form until later stages of compilation (remove them soonish after IPA is done). So having osmething like new_ptr = __builtin_placement_new (oldptr) which would also hold type of the allocated value (not sure how to do that without having declaration of biultin_placement_new for every type but even that would work well for me). This would be useful information because devirt machinery then could expect that the dynamic type did not change for all polymorphic types and subtypes. Would that make sense to you? Probably something for next stage1 though.
[Bug ipa/80899] [6/7/8 Regression] Devirtualization causes incorrect code generation with placement new in some cases
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80899 Jason Merrill changed: What|Removed |Added CC||jason at gcc dot gnu.org --- Comment #5 from Jason Merrill --- (In reply to Jan Hubicka from comment #4) > Is this valid C++? bar.mem is non-POD and is already constructed and it > seems fishy to placement new it to something different. It's very fishy; the code should use aligned_storage rather a different non-trivial type. My old proposed resolution for wg21.link/cwg1116 would have clarified that this is undefined, and might still happen to resolve wg21.link/cwg1027 , but it hasn't been accepted yet. On the other hand, it is careful to use the pointer returned from placement new rather than a pointer derived from mem, and it seems like we ought to use the information from placement new to guide devirtualization. So...sketchy code in a volatile area of semantics, but it seems like we could get it right without breaking important optimizations.
[Bug ipa/80899] [6/7/8 Regression] Devirtualization causes incorrect code generation with placement new in some cases
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80899 Jan Hubicka changed: What|Removed |Added CC||jason at redhat dot com --- Comment #4 from Jan Hubicka --- Is this valid C++? bar.mem is non-POD and is already constructed and it seems fishy to placement new it to something different. Devirtualization machinery does not consider that substructure of polymorphic type may be replaced by arbitrary other type via placement new. The testcase works on mainline. On GCC 7 we get: MEM[(struct foo *)&b].D.6234._vptr.base = &MEM[(void *)&_ZTV3fooIxE + 16B]; MEM[(struct foo *)&b].D.6370._vptr.base = &MEM[(void *)&_ZTV3fooIiE + 16B]; b.val = &b.mem; _8 = MEM[(struct base * *)&b + 8B]; _10 = _8->_vptr.base; _11 = *_10; OBJ_TYPE_REF(_11;(struct base)_8->0) (_8); in a.C.036t.ealias and incorrect devirtualization happens in fre1 just after: int main() () { struct bar b; [100.00%]: MEM[(struct foo *)&b].D.6234._vptr.base = &MEM[(void *)&_ZTV3fooIxE + 16B]; MEM[(struct foo *)&b].D.6370._vptr.base = &MEM[(void *)&_ZTV3fooIiE + 16B]; b.val = &b.mem; foo::f (&b.mem); } because of: Targets of polymorphic call of type 0:struct base token 0 Outer type:struct foo offset 0 This is a complete list. void foo::f() [with T = long long int]/73 a.C:15:28: note: converting indirect call to function void foo::f() [with T = long long int] On mainline we get in the same context: Type inheritance inconsistent devirtualization of OBJ_TYPE_REF(f;&b.mem->0) (&b.mem); to OBJ_TYPE_REF(f;&b.mem->0) Removed EH side-effects. So the devirt machinery is says wrong answer, but FRE got smarter and determines the correct destination with priority.
[Bug ipa/80899] [6/7/8 Regression] Devirtualization causes incorrect code generation with placement new in some cases
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=80899 Jan Hubicka changed: What|Removed |Added Status|SUSPENDED |ASSIGNED --- Comment #3 from Jan Hubicka --- Looks like I set it to suspended instead of assigned and ignored ever since :(