0% found this document useful (0 votes)
5 views46 pages

Compiler Design Lec-8Code Generation and Optimization

Chapter 8 discusses code generation and optimization in compiler design, detailing the processes involved in transforming intermediate representations into target programs. Key topics include issues in code generation, memory management, instruction selection, register allocation, and basic block transformations for optimization. The chapter also covers the use of directed acyclic graphs (DAGs) for representing basic blocks and the importance of local and global optimizations to enhance program efficiency without altering its functionality.

Uploaded by

Seladdin Yassin
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
5 views46 pages

Compiler Design Lec-8Code Generation and Optimization

Chapter 8 discusses code generation and optimization in compiler design, detailing the processes involved in transforming intermediate representations into target programs. Key topics include issues in code generation, memory management, instruction selection, register allocation, and basic block transformations for optimization. The chapter also covers the use of directed acyclic graphs (DAGs) for representing basic blocks and the importance of local and global optimizations to enhance program efficiency without altering its functionality.

Uploaded by

Seladdin Yassin
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPTX, PDF, TXT or read online on Scribd
You are on page 1/ 46

CHAPTER 8

Code Generation and Optimization


Wachemo University(Durame Campus)
College of Engineering and Technology
Department of Computer Science

Mr. Abraham Wolde(2025)

1
Outlines

 Simple Code Generation


 Register Allocation
 DAG Representation
 Peephole Optimization Techniques Teaching
Introduction to Code Generation and Optimization
 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.

05/29/2025 3
Issues in the Design of a Code Generator
 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

05/29/2025 4
Input to the Code Generator
 The input to the code generation consists of the intermediate
representation of the source program produced by front end, together
with information in the symbol table to determine run-time addresses
of the data objects denoted by the names in the intermediate
representation.
 There are several choices for the Intermediate language representation
that can be:-
♦ Linear representation such as postfix notation
♦ Three address representation such as quadruples
♦ Virtual machine representation such as stack machine code
♦ Graphical representations such as syntax trees and DAGs.
05/29/2025 5
 Prior to code generation, the front end must be scanned, parsed and
translated into intermediate representation along with necessary type
checking.
 Therefore, input to code generation is assumed to be error-free.
 The code generation phase can therefore proceed on the assumption
that its input is free of errors.
 In some compilers, this kind of semantic checking is done together
with code generation.

05/29/2025 6
Target Programs
 The output of the code generator is the target program, like the

intermediate code, this output may be take on a variety of forms:-


a) Absolute machine language:- It can be placed in a fixed memory
location and can be executed immediately.
b) Relocatable machine language:- It allows subprograms to be
compiled separately. A set of relocatable object modules can be
linked together and loaded for execution by a linking loader.
c) Assembly language:- Code generation is made easier. Producing an
AL program as output makes the process of code generation
somewhat easier. We use assembly code as the target language for
readability. 7
Memory management
 Names in the source program are mapped to addresses of data objects
in run-time memory by the front end and code generator.
 It makes use of symbol table, that is, a name in a three-address
statement refers to a symbol-table entry for the name.
 Labels in three-address statements have to be converted to addresses
of instructions.

05/29/2025 8
Instruction Selection
 The instructions of target machine should be complete and uniform.
 The uniformity and completeness of the instruction set are important
factors.
 If the target machine does not support each data type in a uniform
manner, then each exception to the general rule requires special
handling.
 Instruction speeds and machine idioms are other important factors
when efficiency of target program is considered. That means; if we do
not care about the efficiency of the target program, instruction
selection is straightforward.
 The quality of the generated code is determined by its speed and size.
05/29/2025 9
 For example, every three-address statement of the form x: =y+z
where x, y, and z are statically allocated, can be translated into the
code sequence
 MOV y, RO /* Load y into register RO */
 ADD z, RO /* add z to RO */
 MOV RO, x /* store RO into x */
 Unfortunately, this kind of statement-by-statement code generation
often produces poor code. For example, the sequence of statements
 Here fourth statement is redundant.
 So, it can be eliminated.

05/29/2025 10
Register Allocation
 Instructions involving register operands are usually shorter and
faster than those involving operands in memory.
 Therefore, efficient utilization of registers is particularly important in
generating good code.
 The use of registers is often subdivided into two sub problems:
♦ During register allocation, we select the set of variables that will
reside in registers at a point in the program is selected.
♦ During a subsequent register assignment phase, we pick the
specific register that a variable will reside in.

05/29/2025 11
Evaluation Order
 The order in which computations are performed can affect the
efficiency of the target code.
 Some computation orders require fewer registers to hold intermediate
results than others.
 But, Picking up a best order is another difficult problem.
 Initially, we shall avoid the problem by generating code for the three-
address statements in the order in which they have been produced-by
the intermediate code generator.

05/29/2025 12
THE 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, source &
destination are data fields.
 It has the following op-codes:-
 MOV (move source to destination)
 ADD (add source to destination)
 SUB (subtract source from destination)
05/29/2025 13
Run-time Storage Management
 Information needed during an execution of a procedure is kept in a
block of storage called an activation record, which includes storage
for names local to the procedure.
 The two standard storage allocation strategies are:-
1) Static allocation:- the position of an activation record in
memory is fixed at compile time.
2) Stack allocation:- a new activation record is pushed onto the
stack for each execution of a procedure. The record is popped
when the activation ends.

05/29/2025 14
Basic Blocks and Flow
Graphs

05/29/2025 15
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 halt or
possibility of branching except at the end.
 It is a sequence of the intermediate code with a single entry and single
exit.
 The following sequence of three-address statements forms a basic
block.

 A name in a basic block is said to be live at a given point if its value is


used after that point in the program or in basic block.
05/29/2025 16
Basic Block Construction:

05/29/2025 17
 Consider the following source code for the dot product of two
vectors a and b of length 20
 A list of three address statements performing this computation on our
target machine is

05/29/2025 18
 Statement (1) is a leader by rule (i)
 Statement (3) is a leader by rule (ii), since the last statement can jump
to it.
 By rule (iii) the statement following (12) is a leader.
 Therefore, statements ( I) and (2) form a basic block,
 The remainder of the program beginning with statement (3) forms a
second basic block.

05/29/2025 19
Transformations on Basic Blocks
 A basic block computes a set of expressions. These expressions are
the values of the names live on exit from the block.
 Two basic blocks are said to be equivalent if they compute the same
set of expressions.
 A number of transformations can be applied to a basic block without
changing the set of expressions computed by the block. This is for
optimizing the code.
 There are two important classes of transformations that can be
applied to basic blocks;
1) Structure Preserving Transformations and
2) Algebraic Transformations
05/29/2025 20
Structure Preserving Transformations
 The primary structure-preserving transformations on basic blocks are:
1) Common subexpression elimination
2) Dead code elimination
3) Renaming of temporary variables
4) Interchange of two independent adjacent statements
 Assumption: basic blocks have no arrays, pointers, or procedure calls

05/29/2025 21
Common subexpression elimination

 Since the second and fourth expressions compute the same


expression, namely, b + c – d, and hence this basic block may be
transformed into the equivalent block.
 Note that although the first and third statements in the above appear
to have the same expression on the right, the second statement
redefines b. therefore, the value of b in the third statement is different
from the value of b in the first, and the first and third statements do
not compute the same expression.
22
Dead-code elimination
 Suppose x is dead, that is, never subsequently used, at the point
where the statement x : = y + z appears in a basic block.
 Then this statement may be safely removed without changing the
value of the basic block.
Renaming temporary variable
 Suppose we have a statement t: = b + c (t is a temporary) can be
changed to u: = b + c (u is a new temporary) and all uses of this
instance of t can be changed to u without changing the value of the
basic block.
 Such a block is called a normal-form block.

23
Interchange of statements.
 Suppose a block has the following two adjacent statements:

 Then we can interchange the two statements in the basic block when
the value of t1 does not affect the value of t2.

05/29/2025 24
Algebraic Transformations
 Algebraic transformations can be used to change the set of
expressions computed by a basic block into an algebraically
equivalent set.
 This includes simplify expressions or replace expensive operations
by cheaper ones.
Examples:
 The exponential operator in the statement x: = y * * 2 usually
requires a function call to implement.
 This statement can be replaced by the cheaper, but equivalent
statement x: = y * y.

05/29/2025 25
Flow Graphs
 Flow graph is a directed graph containing the flow-of-control
information for the set of basic blocks making up a program.
 A graph representation of three-address statements are called a flow
graph.
 The nodes of the flow graph are basic blocks. It has a distinguished
initial; it is the block whose leader is the first statement.

05/29/2025 26
 There is a directed edge from block B1 to block B2 if B2 can
immediately follow B1 in some execution sequence;
♦ There is a conditional or unconditional jump from the last
statement of B1 to the first statement of B2, or
♦ B2 immediately follows B1 in the natural order of the program,
and B1 does not end in an unconditional jump.
 We say that B1 is a predecessor of B2, and B2 is a successor of B1.

05/29/2025 27
E.g.; Flow graph for the vector dot product is given as
follows:

28
 B1 is the initial node.
 B2 immediately follows B1, so there is an edge from B1 to
B2.
 The target of jump from last statement of B1 is the first
statement B2, so there is an edge from B1 (last statement) to
B2 (first statement).
 B1is the predecessor of B2, and B2 is a successor of B1

05/29/2025 29
Loops
 For example, in the above Figure 8.3 there is one loop, consisting of
block B2.
 A loop is a collection of nodes in a flow graph such that
1) All nodes in the collection are strongly connected; that is, from
any node in the loop to any other, there is a path of length one or
more, wholly within the loop, and
2) The collection of nodes has a unique entry, that is, a node in the
loop such that the only way to reach a node of the loop from a
node outside the loop is to first go through the entry.
 A loop that contains no other loops is called an inner loop.

05/29/2025 30
A SIMPLE CODE GENERATOR
 The code generation strategy in this section generates target code for a
sequence of three address statement 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:

05/29/2025 31
Register and Address Descriptors
 The code-generation algorithm uses descriptors to keep track of
register contents and addresses for names.
1) A register descriptor is used to keep track of what is currently in
each register. It is consulted whenever a new register is needed.
 We assume that register descriptors show that initially all the
registers are empty.
2) An address descriptor is used to keeps track of the location (or
locations) where the current value of the name can be found at run
time.
 The location might be a register, a stack location, a memory
address, or some set of these.
05/29/2025 32
The Dag Representation of Basic Blocks
 Directed acyclic graphs (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.

05/29/2025 33
 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.

05/29/2025 34
The Principal Sources of Optimization
 A transformation of a program is called local if it can be performed by
looking only at the statements in a basic block; otherwise, it is called
global.
 Many transformations can be performed at both the local and global level.
 Local transformations are usually performed first.
Function Preserving Transformations
 A Compiler can improve a program without changing the function it
computes.
1) Common Sub Expression Elimination,
2) Copy Propagation
3) Dead Code Elimination
4) Constant Folding
05/29/2025 35
Common Sub expressions
 An occurrence of an expression E is called a common sub expression
if E was previously computed, and the values of variables in E have
not changed since the previous computation, we can avoid re-
computing the expression if we can use the previously computed
value.

05/29/2025 36
Copy Propagation
 Copy-propagation means use of one variable instead of another.
For example;
x=PI;

a=x*r*r;
 The optimization using copy propagation can be done as follows
a=PI * r * r
 Here the variable x is eliminated.

05/29/2025 37
Dead Code Elimination
 A variable is live at a pint in a program if its value can be used
subsequently; otherwise, it is dead at that point.
 A related idea is dead or useless code, statements that compute values
that never get used.
Example:
i:=0;
if (i==1) {
a=b+5;
}
 Here if statement is a dead code because this condition will never get satisfied.
 Hence if statement can be eliminated.
05/29/2025 38
Constant folding
 The substitution of values for names whose values are constant
A=3.14157/2 can be replaced by
A=1.570 there by eliminate the division operation.

05/29/2025 39
Loop Optimization
 The running time of a program may be improved if we decrease the
number of instructions in an inner loop, even if we increase the
amount of code outside that loop.
 Three techniques for loop optimization are
1) Code Motion
2) induction-variable elimination
3) reduction in strength

05/29/2025 40
Code Motion
 An important modification that decreases the amount of code in a loop is code
motion.
 This transformation takes an expression that yields the same result independent of
the number of times a loop is executed and places the expression before the loop.
 For Example,
While (i<=n-2) {
------
}
 Evaluation of n-2 is a loop invariant computation in the above while statements. So
this can be placed outside the loop.
 Code motion will result in the equivalent of
 t=n-2
 While (i<=t)

05/29/2025 41
Reduction in Strength
 Reduction in strength replaces expensive operations by equivalent
cheaper ones on the target machine.
 Certain machine instructions are considerably cheaper than others
and can often be used as special cases of more expensive operators.
 For example; x² is invariably cheaper to implement as x*x than as a
call to an exponentiation routine.
 Fixed point multiplication or division by a power of two is cheaper to
implement as a shift.
 Floating point division by a constant can be implemented as
multiplication by a constant, which may be cheaper.

05/29/2025 42
PEEPHOLE OPTIMIZATION
 A statement-by-statement code-generation strategy often produces
target code that contains redundant instructions and sub optional
constructs.
 The quality of such target code can be improved by applying
"optimizing" transformations to the target program.
 A simple but effective technique for locally improving the target code
is peephole optimization.
 A method for trying to improve 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
sequences, whenever possible.
05/29/2025 43
Characteristic of Peephole Optimizations
♦ Redundant-instruction elimination
♦ Flow-of-control optimizations
♦ Algebraic simplifications
♦ Use of machine idioms

05/29/2025 44
Question & Answer

45
Thank You !!!

46

You might also like