Re: Question about MS C code generation

bonzini@gnu.org (Paolo Bonzini)
3 Dec 2003 20:32:23 -0500

          From comp.compilers

Related articles
Question about MS C code generation ruicui@sohu.com (2003-11-21)
Re: Question about MS C code generation joachim.durchholz@web.de (Joachim Durchholz) (2003-12-03)
Re: Question about MS C code generation tmk@netvision.net.il (2003-12-03)
Re: Question about MS C code generation vbdis@aol.com (2003-12-03)
Re: Question about MS C code generation bonzini@gnu.org (2003-12-03)
| List of all articles for this month |

From: bonzini@gnu.org (Paolo Bonzini)
Newsgroups: comp.compilers
Date: 3 Dec 2003 20:32:23 -0500
Organization: http://groups.google.com
References: 03-11-090
Keywords: code, optimize
Posted-Date: 03 Dec 2003 20:32:22 EST

> if(a<0) b=-5;
> else if(a>=0) b=5;
> else b=0;


I guess that you meant a>0 in the second line.


> [which the compiler rewrites to]
>
> if(a>=0) {
> if(a<=0) b=0;
> else b=5;
> } else b=-5;


The compiler is only inverting the conditions (either according to
what it thinks the branch probabilities are, or just because it likes
it better this way).


Now, let's look at the second snippet. The compiler is trying to
remove a jump, so it does this:


> xor eax, eax
> cmp [ebp+nA], 0
> setle al


AL = (a <= 0) ? 1 : 0;


> dec eax


AL = (a <= 0) ? 0 : -1;


> and eax, 5


AL = (a <= 0) ? 0 : 5;


that is, AL = (a > 0) ? 5 : 0. As I said, this is a transformation
with which the compiler tries to avoid unnecessary jumps; there are a
number of these hardcoded in the optimizer (in the case of gcc, they
call it "if conversion").


On to the next question:


> mov [ebp+nTmp], ecx
> mov edx, [ebp+nTmp]
>
> WHY USE A TEMPORARY VARIABLE ?


Are you using the top optimization level? It does not seem very smart
indeed.


> 4) if asked, how would you write this program in assembly ?


      xor ecx, ecx ;We need the top 24 bits cleared
      xor edx, edx
      cmp [var], 0
      setg cl ;ECX=1 if EAX>0
      setl dl ;EDX=1 if EAX<0
      sub ecx, edx ;ECX=sign of EAX
      lea [ecx*4+ecx],ecx ;ECX=sign of EAX * -5


or


      cmp [var], 0
      setg cl ;CL=1 if EAX>0
      setl dl ;DL=1 if EAX<0
      sub cl, dl ;CL=sign of EAX
      movsx ecx, cl ;ECX=sign of EAX
      lea [ecx*4+ecx],ecx ;ECX=sign of EAX * -5


But I do not expect a compiler to recognize this. It corresponds to
another way to express your expression: 5 * ((a > 0) - (a < 0))


Also note that if you need an 8-bit result you can drop the first two
instructions (the XORs), or the MOVSX in the second example.


Finally, if you are testing a register, I'd suggest OR EAX, EAX
instead of a compare with zero (a byte smaller). And if you are on a
PII or later, what about


      xor ecx, ecx
      cmp [var], 0
      cmovl ecx, -5
      cmovg cl, 5


This *is* something I'd expect out of a smart compiler, if told to
generate CMOV instructions.


Paolo


Post a followup to this message

Return to the comp.compilers page.
Search the comp.compilers archives again.