diff options
Diffstat (limited to 'unittests/Transforms')
-rw-r--r-- | unittests/Transforms/Vectorize/CMakeLists.txt | 2 | ||||
-rw-r--r-- | unittests/Transforms/Vectorize/VPlanDominatorTreeTest.cpp | 196 | ||||
-rw-r--r-- | unittests/Transforms/Vectorize/VPlanLoopInfoTest.cpp | 87 | ||||
-rw-r--r-- | unittests/Transforms/Vectorize/VPlanTestBase.h | 15 |
4 files changed, 298 insertions, 2 deletions
diff --git a/unittests/Transforms/Vectorize/CMakeLists.txt b/unittests/Transforms/Vectorize/CMakeLists.txt index 4f2b8e9a139c..5a9142d17b1e 100644 --- a/unittests/Transforms/Vectorize/CMakeLists.txt +++ b/unittests/Transforms/Vectorize/CMakeLists.txt @@ -6,6 +6,8 @@ set(LLVM_LINK_COMPONENTS ) add_llvm_unittest(VectorizeTests + VPlanDominatorTreeTest.cpp + VPlanLoopInfoTest.cpp VPlanTest.cpp VPlanHCFGTest.cpp ) diff --git a/unittests/Transforms/Vectorize/VPlanDominatorTreeTest.cpp b/unittests/Transforms/Vectorize/VPlanDominatorTreeTest.cpp new file mode 100644 index 000000000000..57f07392d8b8 --- /dev/null +++ b/unittests/Transforms/Vectorize/VPlanDominatorTreeTest.cpp @@ -0,0 +1,196 @@ +//===- llvm/unittests/Transforms/Vectorize/VPlanDominatorTreeTest.cpp -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../lib/Transforms/Vectorize/VPlanHCFGBuilder.h" +#include "VPlanTestBase.h" +#include "gtest/gtest.h" + +namespace llvm { +namespace { + +class VPlanDominatorTreeTest : public VPlanTestBase {}; + +TEST_F(VPlanDominatorTreeTest, BasicVPBBDomination) { + const char *ModuleString = + "define void @f(i32* %a, i32* %b, i32* %c, i32 %N, i32 %M, i32 %K) {\n" + "entry:\n" + " br label %for.body\n" + "for.body:\n" + " %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.inc ]\n" + " br i1 true, label %if.then, label %if.else\n" + "if.then:\n" + " br label %for.inc\n" + "if.else:\n" + " br label %for.inc\n" + "for.inc:\n" + " %iv.next = add nuw nsw i64 %iv, 1\n" + " %exitcond = icmp eq i64 %iv.next, 300\n" + " br i1 %exitcond, label %for.end, label %for.body\n" + "for.end:\n" + " ret void\n" + "}\n"; + + Module &M = parseModule(ModuleString); + + Function *F = M.getFunction("f"); + BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor(); + auto Plan = buildPlainCFG(LoopHeader); + + // Build VPlan domination tree analysis. + VPRegionBlock *TopRegion = cast<VPRegionBlock>(Plan->getEntry()); + VPDominatorTree VPDT; + VPDT.recalculate(*TopRegion); + + VPBlockBase *PH = TopRegion->getEntry(); + VPBlockBase *H = PH->getSingleSuccessor(); + VPBlockBase *IfThen = H->getSuccessors()[0]; + VPBlockBase *IfElse = H->getSuccessors()[1]; + VPBlockBase *Latch = IfThen->getSingleSuccessor(); + VPBlockBase *Exit = Latch->getSuccessors()[0] != H + ? Latch->getSuccessors()[0] + : Latch->getSuccessors()[1]; + // Reachability. + EXPECT_TRUE(VPDT.isReachableFromEntry(PH)); + EXPECT_TRUE(VPDT.isReachableFromEntry(H)); + EXPECT_TRUE(VPDT.isReachableFromEntry(IfThen)); + EXPECT_TRUE(VPDT.isReachableFromEntry(IfElse)); + EXPECT_TRUE(VPDT.isReachableFromEntry(Latch)); + EXPECT_TRUE(VPDT.isReachableFromEntry(Exit)); + + // VPBB dominance. + EXPECT_TRUE(VPDT.dominates(PH, PH)); + EXPECT_TRUE(VPDT.dominates(PH, H)); + EXPECT_TRUE(VPDT.dominates(PH, IfThen)); + EXPECT_TRUE(VPDT.dominates(PH, IfElse)); + EXPECT_TRUE(VPDT.dominates(PH, Latch)); + EXPECT_TRUE(VPDT.dominates(PH, Exit)); + + EXPECT_FALSE(VPDT.dominates(H, PH)); + EXPECT_TRUE(VPDT.dominates(H, H)); + EXPECT_TRUE(VPDT.dominates(H, IfThen)); + EXPECT_TRUE(VPDT.dominates(H, IfElse)); + EXPECT_TRUE(VPDT.dominates(H, Latch)); + EXPECT_TRUE(VPDT.dominates(H, Exit)); + + EXPECT_FALSE(VPDT.dominates(IfThen, PH)); + EXPECT_FALSE(VPDT.dominates(IfThen, H)); + EXPECT_TRUE(VPDT.dominates(IfThen, IfThen)); + EXPECT_FALSE(VPDT.dominates(IfThen, IfElse)); + EXPECT_FALSE(VPDT.dominates(IfThen, Latch)); + EXPECT_FALSE(VPDT.dominates(IfThen, Exit)); + + EXPECT_FALSE(VPDT.dominates(IfElse, PH)); + EXPECT_FALSE(VPDT.dominates(IfElse, H)); + EXPECT_FALSE(VPDT.dominates(IfElse, IfThen)); + EXPECT_TRUE(VPDT.dominates(IfElse, IfElse)); + EXPECT_FALSE(VPDT.dominates(IfElse, Latch)); + EXPECT_FALSE(VPDT.dominates(IfElse, Exit)); + + EXPECT_FALSE(VPDT.dominates(Latch, PH)); + EXPECT_FALSE(VPDT.dominates(Latch, H)); + EXPECT_FALSE(VPDT.dominates(Latch, IfThen)); + EXPECT_FALSE(VPDT.dominates(Latch, IfElse)); + EXPECT_TRUE(VPDT.dominates(Latch, Latch)); + EXPECT_TRUE(VPDT.dominates(Latch, Exit)); + + EXPECT_FALSE(VPDT.dominates(Exit, PH)); + EXPECT_FALSE(VPDT.dominates(Exit, H)); + EXPECT_FALSE(VPDT.dominates(Exit, IfThen)); + EXPECT_FALSE(VPDT.dominates(Exit, IfElse)); + EXPECT_FALSE(VPDT.dominates(Exit, Latch)); + EXPECT_TRUE(VPDT.dominates(Exit, Exit)); + + // VPBB proper dominance. + EXPECT_FALSE(VPDT.properlyDominates(PH, PH)); + EXPECT_TRUE(VPDT.properlyDominates(PH, H)); + EXPECT_TRUE(VPDT.properlyDominates(PH, IfThen)); + EXPECT_TRUE(VPDT.properlyDominates(PH, IfElse)); + EXPECT_TRUE(VPDT.properlyDominates(PH, Latch)); + EXPECT_TRUE(VPDT.properlyDominates(PH, Exit)); + + EXPECT_FALSE(VPDT.properlyDominates(H, PH)); + EXPECT_FALSE(VPDT.properlyDominates(H, H)); + EXPECT_TRUE(VPDT.properlyDominates(H, IfThen)); + EXPECT_TRUE(VPDT.properlyDominates(H, IfElse)); + EXPECT_TRUE(VPDT.properlyDominates(H, Latch)); + EXPECT_TRUE(VPDT.properlyDominates(H, Exit)); + + EXPECT_FALSE(VPDT.properlyDominates(IfThen, PH)); + EXPECT_FALSE(VPDT.properlyDominates(IfThen, H)); + EXPECT_FALSE(VPDT.properlyDominates(IfThen, IfThen)); + EXPECT_FALSE(VPDT.properlyDominates(IfThen, IfElse)); + EXPECT_FALSE(VPDT.properlyDominates(IfThen, Latch)); + EXPECT_FALSE(VPDT.properlyDominates(IfThen, Exit)); + + EXPECT_FALSE(VPDT.properlyDominates(IfElse, PH)); + EXPECT_FALSE(VPDT.properlyDominates(IfElse, H)); + EXPECT_FALSE(VPDT.properlyDominates(IfElse, IfThen)); + EXPECT_FALSE(VPDT.properlyDominates(IfElse, IfElse)); + EXPECT_FALSE(VPDT.properlyDominates(IfElse, Latch)); + EXPECT_FALSE(VPDT.properlyDominates(IfElse, Exit)); + + EXPECT_FALSE(VPDT.properlyDominates(Latch, PH)); + EXPECT_FALSE(VPDT.properlyDominates(Latch, H)); + EXPECT_FALSE(VPDT.properlyDominates(Latch, IfThen)); + EXPECT_FALSE(VPDT.properlyDominates(Latch, IfElse)); + EXPECT_FALSE(VPDT.properlyDominates(Latch, Latch)); + EXPECT_TRUE(VPDT.properlyDominates(Latch, Exit)); + + EXPECT_FALSE(VPDT.properlyDominates(Exit, PH)); + EXPECT_FALSE(VPDT.properlyDominates(Exit, H)); + EXPECT_FALSE(VPDT.properlyDominates(Exit, IfThen)); + EXPECT_FALSE(VPDT.properlyDominates(Exit, IfElse)); + EXPECT_FALSE(VPDT.properlyDominates(Exit, Latch)); + EXPECT_FALSE(VPDT.properlyDominates(Exit, Exit)); + + // VPBB nearest common dominator. + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(PH, PH)); + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(PH, H)); + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(PH, IfThen)); + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(PH, IfElse)); + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(PH, Latch)); + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(PH, Exit)); + + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(H, PH)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(H, H)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(H, IfThen)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(H, IfElse)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(H, Latch)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(H, Exit)); + + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(IfThen, PH)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(IfThen, H)); + EXPECT_EQ(IfThen, VPDT.findNearestCommonDominator(IfThen, IfThen)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(IfThen, IfElse)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(IfThen, Latch)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(IfThen, Exit)); + + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(IfElse, PH)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(IfElse, H)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(IfElse, IfThen)); + EXPECT_EQ(IfElse, VPDT.findNearestCommonDominator(IfElse, IfElse)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(IfElse, Latch)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(IfElse, Exit)); + + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(Latch, PH)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(Latch, H)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(Latch, IfThen)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(Latch, IfElse)); + EXPECT_EQ(Latch, VPDT.findNearestCommonDominator(Latch, Latch)); + EXPECT_EQ(Latch, VPDT.findNearestCommonDominator(Latch, Exit)); + + EXPECT_EQ(PH, VPDT.findNearestCommonDominator(Exit, PH)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(Exit, H)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(Exit, IfThen)); + EXPECT_EQ(H, VPDT.findNearestCommonDominator(Exit, IfElse)); + EXPECT_EQ(Latch, VPDT.findNearestCommonDominator(Exit, Latch)); + EXPECT_EQ(Exit, VPDT.findNearestCommonDominator(Exit, Exit)); +} +} // namespace +} // namespace llvm diff --git a/unittests/Transforms/Vectorize/VPlanLoopInfoTest.cpp b/unittests/Transforms/Vectorize/VPlanLoopInfoTest.cpp new file mode 100644 index 000000000000..55486ba0f14e --- /dev/null +++ b/unittests/Transforms/Vectorize/VPlanLoopInfoTest.cpp @@ -0,0 +1,87 @@ +//===- llvm/unittests/Transforms/Vectorize/VPlanLoopInfoTest.cpp -----===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../lib/Transforms/Vectorize/VPlanLoopInfo.h" +#include "VPlanTestBase.h" +#include "gtest/gtest.h" + +namespace llvm { +namespace { + +class VPlanLoopInfo : public VPlanTestBase {}; + +TEST_F(VPlanLoopInfo, BasicLoopInfoTest) { + const char *ModuleString = + "define void @f(i32* %a, i32* %b, i32* %c, i32 %N, i32 %M, i32 %K) {\n" + "entry:\n" + " br label %for.body\n" + "for.body:\n" + " %iv = phi i64 [ 0, %entry ], [ %iv.next, %for.inc ]\n" + " br i1 true, label %if.then, label %if.else\n" + "if.then:\n" + " br label %for.inc\n" + "if.else:\n" + " br label %for.inc\n" + "for.inc:\n" + " %iv.next = add nuw nsw i64 %iv, 1\n" + " %exitcond = icmp eq i64 %iv.next, 300\n" + " br i1 %exitcond, label %for.end, label %for.body\n" + "for.end:\n" + " ret void\n" + "}\n"; + + Module &M = parseModule(ModuleString); + + Function *F = M.getFunction("f"); + BasicBlock *LoopHeader = F->getEntryBlock().getSingleSuccessor(); + auto Plan = buildHCFG(LoopHeader); + + // Build VPlan domination tree and loop info analyses. + VPRegionBlock *TopRegion = cast<VPRegionBlock>(Plan->getEntry()); + VPDominatorTree VPDT; + VPDT.recalculate(*TopRegion); + VPLoopInfo VPLI; + VPLI.analyze(VPDT); + + VPBlockBase *PH = TopRegion->getEntry(); + VPBlockBase *H = PH->getSingleSuccessor(); + VPBlockBase *IfThen = H->getSuccessors()[0]; + VPBlockBase *IfElse = H->getSuccessors()[1]; + VPBlockBase *Latch = IfThen->getSingleSuccessor(); + VPBlockBase *Exit = Latch->getSuccessors()[0] != H + ? Latch->getSuccessors()[0] + : Latch->getSuccessors()[1]; + + // Number of loops. + EXPECT_EQ(1, std::distance(VPLI.begin(), VPLI.end())); + VPLoop *VPLp = *VPLI.begin(); + + // VPBBs contained in VPLoop. + EXPECT_FALSE(VPLp->contains(PH)); + EXPECT_EQ(nullptr, VPLI.getLoopFor(PH)); + EXPECT_TRUE(VPLp->contains(H)); + EXPECT_EQ(VPLp, VPLI.getLoopFor(H)); + EXPECT_TRUE(VPLp->contains(IfThen)); + EXPECT_EQ(VPLp, VPLI.getLoopFor(IfThen)); + EXPECT_TRUE(VPLp->contains(IfElse)); + EXPECT_EQ(VPLp, VPLI.getLoopFor(IfElse)); + EXPECT_TRUE(VPLp->contains(Latch)); + EXPECT_EQ(VPLp, VPLI.getLoopFor(Latch)); + EXPECT_FALSE(VPLp->contains(Exit)); + EXPECT_EQ(nullptr, VPLI.getLoopFor(Exit)); + + // VPLoop's parts. + EXPECT_EQ(PH, VPLp->getLoopPreheader()); + EXPECT_EQ(H, VPLp->getHeader()); + EXPECT_EQ(Latch, VPLp->getLoopLatch()); + EXPECT_EQ(Latch, VPLp->getExitingBlock()); + EXPECT_EQ(Exit, VPLp->getExitBlock()); +} +} // namespace +} // namespace llvm diff --git a/unittests/Transforms/Vectorize/VPlanTestBase.h b/unittests/Transforms/Vectorize/VPlanTestBase.h index da3b39f4df01..0fc4a9a21c88 100644 --- a/unittests/Transforms/Vectorize/VPlanTestBase.h +++ b/unittests/Transforms/Vectorize/VPlanTestBase.h @@ -50,8 +50,19 @@ protected: doAnalysis(*LoopHeader->getParent()); auto Plan = llvm::make_unique<VPlan>(); - VPlanHCFGBuilder HCFGBuilder(LI->getLoopFor(LoopHeader), LI.get()); - HCFGBuilder.buildHierarchicalCFG(*Plan.get()); + VPlanHCFGBuilder HCFGBuilder(LI->getLoopFor(LoopHeader), LI.get(), *Plan); + HCFGBuilder.buildHierarchicalCFG(); + return Plan; + } + + /// Build the VPlan plain CFG for the loop starting from \p LoopHeader. + VPlanPtr buildPlainCFG(BasicBlock *LoopHeader) { + doAnalysis(*LoopHeader->getParent()); + + auto Plan = llvm::make_unique<VPlan>(); + VPlanHCFGBuilder HCFGBuilder(LI->getLoopFor(LoopHeader), LI.get(), *Plan); + VPRegionBlock *TopRegion = HCFGBuilder.buildPlainCFG(); + Plan->setEntry(TopRegion); return Plan; } }; |