forked from OSchip/llvm-project
[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
This commit is contained in:
parent
33caf89970
commit
f0a25f7253
|
@ -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);
|
||||
|
|
|
@ -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<Instruction>(Builder2.CreateAdd(V, V));
|
||||
Instruction *MulInst = cast<Instruction>(Builder2.CreateMul(AddInst, V));
|
||||
Instruction *SubInst = cast<Instruction>(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<Instruction>(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<Instruction>(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<Instruction>(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<Instruction>(Builder2.CreateAdd(V, V));
|
||||
Instruction *MulInst = cast<Instruction>(Builder2.CreateMul(AddInst, V));
|
||||
Instruction *SubInst = cast<Instruction>(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<Instruction>(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<Instruction>(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 {
|
||||
|
|
Loading…
Reference in New Issue