使用_mm_hadd_ps累加__m128向量编译失败:内联函数问题咨询
问题描述
近期我在使用C intrinsics进行SIMD优化以提升代码性能,需求是将存储4个float的__m128类型变量acc累加为单个float变量ac。我编写了如下代码:
acc = _mm_hadd_ps(acc,acc); acc = _mm_hadd_ps(acc,acc); ac = _mm_cvtss_f32(acc);
该代码逻辑符合需求,但编译失败,编译器输出如下错误信息:
Compiler command failed with code 1 Command: gcc -pipe -std=c17 -g -gdwarf-4 -O3 -Wall -Wextra -Wpedantic -pedantic-errors -ffreestanding -nostdlib -static -march=k8 -mtune=generic -mno-80387 -mno-mmx -D_MM_MALLOC_H_INCLUDED -Wa,-march=k8+cmov+nommx -Wa,-mx86-used-note=no -Wa,--fatal-warnings -Wl,-n -Wl,--fatal-warnings -Wl,--no-dynamic-linker -Wl,--build-id=none -Wl,-z,defs -Wl,-z,noexecstack -Wl,-z,norelro -Wl,-z,noseparate-code -Wl,-Ttext=0x507340f44000 -Wl,-e,sdot -include defs.inc -o user.elf user.c In file included from /usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/include/immintrin.h:33, from user.c:2: user.c: In function 'sdot': /usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/include/pmmintrin.h:56:1: error: inlining failed in call to 'always_inline' '_mm_hadd_ps': target specific option mismatch | _mm_hadd_ps (__m128 __X, __m128 __Y) | ^~~~~~~~~~~ user.c:19:16: note: called from here 19 | __m128 acc3 = _mm_hadd_ps(acc2,acc2); | ^~~~~~~~~~~~~~~~~~~~~~ In file included from /usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/include/immintrin.h:33, from user.c:2: /usr/lib/gcc/x86_64-alpine-linux-musl/10.2.1/include/pmmintrin.h:56:1: error: inlining failed in call to 'always_inline' '_mm_hadd_ps': target specific option mismatch 56 | _mm_hadd_ps (__m128 __X, __m128 __Y) | ^~~~~~~~~~~ user.c:17:18: note: called from here 17 | __m128 acc2 = _mm_hadd_ps(acc1,acc1); | ^~~~~~~~~~~~~~~~~~~~~~
我想咨询:
- 函数必须内联是什么含义?
- 我的代码哪里违反了内联限制?
解答
函数必须内联的含义
always_inline是编译器的属性标记,带这个标记的函数必须被内联到调用它的代码中,不能生成独立的函数体。SIMD intrinsics函数普遍使用这个标记,因为它们本质是特定CPU指令的直接封装,必须直接替换成机器指令,无法作为普通函数调用。如果编译器无法完成内联,就会抛出错误。
代码违反内联限制的原因
问题出在编译选项不支持_mm_hadd_ps对应的CPU指令集:
_mm_hadd_ps是SSE3指令集的函数,而你的编译选项指定了-march=k8(对应AMD Athlon64/Opteron架构,仅支持到SSE2),且没有启用SSE3的编译开关。- 编译器检测到目标架构不支持SSE3指令,无法将
_mm_hadd_ps内联为对应的机器指令,因此触发了"target specific option mismatch"错误。
修复方案
你有两种选择:
- 启用SSE3指令集:在编译选项中添加
-msse3,或者把-march改为支持SSE3的架构(比如-march=core2)。 - 改用SSE2兼容的累加实现:如果必须保留
-march=k8,可以用SSE2指令完成4个float的累加,示例代码如下:// 横向成对相加:结果为 [a+b, c+d, a+b, c+d] __m128 temp = _mm_add_ps(acc, _mm_movehl_ps(acc, acc)); // 将前两个元素相加:结果为 [(a+b)+(c+d), ..., ..., ...] temp = _mm_add_ss(temp, _mm_shuffle_ps(temp, temp, 0x55)); ac = _mm_cvtss_f32(temp);
内容的提问来源于stack exchange,提问作者CopperCableIsolator
相关产品推荐
相关产品推荐

