mc6809e wrote:
I know it's a bit off-topic but do you think the C language held back the 68K in the processor wars? I always felt that C favored processors with a small register set. Often many of the 68K's registers would be idle in compiled code.
It's an interesting question - there is probably something in it. The gains which can be had from handcoding vs compiling on 68k are quite clear.
Both register count and instruction complexity can cause problems for code generation. It's much easier to do consistently with RISC, being more fine-grained. Register count *shouldn't* really be a problem if the compiler generates a decent data flow graph through its IL and the backend is doing things sensibly with that. But in the case of GCC and 68k, that might not be true. The backend is now much older than the compiler and probably full of heuristics and rules-of-thumb (which don't scale well).
Looking at the code produced by GCC4, it does a fair job and uses most of the registers most of the time, but it does really bizarre things on a regular basis. It also uses 'un-optimizations' which are both more complex and slower than a simpler solution. I expect a lot of that has to do with type range safety, which is always pretty lax in handwritten asm programs because the coder tends to know how many bits are active at any point in the code, and where overflows matter. If you index an array in C using an unsigned short, it looks innocent but causes the compiler grief since there is no such addressing mode - you get various kinds of mess generated to cope with those near-invisible foibles. Mul/div arithmetic has even worse problems in this area. I get caught out with that all the time and have to keep checking it.
Some of the codegen quality issues are probably due to the slow, organic way compiler technology grew from the early days and the regular change of worldview on 'ideal hardware'. On the one hand compilers were trying to make optimizations based on 'knowledge' of existing chips, while chip makers were doing the opposite - looking at the most frequently used ops and doing trades in silicon to speed up the most common ones emitted by compilers, at the cost of others. So it got especially messy during the 68020/30/40 and 386/486 era.
Another problem with 68k platform code generation is the large variety of hardware and notions about memory speeds etc. Some of that makes a mockery of optimizations in the compiler. Sticking a 68030 on a 16bit bus (or halving the clock rate of the bus) causes extra problems in that area. The compiler tries to optimize based on what it expects and ends up doing the opposite.
While there are plenty of problems with performance of compiled code when looking closely at it, I think the most significant one is the fact that high level languages don't translate structurally to optimal assembly programs, because there is no sense of resource competition. You could make one tiny tweak to a C program and suddenly lose 20% of your performance. Without studying the disassembly the reason might be out of reach. There isn't really a solution to that - they are very different ways to do something.
Having said all that - the compiler (even on 68k) can generate better code globally than anyone by hand. i.e. it doesn't get bored. A coder can focus better on obvious, intensive areas but if the program is just big and sprawling and there are no really obvious targets to optimize, the compiler can pretty much always do a better job just through automation and scale.