我正在尝试了解有关ARM装配的更多信息,并了解NEON内在函数背后究竟发生了什么。我正在使用最新的Xcode LLVM编译器。我发现通常情况下,内在函数生成的程序集实际上比简单的天真C代码慢。
例如这段代码:
void ArmTest::runTest()
{
const float vector[4] = {1,2,3,4};
float result[4];
float32x4_t vA = vld1q_f32(vector);
asm("#Begin Test");
vA = vmulq_f32(vA, vA);
asm("#End Test");
vst1q_f32(result, vA);
}
生成此输出:
#Begin Test
ldr q0, [sp, #16]
stp q0, q0, [fp, #-48]
ldur q1, [fp, #-32]
fmul.4s v0, v1, v0
str q0, [sp, #16]
#End Test
我无法理解的是为什么所有的装载/存储都在这里击中内存?我一定错过了一些明显的东西,对吗?另外,如何在内联汇编中编写它以使其最佳?我希望只有一条指令,但输出方式不同。
请帮助我理解。
谢谢!
答案 0 :(得分:2)
您需要更好的测试。您的测试不会将计算结果用于任何事情,因此编译器只是通过动作让您开心。看起来你正在使用-O0进行编译,这将产生一堆不必要的加载和存储以用于调试目的。如果使用-O3编译,则所有代码都将被删除。我重新编写了测试以保存结果并使用-O3编译,结果如下:
$ cat neon.c
#include <arm_neon.h>
void runTest(const float vector[], float result[])
{
float32x4_t vA = vld1q_f32(vector);
vA = vmulq_f32(vA, vA);
vst1q_f32(result, vA);
}
$ xcrun -sdk iphoneos clang -arch arm64 -S neon.c -O3
$ cat neon.s
.section __TEXT,__text,regular,pure_instructions
.globl _runTest
.align 2
_runTest: ; @runTest
; BB#0:
ldr q0, [x0]
fmul.4s v0, v0, v0
str q0, [x1]
ret lr
此代码看起来最佳