llvm 在循环中传递添加函数调用(通过归纳变量传递参数)

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

我想写一个在 for 循环中添加函数调用的过程。

我们假设原始源代码如下。

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

我想通过把上面的源代码改成下面的。 (并不是说改变 source 代码,而是真正的 IR 代码。)

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

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

我知道 getOrInsertFunction 方法的用法,但不知道

  1. 寻找循环和归纳变量,
  2. 把函数调用放在函数里面,
  3. 如果有很多循环,将函数调用放在所有循环中。

如果您 运行 clang -emit-llvm 在该源上,您会注意到循环体恰好以一个 phi 节点开始。 (好吧,至少它应该这样做,我懒得去检查。)

有些循环没有归纳变量。但是那些确实有一个 phi 节点和某种增加,一旦你找到循环你就可以识别它们。

要找到循环,可以让一个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必须控制表头,另一个必须在循环中,循环中的值必须是使用phi的算术运算。像这样:

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

如果一个循环没有这样的东西,它可能是例如while(true){…}.

BasicBlock::phis() tells you about its phi nodes, and PHINode::users()returns一列使用它的东西。上例中,%current是算术运算,是%previous的使用者之一,%previous'getIncomingValue(1)returns%current也是.