From f0a25f7253745d8aa3c3692e53110fc20a569bd0 Mon Sep 17 00:00:00 2001 From: Florian Hahn Date: Tue, 6 Mar 2018 13:12:32 +0000 Subject: [PATCH] [CloneFunction] Support BB == PredBB in DuplicateInstructionsInSplit. In case PredBB == BB and StopAt == BB's terminator, StopAt != &*BI will fail, because BB's terminator instruction gets replaced. By using BB.getTerminator() we get the current terminator which we can use to compare. Reviewers: sanjoy, anna, reames Reviewed By: anna Differential Revision: https://reviews.llvm.org/D43822 llvm-svn: 326779 --- llvm/lib/Transforms/Utils/CloneFunction.cpp | 4 +- llvm/unittests/Transforms/Utils/Cloning.cpp | 98 +++++++++++++++++++++ 2 files changed, 101 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp index 16af2c7b808b..3bc178ec88b6 100644 --- a/llvm/lib/Transforms/Utils/CloneFunction.cpp +++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp @@ -811,7 +811,9 @@ llvm::DuplicateInstructionsInSplitBetween(BasicBlock *BB, BasicBlock *PredBB, // Clone the non-phi instructions of BB into NewBB, keeping track of the // mapping and using it to remap operands in the cloned instructions. - for (; StopAt != &*BI; ++BI) { + // Stop once we see the terminator too. This covers the case where BB's + // terminator gets replaced and StopAt == BB's terminator. + for (; StopAt != &*BI && BB->getTerminator() != &*BI; ++BI) { Instruction *New = BI->clone(); New->setName(BI->getName()); New->insertBefore(NewTerm); diff --git a/llvm/unittests/Transforms/Utils/Cloning.cpp b/llvm/unittests/Transforms/Utils/Cloning.cpp index 2ce19bd51a87..9a1ad19ebaa4 100644 --- a/llvm/unittests/Transforms/Utils/Cloning.cpp +++ b/llvm/unittests/Transforms/Utils/Cloning.cpp @@ -251,6 +251,104 @@ TEST_F(CloneInstruction, DuplicateInstructionsToSplit) { delete F; } +TEST_F(CloneInstruction, DuplicateInstructionsToSplitBlocksEq1) { + Type *ArgTy1[] = {Type::getInt32PtrTy(context)}; + FunctionType *FT = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); + V = new Argument(Type::getInt32Ty(context)); + + Function *F = Function::Create(FT, Function::ExternalLinkage); + + BasicBlock *BB1 = BasicBlock::Create(context, "", F); + IRBuilder<> Builder1(BB1); + + BasicBlock *BB2 = BasicBlock::Create(context, "", F); + IRBuilder<> Builder2(BB2); + + Builder1.CreateBr(BB2); + + Instruction *AddInst = cast(Builder2.CreateAdd(V, V)); + Instruction *MulInst = cast(Builder2.CreateMul(AddInst, V)); + Instruction *SubInst = cast(Builder2.CreateSub(MulInst, V)); + Builder2.CreateBr(BB2); + + ValueToValueMapTy Mapping; + + auto Split = DuplicateInstructionsInSplitBetween(BB2, BB2, BB2->getTerminator(), Mapping); + + EXPECT_TRUE(Split); + EXPECT_EQ(Mapping.size(), 3u); + EXPECT_TRUE(Mapping.find(AddInst) != Mapping.end()); + EXPECT_TRUE(Mapping.find(MulInst) != Mapping.end()); + EXPECT_TRUE(Mapping.find(SubInst) != Mapping.end()); + + auto AddSplit = dyn_cast(Mapping[AddInst]); + EXPECT_TRUE(AddSplit); + EXPECT_EQ(AddSplit->getOperand(0), V); + EXPECT_EQ(AddSplit->getOperand(1), V); + EXPECT_EQ(AddSplit->getParent(), Split); + + auto MulSplit = dyn_cast(Mapping[MulInst]); + EXPECT_TRUE(MulSplit); + EXPECT_EQ(MulSplit->getOperand(0), AddSplit); + EXPECT_EQ(MulSplit->getOperand(1), V); + EXPECT_EQ(MulSplit->getParent(), Split); + + auto SubSplit = dyn_cast(Mapping[SubInst]); + EXPECT_EQ(MulSplit->getNextNode(), SubSplit); + EXPECT_EQ(SubSplit->getNextNode(), Split->getTerminator()); + EXPECT_EQ(Split->getSingleSuccessor(), BB2); + EXPECT_EQ(BB2->getSingleSuccessor(), Split); + + delete F; +} + +TEST_F(CloneInstruction, DuplicateInstructionsToSplitBlocksEq2) { + Type *ArgTy1[] = {Type::getInt32PtrTy(context)}; + FunctionType *FT = FunctionType::get(Type::getVoidTy(context), ArgTy1, false); + V = new Argument(Type::getInt32Ty(context)); + + Function *F = Function::Create(FT, Function::ExternalLinkage); + + BasicBlock *BB1 = BasicBlock::Create(context, "", F); + IRBuilder<> Builder1(BB1); + + BasicBlock *BB2 = BasicBlock::Create(context, "", F); + IRBuilder<> Builder2(BB2); + + Builder1.CreateBr(BB2); + + Instruction *AddInst = cast(Builder2.CreateAdd(V, V)); + Instruction *MulInst = cast(Builder2.CreateMul(AddInst, V)); + Instruction *SubInst = cast(Builder2.CreateSub(MulInst, V)); + Builder2.CreateBr(BB2); + + ValueToValueMapTy Mapping; + + auto Split = DuplicateInstructionsInSplitBetween(BB2, BB2, SubInst, Mapping); + + EXPECT_TRUE(Split); + EXPECT_EQ(Mapping.size(), 2u); + EXPECT_TRUE(Mapping.find(AddInst) != Mapping.end()); + EXPECT_TRUE(Mapping.find(MulInst) != Mapping.end()); + + auto AddSplit = dyn_cast(Mapping[AddInst]); + EXPECT_TRUE(AddSplit); + EXPECT_EQ(AddSplit->getOperand(0), V); + EXPECT_EQ(AddSplit->getOperand(1), V); + EXPECT_EQ(AddSplit->getParent(), Split); + + auto MulSplit = dyn_cast(Mapping[MulInst]); + EXPECT_TRUE(MulSplit); + EXPECT_EQ(MulSplit->getOperand(0), AddSplit); + EXPECT_EQ(MulSplit->getOperand(1), V); + EXPECT_EQ(MulSplit->getParent(), Split); + EXPECT_EQ(MulSplit->getNextNode(), Split->getTerminator()); + EXPECT_EQ(Split->getSingleSuccessor(), BB2); + EXPECT_EQ(BB2->getSingleSuccessor(), Split); + + delete F; +} + class CloneFunc : public ::testing::Test { protected: void SetUp() override {