我是 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);
...
}
我运行这个pass之后,字节码变成了
; 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
。我无法理解原因。有帮助吗?
据我所知,
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
.
我无法重现你的输出字节码。你有没有机会忘记说点什么?
这个问题让我很好奇,自己也试了一下
我使用了与问题中相同的 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
在下一条指令中的使用。