sibcall fixup

Fergus Henderson fjh@cs.mu.oz.au
Sun Feb 18 20:16:00 GMT 2001


On 27-Mar-2037, Richard Kenner, GNU C Maintainer <kenner@vlsi1.ultra.nyu.edu> wrote:
>     This one, for instance, barely fits on the screen.  
> 
> Well, the code it was replacing was twice as many lines long so it
> *certainly* didn't fit on the screen.

You're putting more into each line and then putting all of these
complicated lines into the condition of a single if-then-else.
The size is reduced, but the structure is more complicated and so in
the end it's harder to understand, despite being able to see more of
it at once.

> I really don't understand why code of the form:
> 
> 	if (condition1)
> 	  do something;
> 
> 	if (condition2)
> 	  do same thing;
> 
> 	if (condition3)
> 	  do same thing;
> 
> is *ever* better than
> 
> 	if (condition1
> 	    || condition2
> 	    || condition3)
> 	  do something;
> 
> no matter *how* many conditions there are or how complex they are.
> 
> Can you explain?

If the conditions are complex, and "do something" is simple,
then it is easier to analyze that way.

Consider a hypothetical reader who is trying to figure out
whether this code does the right thing.  If the reader sees

	if (condition1)
	  action1;

then they immediately know that when condition1 holds, this code will
perform action1.  They can immediately verify whether that is the
correct action to perform in that case.
Then, when they see

	if (condition2)
	  action1;

they can do the same.

If, on the other hand, the reader sees

	if (condition1
	    || condition2
	    ...

then they can't immediately see what action will be taken when the
first part of the condition is true, so they can't immediately
verify that that sub-case is doing the right thing.  They need
to scroll down to the end of the condition

	    ...
	    || condition)
	  action1;

before they can see the action, and only then can they determine
whether action1 is right for condition1.  Then they need to scroll
back up to condition2, and check that.  Scrolling up and down like
this is not nearly as easy as just reading the code in sequence.

In order to avoid this, the reader may try to remember all the
conditions as they are encountered, and then when they get to the
action, check that the action is appropriate for the all of the
conditions.  But this is harder too, since it requires keeping a
bunch of things in your head, and inevitably this effort will push
something else out of your mental cache.

It is for essentially the same reason that functional
and logic languages allow procedures to be defined by
a sequence of clauses, e.g.
	
	append ([], list) = list
	append ((head : tail), list) = head : (append tail list)

rather than a single clause with an if or case expression.
The point is that it is much easier to verify a single
clause in isolation than to verify a clause involving a
complex logical expression.

Furthermore, IIRC your diff replaced code of the form

	/* comment here */
	var = foo();
	if (var == ...)
		do something;

	/* comment here */
	var = bar();
	if (var == ...)
		do same thing;

with code of the form

	/* comment here */
	if ((var = foo()) == ...
	    /* comment here */
	    || (var = bar()) = ...

This is worse for two reasons, one being that it combines side effects
with the conditions, and the other being that the lack of whitespace
between each condition makes it harder to look at each condition
in isolation.  (Adding blank lines in the condition is not a great
idea either, since that makes the first condition even further away
from the action.)

-- 
Fergus Henderson <fjh@cs.mu.oz.au>  |  "I have always known that the pursuit
                                    |  of excellence is a lethal habit"
WWW: < http://www.cs.mu.oz.au/~fjh >  |     -- the last words of T. S. Garp.



More information about the Gcc-patches mailing list