Description
I am porting some code from c++ to c#. The code uses a common pattern with interlocked cmpxchg trying to update some variable and then comparing the witness value with comparand - to see if update succeeded.
There are two issues:
-
if the comparand is in rax, which is common, we cannot use it for the later comparison (since cmpxchg returns in rax), so we spill comparand to stack and then later compare the witness against the stack value. - That introduces a stack variable and a read from memory and it might be not the best idea. Even if that is all in L1 cache, it is still a memory read, besides we have just done a full fenced operation, and we did the store before that, so I suspect there could be extra costs to this read.
If we need to make a dup of the value for this scenario - can it be to a register? -
in equivalent c++ code I often see no comparison at all as cmpxchg sets flags.
If we are checking if the result is equal/notequal to the comparand, can we try using flags instead?
I think there is a peephole opportunity for both branching based on the equality, and/or turning the result into a value (in sete/setne sense).