123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- //===- GraphPrinter.cpp - 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.
- //
- //===----------------------------------------------------------------------===//
- #include "polly/ScopGraphPrinter.h"
- #include "polly/LinkAllPasses.h"
- #include "polly/ScopDetection.h"
- #include "llvm/Support/CommandLine.h"
- using namespace polly;
- using namespace llvm;
- static cl::opt<std::string>
- ViewFilter("polly-view-only",
- cl::desc("Only view functions that match this pattern"),
- cl::Hidden, cl::init(""));
- static cl::opt<bool> ViewAll("polly-view-all",
- cl::desc("Also show functions without any scops"),
- cl::Hidden, cl::init(false));
- namespace llvm {
- 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 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";
- }
- 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);
- }
- } // namespace llvm
- struct ScopDetectionAnalysisGraphTraits {
- static ScopDetection *getGraph(ScopDetectionWrapperPass *Analysis) {
- return &Analysis->getSD();
- }
- };
- struct ScopViewerWrapperPass
- : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
- ScopDetection *,
- ScopDetectionAnalysisGraphTraits> {
- static char ID;
- ScopViewerWrapperPass()
- : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
- ScopDetection *,
- ScopDetectionAnalysisGraphTraits>(
- "scops", ID) {}
- bool processFunction(Function &F, ScopDetectionWrapperPass &SD) override {
- if (ViewFilter != "" && !F.getName().count(ViewFilter))
- return false;
- if (ViewAll)
- return true;
- // Check that at least one scop was detected.
- return std::distance(SD.getSD().begin(), SD.getSD().end()) > 0;
- }
- };
- char ScopViewerWrapperPass::ID = 0;
- struct ScopOnlyViewerWrapperPass
- : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
- ScopDetection *,
- ScopDetectionAnalysisGraphTraits> {
- static char ID;
- ScopOnlyViewerWrapperPass()
- : DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false,
- ScopDetection *,
- ScopDetectionAnalysisGraphTraits>(
- "scopsonly", ID) {}
- };
- char ScopOnlyViewerWrapperPass::ID = 0;
- struct ScopPrinterWrapperPass
- : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false,
- ScopDetection *,
- ScopDetectionAnalysisGraphTraits> {
- static char ID;
- ScopPrinterWrapperPass()
- : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false,
- ScopDetection *,
- ScopDetectionAnalysisGraphTraits>(
- "scops", ID) {}
- };
- char ScopPrinterWrapperPass::ID = 0;
- struct ScopOnlyPrinterWrapperPass
- : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true,
- ScopDetection *,
- ScopDetectionAnalysisGraphTraits> {
- static char ID;
- ScopOnlyPrinterWrapperPass()
- : DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true,
- ScopDetection *,
- ScopDetectionAnalysisGraphTraits>(
- "scopsonly", ID) {}
- };
- char ScopOnlyPrinterWrapperPass::ID = 0;
- static RegisterPass<ScopViewerWrapperPass> X("view-scops",
- "Polly - View Scops of function");
- static RegisterPass<ScopOnlyViewerWrapperPass>
- Y("view-scops-only",
- "Polly - View Scops of function (with no function bodies)");
- static RegisterPass<ScopPrinterWrapperPass>
- M("dot-scops", "Polly - Print Scops of function");
- static RegisterPass<ScopOnlyPrinterWrapperPass>
- N("dot-scops-only",
- "Polly - Print Scops of function (with no function bodies)");
- Pass *polly::createDOTViewerWrapperPass() {
- return new ScopViewerWrapperPass();
- }
- Pass *polly::createDOTOnlyViewerWrapperPass() {
- return new ScopOnlyViewerWrapperPass();
- }
- Pass *polly::createDOTPrinterWrapperPass() {
- return new ScopPrinterWrapperPass();
- }
- 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;
- }
|