Bug 70723 - Missed optimization opportunity for lambda converted to fun-ptr
Summary: Missed optimization opportunity for lambda converted to fun-ptr
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 6.0
: P3 enhancement
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: c++-lambda, missed-optimization
: 79189 (view as bug list)
Depends on: 4131
Blocks:
  Show dependency treegraph
 
Reported: 2016-04-19 08:15 UTC by m.cencora
Modified: 2025-04-17 05:18 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work: 8.2.1
Known to fail:
Last reconfirmed: 2016-04-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description m.cencora 2016-04-19 08:15:43 UTC
Hi,

the following code gets properly optimized-out if erasedTypeVTable is initialized with &dtor<T> (case [2]), but it is not optimized if initialized with lambda (case [1]).

#include <type_traits>
#include <new>

namespace
{
struct ErasedTypeVTable
{
   using destructor_t = void (*)(void *obj);

   destructor_t dtor;
};

template <typename T>
void dtor(void *obj)
{
   return static_cast<T *>(obj)->~T();
}

template <typename T>
static const ErasedTypeVTable erasedTypeVTable = {
  /* 1 */  [] (void *obj) { return static_cast<T *>(obj)->~T(); }
  /* 2 */ // &dtor<T>
};
struct myType
{
   int a;
};

void meow()
{
   std::aligned_storage<sizeof(myType)>::type storage;
   auto *ptr = new ((char *)(&storage)) myType{5};

   ptr->a = 10;

   erasedTypeVTable<myType>.dtor(ptr);
}

}

int main()
{
   meow();
}

Compiled with -O3 -std=c++14 flags.

g++ --version:
g++ (Ubuntu 6-20160405-0ubuntu1) 6.0.0 20160405 (experimental) [trunk revision 234749]

FWIW, clang 3.8 optimizes both versions.
Comment 1 Richard Biener 2016-04-19 09:53:18 UTC
The initializer of erasedTypeVTable is not statically available but involves
runtime computation:

;; Function void __static_initialization_and_destruction_0(int, int) (null)
;; enabled by -tree-original


if (__initialize_p == 1)
  {
    if (__priority == 65535)
      {
        <<cleanup_point <<< Unknown tree: expr_stmt
  erasedTypeVTable.dtor = {anonymous}::<lambda(void*)>::operator void (*)(void*) (&TARGET_EXPR <D.5974, {}>) >>>>>;
        <<< Unknown tree: expr_stmt
  <<< Unknown tree: void_cst >>> >>>;
      }
  }


;; Function (static initializers for t.C) (null)
;; enabled by -tree-original


<<cleanup_point <<< Unknown tree: expr_stmt
  __static_initialization_and_destruction_0 (1, 65535) >>>>>;


thats probably because the lambda is not evaluated in a constexpr context.
If I make erasedTypeVTable a constexpr I get

t.C: In instantiation of ‘constexpr const {anonymous}::ErasedTypeVTable {anonymous}::erasedTypeVTable<{anonymous}::myType>’:
t.C:36:7:   required from here
t.C:20:41: error: call to non-constexpr function ‘{anonymous}::<lambda(void*)>::operator void (*)(void*)() const’
       static constexpr ErasedTypeVTable erasedTypeVTable = {
                                         ^~~~~~~~~~~~~~~~

not sure how I would make the lambda a constexpr.


There is no pass in GCC that would try to turn the runtime initialization
into static init again (optimizing the runtime initializers and parsing
them back to static initializers).
Comment 2 m.cencora 2016-04-19 12:19:34 UTC
If that's the case then it should get automatically resolved once C++17 is implemented - C++17 introduces constexpr lambdas.

But it would be great to have this optimization also in C++14 mode.
Comment 3 Marc Glisse 2016-04-19 12:46:15 UTC
(In reply to Richard Biener from comment #1)
> There is no pass in GCC that would try to turn the runtime initialization
> into static init again (optimizing the runtime initializers and parsing
> them back to static initializers).

PR65197 contains links to a few related PRs (no particular patch/idea IIRC, just more examples).
Comment 4 Drea Pinski 2021-12-25 12:20:12 UTC
With -std=c++17 (which is the default now), the code is optimized as expected.
With -std=c++14, the dynamic initializer comes into play; there are a few other bugs dealing with that already too.
Comment 5 Drea Pinski 2025-04-17 05:18:22 UTC
*** Bug 79189 has been marked as a duplicate of this bug. ***