diff options
author | Sanjoy Das <sanjoy@playingwithpointers.com> | 2017-02-17 04:21:14 +0000 |
---|---|---|
committer | Sanjoy Das <sanjoy@playingwithpointers.com> | 2017-02-17 04:21:14 +0000 |
commit | 56ccc1cdbf5bcbc3e1fa503efab531d7d8a1229e (patch) | |
tree | e899dd3da610816d9f34aea41f49a4c17d3922d8 /unittests/Transforms/Utils | |
parent | 675c18fef3ae92e2389c6670c4e1049fd7556e08 (diff) |
[JumpThreading] Re-enable JumpThreading for guards
Summary:
JumpThreading for guards feature has been reverted at https://reviews.llvm.org/rL295200
due to the following problem: the feature used the following algorithm for detection of
diamond patters:
1. Find a block with 2 predecessors;
2. Check that these blocks have a common single parent;
3. Check that the parent's terminator is a branch instruction.
The problem is that these checks are insufficient. They may pass for a non-diamond
construction in case if those two predecessors are actually the same block. This may
happen if parent's terminator is a br (either conditional or unconditional) to a block
that ends with "switch" instruction with exactly two branches going to one block.
This patch re-enables the JumpThreading for guards and fixes this issue by adding the
check that those found predecessors are actually different blocks. This guarantees that
parent's terminator is a conditional branch with exactly 2 different successors, which
is now ensured by assertions. It also adds two more tests for this situation (with parent's
terminator being a conditional and an unconditional branch).
Patch by Max Kazantsev!
Reviewers: anna, sanjoy, reames
Reviewed By: sanjoy
Subscribers: llvm-commits
Differential Revision: https://reviews.llvm.org/D30036
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@295410 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'unittests/Transforms/Utils')
-rw-r--r-- | unittests/Transforms/Utils/Cloning.cpp | 47 |
1 files changed, 47 insertions, 0 deletions
diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index 634aa9e7e65..a216959751f 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -201,6 +201,53 @@ TEST_F(CloneInstruction, CallingConvention) { delete F2; } +TEST_F(CloneInstruction, DuplicateInstructionsToSplit) { + 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.CreateRetVoid(); + + ValueToValueMapTy Mapping; + + auto Split = DuplicateInstructionsInSplitBetween(BB2, BB1, 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(AddSplit->getNextNode(), MulSplit); + EXPECT_EQ(MulSplit->getNextNode(), Split->getTerminator()); + + delete F; +} + class CloneFunc : public ::testing::Test { protected: void SetUp() override { |