Search code examples
llvmllvm-clang

llvm pass add function call in loop (args by induction variable)


I want to write a pass for adding a function call in for loop.

Let's assume the original source code is below.

for (int i=0; i<10; ++i)
{
  printf("%d\n", i);
}

I want to make pass like changing the upper source code to below. (Not mean that changing the source code, but IR code in real.)

for (int i=0; i<10; ++i)
{
  EXTERNALFUNC(i); // function call for external function 
                   // and args is induction variable.

  printf("%d\n", i);
}

I know about usage of getOrInsertFunction method but have no idea about

  1. finding the loop & induction variables,
  2. put the function call inside of function,
  3. if there is many loop, put function calls in all loops.

Solution

  • If you run clang -emit-llvm on that source you'll notice that the loop body starts with precisely one phi node. (Well, at least it ought to do that, I haven't bothered to check.)

    Some loops don't have induction variables. But the ones that do will have a phi node and some sort of increase, and you can identify those once you've found the loop.

    To find loops, you can make a LoopInfo, or if you're doing this in a pass, call FAM.getResult<LoopAnalysis>(F); to get the LoopInfo your pass manager has made. For each loop found by LoopInfo, see if it's one you can analyse and do the right thing if it is, and if it isn't. The Loop's header must contain a phi, one of the incoming blocks must dominate the header, another must be in the loop, and the value in the loop must be an arithmetic operation that uses the phi. Like this:

    scan:     ; preds = %scan, %notnull
      %previous = phi i32 [ -1, %notnull ], [ %current, %scan ]
      %current = add i32 %previous, 1
      …
      br i1 %found, label %scan, label %test
    

    If a loop doesn't have anything like this, it may be e.g. while(true){…}.

    BasicBlock::phis() tells you about its phi nodes, and PHINode::users() returns a list of things that use it. In the example above, %current is an arithmethic operation, is one of the users of %previous, and%previous' getIncomingValue(1) returns %current too.