在GCC中重载与矢量类型__m128,__ m256的冲突

时间:2011-05-08 07:34:54

标签: gcc operator-overloading sse avx mingw-w64

我开始在新款英特尔Sandy Bridge处理器上使用AVX指令。我正在使用GCC 4.5.2,MinDM64的TDM-GCC 64位版本。

我想重载operator<<使ostream能够将向量类型__m256__m128等打印到控制台。但我遇到了一个超载的冲突。以下代码中的第二个函数产生错误“与先前声明void f(__vector(8) float)冲突”:

void f(__m128 v) {
cout << 4;
}

void f(__m256 v) {
    cout << 8;
}

似乎编译器无法区分这两种类型,并将它们视为f(float __vector)

有解决方法吗?我无法在网上找到任何东西。非常感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

当遇到与功能模板类似的问题时,我偶然发现了答案。在这种情况下,GCC错误消息实际上提出了一个解决方案:

添加-fabi-version=4编译器选项。

这解决了我的问题,希望在链接标准库时不会出现任何问题。

可以在ABI Policy and GuidelinesABI specification阅读有关ABI(应用程序二进制接口)和GCC的更多信息。 ABI指定在将代码编译为目标文件时如何破坏函数名称。显然,GCC默认使用的ABI版本3无法区分各种矢量类型。

答案 1 :(得分:1)

我对改变编译器ABI标志来解决这个问题的解决方案不满意,所以我去寻找一个不同的解决方案。他们似乎在编写Eigen库时遇到了这个问题 - 有关详细信息,请参阅此源文件http://eigen.tuxfamily.org/dox-devel/SSE_2PacketMath_8h_source.html

我对此的解决方案是他们的略微调整版本:

template <typename T, unsigned RegisterSize>
struct Register
{
    using ValueType = T;
    enum { Size = RegisterSize };

    inline operator T&() { return myValue; }
    inline operator const T&() const { return myValue; }
    inline Register() {}
    inline Register(const T & v) : myValue(v) {} // Not explicit
    inline Register & operator=(const T & v)
    {
        myValue = v;
        return *this;
    }

    T myValue;
};

using Register4 = Register<__m128, 4u>;
using Register8 = Register<__m256, 8u>;
// Could provide more declarations for __m128d, __m128i, etc. if needed

使用上述内容,您可以在Register4Register8等上重载,或者生成采用Register的模板函数,而不会遇到链接问题而无需更改ABI设置。