GCC中的矢量类型__m128,__m256与超载冲突
我已经开始在新的英特尔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)
。
有没有办法解决这个问题?我一直无法在网上找到任何东西。任何帮助是极大的赞赏。
当功能模板出现类似问题时,我意外地偶然发现了答案。在这种情况下,GCC错误信息实际上提出了一种解决方案:
add -fabi-version=4
编译器选项。
这解决了我的问题,希望链接标准库时不会引起任何问题。
人们可以阅读更多关于ABI(应用程序二进制接口)和GCC ABI Policy and Guidelines和ABI specification。 ABI指定代码编译为目标文件时,函数名称是如何被破坏的。显然,默认情况下,GCC使用的ABI版本3无法区分各种矢量类型。
我不满意改变编译器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
使用上面,你可以重载上Register4
,Register8
等等,或者产生模板功能,但不会遇到链接问题,也不会改变ABI设置。
请注意,从gcc-5开始,这不再需要,因为默认的'-fabi-version'已更改。 – 2014-12-04 15:02:00