diff options
author | Whitney Tsang <whitney.uwaterloo@gmail.com> | 2019-07-08 18:30:35 +0000 |
---|---|---|
committer | Whitney Tsang <whitney.uwaterloo@gmail.com> | 2019-07-08 18:30:35 +0000 |
commit | 7d8f30e6b2f27d55d4a14392951e4a61d7598767 (patch) | |
tree | 3714e442c8fce8dd31a825ad4e8b07c541311b18 /llvm/unittests/Transforms | |
parent | 7023bdc46fbbd7f5c4f458488497888f767cd2e0 (diff) | |
download | bcm5719-llvm-7d8f30e6b2f27d55d4a14392951e4a61d7598767.tar.gz bcm5719-llvm-7d8f30e6b2f27d55d4a14392951e4a61d7598767.zip |
Keep the order of the basic blocks in the cloned loop as the original
loop
Summary:
Do the cloning in two steps, first allocate all the new loops, then
clone the basic blocks in the same order as the original loop.
Reviewer: Meinersbur, fhahn, kbarton, hfinkel
Reviewed By: hfinkel
Subscribers: hfinkel, hiraditya, llvm-commits
Tag: https://reviews.llvm.org/D64224
Differential Revision:
llvm-svn: 365366
Diffstat (limited to 'llvm/unittests/Transforms')
-rw-r--r-- | llvm/unittests/Transforms/Utils/CloningTest.cpp | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp index abc18bc377c..514a7708f9f 100644 --- a/llvm/unittests/Transforms/Utils/CloningTest.cpp +++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp @@ -10,6 +10,8 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallPtrSet.h" #include "llvm/Analysis/DomTreeUpdater.h" +#include "llvm/Analysis/LoopInfo.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/Argument.h" #include "llvm/IR/Constant.h" #include "llvm/IR/DIBuilder.h" @@ -355,6 +357,91 @@ TEST_F(CloneInstruction, DuplicateInstructionsToSplitBlocksEq2) { delete F; } +static void runWithLoopInfoAndDominatorTree( + Module &M, StringRef FuncName, + function_ref<void(Function &F, LoopInfo &LI, DominatorTree &DT)> Test) { + auto *F = M.getFunction(FuncName); + ASSERT_NE(F, nullptr) << "Could not find " << FuncName; + + DominatorTree DT(*F); + LoopInfo LI(DT); + + Test(*F, LI, DT); +} + +static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) { + SMDiagnostic Err; + std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C); + if (!Mod) + Err.print("CloneLoop", errs()); + return Mod; +} + +TEST(CloneLoop, CloneLoopNest) { + // Parse the module. + LLVMContext Context; + + std::unique_ptr<Module> M = parseIR( + Context, + R"(define void @foo(i32* %A, i32 %ub) { +entry: + %guardcmp = icmp slt i32 0, %ub + br i1 %guardcmp, label %for.outer.preheader, label %for.end +for.outer.preheader: + br label %for.outer +for.outer: + %j = phi i32 [ 0, %for.outer.preheader ], [ %inc.outer, %for.outer.latch ] + br i1 %guardcmp, label %for.inner.preheader, label %for.outer.latch +for.inner.preheader: + br label %for.inner +for.inner: + %i = phi i32 [ 0, %for.inner.preheader ], [ %inc, %for.inner ] + %idxprom = sext i32 %i to i64 + %arrayidx = getelementptr inbounds i32, i32* %A, i64 %idxprom + store i32 %i, i32* %arrayidx, align 4 + %inc = add nsw i32 %i, 1 + %cmp = icmp slt i32 %inc, %ub + br i1 %cmp, label %for.inner, label %for.inner.exit +for.inner.exit: + br label %for.outer.latch +for.outer.latch: + %inc.outer = add nsw i32 %j, 1 + %cmp.outer = icmp slt i32 %inc.outer, %ub + br i1 %cmp.outer, label %for.outer, label %for.outer.exit +for.outer.exit: + br label %for.end +for.end: + ret void +})" + ); + + runWithLoopInfoAndDominatorTree( + *M, "foo", [&](Function &F, LoopInfo &LI, DominatorTree &DT) { + Function::iterator FI = F.begin(); + // First basic block is entry - skip it. + BasicBlock *Preheader = &*(++FI); + BasicBlock *Header = &*(++FI); + assert(Header->getName() == "for.outer"); + Loop *L = LI.getLoopFor(Header); + EXPECT_NE(L, nullptr); + EXPECT_EQ(Header, L->getHeader()); + EXPECT_EQ(Preheader, L->getLoopPreheader()); + + ValueToValueMapTy VMap; + SmallVector<BasicBlock *, 4> ClonedLoopBlocks; + Loop *NewLoop = cloneLoopWithPreheader(Preheader, Preheader, L, VMap, + "", &LI, &DT, ClonedLoopBlocks); + EXPECT_NE(NewLoop, nullptr); + EXPECT_EQ(NewLoop->getSubLoops().size(), 1u); + Loop::block_iterator BI = NewLoop->block_begin(); + EXPECT_TRUE((*BI)->getName().startswith("for.outer")); + EXPECT_TRUE((*(++BI))->getName().startswith("for.inner.preheader")); + EXPECT_TRUE((*(++BI))->getName().startswith("for.inner")); + EXPECT_TRUE((*(++BI))->getName().startswith("for.inner.exit")); + EXPECT_TRUE((*(++BI))->getName().startswith("for.outer.latch")); + }); +} + class CloneFunc : public ::testing::Test { protected: void SetUp() override { |