2

即使我armv7只编译,NEON 乘法累加内在函数似乎被分解为单独的乘法和加法。

我在 Xcode 最新 4.5 的多个版本、iOS SDK 5 到 6 以及不同的优化设置(通过 Xcode 和直接通过命令行构建)都体验过这一点。

例如,构建和拆卸一些test.cpp包含

#include <arm_neon.h>

float32x4_t test( float32x4_t a, float32x4_t b, float32x4_t c )
{
   float32x4_t result = a;
   result = vmlaq_f32( result, b, c );
   return result;
}

clang++ -c -O3 -arch armv7 -o "test.o" test.cpp
otool -arch armv7 -tv test.o

结果是

test.o:
(__TEXT,__text) section
__Z4test19__simd128_float32_tS_S_:
00000000    f10d0910    add.w   r9, sp, #16 @ 0x10
00000004        46ec    mov ip, sp
00000006    ecdc2b04    vldmia  ip, {d18-d19}
0000000a    ecd90b04    vldmia  r9, {d16-d17}
0000000e    ff420df0    vmul.f32    q8, q9, q8
00000012    ec432b33    vmov    d19, r2, r3
00000016    ec410b32    vmov    d18, r0, r1
0000001a    ef400de2    vadd.f32    q8, q8, q9
0000001e    ec510b30    vmov    r0, r1, d16
00000022    ec532b31    vmov    r2, r3, d17
00000026        4770    bx  lr

而不是vmla.f32.

请问我做错了什么?

4

2 回答 2

3

它要么是错误,要么是 llvm-clang 的优化。armcc 或 gcc 会按您的预期生成 vmla,但如果您阅读Cortex-A 系列程序员指南 v3,它会说:

20.2.3 调度

在某些情况下,可能会有相当长的延迟,尤其是 VMLA 乘法累加(整数 5 个周期;浮点数 7 个周期)。应该优化使用这些指令的代码,以避免在结果值准备好之前尝试使用它,否则会发生停顿。尽管有几个周期会导致延迟,但这些指令确实是完全流水线的,因此可以同时进行多个操作。

因此,llvm-clang 将 vmla 分离为乘法并累加以填充管道是有意义的。

于 2012-10-18T21:16:15.037 回答
1

霓虹灯乘加指令执行操作

c = c + a * b

请注意,目的地和来源之一是相同的。如果要执行操作

d = c + a * b

编译器必须将其分解为两条指令

d = c
d = d + a * b

或者,它可以将其分解为乘法+加法指令

d = a * b
d = d + c

在 Cortex-A8/A9 上,两个变体具有相同的吞吐量,但在 Cortex-A8 上,第二个变体具有较低的延迟,因为乘加指令在许多情况下会导致停顿。

于 2012-10-17T20:37:23.830 回答