我正在尝试从llvm中间代码中删除未使用的块。
首先,我构建一个可到达的基本块集合,从入门基本块开始,并从终结符指令添加所有基本块后继:
bbset.insert(bbterm->getSuccessor(i));
之后,我遍历无法访问的基本块并使用
删除它们DeleteDeadBlock(bb);
来自Utils / BasicBlockUtils.cpp的
它可以工作,但在某些情况下我会遇到段错误。以下是核心转储:
opt: /home/user/llvm-3.3.src/lib/Transforms/Utils/BasicBlockUtils.cpp:38: void llvm::DeleteDeadBlock(llvm::BasicBlock*): Assertion `(pred_begin(BB) == pred_end(BB) || BB->getSinglePredecessor() == BB) && "Block is not dead!"' failed.
0 opt 0x0000000001756825 llvm::sys::PrintStackTrace(_IO_FILE*) + 38
1 opt 0x0000000001756aa2
2 opt 0x000000000175651e
3 libpthread.so.0 0x00007fe1fe76dbb0
4 libc.so.6 0x00007fe1fdbaef77 gsignal + 55
5 libc.so.6 0x00007fe1fdbb25e8 abort + 328
6 libc.so.6 0x00007fe1fdba7d43
7 libc.so.6 0x00007fe1fdba7df2
8 opt 0x000000000138b004 llvm::DeleteDeadBlock(llvm::BasicBlock*) + 139
9 opt 0x0000000000d49c2e
10 opt 0x0000000001652942 llvm::FPPassManager::runOnFunction(llvm::Function&) + 290
11 opt 0x0000000001652ab2 llvm::FPPassManager::runOnModule(llvm::Module&) + 84
12 opt 0x0000000001652dd0 llvm::MPPassManager::runOnModule(llvm::Module&) + 502
13 opt 0x00000000016533a0 llvm::PassManagerImpl::run(llvm::Module&) + 244
14 opt 0x00000000016535ab llvm::PassManager::run(llvm::Module&) + 39
15 opt 0x00000000008c6cb6 main + 5698
16 libc.so.6 0x00007fe1fdb99de5 __libc_start_main + 245
17 opt 0x00000000008b8a39
任何想法可能是什么问题?
答案 0 :(得分:2)
这不是一个段错误,这是一个断言错误,它告诉你问题:前任列表不是空的。您收到此断言错误,因为DeleteDeadBlock
验证您要删除的块没有直接的前任(除了它自己)。
然而,这个测试并不意味着该块是活着的;例如,在这种情况下(假设线条是向下箭头):
entry
/
A B
| |
C D
\ /
E
B和D都死了,但是如果你试图在B之前删除D你会得到断言,因为D有一个前身(它本身不是)。
如何解决这个问题?您可以执行以下操作之一:
unreachable
指令替换其所有前任的终结符)
答案 1 :(得分:0)
您可以使用llvm::EliminateUnreachableBlocks。它从入口块开始对基本块进行深度优先搜索。这有助于识别一旦删除“死”的前任对象后将变为“死”的“活动”块。