如何删除未使用的基本块llvm

时间:2014-01-17 20:43:21

标签: llvm

我正在尝试从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

任何想法可能是什么问题?

2 个答案:

答案 0 :(得分:2)

这不是一个段错误,这是一个断言错误,它告诉你问题:前任列表不是空的。您收到此断言错误,因为DeleteDeadBlock验证您要删除的块没有直接的前任(除了它自己)。

然而,这个测试并不意味着该块是活着的;例如,在这种情况下(假设线条是向下箭头):

entry
 /
A   B
|   |
C   D
 \ /
  E

B和D都死了,但是如果你试图在B之前删除D你会得到断言,因为D有一个前身(它本身不是)。

如何解决这个问题?您可以执行以下操作之一:

  1. 按拓扑顺序处理块
  2. 从要删除的块中删除所有前置任务(例如,使用unreachable指令替换其所有前任的终结符)
    • 您也可以对识别为死亡的所有块执行此操作,然后按任意顺序删除它们

答案 1 :(得分:0)

您可以使用llvm::EliminateUnreachableBlocks。它从入口块开始对基本块进行深度优先搜索。这有助于识别一旦删除“死”的前任对象后将变为“死”的“活动”块。