- The machine-independent code improvement phase performs transformations on the control flow graph.
- local code improvement - it modifies the instruction sequence within each basic block to eliminate redundant loads, stores, and arithmetic computations
- global code improvement - it also identifies and removes a variety of redundancies across the boundaries between basic blocks within a subroutine
- an expression whose value is computed immediately before an if statement need not be recomputed after else
- An expression that appears within the body of a loop need only be evaluated once if its value will not change in subsequent iterations
- Some global improvements change the number of basic blocks and/or the arcs among them
Back-End Compiler Structure Back-End Compiler Structure - The next phase of compilation is target code generation
- This phase strings the basic blocks together into a linear program, translating each block into the instruction set of the target machine and generating branch instructions (or “fall-throughs”) that correspond to the arcs of the control flow graph.
- The output of this phase differs from real assembly language primarily in its continued reliance on virtual registers
Back-End Compiler Structure Back-End Compiler Structure - The final phase of our example compiler structure consists of register allocation and instruction scheduling - machine-specific code improvement
- Register allocation requires that we map the unlimited virtual registers onto the bounded set of registers available in the target machine
- If there aren’t enough architectural registers to go around, we may need to generate additional loads and stores to multiplex a given architectural register among two or more virtual registers
- As described in Section 5.5, instruction scheduling consists of reordering the instructions of each basic block to fill the pipeline(s) of the target machine
Do'stlaringiz bilan baham: |