diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -574,9 +574,9 @@ // Place the block after the current block, if possible, or else at // the end of the function. if (CurBB && CurBB->getParent()) - CurFn->getBasicBlockList().insertAfter(CurBB->getIterator(), BB); + CurFn->insertBasicBlockAt(std::next(CurBB->getIterator()), BB); else - CurFn->getBasicBlockList().push_back(BB); + CurFn->insertBasicBlockAt(CurFn->end(), BB); Builder.SetInsertPoint(BB); } @@ -601,15 +601,15 @@ bool inserted = false; for (llvm::User *u : block->users()) { if (llvm::Instruction *insn = dyn_cast(u)) { - CurFn->getBasicBlockList().insertAfter(insn->getParent()->getIterator(), - block); + CurFn->insertBasicBlockAt(std::next(insn->getParent()->getIterator()), + block); inserted = true; break; } } if (!inserted) - CurFn->getBasicBlockList().push_back(block); + CurFn->insertBasicBlockAt(CurFn->end(), block); Builder.SetInsertPoint(block); } @@ -1469,7 +1469,7 @@ llvm::BasicBlock *FalseDest = CaseRangeBlock; CaseRangeBlock = createBasicBlock("sw.caserange"); - CurFn->getBasicBlockList().push_back(CaseRangeBlock); + CurFn->insertBasicBlockAt(CurFn->end(), CaseRangeBlock); Builder.SetInsertPoint(CaseRangeBlock); // Emit range check. diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -319,8 +319,10 @@ static void EmitIfUsed(CodeGenFunction &CGF, llvm::BasicBlock *BB) { if (!BB) return; - if (!BB->use_empty()) - return CGF.CurFn->getBasicBlockList().push_back(BB); + if (!BB->use_empty()) { + CGF.CurFn->insertBasicBlockAt(CGF.CurFn->end(), BB); + return; + } delete BB; } diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter1/toy.cpp @@ -863,7 +863,7 @@ ThenBB = Builder->GetInsertBlock(); // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), ElseBB); Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); @@ -875,7 +875,7 @@ ElseBB = Builder->GetInsertBlock(); // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), MergeBB); Builder->SetInsertPoint(MergeBB); PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter2/toy.cpp @@ -863,7 +863,7 @@ ThenBB = Builder->GetInsertBlock(); // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), ElseBB); Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); @@ -875,7 +875,7 @@ ElseBB = Builder->GetInsertBlock(); // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), MergeBB); Builder->SetInsertPoint(MergeBB); PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter3/toy.cpp @@ -863,7 +863,7 @@ ThenBB = Builder->GetInsertBlock(); // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), ElseBB); Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); @@ -875,7 +875,7 @@ ElseBB = Builder->GetInsertBlock(); // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), MergeBB); Builder->SetInsertPoint(MergeBB); PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); diff --git a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp --- a/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp +++ b/llvm/examples/Kaleidoscope/BuildingAJIT/Chapter4/toy.cpp @@ -846,7 +846,7 @@ ThenBB = Builder->GetInsertBlock(); // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), ElseBB); Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); @@ -858,7 +858,7 @@ ElseBB = Builder->GetInsertBlock(); // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), MergeBB); Builder->SetInsertPoint(MergeBB); PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); diff --git a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp --- a/llvm/examples/Kaleidoscope/Chapter5/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter5/toy.cpp @@ -650,7 +650,7 @@ ThenBB = Builder->GetInsertBlock(); // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), ElseBB); Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); @@ -662,7 +662,7 @@ ElseBB = Builder->GetInsertBlock(); // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), MergeBB); Builder->SetInsertPoint(MergeBB); PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); diff --git a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp --- a/llvm/examples/Kaleidoscope/Chapter6/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter6/toy.cpp @@ -762,7 +762,7 @@ ThenBB = Builder->GetInsertBlock(); // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), ElseBB); Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); @@ -774,7 +774,7 @@ ElseBB = Builder->GetInsertBlock(); // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), MergeBB); Builder->SetInsertPoint(MergeBB); PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); diff --git a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp --- a/llvm/examples/Kaleidoscope/Chapter7/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter7/toy.cpp @@ -869,7 +869,7 @@ ThenBB = Builder->GetInsertBlock(); // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), ElseBB); Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); @@ -881,7 +881,7 @@ ElseBB = Builder->GetInsertBlock(); // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), MergeBB); Builder->SetInsertPoint(MergeBB); PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); diff --git a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp --- a/llvm/examples/Kaleidoscope/Chapter8/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter8/toy.cpp @@ -867,7 +867,7 @@ ThenBB = Builder->GetInsertBlock(); // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), ElseBB); Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); @@ -879,7 +879,7 @@ ElseBB = Builder->GetInsertBlock(); // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), MergeBB); Builder->SetInsertPoint(MergeBB); PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); diff --git a/llvm/examples/Kaleidoscope/Chapter9/toy.cpp b/llvm/examples/Kaleidoscope/Chapter9/toy.cpp --- a/llvm/examples/Kaleidoscope/Chapter9/toy.cpp +++ b/llvm/examples/Kaleidoscope/Chapter9/toy.cpp @@ -1037,7 +1037,7 @@ ThenBB = Builder->GetInsertBlock(); // Emit else block. - TheFunction->getBasicBlockList().push_back(ElseBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), ElseBB); Builder->SetInsertPoint(ElseBB); Value *ElseV = Else->codegen(); @@ -1049,7 +1049,7 @@ ElseBB = Builder->GetInsertBlock(); // Emit merge block. - TheFunction->getBasicBlockList().push_back(MergeBB); + TheFunction->insertBasicBlockAt(TheFunction->end(), MergeBB); Builder->SetInsertPoint(MergeBB); PHINode *PN = Builder->CreatePHI(Type::getDoubleTy(*TheContext), 2, "iftmp"); diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -678,6 +678,12 @@ /// Requires that this has no function body. void stealArgumentListFrom(Function &Src); + /// Insert \p BB in the basic block list at \p Position. \Returns an iterator + /// to the newly inserted BB. + Function::iterator insertBasicBlockAt(Function::iterator Position, BasicBlock *BB) { + return BasicBlocks.insert(Position, BB); + } + /// Get the underlying elements of the Function... the basic block list is /// empty for external functions. /// diff --git a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp --- a/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp +++ b/llvm/lib/Frontend/OpenMP/OMPIRBuilder.cpp @@ -3617,7 +3617,7 @@ // Emit thenBB and set the Builder's insertion point there for // body generation next. Place the block after the current block. Function *CurFn = EntryBB->getParent(); - CurFn->getBasicBlockList().insertAfter(EntryBB->getIterator(), ThenBB); + CurFn->insertBasicBlockAt(std::next(EntryBB->getIterator()), ThenBB); // Move Entry branch to end of ThenBB, and replace with conditional // branch (If-stmt) diff --git a/llvm/lib/IR/BasicBlock.cpp b/llvm/lib/IR/BasicBlock.cpp --- a/llvm/lib/IR/BasicBlock.cpp +++ b/llvm/lib/IR/BasicBlock.cpp @@ -62,9 +62,9 @@ assert(!Parent && "Already has a parent"); if (InsertBefore) - NewParent->getBasicBlockList().insert(InsertBefore->getIterator(), this); + NewParent->insertBasicBlockAt(InsertBefore->getIterator(), this); else - NewParent->getBasicBlockList().push_back(this); + NewParent->insertBasicBlockAt(NewParent->end(), this); } BasicBlock::~BasicBlock() { diff --git a/llvm/lib/IR/Core.cpp b/llvm/lib/IR/Core.cpp --- a/llvm/lib/IR/Core.cpp +++ b/llvm/lib/IR/Core.cpp @@ -2655,13 +2655,14 @@ BasicBlock *ToInsert = unwrap(BB); BasicBlock *CurBB = unwrap(Builder)->GetInsertBlock(); assert(CurBB && "current insertion point is invalid!"); - CurBB->getParent()->getBasicBlockList().insertAfter(CurBB->getIterator(), - ToInsert); + CurBB->getParent()->insertBasicBlockAt(std::next(CurBB->getIterator()), + ToInsert); } void LLVMAppendExistingBasicBlock(LLVMValueRef Fn, LLVMBasicBlockRef BB) { - unwrap(Fn)->getBasicBlockList().push_back(unwrap(BB)); + unwrap(Fn)->insertBasicBlockAt(unwrap(Fn)->end(), + unwrap(BB)); } LLVMBasicBlockRef LLVMAppendBasicBlockInContext(LLVMContextRef C, diff --git a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp --- a/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp +++ b/llvm/lib/Transforms/Utils/BreakCriticalEdges.cpp @@ -179,7 +179,7 @@ // Insert the block into the function... right after the block TI lives in. Function &F = *TIBB->getParent(); Function::iterator FBBI = TIBB->getIterator(); - F.getBasicBlockList().insert(++FBBI, NewBB); + F.insertBasicBlockAt(++FBBI, NewBB); // Branch to the new block, breaking the edge. TI->setSuccessor(SuccNum, NewBB); diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -670,7 +670,7 @@ continue; // Dead block. // Add the new block to the new function. - NewFunc->getBasicBlockList().push_back(NewBB); + NewFunc->insertBasicBlockAt(NewFunc->end(), NewBB); // Handle PHI nodes specially, as we have to remove references to dead // blocks. diff --git a/llvm/lib/Transforms/Utils/CodeExtractor.cpp b/llvm/lib/Transforms/Utils/CodeExtractor.cpp --- a/llvm/lib/Transforms/Utils/CodeExtractor.cpp +++ b/llvm/lib/Transforms/Utils/CodeExtractor.cpp @@ -999,7 +999,7 @@ newFunction->addFnAttr(Attr); } - newFunction->getBasicBlockList().push_back(newRootNode); + newFunction->insertBasicBlockAt(newFunction->end(), newRootNode); // Create scalar and aggregate iterators to name all of the arguments we // inserted. @@ -1435,21 +1435,17 @@ } void CodeExtractor::moveCodeToFunction(Function *newFunction) { - Function *oldFunc = (*Blocks.begin())->getParent(); - Function::BasicBlockListType &oldBlocks = oldFunc->getBasicBlockList(); - Function::BasicBlockListType &newBlocks = newFunction->getBasicBlockList(); - auto newFuncIt = newFunction->front().getIterator(); for (BasicBlock *Block : Blocks) { // Delete the basic block from the old function, and the list of blocks - oldBlocks.remove(Block); + Block->removeFromParent(); // Insert this basic block into the new function // Insert the original blocks after the entry block created // for the new function. The entry block may be followed // by a set of exit blocks at this point, but these exit // blocks better be placed at the end of the new function. - newFuncIt = newBlocks.insertAfter(newFuncIt, Block); + newFuncIt = newFunction->insertBasicBlockAt(std::next(newFuncIt), Block); } } diff --git a/llvm/lib/Transforms/Utils/LoopUnroll.cpp b/llvm/lib/Transforms/Utils/LoopUnroll.cpp --- a/llvm/lib/Transforms/Utils/LoopUnroll.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnroll.cpp @@ -540,7 +540,7 @@ for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) { ValueToValueMapTy VMap; BasicBlock *New = CloneBasicBlock(*BB, VMap, "." + Twine(It)); - Header->getParent()->getBasicBlockList().insert(BlockInsertPt, New); + Header->getParent()->insertBasicBlockAt(BlockInsertPt, New); assert((*BB != Header || LI->getLoopFor(*BB) == L) && "Header should not be in a sub-loop"); diff --git a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp --- a/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp +++ b/llvm/lib/Transforms/Utils/LoopUnrollAndJam.cpp @@ -374,7 +374,7 @@ for (LoopBlocksDFS::RPOIterator BB = BlockBegin; BB != BlockEnd; ++BB) { ValueToValueMapTy VMap; BasicBlock *New = CloneBasicBlock(*BB, VMap, "." + Twine(It)); - Header->getParent()->getBasicBlockList().push_back(New); + Header->getParent()->insertBasicBlockAt(Header->getParent()->end(), New); // Tell LI about New. addClonedBlockToLoopInfo(*BB, New, LI, NewLoops); diff --git a/llvm/lib/Transforms/Utils/LowerSwitch.cpp b/llvm/lib/Transforms/Utils/LowerSwitch.cpp --- a/llvm/lib/Transforms/Utils/LowerSwitch.cpp +++ b/llvm/lib/Transforms/Utils/LowerSwitch.cpp @@ -160,7 +160,7 @@ BasicBlock *Default) { Function *F = OrigBlock->getParent(); BasicBlock *NewLeaf = BasicBlock::Create(Val->getContext(), "LeafBlock"); - F->getBasicBlockList().insert(++OrigBlock->getIterator(), NewLeaf); + F->insertBasicBlockAt(++OrigBlock->getIterator(), NewLeaf); // Emit comparison ICmpInst *Comp = nullptr; @@ -300,7 +300,7 @@ SwitchConvert(RHS.begin(), RHS.end(), NewLowerBound, UpperBound, Val, NewNode, OrigBlock, Default, UnreachableRanges); - F->getBasicBlockList().insert(++OrigBlock->getIterator(), NewNode); + F->insertBasicBlockAt(++OrigBlock->getIterator(), NewNode); Comp->insertAt(NewNode, NewNode->end()); BranchInst::Create(LBranch, RBranch, Comp, NewNode); diff --git a/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp b/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp --- a/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp +++ b/llvm/unittests/Analysis/FunctionPropertiesAnalysisTest.cpp @@ -325,8 +325,7 @@ EXPECT_TRUE(IR.isSuccess()); invalidate(*F1); FPU.finish(FAM); - EXPECT_EQ(static_cast(FPI.BasicBlockCount), - F1->getBasicBlockList().size()); + EXPECT_EQ(static_cast(FPI.BasicBlockCount), F1->size()); EXPECT_EQ(static_cast(FPI.TotalInstructionCount), F1->getInstructionCount()); } @@ -379,8 +378,7 @@ EXPECT_TRUE(IR.isSuccess()); invalidate(*F1); FPU.finish(FAM); - EXPECT_EQ(static_cast(FPI.BasicBlockCount), - F1->getBasicBlockList().size() - 1); + EXPECT_EQ(static_cast(FPI.BasicBlockCount), F1->size() - 1); EXPECT_EQ(static_cast(FPI.TotalInstructionCount), F1->getInstructionCount() - 2); EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM)); @@ -434,8 +432,7 @@ EXPECT_TRUE(IR.isSuccess()); invalidate(*F1); FPU.finish(FAM); - EXPECT_EQ(static_cast(FPI.BasicBlockCount), - F1->getBasicBlockList().size() - 1); + EXPECT_EQ(static_cast(FPI.BasicBlockCount), F1->size() - 1); EXPECT_EQ(static_cast(FPI.TotalInstructionCount), F1->getInstructionCount() - 2); EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM)); @@ -487,8 +484,7 @@ EXPECT_TRUE(IR.isSuccess()); invalidate(*F1); FPU.finish(FAM); - EXPECT_EQ(static_cast(FPI.BasicBlockCount), - F1->getBasicBlockList().size() - 1); + EXPECT_EQ(static_cast(FPI.BasicBlockCount), F1->size() - 1); EXPECT_EQ(static_cast(FPI.TotalInstructionCount), F1->getInstructionCount() - 2); EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM)); @@ -544,8 +540,7 @@ EXPECT_TRUE(IR.isSuccess()); invalidate(*F1); FPU.finish(FAM); - EXPECT_EQ(static_cast(FPI.BasicBlockCount), - F1->getBasicBlockList().size() - 1); + EXPECT_EQ(static_cast(FPI.BasicBlockCount), F1->size() - 1); EXPECT_EQ(static_cast(FPI.TotalInstructionCount), F1->getInstructionCount() - 2); EXPECT_EQ(FPI, FunctionPropertiesInfo::getFunctionPropertiesInfo(*F1, FAM)); diff --git a/llvm/unittests/IR/FunctionTest.cpp b/llvm/unittests/IR/FunctionTest.cpp --- a/llvm/unittests/IR/FunctionTest.cpp +++ b/llvm/unittests/IR/FunctionTest.cpp @@ -7,12 +7,29 @@ //===----------------------------------------------------------------------===// #include "llvm/IR/Function.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Module.h" +#include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" using namespace llvm; namespace { +static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { + SMDiagnostic Err; + std::unique_ptr Mod = parseAssemblyString(IR, Err, C); + if (!Mod) + Err.print("InstructionsTests", errs()); + return Mod; +} + +static BasicBlock *getBBWithName(Function *F, StringRef Name) { + auto It = find_if( + *F, [&Name](const BasicBlock &BB) { return BB.getName() == Name; }); + assert(It != F->end() && "Not found!"); + return &*It; +} + TEST(FunctionTest, hasLazyArguments) { LLVMContext C; @@ -162,4 +179,64 @@ EXPECT_EQ(Align(4), Func->getPointerAlignment(DataLayout("Fn32"))); } +TEST(FunctionTest, InsertBasicBlockAt) { + LLVMContext C; + std::unique_ptr M = parseIR(C, R"( +define void @foo(i32 %a, i32 %b) { +foo_bb0: + ret void +} + +define void @bar() { +bar_bb0: + br label %bar_bb1 +bar_bb1: + br label %bar_bb2 +bar_bb2: + ret void +} +)"); + Function *FooF = M->getFunction("foo"); + BasicBlock *FooBB0 = getBBWithName(FooF, "foo_bb0"); + + Function *BarF = M->getFunction("bar"); + BasicBlock *BarBB0 = getBBWithName(BarF, "bar_bb0"); + BasicBlock *BarBB1 = getBBWithName(BarF, "bar_bb1"); + BasicBlock *BarBB2 = getBBWithName(BarF, "bar_bb2"); + + // Insert foo_bb0 into bar() at the very top. + FooBB0->removeFromParent(); + auto It = BarF->insertBasicBlockAt(BarF->begin(), FooBB0); + EXPECT_EQ(BarBB0->getPrevNode(), FooBB0); + EXPECT_EQ(It, FooBB0->getIterator()); + + // Insert foo_bb0 into bar() at the very end. + FooBB0->removeFromParent(); + It = BarF->insertBasicBlockAt(BarF->end(), FooBB0); + EXPECT_EQ(FooBB0->getPrevNode(), BarBB2); + EXPECT_EQ(FooBB0->getNextNode(), nullptr); + EXPECT_EQ(It, FooBB0->getIterator()); + + // Insert foo_bb0 into bar() just before bar_bb0. + FooBB0->removeFromParent(); + It = BarF->insertBasicBlockAt(BarBB0->getIterator(), FooBB0); + EXPECT_EQ(FooBB0->getPrevNode(), nullptr); + EXPECT_EQ(FooBB0->getNextNode(), BarBB0); + EXPECT_EQ(It, FooBB0->getIterator()); + + // Insert foo_bb0 into bar() just before bar_bb1. + FooBB0->removeFromParent(); + It = BarF->insertBasicBlockAt(BarBB1->getIterator(), FooBB0); + EXPECT_EQ(FooBB0->getPrevNode(), BarBB0); + EXPECT_EQ(FooBB0->getNextNode(), BarBB1); + EXPECT_EQ(It, FooBB0->getIterator()); + + // Insert foo_bb0 into bar() just before bar_bb2. + FooBB0->removeFromParent(); + It = BarF->insertBasicBlockAt(BarBB2->getIterator(), FooBB0); + EXPECT_EQ(FooBB0->getPrevNode(), BarBB1); + EXPECT_EQ(FooBB0->getNextNode(), BarBB2); + EXPECT_EQ(It, FooBB0->getIterator()); +} + } // end namespace