153 lines · cpp
1//===- GraphPrinter.cpp - Create a DOT output describing the Scop. --------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Create a DOT output describing the Scop.10//11// For each function a dot file is created that shows the control flow graph of12// the function and highlights the detected Scops.13//14//===----------------------------------------------------------------------===//15 16#include "polly/ScopGraphPrinter.h"17#include "polly/ScopDetection.h"18#include "llvm/Support/CommandLine.h"19 20using namespace polly;21using namespace llvm;22 23namespace polly {24std::string ViewFilter;25bool ViewAll;26} // namespace polly27 28static cl::opt<std::string, true>29 XViewFilter("polly-view-only",30 cl::desc("Only view functions that match this pattern"),31 cl::location(ViewFilter), cl::Hidden, cl::init(""));32 33static cl::opt<bool, true>34 XViewAll("polly-view-all",35 cl::desc("Also show functions without any scops"),36 cl::location(ViewAll), cl::Hidden, cl::init(false));37 38namespace llvm {39 40std::string DOTGraphTraits<ScopDetection *>::getEdgeAttributes(41 RegionNode *srcNode, GraphTraits<RegionInfo *>::ChildIteratorType CI,42 ScopDetection *SD) {43 RegionNode *destNode = *CI;44 45 if (srcNode->isSubRegion() || destNode->isSubRegion())46 return "";47 48 // In case of a backedge, do not use it to define the layout of the nodes.49 BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();50 BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();51 52 RegionInfo *RI = SD->getRI();53 Region *R = RI->getRegionFor(destBB);54 55 while (R && R->getParent())56 if (R->getParent()->getEntry() == destBB)57 R = R->getParent();58 else59 break;60 61 if (R && R->getEntry() == destBB && R->contains(srcBB))62 return "constraint=false";63 64 return "";65}66 67std::string68DOTGraphTraits<ScopDetection *>::escapeString(llvm::StringRef String) {69 std::string Escaped;70 71 for (const auto &C : String) {72 if (C == '"')73 Escaped += '\\';74 75 Escaped += C;76 }77 return Escaped;78}79 80void DOTGraphTraits<ScopDetection *>::printRegionCluster(ScopDetection *SD,81 const Region *R,82 raw_ostream &O,83 unsigned depth) {84 O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R)85 << " {\n";86 unsigned LineBegin, LineEnd;87 std::string FileName;88 89 getDebugLocation(R, LineBegin, LineEnd, FileName);90 91 std::string Location;92 if (LineBegin != (unsigned)-1) {93 Location = escapeString(FileName + ":" + std::to_string(LineBegin) + "-" +94 std::to_string(LineEnd) + "\n");95 }96 97 std::string ErrorMessage = SD->regionIsInvalidBecause(R);98 ErrorMessage = escapeString(ErrorMessage);99 O.indent(2 * (depth + 1))100 << "label = \"" << Location << ErrorMessage << "\";\n";101 102 if (SD->isMaxRegionInScop(*R)) {103 O.indent(2 * (depth + 1)) << "style = filled;\n";104 105 // Set color to green.106 O.indent(2 * (depth + 1)) << "color = 3";107 } else {108 O.indent(2 * (depth + 1)) << "style = solid;\n";109 110 int color = (R->getDepth() * 2 % 12) + 1;111 112 // We do not want green again.113 if (color == 3)114 color = 6;115 116 O.indent(2 * (depth + 1)) << "color = " << color << "\n";117 }118 119 for (const auto &SubRegion : *R)120 printRegionCluster(SD, SubRegion.get(), O, depth + 1);121 122 RegionInfo *RI = R->getRegionInfo();123 124 for (BasicBlock *BB : R->blocks())125 if (RI->getRegionFor(BB) == R)126 O.indent(2 * (depth + 1))127 << "Node"128 << static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB))129 << ";\n";130 131 O.indent(2 * depth) << "}\n";132}133 134void DOTGraphTraits<ScopDetection *>::addCustomGraphFeatures(135 ScopDetection *SD, GraphWriter<ScopDetection *> &GW) {136 raw_ostream &O = GW.getOStream();137 O << "\tcolorscheme = \"paired12\"\n";138 printRegionCluster(SD, SD->getRI()->getTopLevelRegion(), O, 4);139}140 141} // namespace llvm142 143bool ScopViewer::processFunction(Function &F, const ScopDetection &SD) {144 if (ViewFilter != "" && !F.getName().count(ViewFilter))145 return false;146 147 if (ViewAll)148 return true;149 150 // Check that at least one scop was detected.151 return std::distance(SD.begin(), SD.end()) > 0;152}153