Open In App

Optimization of Basic Blocks

Improve
Improve
Like Article
Like
Save
Share
Report

Optimization is applied to the basic blocks after the intermediate code generation phase of the compiler. Optimization is the process of transforming a program that improves the code by consuming fewer resources and delivering high speed. In optimization, high-level codes are replaced by their equivalent efficient low-level codes. Optimization of basic blocks 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.

There are two types of basic block optimizations:   

  1. Structure preserving transformations
  2. Algebraic transformations

Basic Block Optimization

Structure-Preserving Transformations:

The structure-preserving transformation on basic blocks includes:

  1. Dead Code Elimination
  2. Common Subexpression Elimination
  3. Renaming of Temporary variables
  4. Interchange of two independent adjacent statements

1.Dead Code Elimination: 

Dead code is defined as that part of the code that never executes during the program execution. So, for optimization, such code or dead code is eliminated. The code which is never executed during the program (Dead code) takes time so, for optimization and speed, it is eliminated from the code. Eliminating the dead code increases the speed of the program as the compiler does not have to translate the dead code.

Example:

// Program with Dead code
int main()
{
    x = 2 
    if (x > 2) 
      cout << "code"; // Dead code
    else 
      cout << "Optimization";
    return 0;
}
// Optimized Program without dead code
int main()
{
    x = 2;
    cout << "Optimization"; // Dead Code Eliminated
    return 0;
}

2.Common Subexpression Elimination:

In this technique, the sub-expression which are common are used frequently are calculated only once and reused when needed. DAG ( Directed Acyclic Graph ) is used to eliminate common subexpressions.

Example: 

 

3.Renaming of Temporary Variables: 

Statements containing instances of a temporary variable can be changed to instances of a 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.

4.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 

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

Algebraic Transformation:

Countless algebraic transformations can be used to change the set of expressions computed  by a basic block into an algebraically equivalent set. Some of the algebraic transformation on basic blocks includes:

  1. Constant Folding
  2. Copy Propagation
  3. Strength Reduction

1. 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)

2. 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 

3. 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)

Loop Optimization: 

Loop optimization includes the following strategies:

  1. Code motion & Frequency Reduction
  2. Induction variable elimination
  3. Loop merging/combining
  4. Loop Unrolling

1. Code Motion & Frequency Reduction

Move loop invariant code outside of the loop.

// Program with loop variant inside loop
int main()
{
    for (i = 0; i < n; i++) {
        x = 10;
        y = y + i;
    }
    return 0;
}
// Program with loop variant outside loop
int main()
{
    x = 10;
    for (i = 0; i < n; i++)
        y = y + i;
    return 0;
}

2. Induction Variable Elimination: 

Eliminate various unnecessary induction variables used in the loop.

// 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;
}

3. Loop Merging/Combining: 

If the operations performed can be done in a single loop then, merge or combine the loops.

// Program with multiple loops
int main()
{
    for (i = 0; i < n; i++)
        A[i] = i + 1;
    for (j = 0; j < n; j++)
        B[j] = j - 1;    
    return 0;
}  
// Program with one loop when multiple loops are merged
int main()
{
    for (i = 0; i < n; i++) {
        A[i] = i + 1;
        B[i] = i - 1;
    }
    return 0;
}

4. Loop Unrolling: 

If there exists simple code which can reduce the number of times the loop executes then, the loop can be replaced with these codes.

// Program with loops
int main()
{
    for (i = 0; i < 3; i++)
        cout << "Cd";
    return 0;
}
// Program with simple code without loops
int main()
{
    cout << "Cd";
    cout << "Cd";
    cout << "Cd";
    return 0;
}

Last Updated : 23 Jun, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads