[Bug c++/109945] New: Escape analysis hates copy elision: different result with -O1 vs -O2
arthur.j.odwyer at gmail dot com
gcc-bugzilla@gcc.gnu.org
Tue May 23 14:00:03 GMT 2023
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109945
Bug ID: 109945
Summary: Escape analysis hates copy elision: different result
with -O1 vs -O2
Product: gcc
Version: unknown
Status: UNCONFIRMED
Keywords: wrong-code
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: arthur.j.odwyer at gmail dot com
Target Milestone: ---
Background:
https://quuxplusone.github.io/blog/2021/03/07/copy-elision-borks-escape-analysis/
The background paradox here is, "When class Widget is subject to copy elision,
then any unseen function can return a prvalue Widget whose address has already
escaped!" Aaron Puchert and I were discussing this, with examples. (He thinks
the resolution of the paradox is "you *must* treat a lot more things as
escaped"; I think an acceptable resolution would be "you may treat copy-elision
itself as a magic that invalidates pointers and references even though the
object is still in the same place.")
But then I came up with an example that didn't rely on copy elision at all. We
both agree this code is perfectly well-defined — yet GCC miscompiles it at -O1!
// https://godbolt.org/z/bTnv68nhG
struct Widget {
Widget();
int i = 1;
int a[4];
};
Widget *global = nullptr;
Widget::Widget() { global = this; }
Widget make() { return Widget(); }
void g() { global->i = 42; }
int main() {
Widget w = make();
int i = w.i;
g();
return (i == w.i);
// Does this need to be reloaded and
// compared? or is it obviously true?
}
gcc -O0 and gcc -O2 both correctly return 0 from main.
gcc -O1 wrongly returns 1 from main.
*At least* since C++17, I think the -O1 result is flat-out wrong codegen. We
have `global == &w`, and so the call to `g()` can definitely modify `w.i`.
(Clang always treats Widgets' addresses as escaped, no matter what Widget looks
like. MSVC's escape analysis is more complicated and I have not yet been able
to trick it into wrong codegen.)
More information about the Gcc-bugs
mailing list