AArch64/ARM64 Tutorial

Chapter 17: Conditional Select

The ARM64 instruction set includes some special instructions that are known as Conditional Select Instructions.


Conditional Select:
csel xD, xN, xM, cond
csel wD, wN, wM, cond

cond would be something such as "eq", "lt", or "ne". Simply put, you are using a conditional branch instruction name but excluding the "b".

In plane English, the csel instruction (extended version) does this...

  1. If cond is true then....
  2. xD = xN
  3. or else...
  4. xD = xM

Conditional Increment:
cinc xD, xN, cond
cinc wD, wN, cond

In plane English, the cinc instruction (extended version) does this...

  1. If cond is true...
  2. xD = xN + 1
  3. or else...
  4. xD is left unchanged

Conditional Select Increment:
csinc xD, xN, xM, cond
csinc wD, wN, wM, cond

In plane English, the csinc instruction (extended version) does this..

  1. If cond is true then...
  2. xD = xN
  3. or else...
  4. xD = xM + 1

The csel, cinc, and csinc instructions can optimize some traditional code that used typical compare and branch instructions.

Example 1 (if w0 = 0 then w4 == w3, or else w4 == w2)

A beginner may write out the example with this sequence....
cmp w0, #0
bne else
mov w4, w3
b end
else:
mov w4, w2
end:

Alternatively a beginner may also write the example like this...
cmp w0, #0
mov w4, w3 // Preload w4 with w3 for it the cond is true when its determined by the following beq branch
beq cond_was_true
mov w4, w2 // Condition not met, update w4 with w2 instead
cond_was_true:

Regardless, we can fully optimize it to this...
cmp w0, #0
csel w4, w3, w2, eq

---

Example 2 (If w0 =/= 0 then w1 will be incremented by 1, or else do nothing)

A beginner may write out the example like this...
cmp w0, #0
beq else
add w1, w1, #1
else:

We can optimize the above to this...
cmp w0, #0
cinc w1, w1, ne

---

Example 3 (If w0 == 0 then increment w1 by 1 or else decrement it by 1)

A beginner may write out the example like this...
cmp w0, #0
bne else
add w1, w1, #1
b end
else:
sub w1, w1, #1
end:

We can optimize the above to this...
cmp w0, #0
sub w2, w1, #1 //using w2 as a temp scratch register
csinc w1, w2, w1, ne


Next Chapter

Tutorial Index