Can be done if (! Boolvar) {... in 1 asm instruction?

This question is more out of curiosity than necessity:

Is it possible to rewrite the code with if ( !boolvar ) { ... so that it is compiled with 1 cpu instruction?

I tried to think about it on a theoretical level, and this is what I came up with:

if ( !boolvar ) { ...

it will be necessary to nullify the variable first, and then the branch, depending on this → 2 commands (negate + branch)

if ( boolvar == false ) { ...

it will be necessary to load the false value into the register, and then branch off depending on this → 2 instructions (load + branch)

if ( boolvar != true ) { ...

you will need to load the value true in the register, and then branch ("branch-if-not-equal") depending on this → 2 instructions (load + "branch-if-not-equal")

Am I really mistaken in my assumptions? Is there something I'm missing out on?

I know that I can release intermediate versions of asm programs, but I would not know how to use it in such a way that I could enable compiler optimization on the one hand and at the same time not have an empty if optimized (or if optimized with its contents, which gives some non-general answer)

PS: Of course, I also searched google and SO for this, but with such short search terms I could not find anything useful

PPS: I would be fine with a semantically equivalent version, which is not the syntactic equivalent, for example. not using if .


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


Edit2: I really learned asm about 15 years ago and retrained about 5 years ago for alpha architecture, but hopefully my question is still clear enough to find out what I'm asking. In addition, you can assume that any processor extension is common in the consumer processor up to AVX2 (the current haswell cpu processor at the time of writing), if that helps to find a good answer.

+4
source share
3 answers

At the end of my post I will say why you should not strive for this behavior (on x86).

As Jerry Coffin wrote, most x86 jumps are case-sensitive.

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

 register int boolvar asm ("ecx"); 

But not all compilers use the j*cxz instruction set. There is a flag for icc to do this, but this is usually not recommended. The Intel manual states that two teams

 test ecx, ecx jz ... 

run faster on the processor.

The reason for this is that x86 is a CISC (complex) instruction set. In real equipment, although the processor will split the complex instructions, which are displayed as a single command in asm, into several micro-commands, which are then executed in the RISC style. It is for this reason that not all instructions require the same execution time, and sometimes several small ones are faster than one large one.

test and jz are single microcommands, but jecxz will be decomposed into these two anyway.

The only reason the j*cxz instruction set exists is if you want to make a conditional jump without changing the flag case.

+2
source

Yes, it is possible - but it will depend on the context in which this code takes place.

Conditional branches in x86 depend on the values ​​in the flag register. To do this, in order to compile up to one instruction, some other code should already set the correct flag, so all that remains is one command of the type jnz wherever .

For instance:

 boolvar = x == y; if (!boolvar) { do_something(); } 

... it could be something like:

  mov eax, x cmp eax, y ; `boolvar = x == y;` jz @f call do_something @@: 

Depending on your point of view, it may even compile only part of the instruction. For example, quite a few instructions can be "given", so they are executed only if some previously defined condition is true. In this case, you may have one instruction to set "boolvar" to the correct value, followed by one to conditionally call the function, so there is no (complete) command corresponding to the if .

Although you are unlikely to see this in well-written C, a single assembly language instruction can include even more. For an obvious example, consider something like:

  x = 10; looptop: -- x; boolvar = x == 0; if (!boolvar) goto looptop; 

This whole sequence can be compiled something like this:

  mov ecx, 10 looptop: loop looptop 
+1
source

ARM architecture (v7 and below) can run any instruction as conditional, so that it can translate only one command

For example, the following cycle

 while (i != j) { if (i > j) { i -= j; } else { j -= i; } } 

can translate to ARM assembly as

 loop: CMP Ri, Rj ; set condition "NE" if (i != j), ; "GT" if (i > j), ; or "LT" if (i < j) SUBGT Ri, Ri, Rj ; if "GT" (Greater Than), i = ij; SUBLT Rj, Rj, Ri ; if "LT" (Less Than), j = ji; BNE loop ; if "NE" (Not Equal), then loop 

x86 has only conditional movement, so if inside if is a simple assignment, then this can be done in 1 command

0
source

Source: https://habr.com/ru/post/1499660/


All Articles