summaryrefslogtreecommitdiffstats
path: root/llvm/unittests/Transforms
diff options
context:
space:
mode:
authorWhitney Tsang <whitney.uwaterloo@gmail.com>2019-07-08 18:30:35 +0000
committerWhitney Tsang <whitney.uwaterloo@gmail.com>2019-07-08 18:30:35 +0000
commit7d8f30e6b2f27d55d4a14392951e4a61d7598767 (patch)
tree3714e442c8fce8dd31a825ad4e8b07c541311b18 /llvm/unittests/Transforms
parent7023bdc46fbbd7f5c4f458488497888f767cd2e0 (diff)
downloadbcm5719-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.cpp87
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 {
OpenPOWER on IntegriCloud