You are on page 1of 20

ACD UNIT-V

Optimization:
Optimization is a program transformation technique, which tries to improve the code by
making it consume less resources (i.e. CPU, Memory) and deliver high speed. In optimization,
high-level general programming constructs are replaced by very efficient low-level programming
codes.
It is the process of removing unneeded code from object code or substituting one piece of
code with another to make the object code faster without changing the output of the object code.

Reasons for Optimizing the Code

• Code optimization is essential to enhance the execution and efficiency of a source code.
• It is mandatory to deliver efficient target code by lowering the number of instructions in a
program.

Objectives of Optimization

❖ Reduce the code size.

❖ Increase code speed.

❖ Enhance the Performance.

❖ Delivers High Speed.

Different Types of Optimization


Optimization is classified broadly into two types:

• Machine-Independent
• Machine-Dependent
Machine Dependent Machine Independent
Machine dependent code optimization is Machine-independent code optimization is applied
applied to object code. to intermediate code.

Involvement with Hardware

Machine dependent optimization involves CPU Machine independent code optimization does not
registers and absolute memory references. involve CPU registers or absolute memory refe

The difference between machine dependent and machine independent code optimization
is that the machine dependent optimization is applied to object code whereas, the machine
independent code optimization is applied to intermediate code.

Machine independent Optimization

Function Preserving Transformations


Function Preserving optimizations deals with the code in a given function in an attempt of
reducing the computational time. There are a number of ways in which a compiler can improve
a program without changing the function it computes
The transformations are
1. Common Sub expression elimination
2. Constant Folding
3. Dead code elimination
4. Copy Propagation
5. Constant Propagation

1.Common Sub expression Elimination.

The expression or sub-expression that has been appeared and computed before and
appears again during the computation of the code is the common sub-expression. Elimination
of that sub-expression is known as Common sub-expression elimination.
The advantage of this elimination method is to make the computation faster and better by
avoiding the re-computation of the expression. In addition, it utilizes memory efficiently.
Example-1
t1=4*i
t2=a[t1]
t3=4*j
t4=4*i
t5=n
t6=b[t4]+t5
The above code can be optimized as

t1=4*i
t=a[t1]
t3=4*j
t5=n
t6=b[t1]+t5

Here the common sub expression t4=4*i is eliminated because its computation is already
done in t1 and value of I is not been changed

Example-2
Before elimination –
a = 10;
b = a + 1 * 2;
c = a + 1 * 2;
d = c + a;
after elimination
a = 10;
b = a + 1 * 2;
d = b + a;
2.Constant Folding
In constant folding the computation of constant is done at compile time instead of execution
time.

Example-1:

int x= 5+7+c;
//Folding applied
int x=12+c;
Example-2:
a=3.14157/2 is replaced by a=1.570

3. Dead code elimination

A variable is said to be live in a program if the value contained into it is used subsequently,
otherwise it is said to be dead code. We have to remove that dead code. (or)
When a program snippet is never used in a program it is removed from the program without
affecting the remaining program. This type of elimination is referred to as the dead code
Elimination.
Example-1:
i=0
if(i==1)
{
a=x+5;
}

Here if statement is dead code because this condition will never get satisfied. So we can delete
that if statement.
After eliminating dead code, the result will be
i=0
Example-2:
Before Optimization
int b = 24;
int c = b - 17;
int a = b;
printf(“%d”,b);
In the above code the integers c and a are never used hence they should be eliminated using the
dead code elimination. The optimized code is as follows.
int b = 24;
printf(“%d”,b);

4.Copy Propagation

Copy Propagation proposes using one variable instead of the other


Example-1:
For example,
a=c;
d = a + b;
In the above code assigning c to a does not make any useful sense hence we can replace a to c.
d = c + b;
Example-2:
x=pi;
area= x*r*r;
after optimization the code will be
area = pi*r*r;
5. Constant Propagation
It can be defined as the process of replacing the constant value of variables in the
expression. In simpler words, we can say that if some value is assigned a known constant,
than we can simply replace that value by constant.

Ex1:

Pi=3.14, r=5;

Area=pi*r*r;

After

Area=3.14*4*4

Ex:2

Before:

a = 30
b = 20 - a /2
c = b * ( 30 / a + 2 ) - a
After:
a = 30
b = 20 - 30/2
c = b * (30 / 30 + 2) – 30.

Loop Optimization techniques

Loop optimization is most valuable machine-independent optimization because program's inner


loop takes bulk to time of a programmer. If we decrease the number of instructions in an inner
loop then the running time of a program may be improved even if we increase the amount of
code outside that loop. The techniques are

1. Code motion
2. Loop unrolling
3. Loop jamming
4. Strength reduction
5. Induction variable elimination
1. Code motion
Code motion is used to decrease the amount of code in loop. This transformation takes a
statement or expression which can be moved outside the loop body without affecting the
semantics of the program.
Example-1

Before optimization: After optimization:


while(i<10) x=y+z;
{ while(i<10)
x=y+z; {
i++; i++;
} }
Example-2:
while (i<=100)
{
a=limit/2 +i;
i++;
}
After code motion the result is as follows:
t= limit-2;
while(i<=100)
{
a=t+i;
i++;
)
2. Loop Unrolling
The loop unrolling technique transforms the loop. Here loop overhead can be reduced by
reducing the number of iterations in the loop and increases the program’s speed by
eliminating the loop control instructions and loop test instructions
Example-1:

Before optimization: After optimization:


int i = 1; int i = 1;
while(i<100) while(i<50)
{ {
a[i] = b[i]; a[i] = b[i];
i++; i++;
} a[i] = b[i];
i++; }
Here the first loop is running 100 times. Second loop will run only 50 times.

Example-2:
for(i=0;i<=10;i++)
{
Add():
}
After optimization:
for(i=0;i<=5;i++)
{
Add():
Add();
}
3. Loop jamming(Loop Fusion)
Loop jamming is the combining the two or more loops in a single loop. It reduces the time
taken to compile the many number of loops.
Example-1:

fore optimization: After optimization:


for(i=0;i<=10;i++) for(i=0;i<=10;i++)
{ {
printf(“TOC”); printf(“TOC”);
} printf(“ACD”);
for(i=0;i<=10;i++) }
{
printf(“ACD”);
}
Example-2:
Initial Code:
for(int i=0; i<5; i++)
a = i + 5;
for(int i=0; i<5; i++)
b = i + 10;
Optimized code:
for(int i=0; i<5; i++)
{
a = i + 5;
b = i + 10;
}
4. Reduction in Strength:
The strength of certain operators is higher than other operators. For example, strength of * is
higher than +. Usually, compiler takes more time for higher strength operators and execution
speed is less. Replacement of higher strength operator by lower strength operator is called a
strength reduction technique .For example

Before optimization: After optimization:


for (i=1;i<=10;i++) temp = 7;
{ for(i=1;i<=10;i++)
sum = i * 7; {
printf(“%d”, sum); temp = temp + 7;
} sum = temp;
printf(“%d”, sum)
}
Example -2:
For example, multiplication (x * 2) is expensive in terms of CPU cycles than (x << 1) and yields
the same result.

5. Induction Variable elimination


A variable is called an induction variable if its value is altered within the loop by a loop-
invariant value. Induction variable elimination can reduce the number of additions (or
subtractions) in a loop, and improve both run-time performance and code space.
Example
// Program with multiple induction variables
int main()
{
i1 = 0;
i2 = 0;
for (i = 0; i < n; i++) {
A[i1++] = B[i2++];
}
return 0; }
// Program with one induction variable
int main()
{
for (i = 0; i < n; i++) {
A[i] = B[i]; // Only one induction variable
} return 0;
}
Principle Sources of Optimization/ Code Optimization Techniques
.
Function-Preserving Transformations.
There are a number of ways in which 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.

Loop Optimizations:
1. Code motion
2. Loop unrolling
3. Loop jamming
4. Strength reduction

Optimization on Basic Blocks


Optimization process can also be applied on a basic block and it can be machine-dependent or
machine-independent. These transformations are useful for improving the quality of code that
will be ultimately generated from basic block . While optimization, we don't need to change the
set of expressions computed by the block. There are two type of basic block optimization. These
are as follows:

1. Structure-Preserving Transformations
2. Algebraic Transformations

1. Structure Preserving transformations:


The primary Structure-Preserving Transformation on basic blocks is as follows:

o Common sub-expression elimination


o Dead code elimination
o Renaming of temporary variables
o Interchange of two independent adjacent statements

A) Common Sub-expression elimination

Common sub expressions need not be computed over and over again. Instead they can be
computed once and kept in store from where it’s referenced.

Example:

a: =b+c
b: =a-d
c: =b+c
d: =a-d

The 2nd and 4th statements compute the same expression: b+c and a-d
Basic block can be transformed to

a: = b+c
b: = a-d
c: = a
B) Dead code elimination d: = b
Generally, a programmer doesn't introduce dead code intentionally. The dead code may be a
variable or the result of some expression computed by the programmer that may not have any
further uses. By eliminating these useless things from a code, the code will get optimize

Example:
A statement p = q + r appears in a block, and p is a dead symbol. It means that it will never be
used subsequently so that we can eliminate this statement. This elimination does not have any
impact on the values of the basic block.

C) Renaming of temporary Variables

Statements containing instances of a temporary variable can be changed to instances of another


new temporary variable without changing the basic block value.
Example: Statement t = a + b can be changed to x = a + b where t is a temporary variable and
x is a new temporary variable without changing the value of the basic block.
D) Interchange of two independent adjacent statements

If a block has two adjacent statements which are independent can be interchanged without
affecting the basic block value.

Example:

t1 = a + b t2 = c + d
t2 = c + d t1 = a + b

These two independent statements of a block can be interchanged without affecting the value
of the block.

2. Algebraic Transformations

Algebraic identities represent another important class of optimizations on basic blocks


Some of the algebraic transformation on basic blocks includes:
A. Constant Folding
B. Copy Propagation
C. Strength Reduction

A. Constant Folding:
Solve the constant terms which are continuous so that compiler does not need to solve this
expression.
Example:
x = 2 * 3 + y ⇒ x = 6 + y (Optimized code)

B. Copy Propagation:
It is of two types, Variable Propagation, and Constant Propagation.
Variable Propagation:
x=y ⇒ z = y + 2 (Optimized code)
z=x+2
Constant Propagation:
x=3 ⇒ z = 3 + a (Optimized code)
z=x+a
C. Strength Reduction:
Replace expensive statement/ instruction with cheaper ones.
x = 2 * y (costly) ⇒ x = y + y (cheaper)
x = 2 * y (costly) ⇒ x = y << 1 (cheaper)

Peephole Optimization
Peephole optimization is a type of code Optimization performed on a small part of the code. It
is performed on a very small set of instructions in a segment of code.
The small set of instructions or small part of code on which peephole optimization is
performed is known as peephole or window.

Objectives of Peephole Optimization:

The objective of peephole optimization is as follows:


1. To improve performance
2. To increase the code speed
3. To reduce code size.

Characteristics of Peephole Optimization


1. Redundant instruction elimination
2. Removal of Unreachable code.
3. Strength Reduction.
4. Algebraic Simplification
5. Use of Machine idioms

Peephole Optimization Techniques/Characteristics of Peephole Optimization

1. Redundant instruction elimination: In this technique the redundancy is eliminated.

For e.g.

Initial code:

MOV R0, a
MOV a.R0

Optimized code:
MOV R0, a
Here we can eliminate second instruction because “a“ is already in R0

2. Removal of Unreachable code: we can remove unreachable code instructions


For Example
sum=0;
if(sum)
{
printf(”%d”,sum);
}
Here the if statement never gets executed hence we can eliminate such unreachable code. After
the optimized code will be
sum=0;

3. Strength Reduction: The operators that consume higher execution time are replaced by the
operators consuming less execution time. For e.g.

Initial code:
y = x * 2;

Optimized code:
y = x + x;

4. Algebraic Simplification: Peephole optimization is an effective technique for algebraic


simplification. The statements such as x = x + 0 or x = x * 1 can eliminated by peephole
optimization.

5. Use of Machine idioms: The target instructions have equivalent machine instructions for
performing some operations. Hence we can replace these target instructions by equivalent
machine instructions in order to improve the efficiency. For e.g., some machine have auto-
increment or auto-decrement addressing modes that are used to perform add or subtract
operations.
a=a+1 is replaced by inc a;
b=b-1 is replaced by dec b;

Introduction to Data –flow Analysis


It is the analysis of flow of data in control flow graph, i.e., the analysis that determines the
information regarding the definition and use of data in program. With the help of this analysis,
optimization can be done. In general, it is a process in which the values are computed using
data flow analysis.
Basic Terminologies –

• Definition Point: a point in a program containing some definition.


• Reference Point: a point in a program containing a reference to a data item.
• Evaluation Point: a point in a program containing evaluation of expression.

Data Flow Properties


1. Available expression
2. Reaching definition
3. Live variable
4. Busy expression
1. Available expression
An expression a + b is said to be available at a program point x if none of its operands gets
modified before their use. It is used to eliminate common sub expressions.
An expression is available at its evaluation point.
Example:
In the above example, the expression L1: 4 * i is an available expression since this expression is
available for blocks B2 and B3, and no operand is getting modified

2. Reaching definition

A definition D is reaching a point x if D is not killed or redefined before that point. It is generally
used in variable/constant propagation.
Example:

In the above example, D1 is a reaching definition for block B2 since the value of x is not
changed (it is two only) but D1 is not a reaching definition for block B3 because the value of x is
changed to x + 2. This means D1 is killed or redefined by D2.

3. Live variable

A variable x is said to be live at a point p if the variable's value is not killed or redefined by some
block. If the variable is killed or redefined, it is said to be dead. It is generally used in register
allocation and dead code elimination.

Example:
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.

4. Busy Expression
An expression is said to be busy along a path if its evaluation occurs along that path, but none of
its operand definitions appears before it. It is used for performing code movement optimization.

Issues in design of 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.

In the code generation phase, various issues can arise:

1. Input to the code generator


2. Target program
3. Memory management
4. Instruction selection
5. Register allocation
6. Evaluation order

1. Input to the code generator


o The input to the code generator contains the intermediate representation of the source program
and the information of the symbol table. The source program is produced by the front end.

o Intermediate representation ha the several choices


a) Postfix notation.
b) Syntax tree.
c) Three address code.

The code generation phase needs complete error-free intermediate code as an input requires.

2. Target program:

The target program is the output of the code generator. The output can be:

a) Assembly language: It allows subprogram to be separately compiled.

b) Relocatable machine language: It makes the process of code generation easier.

c) Absolute machine language: It can be placed in a fixed location in memory and can be
executed immediately.

3. Memory management

In the memory management design, the source program's frontend and code generator
map names address data items in run-time memory. It utilizes a symbol table. In a three-address
statement, a name refers to the name's symbol-table entry. Labels in three-address statements
must be transformed into instruction addresses.

4. Instruction Selection

Nature of instruction set of the target machine should be complete and uniform. If we consider
the efficiency of target machine then the instruction speed and machine idioms are important
factors. The quality of the generated code can be determined by its speed and size.

P:=Q+R
S:=P+T
MOV R0, Q
ADD R0, R
MOV R0, P
MOV R1,P
ADD R1, T
MOV R1, S
5. Register allocation

Register can be accessed faster than memory. The instructions involving operands in register are
shorter and faster than those involving in memory operand. The following sub-problems arise
when we use registers:

• Register allocation: In register allocation, we select the set of variables that will reside in
the register.
• Register assignment: In the Register assignment, we pick the register that contains a
variable.
6. Evaluation order

The efficiency of the target code can be affected by the order in which the computations are
performed. Some computation orders need fewer registers to hold results of intermediate than
others.

The target Language


TARGET MACHINE: Familiarity with the target machine and its instruction set is a prerequisite
for designing a good code generator. Here target language (Assembly Language) is a simple
computer is discussed which is representative of many register machines

A simple target machine model


Our target computer models a three address machine with following operations
Address in the target code
Target code generation deals with assembly language to convert optimized code into machine
understandable format. Target code can be machine readable code or assembly code. Each line
in optimized code may map to one or more lines in machine (or) assembly code, hence there is
a 1:N mapping associated with them .
Example 1 :
L1: a = b + c * d
optimization :
t0 = c * d
a = b + t0
Register Allocation:
Register allocation is the process of assigning program variables to registers and
reducing the number of swaps in and out of the registers. Movement of variables across
memory is time consuming and this is the main reason why registers are used as they available
within the memory and they are the fastest accessible storage location.
Example 1:
R1<--- a
R2<--- b
R3<--- c
R4<--- d
MOV R3, c
MOV R4, d
MUL R3, R4
MOV R2, b
ADD R2, R3
MOV R1, R2
MOV a, R1
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.
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.
Generating Code for Assignment Statements:
The assignment d : = (a-b) + (a-c) + (a-c) might be translated into the following three-address
code sequence:
Code sequence for the example is:
Generating Code for Indexed Assignments
The table shows the code sequences generated for the indexed assignmen a:= b[ i ] and a[ i ]:= b

Generating Code for Pointer Assignments


The table shows the code sequences generated for the pointer assignments a : = *p and *p : = a

You might also like