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

如何在LLVM中的两个块之间插入基本块,llvm,llvm-ir,Llvm,Llvm Ir,这与解决方案描述相似,但我不清楚——或者更好——我试图按照描述的方式来做,但它不起作用(对我来说) 我想做的是: 如果一个基本块有多个后续块,我想插入一个基本块。 所以,如果基本块A有条件地跳转到B或C,我想在A和B之间以及A和C之间插入一个基本块。如果有跳转表,它也应该工作 所以我要做的是: while (...) { // get next basic block and ensure it has at least 2 successors: BasicBlock *origBB

这与解决方案描述相似,但我不清楚——或者更好——我试图按照描述的方式来做,但它不起作用(对我来说)

我想做的是: 如果一个基本块有多个后续块,我想插入一个基本块。 所以,如果基本块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);
  }
}
然而,我得到的错误
指令并不是支配所有用途

我确信解决方案非常简单,但我找不到:-(


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

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

建议a)使用splitBlock()的注释方向错误,因为它是关于插入到边中,因此结果将是错误的。b) 更新phi实际上可以解决这个问题。然而,这是非常复杂的,因为不能使用简单的
replacephiusswith
——如果a->B和a是循环头,B是循环尾(因此返回到B),则会导致编译错误,因此必须仔细评估所有的PHI

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

这并不明显,因为该函数未记录在doxygen类列表中,因此除了通过浏览源代码和包含外,找不到它

下面是如何使用它:

#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
   ...

}

#包括“llvm/Transforms/Utils/BasicBlockUtils.h”
函数()中的void{
...
//将新块插入此BB和成功块B之间的边缘
BasicBlock*insertedBB=SplitEdge(thisBB,successorBB);
如果(!insertedBB){
//SplitEdge可能会失败,例如,如果后继设备是着陆台
返回;
}
//然后将说明放入新的BB中
基本块::迭代器IP=newBB->getFirstInsertionPt();
内部评级机构内部评级(&(*IP));
//然后与IRB合作
//你不需要照顾成功的分支机构B-它已经在那里了
...
}

就是这样,就这么简单。

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

建议a)使用splitBlock()的注释方向错误,因为它是关于插入到边中,因此结果将是错误的。b) 更新phi实际上可以解决这个问题。然而,这是非常复杂的,因为不能使用简单的
replacephiusswith
——如果a->B和a是循环头,B是循环尾(因此返回到B),则会导致编译错误,因此必须仔细评估所有的PHI

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

这并不明显,因为该函数未记录在doxygen类列表中,因此除了通过浏览源代码和包含外,找不到它

下面是如何使用它:

#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
   ...

}

#包括“llvm/Transforms/Utils/BasicBlockUtils.h”
函数()中的void{
...
//将新块插入此BB和成功块B之间的边缘
BasicBlock*insertedBB=SplitEdge(thisBB,successorBB);
如果(!insertedBB){
//SplitEdge可能会失败,例如,如果后继设备是着陆台
返回;
}
//然后将说明放入新的BB中
基本块::迭代器IP=newBB->getFirstInsertionPt();
内部评级机构内部评级(&(*IP));
//然后与IRB合作
//你不需要照顾成功的分支机构B-它已经在那里了
...
}

就是这样,就这么简单。

可以通过查看SI中的Phi节点来解决Phi节点问题,如果有任何节点指向origBB,请将它们改为指向BB。或者你可以使用,这将为你处理几乎所有的事情。我如何在继承者的phi节点上做到这一点?如何纠正它们?我需要一个指向函数调用的指针:)。我不能使用splitBlock(我想),因为它不是关于分割块,而是将一个块插入一条不同的边。你可以在splitBlock()中看到一个如何更正phi节点的示例。phi节点问题可以通过查看SI中的phi节点来解决,如果有引用origBB的节点,则将它们改为引用BB。或者你可以使用,这将为你处理几乎所有的事情。我如何在继承者的phi节点上做到这一点?如何纠正它们?我需要一个指向函数调用的指针:)。我不能使用splitBlock(我想),因为它不是关于分割块,而是将一个块插入到一条不同的边中。您可以在splitBlock()中看到一个如何更正phi节点的示例。