forked from OSchip/llvm-project
[polly] migrate -polly-show to the new pass manager
Reviewed By: Meinersbur Differential Revision: https://reviews.llvm.org/D123678
This commit is contained in:
parent
a6b399ad79
commit
6b3b87376b
|
@ -14,6 +14,9 @@
|
|||
#ifndef LLVM_ANALYSIS_REGIONPRINTER_H
|
||||
#define LLVM_ANALYSIS_REGIONPRINTER_H
|
||||
|
||||
#include "llvm/Analysis/DOTGraphTraitsPass.h"
|
||||
#include "llvm/Analysis/RegionInfo.h"
|
||||
|
||||
namespace llvm {
|
||||
class FunctionPass;
|
||||
class Function;
|
||||
|
@ -24,6 +27,13 @@ namespace llvm {
|
|||
FunctionPass *createRegionPrinterPass();
|
||||
FunctionPass *createRegionOnlyPrinterPass();
|
||||
|
||||
template <>
|
||||
struct DOTGraphTraits<RegionNode *> : public DefaultDOTGraphTraits {
|
||||
DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {}
|
||||
|
||||
std::string getNodeLabel(RegionNode *Node, RegionNode *Graph);
|
||||
};
|
||||
|
||||
#ifndef NDEBUG
|
||||
/// Open a viewer to display the GraphViz vizualization of the analysis
|
||||
/// result.
|
||||
|
|
|
@ -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 *> {
|
||||
|
@ -134,7 +126,7 @@ struct DOTGraphTraits<RegionInfo *> : public DOTGraphTraits<RegionNode *> {
|
|||
printRegionCluster(*G->getTopLevelRegion(), GW, 4);
|
||||
}
|
||||
};
|
||||
} //end namespace llvm
|
||||
} // end namespace llvm
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -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());
|
||||
|
|
|
@ -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 */
|
|
@ -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;
|
||||
|
@ -33,175 +30,125 @@ 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";
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct DOTGraphTraits<ScopDetectionWrapperPass *>
|
||||
: public DOTGraphTraits<RegionNode *> {
|
||||
DOTGraphTraits(bool isSimple = false)
|
||||
: DOTGraphTraits<RegionNode *>(isSimple) {}
|
||||
static std::string getGraphName(ScopDetectionWrapperPass *SD) {
|
||||
return "Scop Graph";
|
||||
}
|
||||
|
||||
std::string getEdgeAttributes(RegionNode *srcNode,
|
||||
GraphTraits<RegionInfo *>::ChildIteratorType CI,
|
||||
ScopDetectionWrapperPass *P) {
|
||||
RegionNode *destNode = *CI;
|
||||
auto *SD = &P->getSD();
|
||||
|
||||
if (srcNode->isSubRegion() || destNode->isSubRegion())
|
||||
return "";
|
||||
|
||||
// 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>();
|
||||
|
||||
RegionInfo *RI = SD->getRI();
|
||||
Region *R = RI->getRegionFor(destBB);
|
||||
|
||||
while (R && R->getParent())
|
||||
if (R->getParent()->getEntry() == destBB)
|
||||
R = R->getParent();
|
||||
else
|
||||
break;
|
||||
|
||||
if (R && R->getEntry() == destBB && R->contains(srcBB))
|
||||
return "constraint=false";
|
||||
std::string DOTGraphTraits<ScopDetection *>::getEdgeAttributes(
|
||||
RegionNode *srcNode, GraphTraits<RegionInfo *>::ChildIteratorType CI,
|
||||
ScopDetection *SD) {
|
||||
RegionNode *destNode = *CI;
|
||||
|
||||
if (srcNode->isSubRegion() || destNode->isSubRegion())
|
||||
return "";
|
||||
|
||||
// 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>();
|
||||
|
||||
RegionInfo *RI = SD->getRI();
|
||||
Region *R = RI->getRegionFor(destBB);
|
||||
|
||||
while (R && R->getParent())
|
||||
if (R->getParent()->getEntry() == destBB)
|
||||
R = R->getParent();
|
||||
else
|
||||
break;
|
||||
|
||||
if (R && R->getEntry() == destBB && R->contains(srcBB))
|
||||
return "constraint=false";
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string
|
||||
DOTGraphTraits<ScopDetection *>::escapeString(llvm::StringRef String) {
|
||||
std::string Escaped;
|
||||
|
||||
for (const auto &C : String) {
|
||||
if (C == '"')
|
||||
Escaped += '\\';
|
||||
|
||||
Escaped += C;
|
||||
}
|
||||
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");
|
||||
}
|
||||
|
||||
std::string getNodeLabel(RegionNode *Node, ScopDetectionWrapperPass *P) {
|
||||
return DOTGraphTraits<RegionNode *>::getNodeLabel(
|
||||
Node, reinterpret_cast<RegionNode *>(
|
||||
P->getSD().getRI()->getTopLevelRegion()));
|
||||
std::string ErrorMessage = SD->regionIsInvalidBecause(R);
|
||||
ErrorMessage = escapeString(ErrorMessage);
|
||||
O.indent(2 * (depth + 1))
|
||||
<< "label = \"" << Location << ErrorMessage << "\";\n";
|
||||
|
||||
if (SD->isMaxRegionInScop(*R)) {
|
||||
O.indent(2 * (depth + 1)) << "style = filled;\n";
|
||||
|
||||
// Set color to green.
|
||||
O.indent(2 * (depth + 1)) << "color = 3";
|
||||
} else {
|
||||
O.indent(2 * (depth + 1)) << "style = solid;\n";
|
||||
|
||||
int color = (R->getDepth() * 2 % 12) + 1;
|
||||
|
||||
// We do not want green again.
|
||||
if (color == 3)
|
||||
color = 6;
|
||||
|
||||
O.indent(2 * (depth + 1)) << "color = " << color << "\n";
|
||||
}
|
||||
|
||||
static std::string escapeString(std::string String) {
|
||||
std::string Escaped;
|
||||
for (const auto &SubRegion : *R)
|
||||
printRegionCluster(SD, SubRegion.get(), O, depth + 1);
|
||||
|
||||
for (const auto &C : String) {
|
||||
if (C == '"')
|
||||
Escaped += '\\';
|
||||
RegionInfo *RI = R->getRegionInfo();
|
||||
|
||||
Escaped += C;
|
||||
}
|
||||
return Escaped;
|
||||
}
|
||||
for (BasicBlock *BB : R->blocks())
|
||||
if (RI->getRegionFor(BB) == R)
|
||||
O.indent(2 * (depth + 1))
|
||||
<< "Node"
|
||||
<< static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))
|
||||
<< ";\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;
|
||||
O.indent(2 * depth) << "}\n";
|
||||
}
|
||||
|
||||
getDebugLocation(R, LineBegin, LineEnd, FileName);
|
||||
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);
|
||||
}
|
||||
|
||||
std::string Location;
|
||||
if (LineBegin != (unsigned)-1) {
|
||||
Location = escapeString(FileName + ":" + std::to_string(LineBegin) + "-" +
|
||||
std::to_string(LineEnd) + "\n");
|
||||
}
|
||||
} // namespace llvm
|
||||
|
||||
std::string ErrorMessage = SD->regionIsInvalidBecause(R);
|
||||
ErrorMessage = escapeString(ErrorMessage);
|
||||
O.indent(2 * (depth + 1))
|
||||
<< "label = \"" << Location << ErrorMessage << "\";\n";
|
||||
|
||||
if (SD->isMaxRegionInScop(*R)) {
|
||||
O.indent(2 * (depth + 1)) << "style = filled;\n";
|
||||
|
||||
// Set color to green.
|
||||
O.indent(2 * (depth + 1)) << "color = 3";
|
||||
} else {
|
||||
O.indent(2 * (depth + 1)) << "style = solid;\n";
|
||||
|
||||
int color = (R->getDepth() * 2 % 12) + 1;
|
||||
|
||||
// We do not want green again.
|
||||
if (color == 3)
|
||||
color = 6;
|
||||
|
||||
O.indent(2 * (depth + 1)) << "color = " << color << "\n";
|
||||
}
|
||||
|
||||
for (const auto &SubRegion : *R)
|
||||
printRegionCluster(SD, SubRegion.get(), O, depth + 1);
|
||||
|
||||
RegionInfo *RI = R->getRegionInfo();
|
||||
|
||||
for (BasicBlock *BB : R->blocks())
|
||||
if (RI->getRegionFor(BB) == R)
|
||||
O.indent(2 * (depth + 1))
|
||||
<< "Node"
|
||||
<< static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))
|
||||
<< ";\n";
|
||||
|
||||
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 DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false> {
|
||||
struct ScopViewerWrapperPass
|
||||
: public DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
|
||||
ScopDetection *,
|
||||
ScopDetectionAnalysisGraphTraits> {
|
||||
static char ID;
|
||||
ScopViewer()
|
||||
: DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false>(
|
||||
ScopViewerWrapperPass()
|
||||
: DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
|
||||
ScopDetection *,
|
||||
ScopDetectionAnalysisGraphTraits>(
|
||||
"scops", ID) {}
|
||||
bool processFunction(Function &F, ScopDetectionWrapperPass &SD) override {
|
||||
if (ViewFilter != "" && !F.getName().count(ViewFilter))
|
||||
|
@ -214,53 +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 DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, true> {
|
||||
struct ScopOnlyViewerWrapperPass
|
||||
: public DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
|
||||
ScopDetection *,
|
||||
ScopDetectionAnalysisGraphTraits> {
|
||||
static char ID;
|
||||
ScopOnlyViewer()
|
||||
: DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, true>(
|
||||
ScopOnlyViewerWrapperPass()
|
||||
: DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
|
||||
ScopDetection *,
|
||||
ScopDetectionAnalysisGraphTraits>(
|
||||
"scopsonly", ID) {}
|
||||
};
|
||||
char ScopOnlyViewer::ID = 0;
|
||||
char ScopOnlyViewerWrapperPass::ID = 0;
|
||||
|
||||
struct ScopPrinter
|
||||
: public DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false> {
|
||||
struct ScopPrinterWrapperPass
|
||||
: public DOTGraphTraitsPrinterWrapperPass<
|
||||
ScopDetectionWrapperPass, false, ScopDetection *,
|
||||
ScopDetectionAnalysisGraphTraits> {
|
||||
static char ID;
|
||||
ScopPrinter()
|
||||
: DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false>(
|
||||
ScopPrinterWrapperPass()
|
||||
: DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false,
|
||||
ScopDetection *,
|
||||
ScopDetectionAnalysisGraphTraits>(
|
||||
"scops", ID) {}
|
||||
};
|
||||
char ScopPrinter::ID = 0;
|
||||
char ScopPrinterWrapperPass::ID = 0;
|
||||
|
||||
struct ScopOnlyPrinter
|
||||
: public DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true> {
|
||||
struct ScopOnlyPrinterWrapperPass
|
||||
: public DOTGraphTraitsPrinterWrapperPass<
|
||||
ScopDetectionWrapperPass, true, ScopDetection *,
|
||||
ScopDetectionAnalysisGraphTraits> {
|
||||
static char ID;
|
||||
ScopOnlyPrinter()
|
||||
: DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true>(
|
||||
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::createDOTOnlyViewerPass() { return new ScopOnlyViewer(); }
|
||||
Pass *polly::createDOTOnlyViewerWrapperPass() {
|
||||
return new ScopOnlyViewerWrapperPass();
|
||||
}
|
||||
|
||||
Pass *polly::createDOTPrinterPass() { return new ScopPrinter(); }
|
||||
Pass *polly::createDOTPrinterWrapperPass() {
|
||||
return new ScopPrinterWrapperPass();
|
||||
}
|
||||
|
||||
Pass *polly::createDOTOnlyPrinterPass() { return new ScopOnlyPrinter(); }
|
||||
Pass *polly::createDOTOnlyPrinterWrapperPass() {
|
||||
return new ScopOnlyPrinterWrapperPass();
|
||||
}
|
||||
|
||||
bool ScopViewer::processFunction(Function &F, const ScopDetection &SD) {
|
||||
if (ViewFilter != "" && !F.getName().count(ViewFilter))
|
||||
return false;
|
||||
|
||||
if (ViewAll)
|
||||
return true;
|
||||
|
||||
// Check that at least one scop was detected.
|
||||
return std::distance(SD.begin(), SD.end()) > 0;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue