如果SSE内在函数缺少某些操作,我想添加默认回退。目前我假设最好通过工会这样做,因为Visual Studio 2013现在是主要的编译器 - 而且我注意到如果使用裸SSE类型_m128 / _m128i而不是工会存在SSE操作时它仍会生成更好的代码。我不知道在VS2015中这是否更好。
所以我尝试这样的事情:
template<class _SIMD>
struct VUnion
{
_SIMD vector;
float lane[sizeof(_SIMD)/sizeof(float)]; // Can assert size makes sense etc
};
template<class _SIMD>
void __vectorcall Func(_SIMD& r, const _SIMD& a, const _SIMD& b)
{
const VUnion<_SIMD>& va{a};
const VUnion<_SIMD>& vb{b};
VUnion<_SIMD>& vr{r};
for(int i = 0; i < sizeof(_SIMD)/sizeof(float); ++i)
vr.lane[i] = LaneFunc(va.lane[i], vb.lane[i]);
}
哪个有效并且允许我仅在没有直接SSE等价物的情况下仅涉及工会。但我担心严格的别名规则等,这究竟是多么正确?
我不确定这对于整数SIMD向量是否只是语言安全而不是浮点数?
如果这不安全那么我怀疑与VS2013兼容的唯一语言安全方法是使用提取内在函数来获取每个通道?并且设置重建所有通道并立即设置整个矢量,这真的是PITA,我不相信它会为代码生成做好事。
另外还不清楚智能编译器如何对每个通道功能的回退进行矢量化。虽然我确信GCC / Clang领先于那里。