Compiler Optimization Techniques PART -I

code optimization is a technique in which the code is transformed to improve the performance. Performance here can be execution time, code size or both.

Now, let me start away with the common techniques used.

Optimization Techniques -

1. Copy Propogation

copy propagation is the process of replacing the occurrences of targets of direct assignments with their values

ex :
int foo ( void )
{
int x, y = 3;
int z;

x = y;
z = 25 + x;
}

this can be optimized as follows :
int foo ( void )
{
int x, y = 3;
int z;

z = 25 + 3; /* if the value of x is not used elsewhere */
/* This type is Serial Copy Propogation */
}

In pipelined process,
int foo ( void )
{
int x, y = 3;
int z;

x = y;
z = 25 + y;
/* Both the above Instructions are issued in Parellel */
/* Allows pipelining the instruction */
}

2. Constant Folding

Here, the compiler analyzes constant valued expressions and perform calculations at the
compile time itself.
/* Verify first line */

Ex :
i.
int foo ( int i )
{
int j, k = 200;

j = i + k;
return j;
}

This function is modified as follows :
int foo ( int i )
{
int j;

j = i + 200; /* Constant Operands are evaluated at compile time */

return j;
}
Since ‘k’ is not used anywhere within this file and ‘k’ is a constant,

ii.
int foo ( void )
{
int i = 3 * 4;

. . . .
. . . .
. . . .

return 0;
}

int foo ( void )
{
int i = 12; /* value substituted at compile time itself */

. . . .
. . . .
. . . .

return 0;
}

Care must be taken to ensure that the behaviour of the arithmetic operations on the host architecture
matches that on the target architecture, as otherwise enabling constant folding will change the
behaviour of the program

3. Strength Reduction

In this method, Expensive operations are replaced with Cheaper ones.

ex :
int foo ( void )
{
int x = 10;
int y;

y = pow ( x, 2 );

. . . .
. . . .
. . . .

return 0;
}

int foo ( void )
{
int x = 10;
int y;

y = x * x /* the compiler may not do exactly the same */

. . . .
. . . .
. . . .

return 0;
}

4. Variable Renaming

This is a technique in which variables are renamed. This is mainly helpful in Multiprocessor
systems. By doing so, the serialization of the process is avoided and improves the performance.

Ex :
int foo ( void )
{
int a, b;
int x, y;
int res;

res = a + 2;
res = res * b;
. . . .
. . . .
res = x + y;
. . . .
. . . .

return 0;
}

int foo ( void )
{
int a, b;
int x, y;
int res, res1;

res = a + 2;
res = res * b; /* pipeline 1 */
. . . .
. . . .
res1 = x + y; /* pipeline 2 */
. . . .
. . . .

return 0;
}

Since both those instructions are independant of each other, by renaming the variables, process
pipelining can be achieved.

5. Common Sub-Expression Elimination

The objective here is to eliminate all those expressions that have already been performed.
This is because Sub-Expressions that appears in more than one place may be Evaluated only once.

Ex :
int main ( void )
{
int mean, res;
int a, b, c;

. . . .
mean = ( a + b ) / 2;
res = c * ( a + b );
. . . .

return i;
}

We see that 'a + b' is the common Sub-Expression. So by eliminating it,
we can reduce the number of instructions.

int main ( void )
{
int mean, res;
int a, b, c;

. . . .
temp$ = ( a + b );
mean = temp$ / 2;
res = c * temp$;
/* The expression ( a + b ) is evaluated only once */
. . . .

return i;
}

contd..
http://c4swimmers.net/portal/node/125

Google