Skip to content

Commit f0a25f7

Browse files
committedMar 6, 2018
[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
1 parent 33caf89 commit f0a25f7

File tree

2 files changed

+101
-1
lines changed

2 files changed

+101
-1
lines changed
 

‎llvm/lib/Transforms/Utils/CloneFunction.cpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -811,7 +811,9 @@ llvm::DuplicateInstructionsInSplitBetween(BasicBlock *BB, BasicBlock *PredBB,
811811

812812
// Clone the non-phi instructions of BB into NewBB, keeping track of the
813813
// mapping and using it to remap operands in the cloned instructions.
814-
for (; StopAt != &*BI; ++BI) {
814+
// Stop once we see the terminator too. This covers the case where BB's
815+
// terminator gets replaced and StopAt == BB's terminator.
816+
for (; StopAt != &*BI && BB->getTerminator() != &*BI; ++BI) {
815817
Instruction *New = BI->clone();
816818
New->setName(BI->getName());
817819
New->insertBefore(NewTerm);

‎llvm/unittests/Transforms/Utils/Cloning.cpp

+98
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,104 @@ TEST_F(CloneInstruction, DuplicateInstructionsToSplit) {
251251
delete F;
252252
}
253253

254+
TEST_F(CloneInstruction, DuplicateInstructionsToSplitBlocksEq1) {
255+
Type *ArgTy1[] = {Type::getInt32PtrTy(context)};
256+
FunctionType *FT = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
257+
V = new Argument(Type::getInt32Ty(context));
258+
259+
Function *F = Function::Create(FT, Function::ExternalLinkage);
260+
261+
BasicBlock *BB1 = BasicBlock::Create(context, "", F);
262+
IRBuilder<> Builder1(BB1);
263+
264+
BasicBlock *BB2 = BasicBlock::Create(context, "", F);
265+
IRBuilder<> Builder2(BB2);
266+
267+
Builder1.CreateBr(BB2);
268+
269+
Instruction *AddInst = cast<Instruction>(Builder2.CreateAdd(V, V));
270+
Instruction *MulInst = cast<Instruction>(Builder2.CreateMul(AddInst, V));
271+
Instruction *SubInst = cast<Instruction>(Builder2.CreateSub(MulInst, V));
272+
Builder2.CreateBr(BB2);
273+
274+
ValueToValueMapTy Mapping;
275+
276+
auto Split = DuplicateInstructionsInSplitBetween(BB2, BB2, BB2->getTerminator(), Mapping);
277+
278+
EXPECT_TRUE(Split);
279+
EXPECT_EQ(Mapping.size(), 3u);
280+
EXPECT_TRUE(Mapping.find(AddInst) != Mapping.end());
281+
EXPECT_TRUE(Mapping.find(MulInst) != Mapping.end());
282+
EXPECT_TRUE(Mapping.find(SubInst) != Mapping.end());
283+
284+
auto AddSplit = dyn_cast<Instruction>(Mapping[AddInst]);
285+
EXPECT_TRUE(AddSplit);
286+
EXPECT_EQ(AddSplit->getOperand(0), V);
287+
EXPECT_EQ(AddSplit->getOperand(1), V);
288+
EXPECT_EQ(AddSplit->getParent(), Split);
289+
290+
auto MulSplit = dyn_cast<Instruction>(Mapping[MulInst]);
291+
EXPECT_TRUE(MulSplit);
292+
EXPECT_EQ(MulSplit->getOperand(0), AddSplit);
293+
EXPECT_EQ(MulSplit->getOperand(1), V);
294+
EXPECT_EQ(MulSplit->getParent(), Split);
295+
296+
auto SubSplit = dyn_cast<Instruction>(Mapping[SubInst]);
297+
EXPECT_EQ(MulSplit->getNextNode(), SubSplit);
298+
EXPECT_EQ(SubSplit->getNextNode(), Split->getTerminator());
299+
EXPECT_EQ(Split->getSingleSuccessor(), BB2);
300+
EXPECT_EQ(BB2->getSingleSuccessor(), Split);
301+
302+
delete F;
303+
}
304+
305+
TEST_F(CloneInstruction, DuplicateInstructionsToSplitBlocksEq2) {
306+
Type *ArgTy1[] = {Type::getInt32PtrTy(context)};
307+
FunctionType *FT = FunctionType::get(Type::getVoidTy(context), ArgTy1, false);
308+
V = new Argument(Type::getInt32Ty(context));
309+
310+
Function *F = Function::Create(FT, Function::ExternalLinkage);
311+
312+
BasicBlock *BB1 = BasicBlock::Create(context, "", F);
313+
IRBuilder<> Builder1(BB1);
314+
315+
BasicBlock *BB2 = BasicBlock::Create(context, "", F);
316+
IRBuilder<> Builder2(BB2);
317+
318+
Builder1.CreateBr(BB2);
319+
320+
Instruction *AddInst = cast<Instruction>(Builder2.CreateAdd(V, V));
321+
Instruction *MulInst = cast<Instruction>(Builder2.CreateMul(AddInst, V));
322+
Instruction *SubInst = cast<Instruction>(Builder2.CreateSub(MulInst, V));
323+
Builder2.CreateBr(BB2);
324+
325+
ValueToValueMapTy Mapping;
326+
327+
auto Split = DuplicateInstructionsInSplitBetween(BB2, BB2, SubInst, Mapping);
328+
329+
EXPECT_TRUE(Split);
330+
EXPECT_EQ(Mapping.size(), 2u);
331+
EXPECT_TRUE(Mapping.find(AddInst) != Mapping.end());
332+
EXPECT_TRUE(Mapping.find(MulInst) != Mapping.end());
333+
334+
auto AddSplit = dyn_cast<Instruction>(Mapping[AddInst]);
335+
EXPECT_TRUE(AddSplit);
336+
EXPECT_EQ(AddSplit->getOperand(0), V);
337+
EXPECT_EQ(AddSplit->getOperand(1), V);
338+
EXPECT_EQ(AddSplit->getParent(), Split);
339+
340+
auto MulSplit = dyn_cast<Instruction>(Mapping[MulInst]);
341+
EXPECT_TRUE(MulSplit);
342+
EXPECT_EQ(MulSplit->getOperand(0), AddSplit);
343+
EXPECT_EQ(MulSplit->getOperand(1), V);
344+
EXPECT_EQ(MulSplit->getParent(), Split);
345+
EXPECT_EQ(MulSplit->getNextNode(), Split->getTerminator());
346+
EXPECT_EQ(Split->getSingleSuccessor(), BB2);
347+
EXPECT_EQ(BB2->getSingleSuccessor(), Split);
348+
349+
delete F;
350+
}
351+
254352
class CloneFunc : public ::testing::Test {
255353
protected:
256354
void SetUp() override {

0 commit comments

Comments
 (0)
Please sign in to comment.