【发布时间】:2019-09-17 01:55:59
【问题描述】:
我注意到在不同的优化级别,Clang 6 有时使用 ldp(加载 neon 寄存器对)作为相邻内存地址 vld1 neon load instrinsics。
我正在尝试使用内联汇编手动强制执行更多加载对指令。源数组保存在堆栈中,当 Clang 本身生成 ldp 指令时,它使用带有偏移量的堆栈指针,但是当我使用内联汇编输入带有索引的数组时,它会扩展为地址的 x 寄存器。然而,这会导致性能回归。我相信这是因为从堆栈中读取速度更快,但是作为源地址的 ax 寄存器可能指向堆,尽管我不确定,但它可能反过来引用堆栈,或者它可能正在从堆中的重复数据中读取. 这是我现在使用的示例。
asm (
"ldp %q[DST1], %q[DST2], [%[SRC]]" "\n"
: [DST1] "=w" (TMP1), [DST2] "=w" (TMP2)
: [SRC] "X" (&K2[8])
);
这就是 Clang 将其扩展为的内容
ldp q19, q4, [x11]
但是我想使用一个带有偏移地址的堆栈指针,从索引的 K2 数组变量中自动解析。例如
ldp q19, q4, [sp,#32]
反汇编代码中堆栈指针地址的偏移量并不相邻,所以我不能硬编码sp寄存器并输入偏移量来加载顺序数据。这是因为 Clang 6 正在将其他函数使用的其他数组中的相同值合并到堆栈中。
GCC 具有 aarch64 机器约束,例如用于堆栈指针 (sp) 寄存器的 k 和用于 stp 和 ldp 存储/加载对指令地址的 Ump我从来没有在 GCC 或 Clang 上工作过,后者在其稀疏文档中没有等效的约束。
我的偏好是使用 Clang 6,因为它生成的代码比 GCC 8 快 6% 以上,因为它将性能关键循环中的大部分指令正确地安排为双重问题。
有没有办法在 Clang 6 中输入带有索引的数组作为输入,并让它自动解析为带有偏移地址的堆栈指针?
【问题讨论】:
标签: stack clang inline-assembly memory-address arm64