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

}
---

Reply via email to