【问题标题】:aarch64 inline assembly stack pointer constraint memory address with offset for Clang 6+aarch64 内联汇编堆栈指针约束内存地址与 Clang 6+ 的偏移量
【发布时间】: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


    【解决方案1】:

    您是否尝试过使用像[SRC] "m" (K2[8]) 这样的内存源操作数?没有它,你甚至没有告诉编译器内存内容也是内联汇编的输入,所以它可能会重新排序你的汇编。商店,或进行死店消除。

    让编译器选择寻址模式是"m" 操作数的全部要点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-09
      • 2016-12-30
      • 2015-07-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-31
      • 2014-03-02
      • 2011-04-23
      相关资源
      最近更新 更多