使用 llvm pass 优化加零

Optimize add zero with llvm pass

int func(int i){                                                                     
     int j;
     j = i + 0;
     return j;                                                                                                                       
 } 

我想练习和学习LLVM transformation pass。 对于上面简单的c函数,我想实现代数识别优化X+0 -> X

我希望优化后的程序是

int func(int i){                                                                     
     int j;                                                                       
     j = i // remove the add instruction                                                                     
     return j;                                                                        
 } 

我阅读了 IRBuilder,我可以创建 Add/Sub/Mul... 很多说明。但是对于处理上述情况,我找不到任何匹配项。

遇到上述情况我应该怎么办?

我也在想能不能去掉指令。

程序将是

int func(int i){                                                                                                                                       
     return i;                                                                        
 } 

我不确定 llvm 是否会在我删除无用的添加指令后自动执行此操作。

运行 clang -O0 -S -emit-llvm -o - test.c 在您的代码上产生以下 IR:

define i32 @func(i32 %i) #0 {
entry:
  %i.addr = alloca i32, align 4
  %j = alloca i32, align 4
  store i32 %i, i32* %i.addr, align 4
  %0 = load i32, i32* %i.addr, align 4
  %add = add nsw i32 %0, 0
  store i32 %add, i32* %j, align 4
  %1 = load i32, i32* %j, align 4
  ret i32 %1
}

如您所见,有add nsw i32 %0, 0指令。这意味着 clang 不会立即优化它(至少在 -O0 上),这是我们将通过我们的传递处理的指令。

我将省略添加您自己的通道所需的样板代码,因为它在 LLVM 文档中有详细描述。

pass 应该做类似(伪代码)

runOnFunction(Function& F)
{
  for(each instruction in F)
    if(isa<BinaryOperator>(instruction))
      if(instruction.getOpcode() == BinaryInstruction::Add)
         if(isa<ConstantInt>(instruction.getOperand(1))
            if(extract value from constant operand and check if it is 0)
              instruction.eraseFromParent()
}

实现避免加零优化 需要做的事情是:

  • 找到y=x+0
  • 所在的指令
  • y 的所有使用替换为 x
  • 记录指令的指针
  • 之后删除