Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

possible to do if (!boolvar) { ... in 1 asm instruction?

This question is more out of curiousity than necessity:

Is it possible to rewrite the c code if ( !boolvar ) { ... in a way so it is compiled to 1 cpu instruction?

I've tried thinking about this on a theoretical level and this is what I've come up with:

if ( !boolvar ) { ...

would need to first negate the variable and then branch depending on that -> 2 instructions (negate + branch)

if ( boolvar == false ) { ...

would need to load the value of false into a register and then branch depending on that -> 2 instructions (load + branch)

if ( boolvar != true ) { ...

would need to load the value of true into a register and then branch ("branch-if-not-equal") depending on that -> 2 instructions (load + "branch-if-not-equal")

Am I wrong with my assumptions? Is there something I'm overlooking?

I know I can produce intermediate asm versions of programs, but I wouldn't know how to use this in a way so I can on one hand turn on compiler optimization and at the same time not have an empty if statement optimized away (or have the if statement optimized together with its content, giving some non-generic answer)

P.S.: Of course I also searched google and SO for this, but with such short search terms I couldn't really find anything useful

P.P.S.: I'd be fine with a semantically equivalent version which is not syntactical equivalent, e.g. not using if.


Edit: feel free to correct me if my assumptions about the emitted asm instructions are wrong.


Edit2: I've actually learned asm about 15yrs ago, and relearned it about 5yrs ago for the alpha architecture, but I hope my question is still clear enough to figure out what I'm asking. Also, you're free to assume any kind of processor extension common in consumer cpus up to AVX2 (current haswell cpu as of the time of writing this) if it helps in finding a good answer.

like image 975
griffin Avatar asked Aug 29 '13 16:08

griffin


1 Answers

At the end of my post it will say why you should not aim for this behaviour (on x86).

As Jerry Coffin has written, most jumps in x86 depend on the flags register.

There is one exception though: The j*cxz set of instructions which jump if the ecx/rcx register is zero. To achieve this you need to make sure that your boolvar uses the ecx register. You can achieve that by specifically assigning it to that register

register int boolvar asm ("ecx");

But by far not all compilers use the j*cxz set of instructions. There is a flag for icc to make it do that, but it is generally not advisable. The Intel manual states that two instructions

test ecx, ecx
jz ...

are faster on the processor.

The reason for being this is that x86 is a CISC (complex) instruction set. In the actual hardware though the processor will split up complex instructions that appear as one instruction in the asm into multiple microinstructions which are then executed in a RISC style. This is the reason why not all instructions require the same execution time and sometimes multiple small ones are faster then one big one.

test and jz are single microinstructions, but jecxz will be decomposed into those two anyways.

The only reason why the j*cxz set of instructions exist is if you want to make a conditional jump without modifying the flags register.

like image 191
Sergey L. Avatar answered Sep 29 '22 06:09

Sergey L.