Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!watmath!clyde!akgua!mcnc!idis!mi-cec!dvk From: dvk@mi-cec.UUCP (Dan Klein) Newsgroups: net.lang.c Subject: C "optimization" (4 of 8) Message-ID: <206@mi-cec.UUCP> Date: Tue, 14-Feb-84 14:23:40 EST Article-I.D.: mi-cec.206 Posted: Tue Feb 14 14:23:40 1984 Date-Received: Fri, 17-Feb-84 04:23:20 EST Lines: 65 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 show how the compilers allocate local variables. The test code declares two local variables, "a", and "b". By using flow analysis it can be seen that the use of "a" and "b" does not overlap. Now a really "great" optimizer would not bother moving the constant values into the local variables, and then pushing them on the stack (since it can also be seen that the only use of the local variable is a place holder). However, both compilers can be forgiven in that it is possible for a debugger to tell you the values of "a" and "b" if they occupy a location, while it is very difficult to make a debugger smart enough to look on the stack during a partially executed routine call. The comparison: 1) C is not smart enough to recognize that the use of the variables overlaps, and instead allocates two locations (on the stack) for them. Bliss on the other hand recognizes this fact, and shares a location for both the variables. DON'T tell me C does it so the debugger can distinguish between the two variables. If the VMS debugger is smart enough to tell the difference, then so can the Unix debuggers. 2) C allocates the variables on the stack, while Bliss chooses to use register 0. Even if Bliss had used two registers, it still could have used R1 and R0. C should also, but instead it plods around playing with the stack. The C code is larger, and also substantially slower. ----------------------------------------+------------------------------------- external routine alpha; | extern alpha(); | routine test(parm) : NoValue = | test() begin | { local a,b; | int a, b; | a = 2; | a = 2; alpha(.a); | alpha(a); b = 5; | b = 5; alpha(.b); | alpha(b); end; | } | | .TITLE FOO | .data | .text .EXTRN ALPHA | LL0: .align 1 | .globl _test .PSECT $CODE$,NOWRT,2 | .set L13,0x0 | .data TEST: .WORD ^M<> | .text MOVL #2, R0 | _test: .word L13 PUSHL R0 | subl2 $8,sp CALLS #1, W^ALPHA | movl $2,-4(fp) MOVL #5, R0 | pushl -4(fp) PUSHL R0 | calls $1,_alpha CALLS #1, W^ALPHA | movl $5,-8(fp) RET | pushl -8(fp) | calls $1,_alpha | ret