Using another pass in a new pass

A pass may require another pass to get some analysis data, heuristics, or any such information to decide on a further course of action. The pass may just require some analysis such as memory dependencies, or it may require the altered IR as well. The new pass that you just saw simply prints the name of the function. Let's see how to enhance it to count the basic blocks in a loop, which also demonstrates how to use other pass results.

Getting ready

The code used in the previous recipe remains the same. Some modifications are required, however, to enhance it—as demonstrated in next section—so that it counts the number of basic blocks in the IR.

How to do it…

The getAnalysis function is used to specify which other pass will be used:

  1. Since the new pass will be counting the number of basic blocks, it requires loop information. This is specified using the getAnalysis loop function:
     LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
  2. This will call the LoopInfo pass to get information on the loop. Iterating through this object gives the basic block information:
    unsigned num_Blocks = 0;
      Loop::block_iterator bb;
      for(bb = L->block_begin(); bb != L->block_end();++bb)
        num_Blocks++;
      errs() << "Loop level " << nest << " has " << num_Blocks
    << " blocks
    ";
  3. This will go over the loop to count the basic blocks inside it. However, it counts only the basic blocks in the outermost loop. To get information on the innermost loop, recursive calling of the getSubLoops function will help. Putting the logic in a separate function and calling it recursively makes more sense:
    void countBlocksInLoop(Loop *L, unsigned nest) {
      unsigned num_Blocks = 0;
      Loop::block_iterator bb;
      for(bb = L->block_begin(); bb != L->block_end();++bb)
        num_Blocks++;
      errs() << "Loop level " << nest << " has " << num_Blocks
    << " blocks
    ";
      std::vector<Loop*> subLoops = L->getSubLoops();
      Loop::iterator j, f;
      for (j = subLoops.begin(), f = subLoops.end(); j != f;
    ++j)
        countBlocksInLoop(*j, nest + 1);
    }
     
    virtual bool runOnFunction(Function &F) {
      LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
      errs() << "Function " << F.getName() + "
    ";
      for (Loop *L : *LI)
        countBlocksInLoop(L, 0);
      return false;
    }

How it works…

The newly modified pass now needs to run on a sample program. Follow the given steps to modify and run the sample program:

  1. Open the sample.c file and replace its content with the following program:
    int main(int argc, char **argv) {
      int i, j, k, t = 0;
      for(i = 0; i < 10; i++) {
        for(j = 0; j < 10; j++) {
          for(k = 0; k < 10; k++) {
            t++;
          }
        }
        for(j = 0; j < 10; j++) {
          t++;
        }
      }
      for(i = 0; i < 20; i++) {
        for(j = 0; j < 20; j++) {
          t++;
        }
        for(j = 0; j < 20; j++) {
          t++;
        }
      }
      return t;
    }
  2. Convert it into a .ll file using Clang:
    $ clang –O0 –S –emit-llvm sample.c –o sample.ll
    
  3. Run the new pass on the previous sample program:
    $ opt  -load (path_to_.so_file)/FuncBlockCount.so  -funcblockcount sample.ll
    

    The output will look something like this:

    Function main
    Loop level 0 has 11 blocks
    Loop level 1 has 3 blocks
    Loop level 1 has 3 blocks
    Loop level 0 has 15 blocks
    Loop level 1 has 7 blocks
    Loop level 2 has 3 blocks
    Loop level 1 has 3 blocks
    

There's more…

The LLVM's pass manager provides a debug pass option that gives us the chance to see which passes interact with our analyses and optimizations, as follows:

$ opt  -load (path_to_.so_file)/FuncBlockCount.so  -funcblockcount sample.ll –disable-output –debug-pass=Structure
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.14.251.128