Skip to content

Commit

Permalink
[VPlan] Introduce VPLoopInfo analysis.
Browse files Browse the repository at this point in the history
The patch introduces loop analysis (VPLoopInfo/VPLoop) for VPBlockBases.
This analysis will be necessary to perform some H-CFG transformations and
detect and introduce regions representing a loop in the H-CFG.

Reviewers: fhahn, rengolin, mkuper, hfinkel, mssimpso

Reviewed By: fhahn 

Differential Revision: https://reviews.llvm.org/D48816

llvm-svn: 338346
  • Loading branch information
dcaballe committed Jul 31, 2018
1 parent 56bf356 commit 3587150
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 1 deletion.
16 changes: 15 additions & 1 deletion llvm/lib/Transforms/Vectorize/VPlan.h
Expand Up @@ -26,6 +26,7 @@
#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLAN_H
#define LLVM_TRANSFORMS_VECTORIZE_VPLAN_H

#include "VPlanLoopInfo.h"
#include "VPlanValue.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
Expand All @@ -52,7 +53,6 @@ class BasicBlock;
class DominatorTree;
class InnerLoopVectorizer;
class InterleaveGroup;
class LoopInfo;
class raw_ostream;
class Value;
class VPBasicBlock;
Expand Down Expand Up @@ -527,6 +527,13 @@ class VPBlockBase {
// support for VPInstructions/Recipes.
printAsOperand(OS, false);
}

/// Return true if it is legal to hoist instructions into this block.
bool isLegalToHoistInto() {
// There are currently no constraints that prevent an instruction to be
// hoisted into a VPBlockBase.
return true;
}
};

/// VPRecipeBase is a base class modeling a sequence of one or more output IR
Expand Down Expand Up @@ -1104,6 +1111,9 @@ class VPlan {
/// VPlan.
Value2VPValueTy Value2VPValue;

/// Holds the VPLoopInfo analysis for this VPlan.
VPLoopInfo VPLInfo;

public:
VPlan(VPBlockBase *Entry = nullptr) : Entry(Entry) {}

Expand Down Expand Up @@ -1150,6 +1160,10 @@ class VPlan {
return Value2VPValue[V];
}

/// Return the VPLoopInfo analysis for this VPlan.
VPLoopInfo &getVPLoopInfo() { return VPLInfo; }
const VPLoopInfo &getVPLoopInfo() const { return VPLInfo; }

private:
/// Add to the given dominator tree the header block and every new basic block
/// that was created between it and the latch block, inclusive.
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp
Expand Up @@ -342,4 +342,10 @@ void VPlanHCFGBuilder::buildHierarchicalCFG() {
VPDomTree.recalculate(*TopRegion);
LLVM_DEBUG(dbgs() << "Dominator Tree after building the plain CFG.\n";
VPDomTree.print(dbgs()));

// Compute VPLInfo and keep it in Plan.
VPLoopInfo &VPLInfo = Plan.getVPLoopInfo();
VPLInfo.analyze(VPDomTree);
LLVM_DEBUG(dbgs() << "VPLoop Info After buildPlainCFG:\n";
VPLInfo.print(dbgs()));
}
45 changes: 45 additions & 0 deletions llvm/lib/Transforms/Vectorize/VPlanLoopInfo.h
@@ -0,0 +1,45 @@
//===-- VPLoopInfo.h --------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
///
/// \file
/// This file defines VPLoopInfo analysis and VPLoop class. VPLoopInfo is a
/// specialization of LoopInfoBase for VPBlockBase. VPLoops is a specialization
/// of LoopBase that is used to hold loop metadata from VPLoopInfo. Further
/// information can be found in VectorizationPlanner.rst.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLOOPINFO_H
#define LLVM_TRANSFORMS_VECTORIZE_VPLOOPINFO_H

#include "llvm/Analysis/LoopInfoImpl.h"

namespace llvm {
class VPBlockBase;

/// Hold analysis information for every loop detected by VPLoopInfo. It is an
/// instantiation of LoopBase.
class VPLoop : public LoopBase<VPBlockBase, VPLoop> {
private:
friend class LoopInfoBase<VPBlockBase, VPLoop>;
explicit VPLoop(VPBlockBase *VPB) : LoopBase<VPBlockBase, VPLoop>(VPB) {}
};

/// VPLoopInfo provides analysis of natural loop for VPBlockBase-based
/// Hierarchical CFG. It is a specialization of LoopInfoBase class.
// TODO: VPLoopInfo is initially computed on top of the VPlan plain CFG, which
// is the same as the incoming IR CFG. If it's more efficient than running the
// whole loop detection algorithm, we may want to create a mechanism to
// translate LoopInfo into VPLoopInfo. However, that would require significant
// changes in LoopInfoBase class.
typedef LoopInfoBase<VPBlockBase, VPLoop> VPLoopInfo;

} // namespace llvm

#endif // LLVM_TRANSFORMS_VECTORIZE_VPLOOPINFO_H
1 change: 1 addition & 0 deletions llvm/unittests/Transforms/Vectorize/CMakeLists.txt
Expand Up @@ -7,6 +7,7 @@ set(LLVM_LINK_COMPONENTS

add_llvm_unittest(VectorizeTests
VPlanDominatorTreeTest.cpp
VPlanLoopInfoTest.cpp
VPlanTest.cpp
VPlanHCFGTest.cpp
)
87 changes: 87 additions & 0 deletions llvm/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

0 comments on commit 3587150

Please sign in to comment.