I'm working on exercise 3.61 of CSAPP, which requires to write a very simple function that checks if a pointer is NULL
before trying to dereference it, which should base on a conditional move instruction rather than a jump. Here's an example I've found online:
long cond(long* p) {
return (!p) ? 0 : *p;
}
According to claims, the function can be compiled into the following assembly:
cond:
xor eax, eax
test rdi, rdi
cmovne rax, QWORD PTR [rdi]
ret
I am running GCC 7.3.0 (from APT package gcc/bionic-updates,now 4:7.3.0-3ubuntu2.1 amd64
) on Ubuntu 18.04 on WSL. The computer is running on an Intel Coffee Lake (i.e. 8th-gen Core-i) processor.
I have tried the following commands:
gcc -S a.c -O3
gcc -S a.c -O3 -march=x86-64
gcc -S a.c -O3 -march=core2
gcc -S a.c -O3 -march=k8
Honestly, I wasn't able to observe any difference in the generated a.s
file, since all of them look like
cond:
xorl %eax, %eax
testq %rdi, %rdi
je .L1
movq (%rdi), %rax
.L1:
ret
Is there any possibility to have such a function that compiles into a conditional move, without a jump?
Edit: As told in comments, the CMOVxx series of instructions loads operands unconditionally, and only the actual assignment operation is conditional, so there'd be no luck to put *p
(or (%rdi)
) as the source operand of CMOV, is it right?
The claim is on this page but I think it's invalid.