有条件地 load/store 的 aarch64 方法是什么?

What's aarch64's way to conditionally load/store?

我知道 armv7 可以使用 load/store 的条件代码,例如 ldrne/streq。但是A64不允许有条件地执行指令。那么我如何将其存档在 arm64 中:

ands    tmp1, dstend, 7 # set nzcv flag with ands
# if not zero, ldr w6, [srcend, -4]!, str w6, [dstend, -4]!
# else, do nothing and goes on
...

对每条指令进行预测是一项使高性能 ARM CPU 更难实现的功能,尤其是在乱序执行的情况下。它是为 AArch64 故意删除的。 (Why are conditionally executed instructions not present in later ARM instruction sets? 引用供应商自己的理由)

如果你需要一些有副作用/可能有错误的东西,比如存储和加载是有条件的,你通常需要分支。

我能想到的唯一值得考虑的无分支选项是 csel 带有指向虚拟位置(例如在堆栈上)与真实位置的指针。然后你仍然实际加载和存储,但不是你关心的位置。这可能更糟,除非分支预测错误惩罚很高 并且 分支很难预测。

void fun0 ( unsigned int x, unsigned int *y )
{
    if(x) *y=0;
    else  *y=1;
}
void fun1 ( unsigned int x, unsigned int *y )
{
    if(x) *y=10;
    else  *y=11;
}
void fun2 ( unsigned int x, unsigned int *y, unsigned int a, unsigned int b )
{
    if(x) *y=a;
    else  *y=b;
}
void fun5 ( unsigned int x, unsigned int *y, unsigned int *z )
{
    if(x) *y=123;
    else  *z=123;
}
0000000000000000 <fun0>:
   0:   7100001f    cmp w0, #0x0
   4:   1a9f17e0    cset    w0, eq  // eq = none
   8:   b9000020    str w0, [x1]
   c:   d65f03c0    ret

0000000000000010 <fun1>:
  10:   7100001f    cmp w0, #0x0
  14:   1a9f17e0    cset    w0, eq  // eq = none
  18:   11002800    add w0, w0, #0xa
  1c:   b9000020    str w0, [x1]
  20:   d65f03c0    ret

0000000000000024 <fun2>:
  24:   7100001f    cmp w0, #0x0
  28:   1a831042    csel    w2, w2, w3, ne  // ne = any
  2c:   b9000022    str w2, [x1]
  30:   d65f03c0    ret

0000000000000034 <fun5>:
  34:   34000080    cbz w0, 44 <fun5+0x10>
  38:   52800f60    mov w0, #0x7b                   // #123
  3c:   b9000020    str w0, [x1]
  40:   d65f03c0    ret
  44:   52800f60    mov w0, #0x7b                   // #123
  48:   b9000040    str w0, [x2]
  4c:   d65f03c0    ret