2011-05-08 61 views
3

我已经开始在新的英特尔Sandy Bridge处理器上播放AVX指令。我使用GCC 4.5.2,MinGW64的TDM-GCC 64bit版本。GCC中的矢量类型__m128,__m256与超载冲突

我想超载运营商< < ostream能够打印出矢量类型__m256,__m128等到控制台。但我遇到了一个超载冲突。下面的代码的第二个函数产生一个错误“的冲突与早先的声明void f(__vector(8) float)”:

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

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

看来,编译器不能两种类型区分和consideres他们两个f(float __vector)

有没有办法解决这个问题?我一直无法在网上找到任何东西。任何帮助是极大的赞赏。

回答

4

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

add -fabi-version=4编译器选项。

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

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

+0

请注意,从gcc-5开始,这不再需要,因为默认的'-fabi-version'已更改。 – 2014-12-04 15:02:00

0

我不满意改变编译器ABI标志来解决这个问题,所以我去寻找一个不同的解决方案。他们似乎在写本征库遇到过这个问题 - 详见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等等,或者产生模板功能,但不会遇到链接问题,也不会改变ABI设置。