Skip to content

Commit

Permalink
[VPlan] Introduce VPlan-based dominator analysis.
Browse files Browse the repository at this point in the history
The patch introduces dominator analysis for VPBlockBases and extend
VPlan's GraphTraits specialization with the required interfaces. Dominator
analysis will be necessary to perform some H-CFG transformations and
to introduce VPLoopInfo (LoopInfo analysis on top of the VPlan representation).

Reviewers: fhahn, rengolin, mkuper, hfinkel, mssimpso

Reviewed By: fhahn

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

llvm-svn: 338310
  • Loading branch information
dcaballe committed Jul 30, 2018
1 parent 47ad09b commit 2a34ac8
Show file tree
Hide file tree
Showing 9 changed files with 382 additions and 23 deletions.
4 changes: 2 additions & 2 deletions llvm/lib/Transforms/Vectorize/LoopVectorize.cpp
Expand Up @@ -7060,8 +7060,8 @@ LoopVectorizationPlanner::buildVPlan(VFRange &Range) {
auto Plan = llvm::make_unique<VPlan>();

// Build hierarchical CFG
VPlanHCFGBuilder HCFGBuilder(OrigLoop, LI);
HCFGBuilder.buildHierarchicalCFG(*Plan.get());
VPlanHCFGBuilder HCFGBuilder(OrigLoop, LI, *Plan);
HCFGBuilder.buildHierarchicalCFG();

return Plan;
}
Expand Down
5 changes: 4 additions & 1 deletion llvm/lib/Transforms/Vectorize/VPlan.cpp
Expand Up @@ -18,14 +18,14 @@
//===----------------------------------------------------------------------===//

#include "VPlan.h"
#include "VPlanDominatorTree.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Analysis/LoopInfo.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/IR/CFG.h"
#include "llvm/IR/Dominators.h"
#include "llvm/IR/InstrTypes.h"
#include "llvm/IR/Instruction.h"
#include "llvm/IR/Instructions.h"
Expand All @@ -34,6 +34,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/GenericDomTreeConstruction.h"
#include "llvm/Support/GraphWriter.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
Expand Down Expand Up @@ -576,3 +577,5 @@ void VPWidenMemoryInstructionRecipe::print(raw_ostream &O,
}
O << "\\l\"";
}

template void DomTreeBuilder::Calculate<VPDominatorTree>(VPDominatorTree &DT);
105 changes: 93 additions & 12 deletions llvm/lib/Transforms/Vectorize/VPlan.h
Expand Up @@ -28,6 +28,7 @@

#include "VPlanValue.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DepthFirstIterator.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/SmallPtrSet.h"
Expand Down Expand Up @@ -516,6 +517,16 @@ class VPBlockBase {

/// Delete all blocks reachable from a given VPBlockBase, inclusive.
static void deleteCFG(VPBlockBase *Entry);

void printAsOperand(raw_ostream &OS, bool PrintType) const {
OS << getName();
}

void print(raw_ostream &OS) const {
// TODO: Only printing VPBB name for now since we only have dot printing
// support for VPInstructions/Recipes.
printAsOperand(OS, false);
}
};

/// VPRecipeBase is a base class modeling a sequence of one or more output IR
Expand Down Expand Up @@ -1037,6 +1048,12 @@ class VPRegionBlock : public VPBlockBase {
EntryBlock->setParent(this);
}

// FIXME: DominatorTreeBase is doing 'A->getParent()->front()'. 'front' is a
// specific interface of llvm::Function, instead of using
// GraphTraints::getEntryNode. We should add a new template parameter to
// DominatorTreeBase representing the Graph type.
VPBlockBase &front() const { return *Entry; }

const VPBlockBase *getExit() const { return Exit; }
VPBlockBase *getExit() { return Exit; }

Expand Down Expand Up @@ -1210,12 +1227,15 @@ inline raw_ostream &operator<<(raw_ostream &OS, VPlan &Plan) {
return OS;
}

//===--------------------------------------------------------------------===//
// GraphTraits specializations for VPlan/VPRegionBlock Control-Flow Graphs //
//===--------------------------------------------------------------------===//
//===----------------------------------------------------------------------===//
// GraphTraits specializations for VPlan Hierarchical Control-Flow Graphs //
//===----------------------------------------------------------------------===//

// Provide specializations of GraphTraits to be able to treat a VPBlockBase as a
// graph of VPBlockBase nodes...
// The following set of template specializations implement GraphTraits to treat
// any VPBlockBase as a node in a graph of VPBlockBases. It's important to note
// that VPBlockBase traits don't recurse into VPRegioBlocks, i.e., if the
// VPBlockBase is a VPRegionBlock, this specialization provides access to its
// successors/predecessors but not to the blocks inside the region.

template <> struct GraphTraits<VPBlockBase *> {
using NodeRef = VPBlockBase *;
Expand Down Expand Up @@ -1247,17 +1267,13 @@ template <> struct GraphTraits<const VPBlockBase *> {
}
};

// Provide specializations of GraphTraits to be able to treat a VPBlockBase as a
// graph of VPBlockBase nodes... and to walk it in inverse order. Inverse order
// for a VPBlockBase is considered to be when traversing the predecessors of a
// VPBlockBase instead of its successors.
// Inverse order specialization for VPBasicBlocks. Predecessors are used instead
// of successors for the inverse traversal.
template <> struct GraphTraits<Inverse<VPBlockBase *>> {
using NodeRef = VPBlockBase *;
using ChildIteratorType = SmallVectorImpl<VPBlockBase *>::iterator;

static Inverse<VPBlockBase *> getEntryNode(Inverse<VPBlockBase *> B) {
return B;
}
static NodeRef getEntryNode(Inverse<NodeRef> B) { return B.Graph; }

static inline ChildIteratorType child_begin(NodeRef N) {
return N->getPredecessors().begin();
Expand All @@ -1268,6 +1284,71 @@ template <> struct GraphTraits<Inverse<VPBlockBase *>> {
}
};

// The following set of template specializations implement GraphTraits to
// treat VPRegionBlock as a graph and recurse inside its nodes. It's important
// to note that the blocks inside the VPRegionBlock are treated as VPBlockBases
// (i.e., no dyn_cast is performed, VPBlockBases specialization is used), so
// there won't be automatic recursion into other VPBlockBases that turn to be
// VPRegionBlocks.

template <>
struct GraphTraits<VPRegionBlock *> : public GraphTraits<VPBlockBase *> {
using GraphRef = VPRegionBlock *;
using nodes_iterator = df_iterator<NodeRef>;

static NodeRef getEntryNode(GraphRef N) { return N->getEntry(); }

static nodes_iterator nodes_begin(GraphRef N) {
return nodes_iterator::begin(N->getEntry());
}

static nodes_iterator nodes_end(GraphRef N) {
// df_iterator::end() returns an empty iterator so the node used doesn't
// matter.
return nodes_iterator::end(N);
}
};

template <>
struct GraphTraits<const VPRegionBlock *>
: public GraphTraits<const VPBlockBase *> {
using GraphRef = const VPRegionBlock *;
using nodes_iterator = df_iterator<NodeRef>;

static NodeRef getEntryNode(GraphRef N) { return N->getEntry(); }

static nodes_iterator nodes_begin(GraphRef N) {
return nodes_iterator::begin(N->getEntry());
}

static nodes_iterator nodes_end(GraphRef N) {
// df_iterator::end() returns an empty iterator so the node used doesn't
// matter.
return nodes_iterator::end(N);
}
};

template <>
struct GraphTraits<Inverse<VPRegionBlock *>>
: public GraphTraits<Inverse<VPBlockBase *>> {
using GraphRef = VPRegionBlock *;
using nodes_iterator = df_iterator<NodeRef>;

static NodeRef getEntryNode(Inverse<GraphRef> N) {
return N.Graph->getExit();
}

static nodes_iterator nodes_begin(GraphRef N) {
return nodes_iterator::begin(N->getExit());
}

static nodes_iterator nodes_end(GraphRef N) {
// df_iterator::end() returns an empty iterator so the node used doesn't
// matter.
return nodes_iterator::end(N);
}
};

//===----------------------------------------------------------------------===//
// VPlan Utilities
//===----------------------------------------------------------------------===//
Expand Down
41 changes: 41 additions & 0 deletions llvm/lib/Transforms/Vectorize/VPlanDominatorTree.h
@@ -0,0 +1,41 @@
//===-- VPlanDominatorTree.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 implements dominator tree analysis for a single level of a VPlan's
/// H-CFG.
///
//===----------------------------------------------------------------------===//

#ifndef LLVM_TRANSFORMS_VECTORIZE_VPLANDOMINATORTREE_H
#define LLVM_TRANSFORMS_VECTORIZE_VPLANDOMINATORTREE_H

#include "VPlan.h"
#include "llvm/ADT/GraphTraits.h"
#include "llvm/IR/Dominators.h"

namespace llvm {

/// Template specialization of the standard LLVM dominator tree utility for
/// VPBlockBases.
using VPDominatorTree = DomTreeBase<VPBlockBase>;

using VPDomTreeNode = DomTreeNodeBase<VPBlockBase>;

/// Template specializations of GraphTraits for VPDomTreeNode.
template <>
struct GraphTraits<VPDomTreeNode *>
: public DomTreeGraphTraitsBase<VPDomTreeNode, VPDomTreeNode::iterator> {};

template <>
struct GraphTraits<const VPDomTreeNode *>
: public DomTreeGraphTraitsBase<const VPDomTreeNode,
VPDomTreeNode::const_iterator> {};
} // namespace llvm
#endif // LLVM_TRANSFORMS_VECTORIZE_VPLANDOMINATORTREE_H
15 changes: 12 additions & 3 deletions llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.cpp
Expand Up @@ -324,13 +324,22 @@ VPRegionBlock *PlainCFGBuilder::buildPlainCFG() {
return TopRegion;
}

VPRegionBlock *VPlanHCFGBuilder::buildPlainCFG() {
PlainCFGBuilder PCFGBuilder(TheLoop, LI, Plan);
return PCFGBuilder.buildPlainCFG();
}

// Public interface to build a H-CFG.
void VPlanHCFGBuilder::buildHierarchicalCFG(VPlan &Plan) {
void VPlanHCFGBuilder::buildHierarchicalCFG() {
// Build Top Region enclosing the plain CFG and set it as VPlan entry.
PlainCFGBuilder PCFGBuilder(TheLoop, LI, Plan);
VPRegionBlock *TopRegion = PCFGBuilder.buildPlainCFG();
VPRegionBlock *TopRegion = buildPlainCFG();
Plan.setEntry(TopRegion);
LLVM_DEBUG(Plan.setName("HCFGBuilder: Plain CFG\n"); dbgs() << Plan);

Verifier.verifyHierarchicalCFG(TopRegion);

// Compute plain CFG dom tree for VPLInfo.
VPDomTree.recalculate(*TopRegion);
LLVM_DEBUG(dbgs() << "Dominator Tree after building the plain CFG.\n";
VPDomTree.print(dbgs()));
}
23 changes: 20 additions & 3 deletions llvm/lib/Transforms/Vectorize/VPlanHCFGBuilder.h
Expand Up @@ -26,29 +26,46 @@
#define LLVM_TRANSFORMS_VECTORIZE_VPLAN_VPLANHCFGBUILDER_H

#include "VPlan.h"
#include "VPlanDominatorTree.h"
#include "VPlanVerifier.h"

namespace llvm {

class Loop;
class VPlanTestBase;

/// Main class to build the VPlan H-CFG for an incoming IR.
class VPlanHCFGBuilder {
friend VPlanTestBase;

private:
// The outermost loop of the input loop nest considered for vectorization.
Loop *TheLoop;

// Loop Info analysis.
LoopInfo *LI;

// The VPlan that will contain the H-CFG we are building.
VPlan &Plan;

// VPlan verifier utility.
VPlanVerifier Verifier;

// Dominator analysis for VPlan plain CFG to be used in the
// construction of the H-CFG. This analysis is no longer valid once regions
// are introduced.
VPDominatorTree VPDomTree;

/// Build plain CFG for TheLoop. Return a new VPRegionBlock (TopRegion)
/// enclosing the plain CFG.
VPRegionBlock *buildPlainCFG();

public:
VPlanHCFGBuilder(Loop *Lp, LoopInfo *LI) : TheLoop(Lp), LI(LI) {}
VPlanHCFGBuilder(Loop *Lp, LoopInfo *LI, VPlan &P)
: TheLoop(Lp), LI(LI), Plan(P) {}

/// Build H-CFG for TheLoop and update \p Plan accordingly.
void buildHierarchicalCFG(VPlan &Plan);
/// Build H-CFG for TheLoop and update Plan accordingly.
void buildHierarchicalCFG();
};
} // namespace llvm

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

add_llvm_unittest(VectorizeTests
VPlanDominatorTreeTest.cpp
VPlanTest.cpp
VPlanHCFGTest.cpp
)

0 comments on commit 2a34ac8

Please sign in to comment.