如何避免Arm Neon函数中d8-d15寄存器的溢出操作?
问题
我有一个通过函数指针调用的函数,会用到全部32个Arm Neon寄存器。按照Arm调用约定,该函数需要溢出并恢复d8-d15寄存器的低段部分,但我希望把这个溢出恢复的负担转移到上层函数,避免在该函数内执行此操作。
示例代码(当前实现)
C代码
#include "arm_neon.h" inline void add(float32x4x4_t &a, float32x4x4_t b) { a.val[0] = vaddq_f32(a.val[0], b.val[0]); a.val[1] = vaddq_f32(a.val[1], b.val[1]); a.val[2] = vaddq_f32(a.val[2], b.val[2]); a.val[3] = vaddq_f32(a.val[3], b.val[3]); } float32x4x4_t foo(float *input, int n) { auto a = vld4q_f32(input); input += 16; auto b = vld4q_f32(input); input += 16; auto c = vld4q_f32(input); input += 16; auto d = vld4q_f32(input); input += 16; do { add(a, b); add(b, c); add(c, d); add(d, d); } while (--n); add(a,b); add(a,c); add(a,d); return a; }
对应汇编输出
foo(float*, int): // @foo(float*, int) stp d11, d10, [sp, #-32]! // 16-byte Folded Spill stp d9, d8, [sp, #16] // 16-byte Folded Spill mov x9, x0
可以看到编译器自动在foo函数开头插入了d8-d11的溢出操作,符合调用约定要求。
当前尝试的上层处理方式
我可以通过在调用者中插入空汇编指令,强制调用者溢出并恢复所有被调用者保存的Neon寄存器:
C代码
float32x4x4_t bar(float *input, int n) { foo(input, n); asm("" : : : "d8","d9","d10","d11","d12","d13","d14","d15"); }
对应汇编输出
bar(float*, int): // @bar(float*, int) stp d15, d14, [sp, #-64]! // 16-byte Folded Spill stp d13, d12, [sp, #16] // 16-byte Folded Spill stp d11, d10, [sp, #32] // 16-byte Folded Spill stp d9, d8, [sp, #48] // 16-byte Folded Spill mov x8, x0
现在的疑问是:有没有办法让非内联的foo函数知晓上层调用者已经处理了这些寄存器的溢出恢复,从而让foo不再自行执行d8-d15的保存与恢复操作?
内容的提问来源于stack exchange,提问作者Aki Suihkonen
相关产品推荐
相关产品推荐

