https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83169
Bug ID: 83169 Summary: Optimizer doesn't correctly handle NRVO if -fno-inline-small-functions or function uninlinable Product: gcc Version: 8.0 Status: UNCONFIRMED Severity: normal Priority: P3 Component: middle-end Assignee: unassigned at gcc dot gnu.org Reporter: ibuclaw at gdcproject dot org Target Milestone: --- Minimal test. --- #include <assert.h> struct Stest { int foo[5]; // Triggers NRVO return on x86_64. }; void* ptest; Stest footest() { Stest data = {}; // <retval> = {}; ptest = &data; // ptest = &<retval>; return data; // return <retval> } int main() { const Stest data = footest(); // data = footest (); // [return slot optimization] assert(ptest == &data); return 0; } --- And permutation of compile-time switches, "PASSES" indicates that runtime exits without assertion failure. --- * g++ -O0 (PASSES) * g++ -O1 (FAILS) * g++ -O1 -finline-small-functions (PASSES) * g++ -O2 (PASSES) * g++ -O2 -fno-inline-small-functions (FAILS) * g++ -O2 -fPIC (FAILS) Looking at the optimized tree dump, for -O2 the compiler determines (I think correctly) that ptest and data share the same address, and so removes the assert. --- main () { const struct Stest data; <bb 2> [local count: 10000]: ptest = &data; data ={v} {CLOBBER}; return 0; } --- However for -O2 -fPIC: --- main () { static const char __PRETTY_FUNCTION__[11] = "int main()"; const struct Stest data; <bb 2> [local count: 10000]: data = footest (); [return slot optimization] __assert_fail ("ptest == &data", "test.cc", 20, &__PRETTY_FUNCTION__); } --- And for -O1: --- main () { static const char __PRETTY_FUNCTION__[11] = "int main()"; const struct Stest data; <bb 2> [local count: 10000]: data = {}; ptest = &data; __assert_fail ("ptest == &data", "test.cc", 20, &__PRETTY_FUNCTION__); } ---