1

I know that armv7 can use condition codes for load/store, like ldrne/streq. But A64 does not allow instructions to be conditionally executed. so how can i archive this in 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
...
Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
Chen Li
  • 4,824
  • 3
  • 28
  • 55
  • 1
    There are no such instructions on ARM64. Consider performing a conditional branch around the load/store operation. – fuz Dec 01 '20 at 14:12
  • 2
    [Why are conditionally executed instructions not present in later ARM instruction sets?](https://stackoverflow.com/q/22168992/995714) – phuclv Dec 01 '20 at 14:39
  • what did you see in the arm documentation with respect to conditional execution or branches, etc? what part of the documents did you not understand? – old_timer Dec 01 '20 at 14:40

2 Answers2

4

Predication of every instruction was a feature that made high-performance ARM CPUs harder to implement, especially with out-of-order execution. It was intentionally removed for AArch64. (Why are conditionally executed instructions not present in later ARM instruction sets? quotes the vendor's own justification)

If you need something with side effects / possible faults like store and load to be conditional, you normally need to branch.

The only branchless option I can think of that seems worth considering would be csel with a pointer to a dummy location (e.g. on the stack) vs. the real location. Then you still actually load and store, but not to the location you care about. This is probably worse unless the branch mispredict penalty is high and the branch is hard to predict.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
-3
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
old_timer
  • 69,149
  • 8
  • 89
  • 168
  • 1
    This is not applicable to OPs scenario as the store itself is conditional, not the value that is stored. The code you show will not work in such a situation. – fuz Dec 01 '20 at 14:41
  • @fuz asking the compiler is much easier than reading the docs, here showing there are some shortcuts but end of the day conditional branches as the per instruction conditionals are gone. Although the docs should have been read before asking this question. Demonstration that you can ask the compiler in a matter of seconds – old_timer Dec 01 '20 at 14:43
  • 1
    I agree with that, but as your code does not show anything really similar to OPs scenario, it does not answer his question. You do not even have any text explaining why the code would be relevant. This makes your answer a bad one. – fuz Dec 01 '20 at 14:44