如何在LLVM中的两个块之间插入一个基本块



这类似于在LLVM中的两个块之间插入块,但解决方案的描述对我来说不清楚——或者更好——我试图按照描述的方式进行,但(对我来说(不起作用。

我想做的事:只要一个基本块有一个以上的后继块,我就想插入一个基本的块。因此,如果基本块A有条件地跳转到B或C,我想在A和B之间以及A和C之间插入一个基本块。如果有跳转表,它也应该有效。

所以我做的是:

while (...) {
// get next basic block and ensure it has at least 2 successors:
BasicBlock *origBB = getNextBB();
Instruction *TI = origBB->getTerminator()
if (!TI || TI->getNumSuccessors() < 2)
continue;
// collect successors:
std::vector<BasicBlock *> Successors;
for (succ_iterator SI = succ_begin(origBB), SE = succ_end(origBB); SI != SE; ++SI) {
BasicBlock *succ = *SI;
Successors.push_back(succ);
}
// now for each successor:
for (uint32_t i = 0; i < Successors.size(); i++) {
// Create a new basic block
BasicBlock *BB = BasicBlock::Create(C, "", &F, nullptr);
// F.getBasicBlockList().push_back(BB); <= this did not work, seem to result in endless loop
IRBuilder<> IRB(BB);
// put instructions into BB
... // omitted
// then add the terminator:
IRB.CreateBr(Successors[i]);
// Now we have to fix the original BB to our new basic block:
TI->setSuccessor(i, BB);
}
}

当我运行此LLVM过程时,我会得到以下错误:PHI node entries do not match predecessors!

好的,所以我认为我必须从继承器中删除相应的前置器,并在setSuccessor((之后添加以下代码:

origBB->replaceSuccessorsPhiUsesWith(Successors[j], BB);
BasicBlock *S = Successors[i];
S->removePredecessor(origBB);

然后我得到错误Instruction does not dominate all uses!

我确信解决方案很简单,但我找不到:

非常感谢您的帮助或指点!

好吧,我在这里回答我自己的问题。

建议使用splitBlock((的注释正朝着错误的方向发展,因为它是关于插入边的,所以结果是错误的。b( 更新phi实际上可以解决这个问题。然而,这是非常复杂的,因为不能使用简单的replacePhiUsesWith——在a->B和a是循环头而B是loob尾的情况下(因此返回B(将导致编译错误,因此必须仔细评估所有phis。

因此,解决方案实际上非常简单,我在浏览llvm:SplitEdge((的源代码时发现了这一点。它正是我想要的,在两个基本块的边缘之间插入一个基本块!

它并不明显,因为doxygen类列表中没有记录该函数,所以除了浏览源代码和include之外,无法找到它。

所以这里如何使用它:

#include "llvm/Transforms/Utils/BasicBlockUtils.h"
void inYourFunction() {
...
// Insert the new block into the edge between thisBB and a successorBB
BasicBlock *insertedBB = SplitEdge(thisBB, successorBB);
if (!insertedBB) {
// SplitEdge can fail, e.g. if the successor is a landing pad
return;
}
// Then put instructions into the new BB
BasicBlock::iterator IP = newBB->getFirstInsertionPt();
IRBuilder<>          IRB(&(*IP));
// and then work with IRB
// You need not to take care of the branch to successorBB - it is already there
...
}

就是这样,就这么简单。