0% found this document useful (0 votes)
13 views9 pages

CD Unit V

The document discusses code optimization in compiler design, emphasizing the transformation of code to improve efficiency without altering its meaning. It outlines various optimization techniques, including function preserving transformations, dead code elimination, and constant propagation, as well as concepts like flow graphs, dominators, and data flow analysis. Additionally, it introduces Partial Redundancy Elimination (PRE) and its benefits, along with algorithms like Lazy Code Motion for enhancing program performance.

Uploaded by

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

CD Unit V

The document discusses code optimization in compiler design, emphasizing the transformation of code to improve efficiency without altering its meaning. It outlines various optimization techniques, including function preserving transformations, dead code elimination, and constant propagation, as well as concepts like flow graphs, dominators, and data flow analysis. Additionally, it introduces Partial Redundancy Elimination (PRE) and its benefits, along with algorithms like Lazy Code Motion for enhancing program performance.

Uploaded by

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

III BTECH II-SEM, CSE: COMPILER DESIGN

UNIT- V
Code Optimization
Introduction:
• It is possible for programmer to perform compiler using his or her knowledge in choosing
better algorithm and data items.
• Optimization is process of transformation of code to an efficient code in terms of space and
time without changing the meaning of code.
• Following constraints are to be considered while applying techniques for code
improvements.
1. Transformation preserves meaning of program. i.e., target code should ensure semantic
equivalence with source program.
2. Program efficiency must be improved by measurable amount without changing
algorithm used in program.
3. When technique is applied on special format, then it is worth transforming to that
format only.
4. Some transformations are applied only after detailed analysis, which is time
consuming. It is not worthy if program runs very few number of times.

Principal source of optimization: 10 marks


• Transformation of program is called local if it is applied with in basic block and global if
applied across basic block.
• There are different types of transformations to improve code and these transformations
depend on kind of optimization required.
1. Function preserving transformations:
These are performed without changing function it computes. These are primarily used
when global optimizations are performed.
2. Structure preserving transformations:
These are performed without changing the set of expressions computed by block.
These are mostly applied locally.
3. Algebraic transformations:
These are used to simplify computation of expression set using algebraic identities.
These can replace expensive operations by cheaper ones.
Example: Multiplication by 2 replace with left shift.

GEETHANJALI INSTITUTE OF SCIENCE AND TECHNOLOGY, NELLORE Y.v.R 1


III BTECH II-SEM, CSE: COMPILER DESIGN

Function preserving transformations:


• Function preserving transformations are
1. Common sub expression elimination
2. Copy propagation
3. Dead code elimination
4. Constant propagation
• Common sub expression elimination can be applied locally and globally. Other techniques
are applied globally.
1. Common sub expression elimination:
• Code can be improved by eliminating common sub expressions from code.
• Expression whose value was previously computed and values of variables in
expressions are not changed since computation can be avoided to recompute it by
using earlier computed value.
Example1:Consider following sample code Example2: Consider following sequence code
a=b*c a=b*c
....... c=4+c
z=b*c+d-c .......
Here z have common sub expression b * c. z=b*c+d-c
its value is not changed after point it was Here expression b*c is not common because
computed and it is used in z. We can avoid value of c is changed after computing b*c.
recomputing by replacing above code as So, we cannot eliminate this expression.
t1 = b * c
a = t1
..........
z = t1 + d - c

2. Copy propagation:
• If there are copy statements of form x=y then in copy propagation use of x is
replaced by y in subsequent expressions.
• Copy propagation is possible if none of the variable is changed after this argument.
Example: consider following code:
a=b+c
d=c //copy statement
........
e=b+d-3

GEETHANJALI INSTITUTE OF SCIENCE AND TECHNOLOGY, NELLORE Y.v.R 2


III BTECH II-SEM, CSE: COMPILER DESIGN
We may notice that code has common sub expressions b + c and b + d, if we replace
variable d by variable c as both have same value.
After apply copy propagation, the above code is
a=b+c
d=c
........
e=b+c-3 ⇒ e=a-3
By copy propagation we can eliminate assignment.
3. Dead code elimination:
• A piece of code which is not reachable that is value it computes is never used
anywhere in program then it is said to be dead code and can be removed from
program safely.
Example:
a=b+c
d=c
........
e=b+c-3
Here expression d = c is never used in the program and d is not used in any lines of
code. So, it can be considered as dead code. It should be eliminated if it is not
disturbing execution of program.
After dead code elimination code should be
a=b+c
........
e=b+c–3
4. Constant Propagation :
• Constant Propagation is process of recognizing and evaluating constant expressions
at compile time rather than run time.
Example: Pi=2217
void area_per(int r)
{
float area, perimeter;
area = Pi * r * r;
print area, perimeter;
}
• At line 1, variable Pi is constant and its value 3.413 is assigned at compile time.
• At line 5 and 6 value of Pi is assigned with 3.413 in runtime.

GEETHANJALI INSTITUTE OF SCIENCE AND TECHNOLOGY, NELLORE Y.v.R 3


III BTECH II-SEM, CSE: COMPILER DESIGN

10 marks
LOOPS IN FLOW GRAPH
• A graph representation of three-address statements, called a flow graph, is useful for
understanding code-generation algorithms, even if the graph is not explicitly
constructed by a code-generation algorithm. Nodes in the flow graph represent
computations, and the edges represent the flow of control.
Dominators:
• In a flow graph, a node d dominates node n, if every path from initial node of the flow
graph to n goes through d. This will be denoted by d dom n.
• Every initial node dominates all the remaining nodes in the flow graph and the entry of
a loop dominates all nodes in the loop. Similarly every node dominates itself.
Example:

Flow graph
*In the flow graph above,
• Initial node, node1 dominates every node.
• node 2 dominates itself
• node 3 dominates all but 1 and 2.
• node 4 dominates all but 1, 2 and 3.
• node 5 and 6 dominates only themselves ,since flow of control can skip around
either by going through the other.
• node 7 dominates 7,8 ,9 and 10.
• node 8 dominates 8,9 and 10.
• node 9 and 10 dominates only themselves.
• The way of presenting dominator information is in a tree, called the dominator tree in
which the initial node is the root.
• The parent of each other node is its immediate dominator. Each node d dominates only
its descendents in the tree.

GEETHANJALI INSTITUTE OF SCIENCE AND TECHNOLOGY, NELLORE Y.v.R 6


III BTECH II-SEM, CSE: COMPILER DESIGN
• The existence of dominator tree follows from a property of dominators; each node has
a unique immediate dominator in that is the last dominator of n on any path from the
initial node to n.
• In terms of the dom relation, the immediate dominator m has the property is d=!n and
d dom n, then d dom m

Dominator tree
D(1)={1} D(6)={1,3,4,6}
D(2)={1,2} D(7)={1,3,4,7}
D(3)={1,3} D(8)={1,3,4,7,8}
D(4)={1,3,4} D(9)={1,3,4,7,8,9}
D(5)={1,3,4,5} D(10)={1,3,4,7,8,10}

Natural Loop:
• One application of dominator information is in determining the loops of a flow graph
suitable for improvement.
• The properties of loops are
• A loop must have a single entry point, called the header. This entry point-dominates all
nodes in the loop, or it would not be the sole entry to the loop.
• There must be at least one way to iterate the loop(i.e.)at least one path back to the
header.
• One way to find all the loops in a flow graph is to search for edges in the flow graph
whose heads dominate their tails. If a→b is an edge, b is the head and a is the tail. These
types of edges are called as back edges.
Example:
In the above graph,
7 → 4 4 DOM 7
10 →7 7 DOM 10
4→3
8→3
9 →1

GEETHANJALI INSTITUTE OF SCIENCE AND TECHNOLOGY, NELLORE Y.v.R 7


III BTECH II-SEM, CSE: COMPILER DESIGN

• The above edges will form loop in flow graph.


• Given a back edge n → d, we define the natural loop of the edge to be d plus the set of
nodes that can reach n without going through d. Node d is the header of the loop.

Inner loop:
• If we use the natural loops as “the loops”, then we have the useful property that unless
two loops have the same header, they are either disjointed or one is entirely contained
in the other. Thus, neglecting loops with the same header for the moment, we have a
natural notion of inner loop: one that contains no other loop.
• When two natural loops have the same header, but neither is nested within the other,
they are combined and treated as a single loop.

Pre-Headers:
• Several transformations require us to move statements “before the header”.
Therefore begin treatment of a loop L by creating a new block, called the preheater.
• The pre-header has only the header as successor, and all edges which formerly
entered the header of L from outside L instead enter the pre-header.
• Edges from inside loop L to the header are not changed.
• Initially the pre-header is empty, but transformations on L may place statements in it.

Two loops with the same header

Introduction of the preheader

GEETHANJALI INSTITUTE OF SCIENCE AND TECHNOLOGY, NELLORE Y.v.R 8


III BTECH II-SEM, CSE: COMPILER DESIGN
• In the above example, the variable a is live at blocks B1, B2, B3 and B4 but is killed at
block B5 since its value is changed from 2 to b + c. Similarly, variable b is live at block
B3 but is killed at block B4.

The foundations of data flow analysis: 10 marks


• The foundations of data flow analysis in compiler design follow basics concepts:
1. Lattices
2. Reaching Definition
3. Control Flow Graph
4. Iterative Algorithms
Lattices:
• These are partially ordered sets. The sets represent the state of the program during
data flow analysis.
• They perform two operations - join operation and meet operation.
• The set elements' lower bound is calculated in the join operation. In meet operation,
there is a merge of two lattices.
Reaching Definition:
• It determines which definition may reach a specific code point. It tracks the
information flow in a code.
• A definition is said to reach a point such that there has been no variable redefinition.
• Reaching definitions track the variables and the values they hold at different points.
Control Flow Graph:
• It is a graphical representation of the control flow in compiler design. The control
flow refers to the computations during the execution of a program.
• Control flow graphs are process-oriented directed graphs. The control flow graph has
two blocks: the entry and exit.
• It helps to analyze the flow of computations and identify potential performance
loopholes.
Iterative Algorithms:
• Iterative algorithms are used to solve data flow analysis problems. The iterative
algorithms used are for reaching problems and for available expressions.
• Iterative algorithms for reaching problems assume that all definitions reach all
points. It then iteratively solves and updates the reachable points for different
definitions.
• For available expressions, it assumes that all expressions are available at all points. It
then iteratively solves and updates the point of use of the expressions.

GEETHANJALI INSTITUTE OF SCIENCE AND TECHNOLOGY, NELLORE Y.v.R 13


III BTECH II-SEM, CSE: COMPILER DESIGN

5 marks
Constant Propagation:
• Constant Propagation is process of recognizing and evaluating constant expressions
at compile time rather than run time.
Example: Pi=2217
void area_per(int r)
{
float area, perimeter;
area = Pi * r * r;
print area, perimeter;
}
• At line 1, variable Pi is constant and its value 3.413 is assigned at compile time.
• At line 5 and 6 value of Pi is assigned with 3.413 in runtime.

Partial Redundancy Elimination: 10 marks


• PRE (Partial Redundancy Elimination) is a compiler optimization method. PRE
aims to remove redundant computations from the program.
• Redundant computations are those that are achieved in more than one instance.
However, it produces the same result every time.
• By removing these redundancies, PRE can enhance the overall performance of
the program by reducing the number of instructions carried out.
• An example of full redundancy is given below.
if(condition1) {
x = a + b;
}
else{
x = a + b;
}
• As you can see in the above example, the computation of A+B is fully redundant.
But the condition of partial redundancy arrived if we modified the code as
follows.
if(condition1) {
x = a + b;
}
if(condition2) {
y = a + b;}

GEETHANJALI INSTITUTE OF SCIENCE AND TECHNOLOGY, NELLORE Y.v.R 14


III BTECH II-SEM, CSE: COMPILER DESIGN
• As you can see in the above example, A+B is only partially redundant because it
is performed along some execution path(“given that both conditions are true”)
but not along all execution paths.

Benefits of PRE:
• We can significantly improve the performance of a program by eliminating
partial redundancies.
1. Execution Time: PRE will reduce the number of instructions that are needed
to be executed to run a program. Since our system has fewer instructions to
execute, it will result in a faster execution time.
2. Power Consumption: PRE will reduce the number of instructions that are
needed to be executed, which will save us power and make our system more
power efficient.
3. Readability: PRE will improve the readability of our program by removing
repeated code and redundancies, which will make it easier for the developers
to read and maintain the code.
4. Debug: PRE will remove unwanted or unnecessary code from our code, which
will make debugging easier and enable developers to find and correct any
errors in the code.

PRE algorithms:
There are various algorithms that are available in the market for our use. Some of the
algorithms that are used worldwide are:
1. Lazy Code Motion Algorithm (LCM)
2. Global Value Numbering Algorithm (GVN).
The Lazy Code Motion Algorithm (LCM):
• The Lazy code motion algorithm (LCM) aims to minimize the total number of
computations that is to be performed to execute a program.
• LCM is the algorithm that works by identifying partially redundant expressions.
And then, it will move them to a point in the control flow graph where they are
guaranteed to be executed at most once.
• It is a Four-Step Algorithm:
1. The first step uses anticipation to determine where the expression can be
placed.
2. The second step will be computing the earliest and latest points for each
expression.

GEETHANJALI INSTITUTE OF SCIENCE AND TECHNOLOGY, NELLORE Y.v.R 15

You might also like