[polly] migrate -polly-show to the new pass manager

Reviewed By: Meinersbur

Differential Revision: https://reviews.llvm.org/D123678
This commit is contained in:
Michael Kruse 2022-05-09 13:38:20 -05:00
parent a6b399ad79
commit 6b3b87376b
8 changed files with 397 additions and 222 deletions

View file

@ -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.

View file

@ -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 {

View file

@ -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());

View file

@ -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 */

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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
}