GCC Devirtualization and Inlining only first Interface

Posted

技术标签:

【中文标题】GCC Devirtualization and Inlining only first Interface【英文标题】: 【发布时间】:2021-04-22 12:19:29 【问题描述】:

我发现以下代码有问题:

看起来 GCC 只能去虚拟化第一个接口 I_Udc。 Interface GCC 不能去虚拟化第二个接口 I_Uac。如果我先写 I_Uac,I_Uac 调用会被内联。

这是编译器资源管理器中的代码: https://godbolt.org/z/z6WEoznfW

class I_Uac

    public:
    virtual float GetIUac() = 0;
;

class I_Udc

    public:
    virtual float GetIUdc() = 0;

;

class DataAcq final : public I_Udc, public I_Uac

    float GetIUac() 
    
        return r;
    

    float GetIUdc()
    
        return m;
    

    private:
        float r = 20;
        float m = 20;
;

DataAcq temp;

I_Uac& temp1 = temp;
I_Udc& temp2 = temp;


int main ()
    
    volatile float r = temp1.GetIUac();
    volatile float m = temp2.GetIUdc();

所以问题是如何强制编译器通过接口引用内联两个函数调用?

【问题讨论】:

为什么是循环?你让编译器哭了...... "调用非虚拟 thunk 到 DataAcq::GetIUac()"。似乎去虚拟化了,但没有内联。 @Jarod42 是的,抱歉我的意思是内联 如果你使用 gcc master(在 Godbolt 上称为 trunk),它会内联。 【参考方案1】:

我知道保证去虚拟化的最佳/唯一方法是一开始就不进行虚拟化。对你的类稍作改动就可以使用 CRTP 方法,尽管它有点丑陋,尤其是在引用基类类型时,它是完全可行的。

#include <cstdio>

template <typename DerivedT>
class I_Uac 
public:
    float GetIUac()  
        return static_cast<DerivedT*>(this)->GetIUac();
    ;
;

template <typename DerivedT>
class I_Udc 
    public:
    float GetIUdc()  
        return static_cast<DerivedT*>(this)->GetIUdc();
    ;
;

template <template <typename...> class... BaseTs>
class DataAcq final : public BaseTs<DataAcq<BaseTs...>>... 
public:
    float GetIUac() 
    
        std::puts("GetIUac"); // much nicer in compiler explorer output
        return r;
    

    float GetIUdc()
    
        std::puts("GetIUdc");
        return m;
    

    private:
        float r = 20;
        float m = 20;
;

DataAcq<I_Udc, I_Uac> temp;
I_Udc<decltype(temp)>& temp1 = temp;
I_Uac<decltype(temp)>& temp2 = temp;

int main ()
    
    volatile float r = temp1.GetIUdc();
    volatile float m = temp2.GetIUac();

https://godbolt.org/z/EMExdoczs

【讨论】:

以上是关于GCC Devirtualization and Inlining only first Interface的主要内容,如果未能解决你的问题,请参考以下文章

FDO - Feedback directed optimization with GCC and Perf

mplayer-ww-37356 rebuild by gcc 4.9 and gcc 5.1

简说GNU, GCC and MinGW (Lu Hongling)

如何在 MacOSX 上的 g++ 中使用 gcc 内置 __sync_bool_compare_and_swap?

configure: error: Building GCC requires GMP 4.2+, MPFR 2.4.0+ and MPC 0.8.0+. 解决

GCC 提供的原子操作