116 changes: 56 additions & 60 deletions llvm/lib/Analysis/DomPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,26 +116,26 @@ struct DominatorTreeWrapperPassAnalysisGraphTraits {
}
};

struct DomViewer : public DOTGraphTraitsViewer<
struct DomViewer : public DOTGraphTraitsViewerWrapperPass<
DominatorTreeWrapperPass, false, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits> {
static char ID;
DomViewer()
: DOTGraphTraitsViewer<DominatorTreeWrapperPass, false, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits>(
"dom", ID) {
: DOTGraphTraitsViewerWrapperPass<
DominatorTreeWrapperPass, false, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits>("dom", ID) {
initializeDomViewerPass(*PassRegistry::getPassRegistry());
}
};

struct DomOnlyViewer : public DOTGraphTraitsViewer<
struct DomOnlyViewer : public DOTGraphTraitsViewerWrapperPass<
DominatorTreeWrapperPass, true, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits> {
static char ID;
DomOnlyViewer()
: DOTGraphTraitsViewer<DominatorTreeWrapperPass, true, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits>(
"domonly", ID) {
: DOTGraphTraitsViewerWrapperPass<
DominatorTreeWrapperPass, true, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits>("domonly", ID) {
initializeDomOnlyViewerPass(*PassRegistry::getPassRegistry());
}
};
Expand All @@ -146,32 +146,31 @@ struct PostDominatorTreeWrapperPassAnalysisGraphTraits {
}
};

struct PostDomViewer : public DOTGraphTraitsViewer<
PostDominatorTreeWrapperPass, false,
PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits> {
struct PostDomViewer
: public DOTGraphTraitsViewerWrapperPass<
PostDominatorTreeWrapperPass, false, PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits> {
static char ID;
PostDomViewer() :
DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, false,
PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits>(
"postdom", ID){
initializePostDomViewerPass(*PassRegistry::getPassRegistry());
}
PostDomViewer()
: DOTGraphTraitsViewerWrapperPass<
PostDominatorTreeWrapperPass, false, PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits>("postdom", ID) {
initializePostDomViewerPass(*PassRegistry::getPassRegistry());
}
};

struct PostDomOnlyViewer : public DOTGraphTraitsViewer<
PostDominatorTreeWrapperPass, true,
PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits> {
struct PostDomOnlyViewer
: public DOTGraphTraitsViewerWrapperPass<
PostDominatorTreeWrapperPass, true, PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits> {
static char ID;
PostDomOnlyViewer() :
DOTGraphTraitsViewer<PostDominatorTreeWrapperPass, true,
PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits>(
"postdomonly", ID){
initializePostDomOnlyViewerPass(*PassRegistry::getPassRegistry());
}
PostDomOnlyViewer()
: DOTGraphTraitsViewerWrapperPass<
PostDominatorTreeWrapperPass, true, PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits>("postdomonly",
ID) {
initializePostDomOnlyViewerPass(*PassRegistry::getPassRegistry());
}
};
} // end anonymous namespace

Expand All @@ -195,58 +194,55 @@ INITIALIZE_PASS(PostDomOnlyViewer, "view-postdom-only",
false, false)

namespace {
struct DomPrinter : public DOTGraphTraitsPrinter<
struct DomPrinter : public DOTGraphTraitsPrinterWrapperPass<
DominatorTreeWrapperPass, false, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits> {
static char ID;
DomPrinter()
: DOTGraphTraitsPrinter<DominatorTreeWrapperPass, false, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits>(
"dom", ID) {
: DOTGraphTraitsPrinterWrapperPass<
DominatorTreeWrapperPass, false, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits>("dom", ID) {
initializeDomPrinterPass(*PassRegistry::getPassRegistry());
}
};

struct DomOnlyPrinter : public DOTGraphTraitsPrinter<
struct DomOnlyPrinter : public DOTGraphTraitsPrinterWrapperPass<
DominatorTreeWrapperPass, true, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits> {
static char ID;
DomOnlyPrinter()
: DOTGraphTraitsPrinter<DominatorTreeWrapperPass, true, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits>(
"domonly", ID) {
: DOTGraphTraitsPrinterWrapperPass<
DominatorTreeWrapperPass, true, DominatorTree *,
DominatorTreeWrapperPassAnalysisGraphTraits>("domonly", ID) {
initializeDomOnlyPrinterPass(*PassRegistry::getPassRegistry());
}
};

struct PostDomPrinter
: public DOTGraphTraitsPrinter<
PostDominatorTreeWrapperPass, false,
PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits> {
: public DOTGraphTraitsPrinterWrapperPass<
PostDominatorTreeWrapperPass, false, PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits> {
static char ID;
PostDomPrinter() :
DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, false,
PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits>(
"postdom", ID) {
initializePostDomPrinterPass(*PassRegistry::getPassRegistry());
}
PostDomPrinter()
: DOTGraphTraitsPrinterWrapperPass<
PostDominatorTreeWrapperPass, false, PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits>("postdom", ID) {
initializePostDomPrinterPass(*PassRegistry::getPassRegistry());
}
};

struct PostDomOnlyPrinter
: public DOTGraphTraitsPrinter<
PostDominatorTreeWrapperPass, true,
PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits> {
: public DOTGraphTraitsPrinterWrapperPass<
PostDominatorTreeWrapperPass, true, PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits> {
static char ID;
PostDomOnlyPrinter() :
DOTGraphTraitsPrinter<PostDominatorTreeWrapperPass, true,
PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits>(
"postdomonly", ID) {
initializePostDomOnlyPrinterPass(*PassRegistry::getPassRegistry());
}
PostDomOnlyPrinter()
: DOTGraphTraitsPrinterWrapperPass<
PostDominatorTreeWrapperPass, true, PostDominatorTree *,
PostDominatorTreeWrapperPassAnalysisGraphTraits>("postdomonly",
ID) {
initializePostDomOnlyPrinterPass(*PassRegistry::getPassRegistry());
}
};
} // end anonymous namespace

Expand Down
65 changes: 29 additions & 36 deletions llvm/lib/Analysis/RegionPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,28 +31,20 @@ onlySimpleRegions("only-simple-regions",
cl::init(false));

namespace llvm {
template<>
struct DOTGraphTraits<RegionNode*> : public DefaultDOTGraphTraits {

DOTGraphTraits (bool isSimple=false)
: DefaultDOTGraphTraits(isSimple) {}
std::string DOTGraphTraits<RegionNode *>::getNodeLabel(RegionNode *Node,
RegionNode *Graph) {
if (!Node->isSubRegion()) {
BasicBlock *BB = Node->getNodeAs<BasicBlock>();

std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) {

if (!Node->isSubRegion()) {
BasicBlock *BB = Node->getNodeAs<BasicBlock>();

if (isSimple())
return DOTGraphTraits<DOTFuncInfo *>
::getSimpleNodeLabel(BB, nullptr);
else
return DOTGraphTraits<DOTFuncInfo *>
::getCompleteNodeLabel(BB, nullptr);
}

return "Not implemented";
if (isSimple())
return DOTGraphTraits<DOTFuncInfo *>::getSimpleNodeLabel(BB, nullptr);
else
return DOTGraphTraits<DOTFuncInfo *>::getCompleteNodeLabel(BB, nullptr);
}
};

return "Not implemented";
}

template <>
struct DOTGraphTraits<RegionInfo *> : public DOTGraphTraits<RegionNode *> {
Expand Down Expand Up @@ -134,7 +126,7 @@ struct DOTGraphTraits<RegionInfo *> : public DOTGraphTraits<RegionNode *> {
printRegionCluster(*G->getTopLevelRegion(), GW, 4);
}
};
} //end namespace llvm
} // end namespace llvm

namespace {

Expand All @@ -145,48 +137,49 @@ struct RegionInfoPassGraphTraits {
};

struct RegionPrinter
: public DOTGraphTraitsPrinter<RegionInfoPass, false, RegionInfo *,
RegionInfoPassGraphTraits> {
: public DOTGraphTraitsPrinterWrapperPass<
RegionInfoPass, false, RegionInfo *, RegionInfoPassGraphTraits> {
static char ID;
RegionPrinter()
: DOTGraphTraitsPrinter<RegionInfoPass, false, RegionInfo *,
RegionInfoPassGraphTraits>("reg", ID) {
: DOTGraphTraitsPrinterWrapperPass<RegionInfoPass, false, RegionInfo *,
RegionInfoPassGraphTraits>("reg", ID) {
initializeRegionPrinterPass(*PassRegistry::getPassRegistry());
}
};
char RegionPrinter::ID = 0;

struct RegionOnlyPrinter
: public DOTGraphTraitsPrinter<RegionInfoPass, true, RegionInfo *,
RegionInfoPassGraphTraits> {
: public DOTGraphTraitsPrinterWrapperPass<
RegionInfoPass, true, RegionInfo *, RegionInfoPassGraphTraits> {
static char ID;
RegionOnlyPrinter()
: DOTGraphTraitsPrinter<RegionInfoPass, true, RegionInfo *,
RegionInfoPassGraphTraits>("reg", ID) {
: DOTGraphTraitsPrinterWrapperPass<RegionInfoPass, true, RegionInfo *,
RegionInfoPassGraphTraits>("reg", ID) {
initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry());
}
};
char RegionOnlyPrinter::ID = 0;

struct RegionViewer
: public DOTGraphTraitsViewer<RegionInfoPass, false, RegionInfo *,
RegionInfoPassGraphTraits> {
: public DOTGraphTraitsViewerWrapperPass<
RegionInfoPass, false, RegionInfo *, RegionInfoPassGraphTraits> {
static char ID;
RegionViewer()
: DOTGraphTraitsViewer<RegionInfoPass, false, RegionInfo *,
RegionInfoPassGraphTraits>("reg", ID) {
: DOTGraphTraitsViewerWrapperPass<RegionInfoPass, false, RegionInfo *,
RegionInfoPassGraphTraits>("reg", ID) {
initializeRegionViewerPass(*PassRegistry::getPassRegistry());
}
};
char RegionViewer::ID = 0;

struct RegionOnlyViewer
: public DOTGraphTraitsViewer<RegionInfoPass, true, RegionInfo *,
RegionInfoPassGraphTraits> {
: public DOTGraphTraitsViewerWrapperPass<RegionInfoPass, true, RegionInfo *,
RegionInfoPassGraphTraits> {
static char ID;
RegionOnlyViewer()
: DOTGraphTraitsViewer<RegionInfoPass, true, RegionInfo *,
RegionInfoPassGraphTraits>("regonly", ID) {
: DOTGraphTraitsViewerWrapperPass<RegionInfoPass, true, RegionInfo *,
RegionInfoPassGraphTraits>("regonly",
ID) {
initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry());
}
};
Expand Down
16 changes: 8 additions & 8 deletions polly/include/polly/LinkAllPasses.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ llvm::Pass *createDependenceInfoPrinterLegacyPass(llvm::raw_ostream &OS);
llvm::Pass *createDependenceInfoWrapperPassPass();
llvm::Pass *
createDependenceInfoPrinterLegacyFunctionPass(llvm::raw_ostream &OS);
llvm::Pass *createDOTOnlyPrinterPass();
llvm::Pass *createDOTOnlyViewerPass();
llvm::Pass *createDOTPrinterPass();
llvm::Pass *createDOTViewerPass();
llvm::Pass *createDOTOnlyPrinterWrapperPass();
llvm::Pass *createDOTOnlyViewerWrapperPass();
llvm::Pass *createDOTPrinterWrapperPass();
llvm::Pass *createDOTViewerWrapperPass();
llvm::Pass *createJSONExporterPass();
llvm::Pass *createJSONImporterPass();
llvm::Pass *createJSONImporterPrinterLegacyPass(llvm::raw_ostream &OS);
Expand Down Expand Up @@ -94,10 +94,10 @@ struct PollyForcePassLinking {
polly::createDependenceInfoPrinterLegacyPass(llvm::outs());
polly::createDependenceInfoWrapperPassPass();
polly::createDependenceInfoPrinterLegacyFunctionPass(llvm::outs());
polly::createDOTOnlyPrinterPass();
polly::createDOTOnlyViewerPass();
polly::createDOTPrinterPass();
polly::createDOTViewerPass();
polly::createDOTOnlyPrinterWrapperPass();
polly::createDOTOnlyViewerWrapperPass();
polly::createDOTPrinterWrapperPass();
polly::createDOTViewerWrapperPass();
polly::createJSONExporterPass();
polly::createJSONImporterPass();
polly::createJSONImporterPrinterLegacyPass(llvm::outs());
Expand Down
94 changes: 94 additions & 0 deletions polly/include/polly/ScopGraphPrinter.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
//===- GraphPrinter.h - Create a DOT output describing the Scop. ----------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// Create a DOT output describing the Scop.
//
// For each function a dot file is created that shows the control flow graph of
// the function and highlights the detected Scops.
//
//===----------------------------------------------------------------------===//

#ifndef POLLY_SCOP_GRAPH_PRINTER_H
#define POLLY_SCOP_GRAPH_PRINTER_H

#include "polly/ScopDetection.h"
#include "polly/Support/ScopLocation.h"
#include "llvm/Analysis/DOTGraphTraitsPass.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
#include "llvm/Analysis/RegionPrinter.h"
#include "llvm/IR/PassManager.h"

using namespace polly;
using namespace llvm;

namespace llvm {

template <>
struct GraphTraits<ScopDetection *> : public GraphTraits<RegionInfo *> {
static NodeRef getEntryNode(ScopDetection *SD) {
return GraphTraits<RegionInfo *>::getEntryNode(SD->getRI());
}
static nodes_iterator nodes_begin(ScopDetection *SD) {
return nodes_iterator::begin(getEntryNode(SD));
}
static nodes_iterator nodes_end(ScopDetection *SD) {
return nodes_iterator::end(getEntryNode(SD));
}
};

template <>
struct DOTGraphTraits<ScopDetection *> : public DOTGraphTraits<RegionNode *> {
DOTGraphTraits(bool isSimple = false)
: DOTGraphTraits<RegionNode *>(isSimple) {}
static std::string getGraphName(ScopDetection *SD) { return "Scop Graph"; }

std::string getEdgeAttributes(RegionNode *srcNode,
GraphTraits<RegionInfo *>::ChildIteratorType CI,
ScopDetection *SD);

std::string getNodeLabel(RegionNode *Node, ScopDetection *SD) {
return DOTGraphTraits<RegionNode *>::getNodeLabel(
Node, reinterpret_cast<RegionNode *>(SD->getRI()->getTopLevelRegion()));
}

static std::string escapeString(llvm::StringRef String);

/// Print the cluster of the subregions. This groups the single basic blocks
/// and adds a different background color for each group.
static void printRegionCluster(ScopDetection *SD, const Region *R,
raw_ostream &O, unsigned depth = 0);

static void addCustomGraphFeatures(ScopDetection *SD,
GraphWriter<ScopDetection *> &GW);
};
} // end namespace llvm

namespace polly {

struct ScopViewer : public DOTGraphTraitsViewer<ScopAnalysis, false> {
ScopViewer() : DOTGraphTraitsViewer<ScopAnalysis, false>("scops") {}

bool processFunction(Function &F, const ScopDetection &SD) override;
};

struct ScopOnlyViewer : public DOTGraphTraitsViewer<ScopAnalysis, false> {
ScopOnlyViewer() : DOTGraphTraitsViewer<ScopAnalysis, false>("scops-only") {}
};

struct ScopPrinter : public DOTGraphTraitsPrinter<ScopAnalysis, false> {
ScopPrinter() : DOTGraphTraitsPrinter<ScopAnalysis, false>("scops") {}
};

struct ScopOnlyPrinter : public DOTGraphTraitsPrinter<ScopAnalysis, true> {
ScopOnlyPrinter() : DOTGraphTraitsPrinter<ScopAnalysis, true>("scopsonly") {}
};

} // end namespace polly

#endif /* POLLY_SCOP_GRAPH_PRINTER_H */
323 changes: 152 additions & 171 deletions polly/lib/Analysis/ScopGraphPrinter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,9 @@
//
//===----------------------------------------------------------------------===//

#include "polly/ScopGraphPrinter.h"
#include "polly/LinkAllPasses.h"
#include "polly/ScopDetection.h"
#include "polly/Support/ScopLocation.h"
#include "llvm/Analysis/DOTGraphTraitsPass.h"
#include "llvm/Analysis/RegionInfo.h"
#include "llvm/Analysis/RegionIterator.h"
#include "llvm/Support/CommandLine.h"

using namespace polly;
Expand All @@ -33,175 +30,126 @@ static cl::opt<bool> ViewAll("polly-view-all",
cl::Hidden, cl::init(false), cl::ZeroOrMore);

namespace llvm {
template <>
struct GraphTraits<ScopDetection *> : public GraphTraits<RegionInfo *> {
static NodeRef getEntryNode(ScopDetection *SD) {
return GraphTraits<RegionInfo *>::getEntryNode(SD->getRI());
}
static nodes_iterator nodes_begin(ScopDetection *SD) {
return nodes_iterator::begin(getEntryNode(SD));
}
static nodes_iterator nodes_end(ScopDetection *SD) {
return nodes_iterator::end(getEntryNode(SD));
}
};

template <>
struct GraphTraits<ScopDetectionWrapperPass *>
: public GraphTraits<ScopDetection *> {
static NodeRef getEntryNode(ScopDetectionWrapperPass *P) {
return GraphTraits<ScopDetection *>::getEntryNode(&P->getSD());
}
static nodes_iterator nodes_begin(ScopDetectionWrapperPass *P) {
return nodes_iterator::begin(getEntryNode(P));
}
static nodes_iterator nodes_end(ScopDetectionWrapperPass *P) {
return nodes_iterator::end(getEntryNode(P));
}
};

template <> struct DOTGraphTraits<RegionNode *> : public DefaultDOTGraphTraits {
DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}

std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) {
if (!Node->isSubRegion()) {
BasicBlock *BB = Node->getNodeAs<BasicBlock>();

if (isSimple())
return DOTGraphTraits<DOTFuncInfo *>::getSimpleNodeLabel(BB, nullptr);

else
return DOTGraphTraits<DOTFuncInfo *>::getCompleteNodeLabel(BB, nullptr);
}

return "Not implemented";
}
};
std::string DOTGraphTraits<ScopDetection *>::getEdgeAttributes(
RegionNode *srcNode, GraphTraits<RegionInfo *>::ChildIteratorType CI,
ScopDetection *SD) {
RegionNode *destNode = *CI;

template <>
struct DOTGraphTraits<ScopDetectionWrapperPass *>
: public DOTGraphTraits<RegionNode *> {
DOTGraphTraits(bool isSimple = false)
: DOTGraphTraits<RegionNode *>(isSimple) {}
static std::string getGraphName(ScopDetectionWrapperPass *SD) {
return "Scop Graph";
}
if (srcNode->isSubRegion() || destNode->isSubRegion())
return "";

std::string getEdgeAttributes(RegionNode *srcNode,
GraphTraits<RegionInfo *>::ChildIteratorType CI,
ScopDetectionWrapperPass *P) {
RegionNode *destNode = *CI;
auto *SD = &P->getSD();
// In case of a backedge, do not use it to define the layout of the nodes.
BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();
BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();

if (srcNode->isSubRegion() || destNode->isSubRegion())
return "";
RegionInfo *RI = SD->getRI();
Region *R = RI->getRegionFor(destBB);

// In case of a backedge, do not use it to define the layout of the nodes.
BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();
BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();
while (R && R->getParent())
if (R->getParent()->getEntry() == destBB)
R = R->getParent();
else
break;

RegionInfo *RI = SD->getRI();
Region *R = RI->getRegionFor(destBB);
if (R && R->getEntry() == destBB && R->contains(srcBB))
return "constraint=false";

while (R && R->getParent())
if (R->getParent()->getEntry() == destBB)
R = R->getParent();
else
break;
return "";
}

if (R && R->getEntry() == destBB && R->contains(srcBB))
return "constraint=false";
std::string
DOTGraphTraits<ScopDetection *>::escapeString(llvm::StringRef String) {
std::string Escaped;

return "";
}
for (const auto &C : String) {
if (C == '"')
Escaped += '\\';

std::string getNodeLabel(RegionNode *Node, ScopDetectionWrapperPass *P) {
return DOTGraphTraits<RegionNode *>::getNodeLabel(
Node, reinterpret_cast<RegionNode *>(
P->getSD().getRI()->getTopLevelRegion()));
Escaped += C;
}

static std::string escapeString(std::string String) {
std::string Escaped;

for (const auto &C : String) {
if (C == '"')
Escaped += '\\';

Escaped += C;
}
return Escaped;
return Escaped;
}

void DOTGraphTraits<ScopDetection *>::printRegionCluster(ScopDetection *SD,
const Region *R,
raw_ostream &O,
unsigned depth) {
O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R)
<< " {\n";
unsigned LineBegin, LineEnd;
std::string FileName;

getDebugLocation(R, LineBegin, LineEnd, FileName);

std::string Location;
if (LineBegin != (unsigned)-1) {
Location = escapeString(FileName + ":" + std::to_string(LineBegin) + "-" +
std::to_string(LineEnd) + "\n");
}

// Print the cluster of the subregions. This groups the single basic blocks
// and adds a different background color for each group.
static void printRegionCluster(ScopDetection *SD, const Region *R,
raw_ostream &O, unsigned depth = 0) {
O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R)
<< " {\n";
unsigned LineBegin, LineEnd;
std::string FileName;
std::string ErrorMessage = SD->regionIsInvalidBecause(R);
ErrorMessage = escapeString(ErrorMessage);
O.indent(2 * (depth + 1))
<< "label = \"" << Location << ErrorMessage << "\";\n";

getDebugLocation(R, LineBegin, LineEnd, FileName);
if (SD->isMaxRegionInScop(*R)) {
O.indent(2 * (depth + 1)) << "style = filled;\n";

std::string Location;
if (LineBegin != (unsigned)-1) {
Location = escapeString(FileName + ":" + std::to_string(LineBegin) + "-" +
std::to_string(LineEnd) + "\n");
}
// Set color to green.
O.indent(2 * (depth + 1)) << "color = 3";
} else {
O.indent(2 * (depth + 1)) << "style = solid;\n";

std::string ErrorMessage = SD->regionIsInvalidBecause(R);
ErrorMessage = escapeString(ErrorMessage);
O.indent(2 * (depth + 1))
<< "label = \"" << Location << ErrorMessage << "\";\n";
int color = (R->getDepth() * 2 % 12) + 1;

if (SD->isMaxRegionInScop(*R)) {
O.indent(2 * (depth + 1)) << "style = filled;\n";
// We do not want green again.
if (color == 3)
color = 6;

// Set color to green.
O.indent(2 * (depth + 1)) << "color = 3";
} else {
O.indent(2 * (depth + 1)) << "style = solid;\n";
O.indent(2 * (depth + 1)) << "color = " << color << "\n";
}

int color = (R->getDepth() * 2 % 12) + 1;
for (const auto &SubRegion : *R)
printRegionCluster(SD, SubRegion.get(), O, depth + 1);

// We do not want green again.
if (color == 3)
color = 6;
RegionInfo *RI = R->getRegionInfo();

O.indent(2 * (depth + 1)) << "color = " << color << "\n";
}
for (BasicBlock *BB : R->blocks())
if (RI->getRegionFor(BB) == R)
O.indent(2 * (depth + 1))
<< "Node"
<< static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))
<< ";\n";

for (const auto &SubRegion : *R)
printRegionCluster(SD, SubRegion.get(), O, depth + 1);
O.indent(2 * depth) << "}\n";
}

RegionInfo *RI = R->getRegionInfo();
void DOTGraphTraits<ScopDetection *>::addCustomGraphFeatures(
ScopDetection *SD, GraphWriter<ScopDetection *> &GW) {
raw_ostream &O = GW.getOStream();
O << "\tcolorscheme = \"paired12\"\n";
printRegionCluster(SD, SD->getRI()->getTopLevelRegion(), O, 4);
}

for (BasicBlock *BB : R->blocks())
if (RI->getRegionFor(BB) == R)
O.indent(2 * (depth + 1))
<< "Node"
<< static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))
<< ";\n";
} // namespace llvm

O.indent(2 * depth) << "}\n";
}
static void
addCustomGraphFeatures(const ScopDetectionWrapperPass *SD,
GraphWriter<ScopDetectionWrapperPass *> &GW) {
raw_ostream &O = GW.getOStream();
O << "\tcolorscheme = \"paired12\"\n";
printRegionCluster(&SD->getSD(), SD->getSD().getRI()->getTopLevelRegion(),
O, 4);
struct ScopDetectionAnalysisGraphTraits {
static ScopDetection *getGraph(ScopDetectionWrapperPass *Analysis) {
return &Analysis->getSD();
}
};
} // end namespace llvm

struct ScopViewer
: public DOTGraphTraitsViewer<ScopDetectionWrapperPass, false> {
struct ScopViewerWrapperPass
: public DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
ScopDetection *,
ScopDetectionAnalysisGraphTraits> {
static char ID;
ScopViewer()
: DOTGraphTraitsViewer<ScopDetectionWrapperPass, false>("scops", ID) {}
ScopViewerWrapperPass()
: DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
ScopDetection *,
ScopDetectionAnalysisGraphTraits>(
"scops", ID) {}
bool processFunction(Function &F, ScopDetectionWrapperPass &SD) override {
if (ViewFilter != "" && !F.getName().count(ViewFilter))
return false;
Expand All @@ -213,51 +161,84 @@ struct ScopViewer
return std::distance(SD.getSD().begin(), SD.getSD().end()) > 0;
}
};
char ScopViewer::ID = 0;
char ScopViewerWrapperPass::ID = 0;

struct ScopOnlyViewer
: public DOTGraphTraitsViewer<ScopDetectionWrapperPass, true> {
struct ScopOnlyViewerWrapperPass
: public DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
ScopDetection *,
ScopDetectionAnalysisGraphTraits> {
static char ID;
ScopOnlyViewer()
: DOTGraphTraitsViewer<ScopDetectionWrapperPass, true>("scopsonly", ID) {}
ScopOnlyViewerWrapperPass()
: DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
ScopDetection *,
ScopDetectionAnalysisGraphTraits>(
"scopsonly", ID) {}
};
char ScopOnlyViewer::ID = 0;
char ScopOnlyViewerWrapperPass::ID = 0;

struct ScopPrinter
: public DOTGraphTraitsPrinter<ScopDetectionWrapperPass, false> {
struct ScopPrinterWrapperPass
: public DOTGraphTraitsPrinterWrapperPass<
ScopDetectionWrapperPass, false, ScopDetection *,
ScopDetectionAnalysisGraphTraits> {
static char ID;
ScopPrinter()
: DOTGraphTraitsPrinter<ScopDetectionWrapperPass, false>("scops", ID) {}
ScopPrinterWrapperPass()
: DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false,
ScopDetection *,
ScopDetectionAnalysisGraphTraits>(
"scops", ID) {}
};
char ScopPrinter::ID = 0;
char ScopPrinterWrapperPass::ID = 0;

struct ScopOnlyPrinter
: public DOTGraphTraitsPrinter<ScopDetectionWrapperPass, true> {
struct ScopOnlyPrinterWrapperPass
: public DOTGraphTraitsPrinterWrapperPass<
ScopDetectionWrapperPass, true, ScopDetection *,
ScopDetectionAnalysisGraphTraits> {
static char ID;
ScopOnlyPrinter()
: DOTGraphTraitsPrinter<ScopDetectionWrapperPass, true>("scopsonly", ID) {
}
ScopOnlyPrinterWrapperPass()
: DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true,
ScopDetection *,
ScopDetectionAnalysisGraphTraits>(
"scopsonly", ID) {}
};
char ScopOnlyPrinter::ID = 0;
char ScopOnlyPrinterWrapperPass::ID = 0;

static RegisterPass<ScopViewer> X("view-scops",
"Polly - View Scops of function");
static RegisterPass<ScopViewerWrapperPass> X("view-scops",
"Polly - View Scops of function");

static RegisterPass<ScopOnlyViewer>
static RegisterPass<ScopOnlyViewerWrapperPass>
Y("view-scops-only",
"Polly - View Scops of function (with no function bodies)");

static RegisterPass<ScopPrinter> M("dot-scops",
"Polly - Print Scops of function");
static RegisterPass<ScopPrinterWrapperPass>
M("dot-scops", "Polly - Print Scops of function");

static RegisterPass<ScopOnlyPrinter>
static RegisterPass<ScopOnlyPrinterWrapperPass>
N("dot-scops-only",
"Polly - Print Scops of function (with no function bodies)");

Pass *polly::createDOTViewerPass() { return new ScopViewer(); }
Pass *polly::createDOTViewerWrapperPass() {
return new ScopViewerWrapperPass();
}

Pass *polly::createDOTOnlyViewerWrapperPass() {
return new ScopOnlyViewerWrapperPass();
}

Pass *polly::createDOTPrinterWrapperPass() {
return new ScopPrinterWrapperPass();
}

Pass *polly::createDOTOnlyPrinterWrapperPass() {
return new ScopOnlyPrinterWrapperPass();
}

Pass *polly::createDOTOnlyViewerPass() { return new ScopOnlyViewer(); }
bool ScopViewer::processFunction(Function &F, const ScopDetection &SD) {
if (ViewFilter != "" && !F.getName().count(ViewFilter))
return false;

Pass *polly::createDOTPrinterPass() { return new ScopPrinter(); }
if (ViewAll)
return true;

Pass *polly::createDOTOnlyPrinterPass() { return new ScopOnlyPrinter(); }
// Check that at least one scop was detected.
return std::distance(SD.begin(), SD.end()) > 0;
}
4 changes: 4 additions & 0 deletions polly/lib/Support/PollyPasses.def
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,10 @@ FUNCTION_ANALYSIS("polly-function-scops", ScopInfoAnalysis())
FUNCTION_PASS("polly-prepare", CodePreparationPass())
FUNCTION_PASS("print<polly-detect>", ScopAnalysisPrinterPass(llvm::errs()))
FUNCTION_PASS("print<polly-function-scops>", ScopInfoPrinterPass(llvm::errs()))
FUNCTION_PASS("polly-scop-viewer", ScopViewer())
FUNCTION_PASS("polly-scop-only-viewer", ScopOnlyViewer())
FUNCTION_PASS("polly-scop-printer", ScopPrinter())
FUNCTION_PASS("polly-scop-only-printer", ScopOnlyPrinter())
#undef FUNCTION_PASS

#ifndef SCOP_ANALYSIS
Expand Down
21 changes: 9 additions & 12 deletions polly/lib/Support/RegisterPasses.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
#include "polly/PruneUnprofitable.h"
#include "polly/ScheduleOptimizer.h"
#include "polly/ScopDetection.h"
#include "polly/ScopGraphPrinter.h"
#include "polly/ScopInfo.h"
#include "polly/Simplify.h"
#include "polly/Support/DumpFunctionPass.h"
Expand Down Expand Up @@ -331,14 +332,13 @@ static void registerPollyPasses(llvm::legacy::PassManagerBase &PM,
return;

if (PollyViewer)
PM.add(polly::createDOTViewerPass());
PM.add(polly::createDOTViewerWrapperPass());
if (PollyOnlyViewer)
PM.add(polly::createDOTOnlyViewerPass());
PM.add(polly::createDOTOnlyViewerWrapperPass());
if (PollyPrinter)
PM.add(polly::createDOTPrinterPass());
PM.add(polly::createDOTPrinterWrapperPass());
if (PollyOnlyPrinter)
PM.add(polly::createDOTOnlyPrinterPass());

PM.add(polly::createDOTOnlyPrinterWrapperPass());
PM.add(polly::createScopInfoRegionPassPass());
if (EnablePolyhedralInfo)
PM.add(polly::createPolyhedralInfoPass());
Expand Down Expand Up @@ -509,16 +509,13 @@ static void buildCommonPollyPipeline(FunctionPassManager &PM,
}

if (PollyViewer)
llvm::report_fatal_error("Option -polly-show not supported with NPM",
false);
PM.addPass(ScopViewer());
if (PollyOnlyViewer)
llvm::report_fatal_error("Option -polly-show-only not supported with NPM",
false);
PM.addPass(ScopOnlyViewer());
if (PollyPrinter)
llvm::report_fatal_error("Option -polly-dot not supported with NPM", false);
PM.addPass(ScopPrinter());
if (PollyOnlyPrinter)
llvm::report_fatal_error("Option -polly-dot-only not supported with NPM",
false);
PM.addPass(ScopOnlyPrinter());
if (EnablePolyhedralInfo)
llvm::report_fatal_error(
"Option -polly-enable-polyhedralinfo not supported with NPM", false);
Expand Down
100 changes: 100 additions & 0 deletions polly/test/ScopDetect/dot-scops-npm.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
; RUN: opt %loadPolly "-passes=polly-scop-printer" -disable-output < %s
; RUN: FileCheck %s -input-file=scops.func.dot
;
; Check that the ScopPrinter does not crash.
; ScopPrinter needs the ScopDetection pass, which should depend on
; ScalarEvolution transitively.

target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"

define void @func(i32 %n, i32 %m, double* noalias nonnull %A) {
; CHECK: digraph "Scop Graph for 'func' function"
; CHECK-NEXT: label="Scop Graph for 'func' function"
; CHECK: Node0x[[EntryID:.*]] [shape=record,label="{entry:\l br label %outer.for\l}"];
; CHECK-NEXT: Node0x[[EntryID]] -> Node0x[[OUTER_FOR_ID:.*]];
; CHECK-NEXT: Node0x[[OUTER_FOR_ID]] [shape=record,label="{outer.for:
; CHECK-NEXT: Node0x[[OUTER_FOR_ID]] -> Node0x[[INNER_FOR_ID:.*]];
; CHECK-NEXT: Node0x[[OUTER_FOR_ID]] -> Node0x[[OUTER_EXIT:.*]];
; CHECK-NEXT: Node0x[[INNER_FOR_ID]] [shape=record,label="{inner.for:
; CHECK-NEXT: Node0x[[INNER_FOR_ID]] -> Node0x[[BABY1_ID:.*]];
; CHECK-NEXT: Node0x[[INNER_FOR_ID]] -> Node0x[[INNER_EXIT_ID:.*]];
; CHECK-NEXT: Node0x[[BABY1_ID]] [shape=record,label="{body1:
; CHECK-NEXT: Node0x[[BABY1_ID]] -> Node0x[[INNER_INC_ID:.*]];
; CHECK-NEXT: Node0x[[INNER_INC_ID]] [shape=record,label="{inner.inc:
; CHECK-NEXT: Node0x[[INNER_INC_ID]] -> Node0x[[INNER_FOR_ID]][constraint=false];
; CHECK-NEXT: Node0x[[INNER_EXIT_ID]] [shape=record,label="{inner.exit:
; CHECK-NEXT: Node0x[[INNER_EXIT_ID]] -> Node0x[[OUTER_INC_ID:.*]];
; CHECK-NEXT: Node0x[[OUTER_INC_ID]] [shape=record,label="{outer.inc:
; CHECK-NEXT: Node0x[[OUTER_INC_ID]] -> Node0x[[OUTER_FOR_ID]][constraint=false];
; CHECK-NEXT: Node0x[[OUTER_EXIT]] [shape=record,label="{outer.exit:
; CHECK-NEXT: Node0x[[OUTER_EXIT]] -> Node0x[[RETURN_ID:.*]];
; CHECK-NEXT: Node0x[[RETURN_ID]] [shape=record,label="{return:
; CHECK-NEXT: colorscheme = "paired12"
; CHECK_NEXT: subgraph cluster_0x[[:.*]] {
; CHECK_NEXT: label = "";
; CHECK_NEXT: style = solid;
; CHECK_NEXT: color = 1
; CHECK_NEXT: subgraph cluster_0x[[:.*]] {
; CHECK_NEXT: label = "";
; CHECK_NEXT: style = filled;
; CHECK_NEXT: color = 3 subgraph cluster_0x7152c40 {
; CHECK_NEXT: label = "";
; CHECK_NEXT: style = solid;
; CHECK_NEXT: color = 5
; CHECK_NEXT: subgraph cluster_0x[[:.*]] {
; CHECK_NEXT: label = "";
; CHECK_NEXT: style = solid;
; CHECK_NEXT: color = 7
; CHECK_NEXT: Node0x[[INNER_FOR_ID]];
; CHECK_NEXT: Node0x[[BABY1_ID]];
; CHECK_NEXT: Node0x[[INNER_INC_ID]];
; CHECK_NEXT: }
; CHECK_NEXT: Node0x[[OUTER_FOR_ID]];
; CHECK_NEXT: Node0x[[INNER_EXIT_ID]];
; CHECK_NEXT: Node0x[[OUTER_INC_ID]];
; CHECK_NEXT: }
; CHECK_NEXT: Node0x[[OUTER_EXIT]];
; CHECK_NEXT: }
; CHECK_NEXT: Node0x[[EntryID]];
; CHECK_NEXT: Node0x[[RETURN_ID]];
; CHECK_NEXT: }
; CHECK_NEXT: }

entry:
br label %outer.for

outer.for:
%j = phi i32 [0, %entry], [%j.inc, %outer.inc]
%j.cmp = icmp slt i32 %j, %n
br i1 %j.cmp, label %inner.for, label %outer.exit

inner.for:
%i = phi i32 [1, %outer.for], [%i.inc, %inner.inc]
%b = phi double [0.0, %outer.for], [%a, %inner.inc]
%i.cmp = icmp slt i32 %i, %m
br i1 %i.cmp, label %body1, label %inner.exit

body1:
%A_idx = getelementptr inbounds double, double* %A, i32 %i
%a = load double, double* %A_idx
store double %a, double* %A_idx
br label %inner.inc

inner.inc:
%i.inc = add nuw nsw i32 %i, 1
br label %inner.for

inner.exit:
br label %outer.inc

outer.inc:
store double %b, double* %A
%j.inc = add nuw nsw i32 %j, 1
br label %outer.for

outer.exit:
br label %return

return:
ret void
}