在 LLVM 自定义优化过程中删除指令时出现段错误
Segfault on removing instruction in LLVM custom optimization pass
这是我写的优化过程。它将任何以零作为其操作数之一的乘法替换为简单的零。
struct FoldConstant : public llvm::FunctionPass {
static char ID;
FoldConstant() : llvm::FunctionPass(ID) {}
bool runOnFunction(llvm::Function &func) override {
for (auto &block : func) {
for (auto &inst : block) {
if (inst.isBinaryOp()) {
llvm::Value *left = inst.getOperand(0);
llvm::Value *right = inst.getOperand(1);
if (inst.getOpcode() == 17) {
if (llvm::ConstantInt *lc =
llvm::dyn_cast<llvm::ConstantInt>(left)) {
if (lc->getSExtValue() == 0) {
inst.replaceAllUsesWith(left);
inst.eraseFromParent();
}
}
if (llvm::ConstantInt *rc =
llvm::dyn_cast<llvm::ConstantInt>(right)) {
if (rc->getSExtValue() == 0) {
inst.replaceAllUsesWith(right);
inst.eraseFromParent();
}
}
}
}
}
}
return true;
}
};
现在,当我运行它在下面的红外源
; ModuleID = 'bootleg c compiler'
source_filename = "bootleg c compiler"
define i32 @constant_folding(i32 %b) {
entry:
%b1 = alloca i32
store i32 %b, i32* %b1
%b2 = load i32, i32* %b1
%mul = mul i32 %b2, 0
ret i32 %mul
}
它给出了一个段错误,下面是堆栈跟踪。
sumit@HAL9001:~/Coding/cc$ opt -S -load ./opt.so -foldconst < output.ll
Stack dump:
0. Program arguments: opt -S -load ./opt.so -foldconst
1. Running pass 'Function Pass Manager' on module '<stdin>'.
2. Running pass 'constant folding' on function '@constant_folding'
#0 0x00007f5e0522e4ff llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x9814ff)
#1 0x00007f5e0522c7b0 llvm::sys::RunSignalHandlers() (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x97f7b0)
#2 0x00007f5e0522eac5 (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x981ac5)
#3 0x00007f5e08f563c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x153c0)
#4 0x00007f5e08f73986 llvm::Value::getValueID() const /usr/lib/llvm-10/include/llvm/IR/Value.h:485:12
#5 0x00007f5e08f73ae2 llvm::Instruction::getOpcode() const /usr/lib/llvm-10/include/llvm/IR/Instruction.h:125:54
#6 0x00007f5e08f73b04 llvm::Instruction::isBinaryOp() const /usr/lib/llvm-10/include/llvm/IR/Instruction.h:130:46
#7 0x00007f5e08f74857 FoldConstant::runOnFunction(llvm::Function&) /home/sumit/Coding/cc/c.opt.cpp:75:17
#8 0x00007f5e05333d76 llvm::FPPassManager::runOnFunction(llvm::Function&) (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0xa86d76)
#9 0x00007f5e05333ff3 llvm::FPPassManager::runOnModule(llvm::Module&) (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0xa86ff3)
#10 0x00007f5e053344a0 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0xa874a0)
#11 0x00000000004bf3f8 main (/usr/lib/llvm-10/bin/opt+0x4bf3f8)
#12 0x00007f5e043970b3 __libc_start_main /build/glibc-ZN95T4/glibc-2.31/csu/../csu/libc-start.c:342:3
#13 0x00000000004ad0de _start (/usr/lib/llvm-10/bin/opt+0x4ad0de)
Segmentation fault (core dumped)
到目前为止,我已尝试更改我的代码以使用
llvm::BasicBlock::iterator iter(inst);
llvm::ReplaceInstWithValue(block.getInstList(), iter, right);
但这并没有什么区别。任何帮助将不胜感激。
就像@500-internal-server-error 在对我的问题的评论中指出的那样,出现段错误是因为我在循环遍历容器(基本块)时从容器(基本块)中删除了元素(指令)。我现在正在使用以下代码,它按预期工作。
struct FoldConstant : public llvm::FunctionPass {
static char ID;
FoldConstant() : llvm::FunctionPass(ID) {}
bool runOnFunction(llvm::Function &func) override {
bool changed = false;
vector<llvm::Instruction *> instsToDelete;
for (auto &block : func) {
for (auto &inst : block) {
if (inst.isBinaryOp()) {
llvm::Value *left = inst.getOperand(0);
llvm::Value *right = inst.getOperand(1);
if (inst.getOpcode() == 17) {
if (llvm::ConstantInt *lc =
llvm::dyn_cast<llvm::ConstantInt>(left)) {
if (lc->getSExtValue() == 0) {
instsToDelete.push_back(&inst);
inst.replaceAllUsesWith(left);
changed = true;
}
}
if (llvm::ConstantInt *rc =
llvm::dyn_cast<llvm::ConstantInt>(right)) {
if (rc->getSExtValue() == 0) {
instsToDelete.push_back(&inst);
inst.replaceAllUsesWith(right);
changed = true;
}
}
}
}
}
}
for (auto inst : instsToDelete) {
inst->eraseFromParent();
}
return changed;
}
};
我将指向我需要删除的指令的指针存储在一个向量中,稍后再删除它们。
这是我写的优化过程。它将任何以零作为其操作数之一的乘法替换为简单的零。
struct FoldConstant : public llvm::FunctionPass {
static char ID;
FoldConstant() : llvm::FunctionPass(ID) {}
bool runOnFunction(llvm::Function &func) override {
for (auto &block : func) {
for (auto &inst : block) {
if (inst.isBinaryOp()) {
llvm::Value *left = inst.getOperand(0);
llvm::Value *right = inst.getOperand(1);
if (inst.getOpcode() == 17) {
if (llvm::ConstantInt *lc =
llvm::dyn_cast<llvm::ConstantInt>(left)) {
if (lc->getSExtValue() == 0) {
inst.replaceAllUsesWith(left);
inst.eraseFromParent();
}
}
if (llvm::ConstantInt *rc =
llvm::dyn_cast<llvm::ConstantInt>(right)) {
if (rc->getSExtValue() == 0) {
inst.replaceAllUsesWith(right);
inst.eraseFromParent();
}
}
}
}
}
}
return true;
}
};
现在,当我运行它在下面的红外源
; ModuleID = 'bootleg c compiler'
source_filename = "bootleg c compiler"
define i32 @constant_folding(i32 %b) {
entry:
%b1 = alloca i32
store i32 %b, i32* %b1
%b2 = load i32, i32* %b1
%mul = mul i32 %b2, 0
ret i32 %mul
}
它给出了一个段错误,下面是堆栈跟踪。
sumit@HAL9001:~/Coding/cc$ opt -S -load ./opt.so -foldconst < output.ll
Stack dump:
0. Program arguments: opt -S -load ./opt.so -foldconst
1. Running pass 'Function Pass Manager' on module '<stdin>'.
2. Running pass 'constant folding' on function '@constant_folding'
#0 0x00007f5e0522e4ff llvm::sys::PrintStackTrace(llvm::raw_ostream&) (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x9814ff)
#1 0x00007f5e0522c7b0 llvm::sys::RunSignalHandlers() (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x97f7b0)
#2 0x00007f5e0522eac5 (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0x981ac5)
#3 0x00007f5e08f563c0 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x153c0)
#4 0x00007f5e08f73986 llvm::Value::getValueID() const /usr/lib/llvm-10/include/llvm/IR/Value.h:485:12
#5 0x00007f5e08f73ae2 llvm::Instruction::getOpcode() const /usr/lib/llvm-10/include/llvm/IR/Instruction.h:125:54
#6 0x00007f5e08f73b04 llvm::Instruction::isBinaryOp() const /usr/lib/llvm-10/include/llvm/IR/Instruction.h:130:46
#7 0x00007f5e08f74857 FoldConstant::runOnFunction(llvm::Function&) /home/sumit/Coding/cc/c.opt.cpp:75:17
#8 0x00007f5e05333d76 llvm::FPPassManager::runOnFunction(llvm::Function&) (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0xa86d76)
#9 0x00007f5e05333ff3 llvm::FPPassManager::runOnModule(llvm::Module&) (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0xa86ff3)
#10 0x00007f5e053344a0 llvm::legacy::PassManagerImpl::run(llvm::Module&) (/lib/x86_64-linux-gnu/libLLVM-10.so.1+0xa874a0)
#11 0x00000000004bf3f8 main (/usr/lib/llvm-10/bin/opt+0x4bf3f8)
#12 0x00007f5e043970b3 __libc_start_main /build/glibc-ZN95T4/glibc-2.31/csu/../csu/libc-start.c:342:3
#13 0x00000000004ad0de _start (/usr/lib/llvm-10/bin/opt+0x4ad0de)
Segmentation fault (core dumped)
到目前为止,我已尝试更改我的代码以使用
llvm::BasicBlock::iterator iter(inst);
llvm::ReplaceInstWithValue(block.getInstList(), iter, right);
但这并没有什么区别。任何帮助将不胜感激。
就像@500-internal-server-error 在对我的问题的评论中指出的那样,出现段错误是因为我在循环遍历容器(基本块)时从容器(基本块)中删除了元素(指令)。我现在正在使用以下代码,它按预期工作。
struct FoldConstant : public llvm::FunctionPass {
static char ID;
FoldConstant() : llvm::FunctionPass(ID) {}
bool runOnFunction(llvm::Function &func) override {
bool changed = false;
vector<llvm::Instruction *> instsToDelete;
for (auto &block : func) {
for (auto &inst : block) {
if (inst.isBinaryOp()) {
llvm::Value *left = inst.getOperand(0);
llvm::Value *right = inst.getOperand(1);
if (inst.getOpcode() == 17) {
if (llvm::ConstantInt *lc =
llvm::dyn_cast<llvm::ConstantInt>(left)) {
if (lc->getSExtValue() == 0) {
instsToDelete.push_back(&inst);
inst.replaceAllUsesWith(left);
changed = true;
}
}
if (llvm::ConstantInt *rc =
llvm::dyn_cast<llvm::ConstantInt>(right)) {
if (rc->getSExtValue() == 0) {
instsToDelete.push_back(&inst);
inst.replaceAllUsesWith(right);
changed = true;
}
}
}
}
}
}
for (auto inst : instsToDelete) {
inst->eraseFromParent();
}
return changed;
}
};
我将指向我需要删除的指令的指针存储在一个向量中,稍后再删除它们。