[comp.unix.wizards] C code optimization for a =

WILCOX@nosc-tecr.arpa (05/28/89)

Assuming that the target machine implements two's compliment arithmetic
and doesn't have store condition code instructions, there is a simple
optimization that few C compilers seem to use.  Given:

     int a;
     int b, c;
     a = (b < c);

the usual approach is something like:

     a = 0;
     if( ! (b < c)) goto label;
     a = 1;
label:

A better approach would seem to be:

a = (unsigned)((c - b) >> (WIDTH_OF_INT_IN_BITS - 1));

In other words, subtract rather than compare, and shift the resulting sign
bit into the least-significant bit position with zero extend.  There is
also a variation using signed rather than unsigned shift, which generates
either -1 or 0, followed by an increment to produce either 0 or 1.

     --Dwight Wilcox
       Code 412
       Naval Ocean Systems Center
       San Diego, CA  92152-5000

WILCOX@nosc-tecr.arpa (05/28/89)

Wooops!  I was thinking of the signed form and got put "c - b" instead
of "b - c".  Unsigned form should be:

a = (b < c); ==>

a = (unsigned)((b - c) >> (WIDTH_OF_INT_IN_BITS - 1));

     --Dwight Wilcox
       Code 412
       Naval Ocean Systems Center
       San Diego, CA  92152-5000

augustss@cs.chalmers.se (Lennart Augustsson) (05/29/89)

In article <19787@adm.BRL.MIL> WILCOX@nosc-tecr.arpa writes:
>
> ...
>     int a;
>     int b, c;
>     a = (b < c);
>
> [ should be replaced by ]
>
>a = (unsigned)((b - c) >> (WIDTH_OF_INT_IN_BITS - 1));
>
Good idea, but it doesn't work.  Assuming 16 bit integers, take
  b = -32768;	(0x8000)
  c = 32767;    (0x7fff)
now clearly b < c will evaluate to 1, but (unsigned)((b - c) >> 15 will
evaluate to 0, since b-c evaluates to 1 (0x0001).

	-- Lennart Augustsson


	Lennart Augustsson
Email:	augustss@cs.chalmers.se or augustss@chalmers.csnet