Path: utzoo!attcan!uunet!lll-winken!lll-tis!helios.ee.lbl.gov!nosc!ucsd!ames!umd5!mimsy!chris
From: chris@mimsy.UUCP (Chris Torek)
Newsgroups: comp.std.c
Subject: Re: the logical xor operator!
Message-ID: <12178@mimsy.UUCP>
Date: 28 Jun 88 00:10:54 GMT
References:  <1719@ogcvax.ogc.edu> <1309@ark.cs.vu.nl> <4772@haddock.ISC.COM>
Organization: U of Maryland, Dept. of Computer Science, Coll. Pk., MD 20742
Lines: 87

>In article <3254@rpp386.UUCP> jfh@rpp386.UUCP (The Beach Bum) writes:
>>in particular, i believe (a == 0)^(b == 0) most likely can't be as well
>>optimized as (a == 0)!=(b == 0).

In article <4772@haddock.ISC.COM> karl@haddock.ISC.COM (Karl Heuer) writes:
>Nonsense.  "!=" and "^" produce the same result when both operands are
>normalized booleans; therefore a compiler which detects this situation is free
>to generate its favorite logical-xor construct for both.  In practice, few if
>any compilers bother to do this.

In fact, the 4BSD Vax PCC does nothing special about either one.  For

	if ((a==0) != (b==0))
		code;

one gets code of the form

	test a
	branch if not 0 -+
	r0 = 1		 |
    +---branch		 |
    |  	r0 = 0 <---------+
    +->	test b
	branch if not 0 -+
	r1 = 1		 |
    +---branch		 |
    |  	r1 = 0 <---------+
    +->	compare* r0,r1
	branch if equal -+
			 |
	... <------------+

The only difference for

	if ((a==0) ^ (b==0))

is that the `compare' (marked with `*') turns into an `xor'.

For assignment statements, however,

	c = (a==0) != (b==0);	/* or c = (a==0) ^ (b==0) */

the code remains the same up until the `*' above; from there it
reads either

	compare r0,r1
	branch if equal -+
	r0 = 1		 |
    +---branch		 |
    |	r0 = 0 <---------+
    +->	move r0,c

or

	xor r0,r1
	move result,c

Hence in a dumb compiler (PCC) the logical operation is more efficient.
A good `rule of thumb' is this:

    -------------------------------------------------------------
    Logical operators are never slower than arithmetic operators.
    -------------------------------------------------------------

[are there any machines for which this is false?]

Comparison of two arbitrary quantities (as by a dumb compiler above)
is a subtraction, which is arithmetic, hence ^ either ties or wins.

Incidentally, in the 4.3BSD-tahoe Vax compiler, neither

	if ((a == 0) != (b == 0))

nor

	if ((a == 0) ^ (b == 0))

produce the best code.  The best logical exclusive or sequence for
`if' statements comes from

	if (a ? !b : b)

which generates only 7 instructions, of which at most 5 are executed.
Part of this is from some tweaks Donn Seeley and I installed recently
to improve the code generated for the getc() and putc() macros.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris@mimsy.umd.edu	Path:	uunet!mimsy!chris