c – GCC无法优化涉及成员函数指针的委托lambda函数

我使用GCC4.9.2和clang3.6.0编译了以下c 14代码.

我用-O3标志.

#include <utility>

struct S
{
    int a;
    int A () const { return a; }
};

template <class F, class ... Args>
int Func (F && f, Args && ... args)
{
    return f(std::forward<Args>(args) ...);
}

using PtrA = int (S::*)() const;

int F (S const & s, PtrA ptr) { return (s.*ptr)() * 5; }

int p (S const & s) { return s.A() * 5; }

int P1 (S const & s) { return Func(&F, s , &S::A); }
int P2 (S const & s) { return Func([](S const & s, auto f) { return (s.*f)() * 5; }, s, &S::A); }
int P3 (S const & s) { return ([](S const & s, auto f) { return (s.*f)() * 5; })(s, &S::A); }
int P4 (S const & s) { return Func([](S const & s) { return s.A() * 5; }, s); }

Func通过向函数对象传递参数来调用委托的函数对象.

P1,P2,P3和P4与p的工作方式不同.
P1委托F,它是涉及成员函数指针(PtrA)的函数.
P2委托lambda函数,它的作用与F相同.
P3直接调用lambda函数.
P4在不使用成员函数指针的情况下调用另一个lambda函数.

与GCC对此代码的objdump是

// p, P1, P3, P4
mov    (%rdi),%eax
lea    (%rax,%rax,4),%eax
retq   


// P2
sub    $0x8,%rsp
callq  49 <_Z2P2RK1S+0x9> // this address points to "add" in the next line.
add    $0x8,%rsp
lea    (%rax,%rax,4),%eax
retq

对于p,P1,P3,P4,GCC输出良好的代码.
奇怪的是,对于P2,GCC显然输出了错误的代码.

另一方面,clang输出

// p, P1, P2, P3, P4
imul   $0x5,(%rdi),%eax
retq

虽然这不是很好,但至少所有功能的输出都是相同的.

我的问题是,是否有正确的理由,GCC无法优化这一点,即p和P1-P4之间存在C程序的差异.

如果第一个问题的答案为否,那么这是GCC优化器中的已知错误吗?

这个问题的动机是a Japanese article

最佳答案 似乎GCC 5及其后续实际上能够进行优化,参见
gcc.godbolt.org

P2(S const&):
    mov eax, DWORD PTR [rdi]
    lea eax, [rax+rax*4]
    ret
点赞