我目前正在开发一些执行大量复数乘法的软件。我有兴趣看看编译器处理std :: complex有多好,所以检查编译器输出:
#include <complex>
std::complex<float> comp(std::complex<float> x, std::complex<float> y)
{
return x * y;
}
生成
vmov.f32 s14, s0 ; why?
vmul.f32 s13, s2, s1
vmul.f32 s15, s3, s1
vmla.f32 s13, s3, s14
vnmls.f32 s15, s2, s14
vmov.f32 s1, s13
vmov.f32 s0, s15 ; why?
bx lr
我很欣赏它是一个人为的例子,并且在任何需要执行的代码中将函数放在函数内是不明智的,但我无法理解为什么编译器将s0复制到s14,而不是使用s0作为操作数。 vmla
和vnmls
指示,如果要将s0
用作vnmls
指令中的目的地,则可以删除最后vmov
。是否有理由生成这些我忽略的指令?
这个编译器是gcc 5.4.1,-O3 -ffast-math -mfpu=neon -mfloat-abi=hard
作为参数。
Paul R - 感谢您的评论,内联它确实整理了它,将参数更改为const引用将代码更改为
comp(std::complex<float> const&, std::complex<float> const&):
vldr.32 s0, [r0, #4]
vldr.32 s13, [r1]
vldr.32 s12, [r1, #4]
vmul.f32 s11, s13, s0
vldr.32 s14, [r0]
vmul.f32 s15, s12, s0
vmla.f32 s11, s12, s14
vnmls.f32 s15, s13, s14
vmov.f32 s1, s11
vmov.f32 s0, s15
bx lr