0% found this document useful (0 votes)
58 views

Code Generation and Optimization

Uploaded by

vakame5133
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
58 views

Code Generation and Optimization

Uploaded by

vakame5133
Copyright
© © All Rights Reserved
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 42

Injibara University

Department of Computer Science


Compiler Design (CoSc3112)

Chapter 8: Code Generation and Optimization


Minychil F.
Contents
Chapter 8: Code Generation and Optimization (4hr)
8.1. Simple Code Generation

8.2. Register Allocation

8.3. DAG Representation

8.4. Peephole Optimization Techniques


Introduction to Code Generation
 The final phase in compiler model is the code generator.

 It takes as input an intermediate representation of the source program and produces as


output an equivalent target program.

 The code generation techniques presented below can be used whether or not an
optimizing phase occurs before code generation.
Cont…
 The source code written in a higher-level language is transformed into a
lower-level language that results in a lower-level object code should have
the following minimum properties:
It should carry the exact meaning of the source code.
It should be efficient in terms of CPU usage and memory management .
Issues in the design of a code generator
Code generator converts the intermediate representation of source code into
a form that can be readily executed by the machine.
The following issues arise during the code generation phase :
1. Input to code generator

2. Target program

3. Memory management

4. Instruction selection

5. Register allocation

6. Evaluation order
TARGET MACHINE
 Familiarity with the target machine and its instruction set is a prerequisite for
designing a good code generator.

 The target computer is a byte-addressable machine with 4 bytes to a word.

 It has n general-purpose registers, R0, R1, . . . , Rn-1.

 It has two-address instructions of the form:

op source, destination
where, op is an op-code, and source and destination are data fields.
Cont…
 It has the following op-codes :
 MOV (move source to destination)

 ADD (add source to destination)

 SUB (subtract source from destination)

 The source and destination of an instruction are specified by combining registers


and memory locations with address modes.

 For example :
 MOV R0, M stores contents of Register R0 into memory location M ;

 MOV 4(R0), M stores the value contents(4+contents(R0)) into M.


A SIMPLE CODE GENERATOR
• A code generator generates target code for a sequence of three- address
statements and effectively uses registers to store operands of the
statements.
• For example: consider the three-address statement a := b+c
• It can have the following sequence of codes:
ADD Rj, Ri Cost = 1 // if Ri contains b and Rj contains c
(or)
ADD c, Ri Cost = 2 // if c is in a memory location
(or)
MOV c, Rj Cost = 3 // move c from memory to Rj and add
ADD Rj, Ri
Cont…
Instruction costs :
 Instruction cost = 1+cost for source and destination address modes. This cost
corresponds to the length of the instruction.
 Address modes involving registers have cost zero.

 Address modes involving memory location or literal have cost one.

 Instruction length should be minimized if space is important. Doing so also


minimizes the time taken to fetch and perform the instruction.
 For example : MOV R0, R1 copies the contents of register R0 into R1. It has cost
one, since it occupies only one word of memory.
Cont…
The three-address statement a : = b + c can be implemented by many different
instruction sequences :
i) MOV b, R0
ADD c, R0 cost = 6
MOV R0, a
ii) MOV b, a
ADD c, a cost = 6
iii) Assuming R0, R1 and R2 contain the addresses of a, b, and c :
MOV *R1, *R0
ADD *R2, *R0 cost = 2
In order to generate good code for target machine, we must utilize its addressing
capabilities efficiently.
Cont…
• Register and Address Descriptors:
A register descriptor is used to keep track of what is currently in each registers.

The register descriptors show that initially all the registers are empty.

An address descriptor stores the location where the current value of the name
can be found at run time.
A code-generation algorithm:
• The algorithm takes as input a sequence of three-address statements
constituting a basic block. For each three-address statement of the form x :
= y op z, perform the following actions:
1. Invoke a function getreg to determine the location L where the result of the
computation y op z should be stored.
2. Consult the address descriptor for y to determine y’, the current location of y.
Prefer the register for y’ if the value of y is currently both in memory and a
register. If the value of y is not already in L, generate the instruction MOV y’ , L to
place a copy of y in L.
3. Generate the instruction OP z’ , L where z’ is a current location of z.
Prefer a register to a memory location if z is in both. Update the address descriptor
of x to indicate that x is in location L. If x is in L, update its descriptor and remove
x from all other descriptors.
4. If the current values of y or z have no next uses, are not live on exit from the
block, and are in registers, alter the register descriptor to indicate that, after
execution of x : = y op z , those registers will no longer contain y or z
Cont…
Generating Code for Assignment Statements:
• The assignment d : = (a-b) + (a-c) + (a-c) might be translated into the
following three address code sequence:
t:=a–b

u:=a–c

v:=t+u

d : = v + u with d live at the end.


Code sequence for the example is:
Cont…
Generating Code for Indexed Assignments
• The table shows the code sequences generated for the indexed
assignment statements a : = b [ i ] and a [ i ] : = b
Cont…
Generating Code for Pointer Assignments
• The table shows the code sequences generated for the pointer assignments
a : = *p and *p: =a
Cont…
Generating Code for Conditional Statements
Register Allocation
• Register allocation is an important step in code generation and
optimization processes in compilers.

• It involves assigning variables and values to a limited number of registers


in a computer system.

• The goal of register allocation is to minimize memory accesses, which are


typically slower than register accesses, and to optimize the usage of
available registers for efficient execution of the generated code.
Cont….
The register allocation process typically involves the following steps:
1. Variable Lifetime Analysis.

2. Register Interference Analysis.

3. Register Allocation Algorithms.

4. Spilling and Spill Code


• Spilling refers to the process of storing variables in memory temporarily when there are not enough registers to
hold all variables simultaneously.

• Spill code is additional instructions inserted into the generated code to move variables between registers and
memory.

5. Optimizations: Register allocation is often performed in conjunction with other optimizations


THE DAG REPRESENTATION FOR BASIC BLOCKS
 A basic block is a sequence of consecutive statements
in which flow of control enters at the beginning and
leaves at the end without any halt or possibility of
branching except at the end.

 The following sequence of three-address statements


forms a basic block:
t1 : = a * a

t2 : = a * b

t3 : = 2 * t2

t4 : = t1 + t3

t5 : = b * b

t6 : = t4 + t5
Cont…
 A DAG for a basic block is a directed acyclic graph with the following labels on
nodes:
1. Leaves are labeled by unique identifiers, either variable names or constants.

2. Interior nodes are labeled by an operator symbol.

3. Nodes are also optionally given a sequence of identifiers for labels to store the computed values.

 DAGs are useful data structures for implementing transformations on basic blocks.

 It gives a picture of how the value computed by a statement is used in subsequent


statements.

 It provides a good way of determining common sub - expressions.


Algorithm for construction of DAG
Cont…
Stages in DAG Construction
Cont…
Stages in DAG Construction
Cont…
Stages in DAG Construction
Cont…
Stages in DAG Construction
Cont…
Stages in DAG Construction
Cont…
Stages in DAG Construction
Class Works
• t0 = a + b
• t1 = t0 + c
• d = t0 + t1
Code Optimization
 The code produced by the straight forward compiling algorithms can often
be made to run faster or take less space, or both. This improvement is
achieved by program transformations that are traditionally called
optimizations.
 Compilers that apply code-improving transformations are called optimizing
compilers.
Cont…
• The code optimization in the synthesis phase is a program transformation
technique, which tries to improve the intermediate code by making it consume fewer
resources (i.e. CPU, Memory) so that faster-running machine code will result.

• Compiler optimizing process should meet the following objectives: -


 The optimization must be correct, it must not, in any way, change the meaning of the program.

 Optimization should increase the speed and performance of the program.

 The compilation time must be kept reasonable.

 The optimization process should not delay the overall compiling process
Cont…
• When to Optimize?
Optimization of the code is often performed at the end of the development stage
since it reduces readability and adds code that is used to increase the performance.
• Why Optimize?
Optimizing an algorithm is beyond the scope of the code optimization phase. So
the program is optimized. And it may involve reducing the size of the code.
So optimization helps:
1. Reduce the space consumed and increases the speed of compilation.
2. Manually analyzing datasets involves a lot of time. Hence we make use of software like
display for data analysis. Similarly manually performing the optimization is also tedious and
is better done using acode optimizer.
3. An optimized code often promotes re-usability
Types of Code Optimization
1. Machine Independent Optimization
• This code optimization phase attempts to improve the intermediate code to get a better
target code as the output.
• The part of the intermediate code which is transformed here does not involve any CPU
registers or absolute memory locations OR
• Transforms a program that improve the target code without taking into consideration any
properties of the target machine
2. Machine Dependent Optimization
• Machine-dependent optimization is done after the target code has been generated and
when the code is transformed according to the target machine architecture.
• It involves CPU registers and may have absolute memory references rather than relative
references.
• It is based on register allocation and utilization of special machine-instruction sequences.
Code Optimization
 The criteria for code improvement transformations:
1. The transformation must preserve the meaning of programs
2. Transformation must, on the average, speedup programs by a measurable amount
3. The transformation must be worth the effort
Code Optimization
Function-Preserving Transformations
 There are a number of ways in which a compiler can improve a program without
changing the function it computes

 Function preserving transformations examples:


Common sub expression elimination

Copy propagation,

Dead-code elimination

Constant folding
Where to apply Optimization?
1. Source program
 Optimizing the source program involves making changes to the algorithm or changing the
loop structures. User is the actor here.

2. Intermediate Code
 Optimizing the intermediate code involves changing the address calculations and
transforming the procedure calls involved. Here compiler is the actor.

3. Target Code
 Optimizing the target code is done by the compiler. Usage of registers, select and move
instructions is part of optimization involved in the target code
Phases of Optimization
• There are generally two phases of optimization:

1. Global Optimization:
Transformations are applied to large program segments that includes functions,
procedures and loops.

2. Local Optimization:
Transformations are applied to small blocks of statements.

The local optimization is done prior to global optimization


Peephole Optimization
• A statement-by-statement code-generations strategy often produces target code that
contains redundant instructions and suboptimal constructs.

• The quality of such target code can be improved by applying “optimizing”


transformations to the target program.

• A simple but effective technique for improving the target code is peephole
optimization, a method for trying to improving the performance of the target program
by examining a short sequence of target instructions (called the peephole) and
replacing these instructions by a shorter or faster sequence, whenever possible.
Peephole Optimization Techniques

• Peephole optimization is an optimization technique performed on a


small set of compiler-generated instructions;

• The small set is known as the peephole or window.

• Peephole optimization involves changing the small set of instructions


to an equivalent set that has better performance
PEEPHOLE OPTIMIZATION
• The peephole is a small, moving window on the target program.

• The code in the peephole need not be contiguous, although some implementations do
require this. It is characteristic of peephole optimization that each improvement may
spawn opportunities for additional improvements.
cont
 Characteristics of peephole optimizations:
Redundant-instructions elimination

Flow-of-control optimizations

Algebraic simplifications

Use of machine idioms/expressions

Unreachable Code
End of chapter

You might also like