< previous page page_118 next page >

Page 118
The use of code optimization in a compiler can reduce superfluous load and store instructions, provide better register utilization, and reduce the number of unconditional branches, but does not affect source-code-specified actions.
The invariant operations include those that consume the most time on a per-instruction basis. These are the so-called run-on instructions that will be described in Chapter 4. They are also the most expensive operations to speed up. The overhead instructions can be minimized by compiler optimization, but unfortunately they are also the ones that execute most rapidly, especially in modern pipelined machines, thus eliminating exactly those instructions that can be made easiest to execute.
Recognizing this, designers have proposed the RISC architectural approach (L/S) that does not reduce the number of overhead instructions [?]. Their goal is to accept a relatively large occurrence of overhead instructions, but to simplify the overall structure of the machine so that cycle time can be reduced. Any additional available hardware can then be used to speed up the invariant instructions (e.g., faster floating-point operations or the use of register windows to improve call/return). As a consequence, the number of formats (the code density) is reduced; this increases the dynamic size of the program as it is interpreted by the machine. This simplifies the task of machine design per se, but increases the scope, size, and complexity of the (on-and off-chip) cache system, since large resulting program sizes require larger caches to maintain a reasonable cache "hit" rate.
2.6.4 Code Density
The instruction set has two general effects on processor design. It has a direct effect on the complexity of a processor implementation, and it partially determines the effectiveness of memory use through its corresponding code density (Figure 2.40).
Code density is simply a measure of the instruction traffic; it is the reciprocal of the number of (instruction) bits required to execute a program (the dynamic program size) normalized by the dynamic HLL operation count. Code density is not directly related to the amount of time it takes to execute any particular instruction. Code density cannot be ignored, as we shall see in Chapter 5. On the one hand, if one encodes the instruction stream so as to complicate the decoding of the instruction, as in the VAX, the performance of the processor can decrease dramatically. On the other hand, low code density results in large dynamic program sizes, which require large instruction buffers and large caches to provide required instruction bandwidth.
The canonic HLL instructions are generally the same as the invariant instructions mentioned in the previous section. The instruction set and the level of compiler optimization determine the number of additional instructions that are required to execute a program. The way each instruction is encoded determines the average size of the instruction. The number of instructions that appear in the execution of a program is largely a function of the format set. The encoding of the instruction is a function of the number of formats and the particular type of code used to represent objects.

 
< previous page page_118 next page >