https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111496

            Bug ID: 111496
           Summary: Optimizer issue when reinitializing an object of a
                    standard-layout class with a trivial copy constructor
                    and a trivial destructor
           Product: gcc
           Version: 13.2.1
               URL: https://godbolt.org/z/hf8qf6qan
            Status: UNCONFIRMED
          Keywords: ABI, missed-optimization
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: rogerio.souza at gmail dot com
  Target Milestone: ---
              Host: x86_64

Created attachment 55948
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=55948&action=edit
Teste case to reproduce the optimization issue

In some cases, reinitializing an object of a standard-layout class with a
trivial copy constructor and a trivial destructor needs something more complex
than *this={} if this line is in a hot cycle. For some reason, gcc creates an
new object on stack which is copied to the target location. 

Well, it's literally what *this={} should do, but I expected the compiler to
elide the copying.
Calling the destructor explicitly and reconstructing the object with a
placement new gives the desired code without the extra copying, but looks kinda
ugly.

The issue seems to be present in gcc9, gcc12, and gcc13, but different contents
the class trigger the generation of inferior code. Clang seems to produce the
shortest and the fastest code for this kind of operation.

Using -Os makes the compiler generate the improved binary code. Also replacing
"[[gnu::used]] void reset() { *this = {}; }" per "[[gnu::used]] void reset() {
A2 a2; *this = a2; }" improved the binary code generated.

The reproducible example is available at:

https://godbolt.org/z/hf8qf6qan

Source code:

#include <memory>

struct A {
    [[gnu::used]] void reset() { *this = A(); }
private:
    int b[4] = {};
    char* p = {};
    int x = {};
};

struct A2 {
    [[gnu::used]] void reset() { *this = {}; }
private:
    int b[4] = {};
    char* p = {};
    int x = {};
};

struct A3 {
    [[gnu::used]] void reset() {
        this->~A3();
        new(this) A3;
    }
private:
    int b[4] = {};
    char* p = {};
    int x = {};
};

---------------------

Regards,
Rogerio
  • [Bug c++/111496] New: Optimize... rogerio.souza at gmail dot com via Gcc-bugs

Reply via email to