diff --git a/llvm/include/llvm/IR/Instruction.h b/llvm/include/llvm/IR/Instruction.h --- a/llvm/include/llvm/IR/Instruction.h +++ b/llvm/include/llvm/IR/Instruction.h @@ -129,6 +129,11 @@ /// specified instruction. void insertAfter(Instruction *InsertPos); + /// Inserts an unlinked instruction into \p BB at position \p It and returns + /// the iterator of the inserted instruction. + SymbolTableList::iterator + insertAt(BasicBlock *BB, SymbolTableList::iterator It); + /// Unlink this instruction from its current basic block and insert it into /// the basic block that MovePos lives in, right before MovePos. void moveBefore(Instruction *MovePos); diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -95,6 +95,13 @@ this); } +BasicBlock::iterator Instruction::insertAt(BasicBlock *BB, + BasicBlock::iterator It) { + assert(getParent() == nullptr && "Expected detached instruction"); + assert((It == BB->end() || It->getParent() == BB) && "It not in BB"); + return BB->getInstList().insert(It, this); +} + /// Unlink this instruction from its current basic block and insert it into the /// basic block that MovePos lives in, right before MovePos. void Instruction::moveBefore(Instruction *MovePos) { diff --git a/llvm/unittests/IR/InstructionsTest.cpp b/llvm/unittests/IR/InstructionsTest.cpp --- a/llvm/unittests/IR/InstructionsTest.cpp +++ b/llvm/unittests/IR/InstructionsTest.cpp @@ -1681,5 +1681,43 @@ EXPECT_EQ(H.getAllocationSizeInBits(DL), TypeSize::getFixed(160)); } +TEST(InstructionsTest, InsertAtBegin) { + LLVMContext Ctx; + std::unique_ptr M = parseIR(Ctx, R"( + define void @f(i32 %a, i32 %b) { + entry: + ret void + } +)"); + Function *F = &*M->begin(); + Argument *ArgA = F->getArg(0); + Argument *ArgB = F->getArg(1); + BasicBlock *BB = &*F->begin(); + Instruction *Ret = &*BB->begin(); + Instruction *I = BinaryOperator::CreateAdd(ArgA, ArgB); + auto It = I->insertAt(BB, BB->begin()); + EXPECT_EQ(&*It, I); + EXPECT_EQ(I->getNextNode(), Ret); +} + +TEST(InstructionsTest, InsertAtEnd) { + LLVMContext Ctx; + std::unique_ptr M = parseIR(Ctx, R"( + define void @f(i32 %a, i32 %b) { + entry: + ret void + } +)"); + Function *F = &*M->begin(); + Argument *ArgA = F->getArg(0); + Argument *ArgB = F->getArg(1); + BasicBlock *BB = &*F->begin(); + Instruction *Ret = &*BB->begin(); + Instruction *I = BinaryOperator::CreateAdd(ArgA, ArgB); + auto It = I->insertAt(BB, BB->end()); + EXPECT_EQ(&*It, I); + EXPECT_EQ(Ret->getNextNode(), I); +} + } // end anonymous namespace } // end namespace llvm