Download as pdf or txt
Download as pdf or txt
You are on page 1of 36

CODE OPTIMIZATION

• To make target programs fast, small, and maintainable, a


compilation process has the optimization phase
• The code optimization phase applies a sequence of optimizing
transformations that transforms the input program to a program
that requires fewer sources.
• The optimizing compiler tends to generate a target program with
higher execution efficiency. Notably. these optimizations must
follow the following conditions:
1. Optimization must maintain semantic equivalence between the
original source and the optimized code.
2. The algorithm remains unchanged as much as possible.
3. Results before and after optimization should remain unchanged.
4. The optimize code should avoid redundancy and produce less
code.
Classification of Compiler Optimization

• Language-dependent and language-independent


• Machine dependent and machine independent
• Scope of optimization
• Peephole optimization
• Local optimization
• Global optimization
• Loop optimization
Principal sources of optimization for compiler

• These include transformations such


• compile time evaluation,
• Common Sub-Expression Elimination (CSE),
• variable propagation,
• code movement,
• strength reduction,
• dead code elimination,
• loop optimization.
Compile time evaluation

• Constant folding : it reters is the • Constant propagation: They refer to the task of
replacement of expressions that can replacing the name variables with constants
be evaluated at compile time by that have been assigned to them earlier, It is
their computed values an indirect optimization that does not lead to
• For example. the statement any optimization itself but helps in other
A=5+3+A+C can be replaced by optimization
A=8+A+C. Note that the values 5 and • For example:
3 are variables at compile time and PI=3.141592 …..
the sub-expression 5+3 can be pre R=PI/180.0
computed and replaced with 8 in Constnt prapogation would transform this code into
the original expression. leading to PI=3.141592….
A=8+A+C R=3.141592/180.0
After applying folding transformation in the preceding
co the code becomes
PI=3.141502….
R=0.0174644
Common Sub-Expression Elimination

• Common Sub-Expression Elimination :Programmers often write expressions that


contain sub-expressions, which compute the same value.
• Code optimizer must identify the common sub-expression, and eliminate it
because would amount to performing the same operation repeatedly thus
wasting much of the time.
• Once Identified, It is evaluated only once and values are substituted at
respective sub expression occurrences.
• Consider the following example:
Y=a+b
Z=a+b-10
• The preceding code contains common sub-expression a+b and thus can be
optimized by using a new variable temp for it and replacing all occurrences of
a+b with it as follows:
Temp= a+b
Y= temp
Z= temp – 10
Variable Propagation

• Variable Propagation: Variable propagation is the method of


optimization that replaces one variable with another variable holding
identical value. This would increase the probability of generating
common sub-expressions.
a=b….
y=a*4
z=b*4+10
The above code variable a and b are same
a=b…
Y=b*4
Z=b*4+10
Code Movement

• Code movement is the method in which code from one part of the
program is moved to another part so that the resulting program is
more efficient.
• The modified programs maintain the semantic equivalence even
after modification
• Reduction of execution frequency: It means reducing the execution
frequency of the code being removed.
• It is the transformation that identifies the common pieces of code to
be evaluated at various places in the program and moves them within
the code such the their frequency of execution is reduced.
• It can be done in two ways: code holsting and loop optimization
• Code hoisting moves the pieces of code to some earlier parts of the
program to reduce their frequency of execution.
• On the other hand, loop optimization moves code statement(s) from
the loop body whose values do not depend on loop iterations.
• This is done because these are loop-Invariant statements and keeping
them in the loop will only invite repetitive execution of the same
code.
• code movement is motivated by the following reasons:
• To reduce the code space of the program: It means reducing the
code size by moving the piece of code to earlier parts of the
program so that the code generated is substantially small.
• Consider the following example:
if p > q then
X= a *10
Else
Y = a 10 +20
• We note that a 10 is computed twice. The code can be modified to
compute a *10 only once before the if statement. The resulting code
is as follows:
temp= a*10
if p > q then
X= temp
Else Y = temp +20
• The code for a 10 is generated only once.
Dead Code Elimination:

• The portion of the program statements that is never visited and executed
under any situation is called dead code and can be removed from the
program without affecting program behaviour and performance
• A variable that is defined but not used in the entire program is considered to
be a dead variable
• example
• flag=false;
• ….
• ….
• if(flag)
• a=b+c:
• Data flow analysis reveals that each time the program reaches the if (flag)
statement, the value of flag is always false.
• This means the statement a=b+c would never be executed
• Therefore, the test and the assignment statements are considered to be dead
code and can be safely removed from the object code,
Loop optimization

•Loop optimization plays an important role in improving the performance


of the source code by reducing overheads associated with executing loops.
•Loop Optimization can be done by removing:
•Loop invariant
•Loop unrolling
•Loop interchange
•Loop splitting
•Loop peeling
•Loop fission
Loop optimization:Loop Invariant
i = i =

1 1

s= 0 s= 0

s= s +
do{ a =5

i a =5 do{
s= s + i
i=i+
i=i+1
1
{
while (i < =n) {
while (i < =n)
Bringing a=5 outside the do while loop, is called
code motion.
Loop optimization:Loop unrolling

• Loop unrolling: It is an optimization technique where the code constituting the loop
body, is reproduced a number of times.
• This improves the time efficiency of the execution process
• Loop unrolling increases the program’s speed by eliminating loop control instruction and
loop test instructions.
• For example
int x;
for (x = 0; x < 100; x++)
{
delete(x);
}
After performing loop unrolling • Because of this modification the
int x; new proram has to make only 20
iteration instead of 100
for (x = 0; x < 100; x += 5 )
{
delete(x);
delete(x + 1);
delete(x + 2);
delete(x + 3);
delete(x + 4);
}
Loop optimization: Loop interchange

• This optimization interchanges the • The code fragment given before makes
inner loops with the outer loops to nonlocal references.
improve the nesting structure of the
loops, thereby helping In improving the • The code can be improved by
localization of memory references and interchanging the inner and outer loops
enabling further loop transformations. with better locality of reference.
• Consider the segment of code involving • The code can be rewritten as follows:
arrays in the following loop: for i= 0 to 50 do
for j= 0 to 50 do for j=0 to 50 do
for i=0 to 50 do A[i][j]=..
A[i][j]=…….
• The modified access pattern would be
a[0][0]. a[0] [1]. a[0][2].... etc., which
may offer better locality of references
in many cases.
Loop optimization: Loop splitting

• It refers to the method of • After loop splitting, the previous


simplifying a loop by breaking it loop splits into three loops as
into multiple loops. follows:
• The resulting multiple loops for i= 1 to 49 do
possess the same bodies but b1
iterate over a different end loop
contiguous index range. for i= 50 to 59 do
b2
• Consider the following example: end loop
for i= 1 to 100 do
for i= 60 to 100 do
if i <50 then b1
b3
if 50<= i < 60 then b2 else b3
End loop
Loop optimization: Loop peeling

• It is a special case of loop i=1


splitting which splits any b1
problematic first (or last) few
iterations from the loop and for i=2 to 50 do
performs them outside of the b2
loop body. end loop
• For example:
for i=1 to 50 do
If i=1 then b1 else b2
end loop
Loop optimization: Loop fission

• It refers to breaking the loop into • The preceding code fragment can be
multiple loops over the same index improved for locality in the
range. reference pattern by rewriting it as
• Each loop carries a part of the body follows:
of the loop. for i= 1 to 50 do
x[i] = ..
• For instance, consider the following end loop
loop code: for i= 1 to 50 do
for i= 1 to 50 do y[i] =..
x[i] = end loop
y[i] =
end loop • Note that both loops access
different variables and hence offer
better memory reference
performances
Strength Reduction

• The strength of certain • For example, multiplication by


operators is higher than other a power of 2 can be replaced
operators by left shift (i.e., x * 8 can be
• For example, strength of * is implemented as x << 3).
higher than +. • In addition, operations such as
• Usually, compiler takes more multiplication by small
time for higher strength numbers can be replaced by
operators and execution speed multiple additions.
is less
• The examples discussed as follows make the concept of strength reduction
much clear:
• Replace exponentiation by multiplication: For example. X2 is invariably cheaper to
implement as x* x than to call to an exponentiation routine.
• Replace fixed-point multiplication or division by a power of two as a shift: Shift operation
Is cheaper than Implementing multiplication or division. For example, x<<1 is cheaper than
x*2 and x>>1 is cheaper than x/2.
• Note that most of a program's execution time is generally spent in the smaller
sections of the program code and that the code is often inside a loop that is
executed over and over.
• Consider the following code: • It can be simplified and
C = 8; replaced with weaker
additions as follows:
for (i = 0; i < N; i++) C = 8;
{ k = 0;
for (i = 0; i < N; i++)
y[i] = c * i;
{
} Y[i] = k ;
k = k + c;
}
Peephole Optimization

• Redundant instructions may be discarded during the final code


generation.
• The compiler uses a method called peephole optimization to discover
local improvements by looking at a window on the code.
• This tiny window corresponds to a peephole that moves over the
program.
• The method slides the peephole over the code examines the contents to
match patterns (with a limited set of patterns).
• Limited sets of patterns were deployed by early peephole optimizers.
• These patterns were coordinated with thorough search over the
program.
• Some common examples of program transformations that
characterize the peephole optimization are listed below:
1. Elimination of redundant loads and stores
2. Elimination of unreachable code
3. Algebraic simplifications
4. Reduction of strength(refer slide 20-22)
5. Use of machine idioms
6. Elimination of multiple jumps
Elimination of redundant loads and stores

• Code generation by statement • Consider a set of arithmetic


by-statement strategy often statements:
produces code with a set of • x = y + z:
redundant load and store
instructions. • a = x + b:
• The compiler must save the
computed values in the memory
only when there are no available
registers that keep the valve
furthermore and require the
value the next use in future
• A statement-by-statement code generation strategy straightforwardly
implements the preceding statements as follows:
1. MOV y, RO Copy y to the register RO;
2. ADD z, RO Add z to the register RO, the register RO is now y + z (x)
3. MOV RO, X Copy the register RO to x
4. MOV X, RO Copy x to the register RO
5. ADD b, RO Add b to the register RO, the register RO is now x + b [(y + z) + b]
6. MOV RO, a Copy the register RO to a
• The above mentioned code can be optimized to
• MOV y, RO : Copy y to the register RO
• ADD z, RO : Add z to the register RO, the register RO is now y+z
or (x)
• MOV RÓ, X : Copy the register RO to x
• ADD b, RO : Add b to the register RO, the register RO is now
y+z+b or[(x)+b]
• MOV RO, a : Copy the register RO to a
Identifying Unreachable Instructions

• Unreachable code is undesirable for the Presence of unreachable code in the


following reasons: program may be the result of a number of
reasons. This can include:
1. It occupies unnecessary memory that
can be used by other program objects 1. Presence of complex conditional
if made available branches in the program code which
makes a set of statements never
2. It results in unwanted caching of reachable
instructions into the CPU instruction
cache, thereby decreasing data 2. Internal transformations done with
locality the help of an optimizing compiler.
For example, common-sub expression
3. The documentation of a piece of code elimination
(which has no effect as it doesn't
execute ever)causes wastage of time • Removal of unreachable code surely
and effort. optimizes the program in term of size
and has been taken seriously by most
optimizing compilers.
• Consider a fragment of C code • the program control flow will
int foo(int a , int b) never reach the definition
c=a*b
{
• This is because the function
int c; returns before the definition is
return a+b; reached
c=a*b; • Therefore, the definition of
a*b can be discarded
}
Simplify Algebraic Expressions

• Most of the programs can be optimized by performing algebraic


simplifications,
• For example, the program contains statements such as:
a=a+0
a=a*1
• then these statements can be eliminated because zero is an
additive Identity and one is multiplicative identity.
• These statements bring no change in the values contained in
variable a
• The benefit of simplifying algebraic expression is clearly visible: it
will reduce the amount of Large code and thus save memory space
and execution time.
Use Faster Machine Instructions

• The target machine has many • The quality of the code when
instructions that can be pushing or popping a stack is
implemented directly by the enhanced with the help of these
underlying hardware. modes.
• Identifying specific situations in the • They can also help in implementing
instruction and using such hardware statements such as a = a + 1.
instructions can reduce execution • Consider an example instruction
time significantly. that adds constant 1 to the register
• Auto-increment and auto-decrement R.
instructions are among such • ADD #1,R
advanced hardware-oriented
instructions. • It can be replaced by INC R
• A good optimizing compiler is • The latter instruction is equivalent
expected to implement such faster to the former instruction but costs
instructions. less and more efficient.
Elimination of Multiple Jumps

• The user program often contains • This sequence of code containing


multiple jump sequences, and jump sequence can be replaced
control flow analysis of the by
program can help you to optimize goto L2
the program by replacing the
jump sequences, as illustrated as ….
follows: L1 :goto L2
goto L1 • This simplification leads to
…… time-efficient execution of the
target program and makes the
L1 :goto L2 flow of the program much
simpler.
Z=3; Z=3;
Y=5; Y=5;
For(int i=0;i<=n;i++) code X=8
motion/constant folding and t1=x*x🡺 CF AND CP=>t1=64;
prapogation🡺
For(int i=0;i<=n;i++)
{ x=y+z;
{
a[i]=6*i+x*x;
A[i]=6*i+t1
}
}
• Final optimized code:
for(int i=0;i<=n;i++)
{
a[i]=6*i+64;
}

You might also like