https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84411
Bug ID: 84411 Summary: Missed optimization: static guard variable generated for empty virtual destructor Product: gcc Version: 8.0.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: arthur.j.odwyer at gmail dot com Target Milestone: --- Consider the following program: struct Base { constexpr Base() = default; virtual int foo(); // virtual ~Base() = default; }; struct Derived : public Base { constexpr Derived() = default; virtual int foo() override; }; Base& get_base() { static Derived d; return d; } This is a simplified version of the current idioms around `std::error_category` and `std::pmr::memory_resource`, except that for now I have commented-out the virtual destructor. Notice that because `Derived d` is trivially destructible, no atomic guard variable is generated to register its destructor with __cxa_atexit. Now uncomment the defaulted virtual destructor of `Base`. The semantics of `Derived d` have not changed: we are still expecting to call ~Derived by non-virtual dispatch, and ~Derived is still known statically to be a no-op. But now suddenly GCC decides to generate an atomic guard variable and a call to `__cxa_atexit`! I think GCC could do better here, and if it did, it would eliminate a lot of atomic instructions in the critical path for things like `std::error_code{}` and `std::pmr::new_delete_resource()`.