Code Optimization • It refers to the techniques used by the compiler to improve execution efficiency of generated object code. • It involves complex analysis of the intermediate code and the performance of various transformations but every optimizing transformation must also preserve the semantic of the program. Types Of Code Optimization Code Optimization Machine Independent Optimization can be performing independently of the target machine for which compiler is generating code. Machine Dependent Requires the knowledge of target machine. Basic blocks For performing code optimization we need to • Detect the loops • Detection is performed by Control Flow Analysis on Program Flow Graph. Atomic Block is sequence of 3-address statement where control enters at the beginning and leaves only at the end without any jumps or halts. Finding the basic blocks In order to find the basic blocks, we need to find the leaders in the program then a basic block will start from one leader to next leader but not including the next leader. Identifying the leaders in the basic blocks 1. First statement is a leader. 2. Any statement which is the target of conditional or unconditional statement is a leader. 3. Any statement which immediately follows a conditional statement or unconditional statement is a leader. Identifying the leaders in the basic e.g:- blocks fact(x) { int f = 1; for (i =2; i<=x; i++) { f = f*i ; } return f; } Identifying the leaders in the basic blocks Three Address Code Leader 1 1. f=1 2. i=2 Leader 2 Leader 3 Leader 4 3. if i<=x goto 9 4. 5. 6. 7. 8. t1 = f*i ; f = t1 ; t2 = i+1 ; i = t2 ; goto(3)0 9. goto calling program Block 1 Block 2 Block 3 Block 4 Flow Graph • Directed graph represents the basic blocks and their successor relationship. • The nodes of the flow graph are the basic blocks. One node is distinguished as initial (block whose leader is first statement). • There is a directed edge from block B1 to block B2 if B2 could immediately follow B1 during execution that is if: a) There is a conditional or unconditional jump from the last statement of B1 to the first statement of B2 or b) B2 immediately follows B1 does not end in an unconditional jump. • We say that B1 is predecessor of B2 and B2 is successor of B1 Identifying the leaders in the basic blocks Three Address Code Leader 1 1. f=1 2. i=2 Leader 2 Leader 3 Leader 4 3. if i<=x goto 9 4. 5. 6. 7. 8. t1 = f*i ; f = t1 ; t2 = i+1 ; i = t2 ; goto(3)0 9. goto calling program Block 1 Block 2 Block 3 Block 4 Flow Graph Loop Optimization The Topics under Machine Independent Optimization are as follows: 1. Loop Optimization a) Code Motion or Frequency reduction b) Loop Unrolling c) Loop Jamming 2. Strength Reduction 3. Constant Folding 4. Copy Propagation 5. Redundancy Elimination 6. Algebraic Simplification 1. Loop Optimization • while, do-while, for statements give rise to loops in program • Most of the execution time is spent in relatively little of the program . • 90-10 rule- 90% of time is spent in 10% of code. Thus the most heavily travelled part of a program, the inner loops are an obvious target for optimization • removal of loop- invariant computations • elimination of induction variables 1- a) Code Motion or Frequency Reduction The running time of program may be improved if we decrease the length of one of its loop especially an inner loop even if we increase the amount of code outside the loops. Code Motion is moving a code from high frequency regions to low frequency regions. e.g:A=30, i=1,t= sin(A)*cos(A) ; A=30,i=1; Code Motion while (i<=10000) while (i<=10000) { { i= t+i ; i= (sin(A)*cos(A))+i ; } } 1- b) Loop Unrolling loop unrolling is also known as loop unwinding , is a loop transformation technique that attempts to optimize program execution speed at the expense of binary size, decreasing the number of comparisons. e.g:i=0; i= 0; while (i<10000) { while (i<10000) x[i] = i; { Loop Unrolling i = i+1; x[i] = i; x[i] = i; i = i+1; i = i+1; } } It checks for 10000 times It checks for 5000 times 1- c) Loop jamming loop jamming is combining two or more loops in a single loop. It reduces the time taken to compile many number of loops. i=1 ; i=1 ; while (i<10000) while (i<10000) { { x = 5+i; y = 25+i; i = i+1; i = i+1; } } Comparison = 10000 Statement execution= 20000 Comparison = 10000 Statement execution= 20000 i=1 ; while (i<10000) { x = 5+i ; y = 25+i; i = i+1; } Comparison = 10000 Statement execution= 3000 2) Strength Reduction • The replacement of expensive operation by a cheaper one is termed as reduction in strength. • Costly operation is reduced by cheaper operation. * is costly operation whereas + is less costly. e.g. 4*i computation time is more i+i+i+i computation time is less 3) Constant folding The Computation of constant is done at compile time instead of execution time. Replace an expression that can be computed at compile time by its values. e.g. y = x+5+4+4+3+2 y = x+14 4) Copy Propagation The value of variable is replaced and computation of an expression is done at compile time. e.g. x=5 y = 4 Copy Propagation z =5+4 Constant Folding z = 9 z= x+y DAG REPRESENTATION OF BASIC BLOCKS • For analyzing basic blocks • A DAG is a directed graph with no cycles which give a picture of how the value computed by each statement in a basic block is used in subsequent statements in the block. • Constructing a DAG for three address code can give following information. Determining common subexpression within a block. Determining which names are used inside the block but evaluated outside the block (those for which a leaf is created at same time). Determining which statements of the block could have their value used outside the block. • In DAG notes are given following labels Leaves are labeled by unique identifiers either variable names or constants. Interior notes are labeled by an operator symbol. Notes are also optionally given an extra set of identifiers for labels. e.g. (a+b)(a+b+c) from infix expression we draw a parse tree * + + a b c + a b t1= a+b t2=a+b t3=t2*c t4= t1*t3 e.g. the postfix expression of above expression is ab+*ab+c Now we draw a DAG which is optimized in nature t1= a+b t2= t1+c t3= t1* t2 DAG vs Flow Graph • Each node of the flow graph can be represented by a DAG, since each node of the flow graph stands for a basic block. • DAG representation of a basic block is nothing more nor less then an optimized version of “triples” form of intermediate code. VALUE METHOD AND ALGEBRAIC LAWS • To implement DAG construction algorithm, it is required to check whether a node with specified children and a specified operator existed. for this the entire list of created nodes needs to be examined. • To determine whether such node exists or not, a data structure such as hash table can be used . • This idea was given by Cocke and Schwartz. • A node of the DAG is really just a pointer into an array or arrays, holds the information about the node. ALGEBRAIC SIMPLIFICATION Create node with left child m and right child n with operator + , we should certainly check whether such a node already exists. But on most m/c multiplication is commutative, so we should also check for a node having operator *, left child m and right child n. a = m+n b = n+m * ,a m n n * ,b m + ,a m n + ,b n m ALGEBRAIC SIMPLIFICATION The associative law may also be applied to improve code generated from a DAG. e.g. A = B+C E = C+D+B E= A+D Eliminating trivial Simplification y = z*1 y=z y=z+0 y=z Global data flow analysis • To efficiently optimize the code compiler collects all the information about the program and distribute this information to each block of the flow graph. This process is known as dataflow graph analysis. • Certain optimization can only be achieved by examining the entire program. It can't be achieve by examining just a portion of the program. • For this kind of optimization user defined chaining is one particular problem. • Here using the value of the variable, we try to find out that which definition of a variable is applicable in a statement. Example-1 • Based on the local information a compiler can perform some optimizations. • Ex: x = a + b; x = 6 * 3; • In this code, the first assignment of x is useless. The value computed for x is never used in the program. • At compile time the expression 6*3 will be computed, simplifying the second assignment statement to x = 18; Example-2 • Some optimization needs more global information. For example, consider the following code: a = 1; b = 2; c = 3; if (....) x = a + 5; else x = b + 4; c = x + 1; • In this code, at line 3 the initial assignment is useless and x +1 expression can be simplified as 7. Global data flow analysis • But it is less obvious that how a compiler can discover these facts by looking only at one or two consecutive statements. A more global analysis is required so that the compiler knows the following things at each point in the program. Which variables are guaranteed to have constant values. Which variables will be used before being redefined. • Data flow analysis is used to discover this kind of property. The data flow analysis can be performed on the program's control flow graph (CFG). • The control flow graph of a program is used to determine those parts of a program to which a particular value assigned to a variable might propagate.