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.
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.
The getAnalysis
function is used to specify which other pass will be used:
getAnalysis
loop function:LoopInfo *LI = &getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
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 ";
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; }
The newly modified pass now needs to run on a sample program. Follow the given steps to modify and run the sample program:
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; }
.ll
file using Clang:$ clang –O0 –S –emit-llvm sample.c –o sample.ll
$ 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
3.14.251.128