I seem to have acquired an acute fascination with the VAX architecture.
As part of that, I'm curious to know about the quality and methods employed by the old VAX compilers. Did they schedule the code? Did they use link-time optimizations? Did they have tables on the costs of various instructions? Did they have flags for targetting different members of the VAX family? How good were their register allocators? Did they inline functions? Did they generate alternate entrypoints where they could, in order to avoid the horrid CALLS/CALLG/RET instructions? Could they pass parameters in registers for functions that were only used "internally" in a module/program?
What tricks did they employ to get decent floating-point performance out of an architecture that wasn't really well-suited to that?
(16 "general-purpose registers, of which one was the PC, one was the SP, and two others were also used by the system. Floating-point operations used the same registers as integer operations, and double floating-point used register pairs. This puts a rather low limit on what you can keep in registers)
-Peter [As I recall, the answers to all of those questions was "sometimes", except that I don't recall any that generated model-specific code. -John]
The Design of an Optimizing Compiler William Allan Wulf 1980
Louis [I have both books. The first one tells you all about code generation for the Vax as done by their PL/I and C compiler. It was a pretty normal compiler for the late 70s, reasonable common subexpression handling and pre-graph-coloring register allocation. They spent a lot of effort in instruction selection, to use all of the Vax instructions and address modes. The Wulf book is a classic, but the target was the PDP-11, not the Vax. -John]
On Tue, 5 Jun 2006, Louis Krupp wrote: > You might find some of what you want in this book about DEC's PL/I compiler:
Thank you. It's on my wishlist now :)
> [I have both books. The first one tells you all about code generation > for the Vax as done by their PL/I and C compiler. It was a pretty > normal compiler for the late 70s, reasonable common subexpression > handling and pre-graph-coloring register allocation. They spent a lot
Which doesn't have to be bad at all.
> of effort in instruction selection, to use all of the Vax instructions > and address modes.
Interesting.
I found this paper:
Cheryl A. Wiecek, "A Case Study of VAX-11 Instruction Set Usage For Compiler Execution", 1982.
She instrumented six different compilers while they compiled to see what their dynamic instruction stream looked like.
Table 4 in the paper lists the frequency of the various addressing modes across the six compilers. One thing that is abundantly clear when looking at that table is that the VAX had many more addressing modes than it could reasonably use (some are not used at all or only used by .1 % of the instructions).
Another thing is that the PL/I compiler (itself implemented in PL/I) had a sweet tooth for word displacements (13.9%), whereas the BLISS, COBOL, and FORTRAN compilers (all implemented in BLISS) barely used it (0.9-2.0%). Autoincrement is not used much, except by the BASIC compiler (implemented in BASIC) where it is a whopping 17.4% (2.6-4.8% for the others). Autodecrement is barely used by anybody.
Register deferred (i.e. load/store of a datum stored at an address pointed to by a register, with no displacement) is barely used by the Pascal (2.0%) and PL/I (2.5%) compilers, used 4-5 times as often by the BASIC (9.0%), BLISS (8.6%), and FORTRAN (9.1%) compilers. Surprisingly, COBOL uses it almost twice as often (15.3%) as the other compilers implemented in BLISS.
Two-address instructions are used a lot more than I thought, which makes me very happy (47.2%).
(src, src, dst) three-address instructions were rare (3.2%!), which also makes me very happy. 23.4% of those were (literal, register, register).
Something that makes me less happy, is the very high frequency of branches (34.7% including calls and returns) and the short sequences between those branch-type instructions (3.9, including the branch!).
Actually, the difference between the implementation languages is very clear here: the compilers written in BLISS have almost identical sequence lengths (3.3-3.6 instructions / 12.2-13.0 bytes), whereas the others had longer sequences, both in terms of instructions and in terms of bytes. PASCAL and PL/I are similar for some reason (4.5-4.7 instructions / 18.7 - 19.0 bytes).
The paper talks a little bit about how the registers are used (about 40 lines) but it says nothing about how many registers were live at a time or about whether some of the loads and stores could have been eliminated.
I think an analysis of floating-point code could have been particularly revealing. She also doesn't say why so many branch-type instructions were necessary, neither does she look into how to reduce the marked overhead of using CALLG/CALLS/RET instructions instead of the more light-weight (BSB/JSB/RSB).
Does anybody know whether it was practical to use two entry-points for exported functions, a fast one and a slow one?
I don't know much about the internals of the VAX compilers other than they were all optimizing compilers that subscribed to the same calling standard, enforced by the VMS operating system and the one linker. That's why you could develop multiple modules of a software system in multiple languages (VAX-BASIC, VAX-FOTRAN, VAX-COBOL, etc) and link the object modules together into a single EXE file.
The VAX hardware and VMS Operating System were designed together and were a beautiful system. Digital Equipment Corporation (DEC) did a good job transitioning to Alpha and OpenVMS.
John Fredrickson
"Peter "Firefly" Lund" <fire...@diku.dk> wrote in message
On Wed, 07 Jun 2006 20:18:28 -0700, John Fredrickson <jaf...@verizon.net> wrote:
> Peter,
> I don't know much about the internals of the VAX compilers other than > they were all optimizing compilers that subscribed to the same calling > standard, enforced by the VMS operating system and the one > linker. That's why you could develop multiple modules of a software > system in multiple languages (VAX-BASIC, VAX-FOTRAN, VAX-COBOL, etc) > and link the object modules together into a single EXE file.
It goes a bit further. They developed a tool SDL, Structure Definition Language, which allow for data declarations in a language independent manner. By specifying the desired target language an include would be generated in that language, However, unlike Prime, DG or Wang, there was no common backend except for PL/I, C, Pascal and Pearl.
> The VAX hardware and VMS Operating System were designed together and > were a beautiful system. Digital Equipment Corporation (DEC) did a > good job transitioning to Alpha and OpenVMS.
I think you will get some argument on that, the Alpha instruction set left a lot to be desired, which is one reason a lot of the VAX objecrs were 'VEST'ed
Peter "Firefly" Lund wrote: > I seem to have acquired an acute fascination with the VAX architecture. > As part of that, I'm curious to know about the quality and methods > employed by the old VAX compilers.
(snip of a variety of questions about the compilers)
Used MicroVAX systems are fairly cheap, and if they are still too expensive, emulators are available. You can get a free hobbyist license to run any version of VMS or OpenVMS that you can find, and pretty many versions are available. The hobbyist license includes most of the compilers, and other programs that you might want to run.
The license restrictions are pretty much non-profit hobby usage, which sounds just like what you are interested in. See:
>>The VAX hardware and VMS Operating System were designed together and >>were a beautiful system. Digital Equipment Corporation (DEC) did a >>good job transitioning to Alpha and OpenVMS. > I think you will get some argument on that, the Alpha instruction set > left a lot to be desired, which is one reason a lot of the VAX objecrs > were 'VEST'ed
Really? AFAICT, the three main reasons for VESTing (binary translation with run-time support) were
- no source available (hah! so what else is new?) - the relevant compiler was not ported to Alpha (e.g., SCAN) - performance was good enough for the translated code, why bother with re-everythinging it?
Code heavily using the "commercial" instruction set suffered, but it was already suffering on the later VAX implementations. Sometimes the compiler upgrade helped - for instance, certain COBOL data types were implemented as BCD on VAX but changed to use native 64-bit integers on Alpha. VESTing such applications could only have made things worse.
On Mon, 12 Jun 2006 20:50:59 -0700, Jan Vorbrüggen
<jvorbrueg...@mediasec.de> wrote: >>> The VAX hardware and VMS Operating System were designed together and >>> were a beautiful system. Digital Equipment Corporation (DEC) did a >>> good job transitioning to Alpha and OpenVMS. >> I think you will get some argument on that, the Alpha instruction set >> left a lot to be desired, which is one reason a lot of the VAX objecrs >> were 'VEST'ed
> Really? AFAICT, the three main reasons for VESTing (binary translation > with run-time support) were
You are quite right, not sure what I had in mind when I wrote that, VESTing had nothing to do directly with the instruction, only in the manner you indicated.
> - no source available (hah! so what else is new?) > - the relevant compiler was not ported to Alpha (e.g., SCAN) > - performance was good enough for the translated code, why bother with > re-everythinging it?
> Code heavily using the "commercial" instruction set suffered, but it > was already suffering on the later VAX implementations. Sometimes the > compiler upgrade helped - for instance, certain COBOL data types were > implemented as BCD on VAX but changed to use native 64-bit integers on > Alpha. VESTing such applications could only have made things worse.
We discovered that when we ported PL/I to Tru64 (OSF-1) ca. 1994 That is just one of the many design flaws in the Alpha. Power PC (last time I looked some years ago) has only a one tick penalty for unaligned access, effectively making it a byte addressable machine. The early Alphas omitted sign-extend byte and 16-bit word moves so that an instruction like C = A + B; took 17 ticks if these were fixed bin(15) but only 4 if fixed bin(31)
The port itself was interesting, we used Jack Davidson's VPO as the backend and we modified and existing more-or-less traditional code generator to emit the RTLs for VPO. This required some hammering to support things like lexical scoping. The alignement requirements effect the performance of PL/I considerably.
Tom Linden wrote: > the Alpha instruction set left a lot to be desired
As one who amuses himself with both compilers and processor design, I'm curious what shortcomings the Alpha instruction set had. I only looked into it a little, and that a dozen or so years ago, but it looked pretty nice then...
our moderator wrote: >...normal compiler for the late 70s, reasonable common subexpression >handling and pre-graph-coloring register allocation. They spent a lot >of effort in instruction selection, to use all of the Vax instructions >and address modes...
Which in fact was a mistake, because on a good many of the VAX models, the code ran faster if you used only the simpler instructions and modes, and built up anything fancy as a multi-instruction sequence using them. The simple stuff often got fast-tracked during instruction decoding. Some of the inspiration of the RISC movement came from this.
(A good illustration of the penalty paid for all the VAX's complexity came from comparing the VAX 730 to the PDP-11/44. They came in the same box, and were roughly contemporary. The 730 CPU filled almost all of the box, to the point that some special two-in-one peripheral cards got invented just so you could build a complete system without needing an expansion box. The 44 CPU, despite making much less use of custom/semicustom LSI, occupied less than half of the box. And for problems that would fit in its 16-bit address space, the 44 was 2-3 times as fast.) -- spsystems.net is temporarily off the air; | Henry Spencer mail to henry at zoo.utoronto.ca instead. | he...@spsystems.net