Using GCC as an Efficient, Portable Back-End

In order to generate eecient object code for modern microprocessors , aggressive compilers customize their code generators (the back-end of the compiler) for each target processor. Customized back-ends, however, are major undertakings that most experimental compilers writers cannot aaord. We describe a method to easily generate eecient object code for virtually any UNIX platform. The method relies on Gnu's GCC compiler and its extensions to the C language. These techniques have been applied to pHluidd1], a pH/Id compiler. The techniques, their application to pHluid and some performance results are reported in this paper. 1 Introduction Making the best use of modern microprocessors requires very sophisticated instruction scheduling due to their multiple instruction issuing capabilities and longer pipelines. To generate the best possible code, aggressive compilers customize back-ends for each supported architecture. Such back-end customization requires substantial time as well as signiicant expertise in the target architecture, assets that small compiler eeorts generally do not have. An attractive solution to an experimental compiler writer is to compile to a standard language such as C and let the C compiler do the nal code generation. Such a technique is desirable because generating the code becomes trivial, the generated code is extremely portable and it can use a large body of existing support libraries and tools. In fact, many language implementations, such as Scheme2C, F2C (For-tran), P2C (Pascal), and Kyoto Common Lisp are all compiled to C rather than directly to object code. Though there is some loss of eeciency, the loss is relatively small since the execution model of these languages is essentially the same as C's. Procedures in the source languages correspond to procedures in C, and the programmers using those languages are used to making the same decisions as programmers writing native C. For programming languages that naturally generate very short threads of control which we will call multithreaded languages , however, the overhead of the general C procedure call mechanism is too high. Short threads do not need to build the C procedure linkage nor allocate a C stack frame, and generally pass very few, if any, variables. Thus, a simple jump is a suucient mechanism to transfer control for multi-threaded code and register passing conventions are suucient for passing values. Support for such operations is found on virtually all modern microprocessors in the form of fast branches which look-ahead in the instruction stream and large register sets. A …