向量扩展的最佳选择函数?

时间:2014-08-18 07:39:09

标签: c++ gcc c++11 clang simd

OpenCL有select function,可用于所有向量参数。 clang和gcc都支持向量类型,但只有gcc目前支持三元运算符支持向量,并且它们都没有类似OpenCL的select函数。我试图实现替换,但结果不是最优的,gcc和clang都会产生条件跳转。但是,gcc在三元运算符方面表现相当不错,所以它非常适合作为替代品。是否存在类似select函数的最佳解决方案(特别是在clang下),它是什么?以下是一些非理想的想法:

template <typename U, typename V>
inline V select(U const s, V const a, V const b) noexcept
{
// a for loop gives horrible results
/*
  constexpr U zero{}; // for clang only

  return (-(s != zero) * a) - ((s == zero) * b);
*/
  return V{
    s[0] ? a[0] : b[0],
    s[1] ? a[1] : b[1],
    s[2] ? a[2] : b[2],
    s[3] ? a[3] : b[3]
  }; // for 4-component vectors only, one could generalize with the indices trick
/*
  return s ? a : b; // for gcc
*/
}

1 个答案:

答案 0 :(得分:0)

这将编译为gcc和clang下的半好代码:

template <typename U, typename V>
constexpr inline V select(U const s, V const a, V const b) noexcept
{      
  return V((s & U(a)) | (~s & U(b)));
}

asm上市:

Dump of assembler code for function select<int __vector(4), float __vector(4)>(int __vector(4), float __vector(4), float __vector(4)):
   0x00000000004009c0 <+0>:     andps  %xmm0,%xmm1
   0x00000000004009c3 <+3>:     andnps %xmm2,%xmm0
   0x00000000004009c6 <+6>:     orps   %xmm1,%xmm0
   0x00000000004009c9 <+9>:     retq   
End of assembler dump.

这仍然不如优化器产生的效果好。它的工作方式是滥用矢量强制转换和事实,比较操作在比较匹配的地方产生-1(全1)整数。至少不需要算术运算。