24

I am self studying about compilers, and get hands on very good textbooks about the subject. I am thinking in develop a compiler using the almighty llvm infrastructure to cross compile to old computers, initially MSX ones. The thing is, i can't get an impression on how much benefit one could get on using this approach, over what is already on old compilers.

Obviously, the possibility to reuse code over different platforms is one, if a common compiler is to be developed, but the idea is getting the most of such processors, using modern optimization.

I understand that some obviously don't apply, like scheduling, but there is a lot of things that are done before code generation, and will be beneficial to every backend. The question i make is, how beneficial it will be to deliver such tool, compared to what is already on legacy compilers, and to modern ones too (sdcc and others). Also, how much this kind of effort could be beneficial to ease multi platform development (Uzix and the like) considering the severe restrictions on those platforms?

EDIT: I changed the subject of the question to reflect only MSX, to adjust the scope that was too broad.

9
  • This feels a little too broad, and likely off-topic. Targeting "old" processors is done by cross-compilers as a matter of course, and few of the folks doing that consider what they are doing "retro".
    – user12
    Commented Apr 22, 2016 at 16:07
  • There are tools for developing software for old computers, and people developing soft for those computers. Doing new soft for old hardware is a common activity on retrocomputing. Obviously the compiler will not be retro, but will be used for retro. :)
    – flavio
    Commented Apr 22, 2016 at 16:27
  • 1
    Coding is coding, and techniques are techniques and tools are tools. My main. Issue is that this question feels too broad.
    – user12
    Commented Apr 22, 2016 at 17:05
  • 6
    I think it's on-topic, but too broad. You can't do branch-prediction optimization without a branch predictor, you can't do out-of-order scheduling on an in-order CPU, you can't do cache alignment without a cache, register allocation strategies are very different if you've only got one register, loop unrolling is bad if you've only got 2K of RAM, and so on. If you want to ask about how specific techniques apply to specific processors, go ahead, but "modern compiler techniques" and "old processors" are simply too broad.
    – Mark
    Commented Apr 22, 2016 at 17:59
  • Ok, i understand the point. I will change "initially MSX", to focus on MSX, and make specific questions to other platforms when get to that point on development.
    – flavio
    Commented Apr 22, 2016 at 18:16

5 Answers 5

24

Places where LLVM will provide no benefit, and may reduce performance:

  • The Z80 has no CPU cache, accessing memory directly instead. Any optimizations based around increasing cache efficiency (eg. aligning sequentially-accessed data to fit in a single cache line, or re-ordering instructions to group common execution paths together) will have, at best, no effect.
  • The Z80 is a strictly in-order CPU with just a single execution unit. Optimizations such as instruction re-ordering to permit out-of-order or parallel execution will have no effect.
  • The Z80 has a shallow-to-nonexistent pipeline and no speculative execution. Optimizations based around branch prediction or preventing pipeline stalls will have no effect.
  • The Z80 is often paired with a small amount of RAM. Many optimizations (such as loop unrolling or function inlining) make the program larger, and can't be used if the program would no longer fit in RAM.

Places where LLVM will shine:

  • Anything based on abstract analysis of the code, such as constant folding or common-subexpression elimination. Many of these techniques were developed long after the original Z80 compilers.
  • Register allocation: The Z80 has approximately 17 registers (depending on how you count), with complex rules about how you can use them. LLVM's design can draw on 30-40 years of research in this area that older compilers can't.

The improvement in abstract-analysis techniques in the past 40 years is huge. Even in the absence of hardware-specific optimizations, I'd expect LLVM-generated code to be much faster than that from older compilers, and competitive with all but the best hand-optimized assembly.

9
  • do you think that intrinsics can be useful on the context of eliminating the inline assembly, or the optimizations will make a better job and render them useless?
    – flavio
    Commented Apr 23, 2016 at 14:44
  • That's something you'll have to figure out by benchmarking.
    – Mark
    Commented Apr 23, 2016 at 18:22
  • Those disadvantages are common with modern mcu parts. I'm not sure if LLVM targets those effectively yet, but presumably its only a matter of time - noone wants to maintain more architectures going forward than necessary. Commented Jun 2, 2016 at 8:04
  • 2
    Well, actually, you can benefit from branch predictions for Z80, because following or not following a conditional jp/call/ret takes a different amount of time. Using a faster option for a more common pathway would speed the program up. Of course, the difference is tiny and would only matter inside of the tightest of loops.
    – introspec
    Commented Oct 26, 2017 at 7:41
  • 2
    The massive increase in computing resources will also allow the compiler to try more advanced optimization than would have been possible in the past. Even the most powerful mainframes of the 70s-80s had limited computing power compared to a current laptop. Commented Oct 26, 2017 at 16:05
11

Z88DK is a suite of development tools for Z80 targets that includes a couple of different C compilers (one a variant of Small C and one a patched version of SDCC) and an assembly-level optimizer that is run as a post-filter on the output of these compilers. It also has a highly hand-optimized library.

They've published a set of benchmarks versus some older Z80 compilers (e.g. HISOFT-C and SDCC without their updates/optimizer) that depending on application show gains from 15% (Dhrystone) to 300% (Pi calculation). At the same time they show gains in code size varying from 7% to about 90% (I presume due to elimination of large chunks of duplicate code). Floating point performance is lower than some of the older compilers however - but that's because they're using higher-precision 48-bit floats rather than the 32-bit floats used by the older compilers.

It is able to target a variety of platforms including MSX, CP/M, and many of the early 80s home computers that used Z80 CPUs.

1
  • They are even using llvm! Very good to know.
    – flavio
    Commented Dec 15, 2017 at 1:12
7

i can't get an impression on how much benefit one could get on using this approach, over what is already on old compilers.

If that were true, then old games would be developed using those old compilers, instead of hand-coded assembly. Old compilers were, mostly, very naive in terms of code optimization due to they being executing in the very same system they are producing code for, thus suffering from severe lack of precious RAM that would be needed to implement more sophisticated optimization techniques.

1
  • Yes, good point. I'm trying to get some feedback on how much benefit will be achieved because there is some modern compilers that do some good work, but improving those (sdcc, even gcc have a z80 generator) apparently have less effort than expected. I just don't know if it is because is difficult to improve the backend for, say, gcc, or the benefit will be minimal and people just don't bother.
    – flavio
    Commented Apr 22, 2016 at 17:25
7

regular user of the MSX-C compiler here. MSX-C is a rebranded version of the LSI-C 80 compiler bundled with an MSX-specific library. It comes with the same limitations and benefits:

  • PRO: When calling functions, MSX-C passes arguments on the CPU registers instead of the stack (as SDCC or Hitech-C do). This results in a big performance improvement in programs that do a lot of function calling.

  • CON: The compiler doesn't do any memory switching during the compile process. This means that you run out of memory quickly when developing complex programs. This forces the developer to split the program in smaller units and compile/link per parts.

  • CON: MSX-C only understands K&R C. SDCC and Hitech-C support more modern dialects of C.

  • PRO: MSX-C runs natively on the MSX. There's no need to waste time compiling under Linux/Windows and moving the binary to the MSX.

In my opinion, just writing a compiler for MSX able to use the memory mapper would be a huge improvement. Running out of memory is the biggest annoyance I've found so far.

7
  • When you say "The compiler doesn't do any memory switching during the compile process" you are stating that the compiler doesn't use the memory for itself, or doesn't compile softwares that use more (if existent) memory?
    – flavio
    Commented Apr 23, 2016 at 16:46
  • Sorry for the late reply. Just saw your comment now. I meant that the compiler itself doesn't use the memory. Even if your computer has 256KB or more the compiler only uses the 64KB mapped into the Z80 address space, often running out of memory. Commented May 4, 2016 at 14:45
  • wow, thats sad :) The compiler itself doesn't comply with the MSX standard... Thanks for the reply.
    – flavio
    Commented May 5, 2016 at 15:26
  • Nobody said that the compiler doesn't comply with the MSX standard. I only said it doesn't use mapped memory. Commented May 7, 2016 at 5:37
  • mapped memory isn't a standard on msx? I need to read more :p
    – flavio
    Commented May 7, 2016 at 16:56
1

I would reply in a more cagey fashion. It would certainly be useful to have a better C compiler for Z80 - the existing ones are not producing very good code. It is also clear that a number of people are experimenting, even with these not very good compilers, and end up creating new and useful software. Some of these software are definitely not bad. My real concerns are as follows:

  • It is clear that you ought to be able to write a better compiler than the existing ones. It is not clear if you can write a really good compiler - the one that would tempt asm coders to switch, because the gap between a good asm code and a good compiled code on Z80 platforms at the moment is massive.
  • Part of the problem is to do with the fact that C was not really designed with 8-bit platforms in mind. The vast majority of the code assumes at least 16-bit int; the local variables cannot be efficiently allocated on stack and addressed on Z80, which makes implementation of function parameters very painful, especially with recursion allowed. It can all be supported, of course, but at the cost of writing significantly less efficient code. To address this things properly you would need to make changes to the language itself, and that will put a lot of people off.
  • To make matters worse, a lot of paradigms for efficient Z80 coding are really not fitting into C. Things like movable stack pointers, self-modifying code, partial loop unrolling are just not catered for. Just like every Z80 coder, I would love to see a compiler with a bit of intuition for the use of Z80 registers, but I do not hold much hope.
10
  • Compared with the 6502 for example, I thought the Z80 doesn't deal all that badly with C code. I'd be interested to see some concrete examples of the kinds C constructs you mean. Commented Oct 26, 2017 at 9:00
  • If one has an array less than 256 bytes, there are three ways it can be placed: 1. Aligned with a 256-byte page; 2. Aligned so that it doesn't cross a 256-byte page; 3. Arbitrarily. Approach #1 is much faster than #2, which is in turn much faster than #3. C offers no way to exploit such layouts.
    – supercat
    Commented Oct 26, 2017 at 14:52
  • 2
    The C language may not support these paradigms, but there's nothing preventing a C compiler from supporting them. Loop unrolling, partial or otherwise, has been supported by optimizing compilers for decades, and aligning data for efficiency has been around even longer.
    – Mark
    Commented Oct 26, 2017 at 19:21
  • 1
    Why discuss 6502 at all if we are talking about C on Z80?! The fundamental issue that I mentioned explicitly is allocation of local variables. You kind of have to do it on the stack, thus you would have to do awkward manipulations with SP. Static allocation would break the recursion.
    – introspec
    Commented Oct 27, 2017 at 10:29
  • 1
    @Wilson: For code that doesn't need to use recursion or do anything too tricky with function pointers, there would be no particular difficulty making a C-to-6502 compiler that could generate decent code, and could overlay the automatic variables of functions that wouldn't be in scope simultaneously. Generating good code for the 6502 under such circumstances would likely be easier than doing so for the Z80.
    – supercat
    Commented May 7, 2018 at 20:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .