When I try to use _mm_loadu_si32, VScode gives me the error message:
a value of type "int" cannot be used to initialize an entity of type "__m128i
When trying to compile, I get the error message:
implicit declaration of function '_mm_loadu_si32'

The weird part is that a couple lines before _mm_loadu_si32, I'm using _mm_loadu_si128 without having any kind of problems. _mm_loadu_si64 also works.
Also, on windows, my program compiles.

我跑了sudo apt-get updatesudo apt-get upgrade,所以问题不是过时的软件.这是某种局限于Ubuntu的gcc错误吗?

OS: Ubuntu 20.04
gcc: 9.4.0

推荐答案

您的GCC太旧,需要GCC11才能在immintrin.h之前定义它

And you need GCC11.3 or GCC12 for a non-broken version,将加载的字节放置在结果向量中的正确位置,并确保对齐/严格别名安全.GCC bug 99754

GCC和/或clang有时会错过定义一些"助手"内部函数,最终只能找到它们.这就是其中之一,更糟糕的是,第一次try 添加它是buggy.有一些GCC版本(GCC11.0到11.2)支持它,但编译错误(加载后将dword或文字洗牌到顶部元素,而不是底部,因为它们在头实现中使用_mm_set而不是_mm_setr.)


FP等效的4字节负载__m128 _mm_load_ss(float*)已经被永远定义,但在GCC的实现中仍然不像在其他编译器中那样对对齐或严格别名安全.GCC的头对float*进行解列,而不是使用memcpy__attribute__((aligned(1),may_alias))指针类型.那是GCC bug PR84508.

不幸的是,在GCC中,使用_mm_castps_si128( _mm_load_ss( (float*)ptr ))也是not安全的.


旧编译器的可移植实现

对于别名安全的未对齐4字节加载,最好的 Select 可能是这种可移植的实现:

__m128i movd_load(void *p)
{
    int tmp;                       // int32_t on implementations that support intrinsics
    memcpy(&tmp, p, sizeof(tmp));  // unaligned aliasing-safe load
    return _mm_cvtsi32_si128(tmp);
}

这在GCC/clang/MSVC(100显示全部)上编译得很好.GCC和clang的旧版本和新版本:测试了GCC4.7和GCC12,只是预期的movd xmm0, [rdi]/ret.

但它在ICC上编译很愚蠢,加载到EAX,然后要么存储/重新加载,要么movd xmm0, eax,而不是movd的内存源操作数.


这对于pmovzx/pmovsx负载(将负载缩小到__m128i,尤其是未对齐和混叠安全负载的重要用例之一)也很有用,例如

#if defined(__SSE4_1__) || defined (_MSC_VER)
__m128i pmovzxbd_load(void *p)
{
    __m128i v = movd_load(p);
    return _mm_cvtepu8_epi32(v);  // folds the load with GCC9 or later
    // but not ICC or MSVC, or earlier GCC: they all movd into an XMM reg and pmovzxbd xmm0,xmm0
    // clang gets this right, with a mem src pmovzxbd
}
#endif
# GCC8.5 -O2 -march=skylake -mno-avx
# and MSVC19.14.  ICC 2021 is even worse, going through EAX
pmovzxbd_load:
        movd    xmm0, DWORD PTR [rdi]
        pmovzxbd        xmm0, xmm0
        ret
# GCC9.5 -O2 -march=skylake -mno-avx
# and clang
pmovzxbd_load:
        pmovzxbd        xmm0, DWORD PTR [rdi]
        ret

C++相关问答推荐

为什么这个C程序代码会产生以下结果?

为什么在C中设置文件的位置并写入文件,填充空字符?

使用单个字节内的位字段

getchar读css + z还是返回css?

为什么在Linux(特别是Ubuntu 20.04LTS)上,POSIX共享内存对象在重启后仍然存在,然后突然变成了根用户?

可以将C变量限制为特定的读/写速度吗?

解决S随机内存分配问题,实现跨进程高效数据共享

如何编写一个for循环来计算C中各项的总和?

c程序,让用户输入两类数字,并给出输出用户输入多少个数字

基于蝶数恰好有8个除数的事实的代码

&stdbool.h&q;在嵌入式系统中的使用

将size_t分配给off_t会产生符号转换错误

如果类型是新的,offsetof是否与typeof一起工作?

分支预测和UB(未定义的行为)

如何不断地用C读取文件?

";错误:寄存器的使用无效;当使用-masm=intel;在gcc中,但在AT&;T模式

C23 中的 [[reproducible]] 和 [[unsequenced]] 属性是什么?什么时候应该使用它们?

当循环变量在溢出时未定义时,可以进行哪些优化?

C99 的 %zu 格式说明符不起作用

如何根据当前舍入方向将float转换为int?