I'm bothered a bit about the use of llvm-mos (or really any C compiler) for developing low-level 6502 code. The 6502 is my favourite CPU, but it's not very well suited to C, and most C compilers don't emit well-optimized 6502 assembly compared to what a manual coder would do.
If he had to use a C compiler just so he didn't go insane, however (which I sympathize with), it seems to me that cc65 would have been a better choice and certainly more widely used. But most assemblers implement a good macro system which helps with sanity.
>The above code fills a graphics 8 screen. CC65 ran in 4587 jiffies while MOS did so in 2631. Another test leveraging lookups saw CC65 running in 2663 jiffies while MOS ran in 396 jiffies.
> I have C code that leverages page zero that brings CC65 down to 664 jiffies while MOS runs in 358.
Interesting post, thanks. It certainly seems like llvm-mos' codegen is improving markedly modulo some concerns brought up over bloat. But I also note that a number of the performance recommendations (prefer using more globals, avoid passing structures presumably due to the limited hardware stack) aren't exactly current programming convention - and for that matter, they're exactly what you would do writing assembly by hand. These recommendations would be true for cc65 too of course, but it still makes the point that using C to develop on 6502 is just making the dog walk, not the dog walking well.
The AtariAge results are fairly out-of-date; I think that's even before we started doing whole-program zero-page allocation.
The only real 6502-specific C caveat left for llvm-mos is that you should strongly prefer structs of arrays to arrays of structs; and that's not even that 6502-specific. Otherwise, standard C gives fairly tight assembly.
That being said, every couple hundred lines of generated assembly for any reasonably-sized C program will contain at least one WTF, from a human point of view. Removing those WTFs one at a time is the long tail of a compiler engineer. Still, I'm not going anywhere!
"As for the code itself, we perform a remarkably effective loop optimization that detects 16-bit index operations that can be converted to a 16-bit index plus an 8-bit offset. The latter is a directly-supported addressing mode on the 6502, and 8-bit index manipulation can be done in a single instruction.
This allows us to convert idiomatic 16-bit "int c" loops into something much more suitable for the 6502. Eventually, we hope that optimizations of this kind will transform standard, naive C code into tightly optimized 6502 code. "
I feel kinda sad that macro assembly is a lost branch of the programming language tree. to me it feels pretty lisp-like in that its more of an exercise in world-building than 'a then b then c'. it also makes it alot more feasible to use all those interesting processor-specific frobs.
I guess assemblers would have had to have evolved past fighting over intel vs at&t.
I mean, I think it suffers the same problem as lisp on that front. If you're coming into a codebase would you rather read boring C or try to figure out the mind of the person who crafted the lisp/macros in it?
Even C codebases can suffer this with obnoxiously clever macros, but it's rarer at least.
cc65 did not support the tricks he needed to do to support relocatable code, or at least he couldn't figure out how to get cc65 to support them. From another forum:
"I was going to do it all with cc65 but then couldn't figure out how to persuade cc65 to produce CP/M-65 binaries with the relocations"
If he had to use a C compiler just so he didn't go insane, however (which I sympathize with), it seems to me that cc65 would have been a better choice and certainly more widely used. But most assemblers implement a good macro system which helps with sanity.