Messages in this thread | | | Date | Tue, 17 Nov 1998 03:16:25 GMT | From | "Theodore Y. Ts'o" <> | Subject | Re: The Kommunity vs. Dick Johnson |
| |
Date: Mon, 16 Nov 1998 08:17:25 -0500 (EST) From: Isaac Connor <iconnor@penultima.ml.org>
I am aware of many instances where gcc was able to produce better code than some asm-advocates I know. It also seems to me, that you have to look at register use, and how that affects code before and after the asm function.
This of course proves nothing. The real acid test is whether or not GCC can produce better code than the what the *best* asm-advocates can produce. For example, I've yet to see a version of gcc which can do a good job of compiling the MD5 crypto checksum. The problem is that you have to be really clever to keep all of the MD5 accumulators in registers, and every gcc I've played with fails to do this, and ends up placing at least one or more of the MD5 state variables on the stack. Hence, in general gcc doesn't seem to handle algorithms which puts pressure on the i386's absurdly small register file.
A programmer who knows what he or she is doing can usually do better register placement than GCC, simply because the i386's register file is so small and with many specialized uses of individual registers. This makes register placement critical, and in general, when I've had to look at the GCC-generated assembler, I haven't been impressed with the job that it's done. The MD5 algorithm is just one example which is proof-positive that gcc can't find a register allocation scheme which allows all of the MD5 variables to be left in registers, and a human-coded MD5 algorithm handily proves that it can be found --- it's just that GCC can't find it.
Also at last check, GCC doesn't know how to handle data-dependent rotates. i.e,
extern inline __u32 rotate_left(int i, __u32 word) { return (word << i) | (word >> (32 - i)); }
should compile to this:
extern inline __u32 rotate_left(int i, __u32 word) { __asm__("roll %%cl,%0" :"=r" (word) :"0" (word),"c" (i)); return word; }
.... but GCC doesn't know how to handle this sort of thing. (Which is why the /dev/random driver has an explicit inline __asm__ to take advantage of this very handy i386 instruction.)
The bottom-line is that the i386, being a CISC architecture, is such that it will be very hard for gcc to really take full advantage of the i386 instruction set. Thus, it's likely that hand-assemblers will have a much easier producing better code than gcc.
People who say that compilers can "obviously" always produce better code than hand-assemblers are usually parrotting the usual dogma heard in compiler classes. While it's usually true, there are notable exceptions, and it shouldn't be all that surprising that kernel programmers (and crypto programmers) have an easier time finding the sticky cases which gcc doesn't handle well at all.
- Ted
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |