C "neatener" - another example (#9)

Dan Klein dvk at mi-cec.UUCP
Mon Feb 20 07:26:06 AEST 1984

This is a continuation of my diatribe on "C doesn't optimize, it neatens".
In this and other articles, I compare a true optimizing compiler (Bliss-32
running under VMS) to a code neatener (C running under BSD 4.1c).  Any and
all counterexamples are welcome.  However, this is NOT a comparison of the
languages.  Both C and Bliss have their good and bad points.  This is simply
a comparison of the code they generate.  As in all examples, the source
code and uncensored assembly code is presented.  In all examples, the C source
and Bliss source are as nearly identical as language differences permit.  I
have not taken advantage of any "tricks" to get either language to perform
better or worse than the other.  The optimizer was enabled for both languages.

		-Dan Klein, Mellon Institute, Pittsburgh	(412)578-3382

In this example I declare three variables as register variables, clear them,
and pass them to a routine.  Well, C loses again.
	1) Each variable gets the same value (namely 0), but Bliss saves space
and time by having three CLRL's, while C does a CLRL and then MOVL's the first
register into the other two.  This is apparently a maneuver to save space when
the right hand side is complex (i.e. calculate it once, and then put the known
result into the other destinations).  It loses here, since s CLRL is faster
than a MOVL.
	2) C allocates R9, R10, and R11, while Bliss uses R0, R1, and R2.  This
in itself is no big deal, but the C routine has to save three registers on
routine entry, while Bliss only has to save 1 (namely R2, since R0 and R1 are
the return registers).  Compare the entry masks to see this.
	3) The biggest lose of them all!  C does three consecutive PUSHL's to
pass the arguments to "alpha".  Bliss knows that all the parameters are
registers, and does 1 PUSHR.  C could have done this too (i.e. the registers
are declared in the right order to do this).  While the register pushes take
the same amount of time, the instruction interpretation is slower in C, and
of course, the volume of code is greater.
external routine alpha;			|	extern  alpha();
routine TEST : novalue =		|	test()
	begin				|	{
	register a,b,c;			|	    register int a, b, c;
	a = b = c = 0;			|	    a = b = c = 0;
	alpha(.a, .b, .c);		|	    alpha(a, b, c);
	end;				|	}
					|		.data
	.TITLE  FOO			|		.text
					|	LL0:	.align  1
	.EXTRN  ALPHA			|		.globl  _test
					|		.set	L13,0xe00
	.PSECT  $CODE$,NOWRT,2		|		.data
					|		.text
TEST:	.WORD	^M<R2>			|	_test:  .word	L13
	CLRL	R2			|		clrl	r9
	CLRL	R1			|		movl	r9,r10
	CLRL	R0			|		movl	r10,r11
	PUSHR	#^M<R0,R1,R2>		|		pushl	r9
	CALLS	#3, W^ALPHA		|		pushl	r10
	RET				|		pushl	r11
					|		calls	$3,_alpha
					|		ret

More information about the Comp.lang.c mailing list