C语言 使用insertAfter()插入LLVM指令

kfgdxczn  于 2023-04-19  发布在  其他
关注(0)|答案(2)|浏览(169)

我是LLVM的新手,我正在做一些实验,比如插入一条指令。
我的main.c如下所示:

int foo(int e, int a) {
  int b = a + 1;
  int c = b * 2;
  b = e << 1;
  int d = b / 4;
  return c * d;
}

我使用下面的命令生成LLVM字节码

clang-12 -O0 -Xclang -disable-O0-optnone -emit-llvm -c main.c -o main.bc
opt-12 -S -mem2reg main.bc -o main.ll

字节码是

; Function Attrs: noinline nounwind uwtable
define dso_local i32 @foo(i32 %0, i32 %1) #0 {
  %3 = add nsw i32 %1, 1
  %4 = mul nsw i32 %3, 2
  %5 = shl i32 %0, 1
  %6 = sdiv i32 %5, 4
  %7 = mul nsw i32 %4, %6
  ret i32 %7
}

我使用代码在第一条指令后插入一条指令:

bool runOnBasicBlock(BasicBlock &B) {
    // get the first and second instruction
Instruction &Inst1st = *B.begin();
Instruction *NewInst = BinaryOperator::Create(
        Instruction::Add, Inst1st.getOperand(0), Inst1st.getOperand(0));
NewInst->insertAfter(&Inst1st);
...
}

在我运行此遍之后,字节码将更改为

; Function Attrs: noinline nounwind uwtable
define dso_local i32 @foo(i32 %0, i32 %1) #0 {
  %3 = add nsw i32 %1, 1
  %4 = add i32 %1, %1
  %5 = mul nsw i32 %4, 2
  %6 = shl i32 %0, 1
  %7 = sdiv i32 %6, 4
  %8 = mul nsw i32 %5, %7
  ret i32 %8
}

插入的指令好像是b = a + a;,所以指令%4 = mul nsw i32 %3, 2变成了%5 = mul nsw i32 %4, 2,我不明白原因,有帮助吗?

fykwrbwg

fykwrbwg1#

据我所知,NewInst->insertAfter(&Inst1st);从块中生成

int b = a + 1;
int c = b * 2;

以下块

int b = a + 1, a + a;
int c = b * 2;

因此,b丢弃先前值%3并获得新值%4,并且进一步mul使用b的新值。

zpqajqem

zpqajqem2#

我无法复制您的输出字节码,您是否忘记了什么?

这个问题让我很好奇,我自己也试了一下。
我使用了与问题中相同的c文件,并使用相同的命令来生成LLVM字节码,唯一的区别是我使用了LLVM 16。
正如预期的那样,我得到了与您相同的初始字节码:

; Function Attrs: noinline nounwind uwtable
define dso_local i32 @foo(i32 noundef %e, i32 noundef %a) #0 {
entry:
  %add = add nsw i32 %a, 1
  %mul = mul nsw i32 %add, 2
  %shl = shl i32 %e, 1
  %div = sdiv i32 %shl, 4
  %mul1 = mul nsw i32 %mul, %div
  ret i32 %mul1
}

我使用您提供的代码编写了以下函数pass,以便在第一条指令之后插入add指令:

#include "llvm/IR/Instructions.h"
...
PreservedAnalyses FuncPass::run(Function &F, FunctionAnalysisManager &AM) {
  for (auto &B : F) {
    Instruction &Inst1st = *B.begin();
    Instruction *NewInst = BinaryOperator::Create(
        Instruction::Add, Inst1st.getOperand(0), Inst1st.getOperand(0));
    NewInst->insertAfter(&Inst1st);
  }
  return PreservedAnalyses::none();
}

然后我通过上面的函数传递运行字节码,但我得到的结果与你的不同

; Function Attrs: noinline nounwind uwtable
define dso_local i32 @foo(i32 noundef %e, i32 noundef %a) #0 {
entry:
  %add = add nsw i32 %a, 1
  %0 = add i32 %a, %a
  %mul = mul nsw i32 %add, 2
  %shl = shl i32 %e, 1
  %div = sdiv i32 %shl, 4
  %mul1 = mul nsw i32 %mul, %div
  ret i32 %mul1
}

我的结果字节码,与你的类似,在第一条指令之后包含新的add指令,但是尽管你输出了字节码,这个新的add指令的结果并没有取代下一条指令中变量b的使用

相关问题