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__);
}
---