【发布时间】:2021-08-15 23:45:49
【问题描述】:
我正在为 x64 和 neon 开发 C++ 内部包装器。我希望我的函数是 constexpr。我的动机类似于Constexpr and SSE intrinsics,但编译器 (GCC) 在 constexpr 函数中可能不支持#pragma omp simd 和内在函数。下面的代码只是一个演示(自动矢量化就足够了)。
struct FA{
float c[4];
};
inline constexpr FA add(FA a, FA b){
FA result{};
#pragma omp simd // clang error: statement not allowed in constexpr function
for(int i = 0; i < 4; i++){ // GCC error: uninitialized variable 'i' in 'constexpr' function
result.c[i] = b.c[i] + a.c[i];
}
return result;
}
struct FA2{
__m128 c;
};
inline constexpr FA2 add2(FA2 a, FA2 b){
FA2 result{};
result.c = _mm_add_ps(a.c,b.c); // GCC error: call to non-'constexpr' function '__m128 _mm_add_ps(__m128, __m128)'
return result; // fine with clang
}
无论如何,我必须提供参考 C++ 代码以实现可移植性。有没有一种代码高效的方式让编译器在编译时使用参考代码?
f(){
if(){
// constexpr version
}else{
// intrinsic version
}
}
它应该适用于所有支持 omp、内在函数和 C++20 的编译器。
【问题讨论】:
-
有趣的是,add() 可以在 MSVC 上编译,但是 add2 给出了这个错误:error C3615: constexpr function 'add2' cannot result in a constant expression
-
英特尔接受这两种功能。
-
这正是引入std::is_constant_evaluated 的场景类型
-
GCC/clang 头文件定义
_mm_add_ps没有constexpr所以你基本上不走运,除非你使用编译器特定的东西,比如a.c + b.c来使用 GNU C 本机向量语法 (@987654328 GNU C 中的@ 是一个浮点向量,+ 操作符对它起作用。__m128i是一个两个 long long 的向量)。哦,我对你已经链接的问答的回答已经有一个例子,在整数向量上使用 GNU C 本机向量语法==而不是_mm_cmpeq_epi32:P
标签: c++ openmp constexpr intrinsics