1 //===- GraphPrinter.cpp - Create a DOT output describing the Scop. --------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // Create a DOT output describing the Scop. 11 // 12 // For each function a dot file is created that shows the control flow graph of 13 // the function and highlights the detected Scops. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "polly/LinkAllPasses.h" 18 #include "polly/ScopDetection.h" 19 #include "llvm/Analysis/DOTGraphTraitsPass.h" 20 #include "llvm/Analysis/RegionInfo.h" 21 #include "llvm/Analysis/RegionIterator.h" 22 23 using namespace polly; 24 using namespace llvm; 25 26 namespace llvm { 27 template <> 28 struct GraphTraits<ScopDetection *> : public GraphTraits<RegionInfo *> { 29 static NodeType *getEntryNode(ScopDetection *SD) { 30 return GraphTraits<RegionInfo *>::getEntryNode(SD->getRI()); 31 } 32 static nodes_iterator nodes_begin(ScopDetection *SD) { 33 return nodes_iterator::begin(getEntryNode(SD)); 34 } 35 static nodes_iterator nodes_end(ScopDetection *SD) { 36 return nodes_iterator::end(getEntryNode(SD)); 37 } 38 }; 39 40 template <> struct DOTGraphTraits<RegionNode *> : public DefaultDOTGraphTraits { 41 DOTGraphTraits(bool isSimple = false) : DefaultDOTGraphTraits(isSimple) {} 42 43 std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) { 44 if (!Node->isSubRegion()) { 45 BasicBlock *BB = Node->getNodeAs<BasicBlock>(); 46 47 if (isSimple()) 48 return DOTGraphTraits<const Function *>::getSimpleNodeLabel( 49 BB, BB->getParent()); 50 else 51 return DOTGraphTraits<const Function *>::getCompleteNodeLabel( 52 BB, BB->getParent()); 53 } 54 55 return "Not implemented"; 56 } 57 }; 58 59 template <> 60 struct DOTGraphTraits<ScopDetection *> : public DOTGraphTraits<RegionNode *> { 61 DOTGraphTraits(bool isSimple = false) 62 : DOTGraphTraits<RegionNode *>(isSimple) {} 63 static std::string getGraphName(ScopDetection *SD) { return "Scop Graph"; } 64 65 std::string getEdgeAttributes(RegionNode *srcNode, 66 GraphTraits<RegionInfo *>::ChildIteratorType CI, 67 ScopDetection *SD) { 68 RegionNode *destNode = *CI; 69 70 if (srcNode->isSubRegion() || destNode->isSubRegion()) 71 return ""; 72 73 // In case of a backedge, do not use it to define the layout of the nodes. 74 BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>(); 75 BasicBlock *destBB = destNode->getNodeAs<BasicBlock>(); 76 77 RegionInfo *RI = SD->getRI(); 78 Region *R = RI->getRegionFor(destBB); 79 80 while (R && R->getParent()) 81 if (R->getParent()->getEntry() == destBB) 82 R = R->getParent(); 83 else 84 break; 85 86 if (R->getEntry() == destBB && R->contains(srcBB)) 87 return "constraint=false"; 88 89 return ""; 90 } 91 92 std::string getNodeLabel(RegionNode *Node, ScopDetection *SD) { 93 return DOTGraphTraits<RegionNode *>::getNodeLabel( 94 Node, SD->getRI()->getTopLevelRegion()); 95 } 96 97 static std::string escapeString(std::string String) { 98 std::string Escaped; 99 100 for (const auto &C : String) { 101 if (C == '"') 102 Escaped += '\\'; 103 104 Escaped += C; 105 } 106 return Escaped; 107 } 108 109 // Print the cluster of the subregions. This groups the single basic blocks 110 // and adds a different background color for each group. 111 static void printRegionCluster(const ScopDetection *SD, const Region *R, 112 raw_ostream &O, unsigned depth = 0) { 113 O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void *>(R) 114 << " {\n"; 115 std::string ErrorMessage = SD->regionIsInvalidBecause(R); 116 ErrorMessage = escapeString(ErrorMessage); 117 O.indent(2 * (depth + 1)) << "label = \"" << ErrorMessage << "\";\n"; 118 119 if (SD->isMaxRegionInScop(*R)) { 120 O.indent(2 * (depth + 1)) << "style = filled;\n"; 121 122 // Set color to green. 123 O.indent(2 * (depth + 1)) << "color = 3"; 124 } else { 125 O.indent(2 * (depth + 1)) << "style = solid;\n"; 126 127 int color = (R->getDepth() * 2 % 12) + 1; 128 129 // We do not want green again. 130 if (color == 3) 131 color = 6; 132 133 O.indent(2 * (depth + 1)) << "color = " << color << "\n"; 134 } 135 136 for (const auto &SubRegion : *R) 137 printRegionCluster(SD, SubRegion.get(), O, depth + 1); 138 139 RegionInfo *RI = R->getRegionInfo(); 140 141 for (const auto &BB : R->blocks()) 142 if (RI->getRegionFor(BB) == R) 143 O.indent(2 * (depth + 1)) 144 << "Node" 145 << static_cast<void *>(RI->getTopLevelRegion()->getBBNode(BB)) 146 << ";\n"; 147 148 O.indent(2 * depth) << "}\n"; 149 } 150 static void addCustomGraphFeatures(const ScopDetection *SD, 151 GraphWriter<ScopDetection *> &GW) { 152 raw_ostream &O = GW.getOStream(); 153 O << "\tcolorscheme = \"paired12\"\n"; 154 printRegionCluster(SD, SD->getRI()->getTopLevelRegion(), O, 4); 155 } 156 }; 157 158 } // end namespace llvm 159 160 struct ScopViewer : public DOTGraphTraitsViewer<ScopDetection, false> { 161 static char ID; 162 ScopViewer() : DOTGraphTraitsViewer<ScopDetection, false>("scops", ID) {} 163 }; 164 char ScopViewer::ID = 0; 165 166 struct ScopOnlyViewer : public DOTGraphTraitsViewer<ScopDetection, true> { 167 static char ID; 168 ScopOnlyViewer() 169 : DOTGraphTraitsViewer<ScopDetection, true>("scopsonly", ID) {} 170 }; 171 char ScopOnlyViewer::ID = 0; 172 173 struct ScopPrinter : public DOTGraphTraitsPrinter<ScopDetection, false> { 174 static char ID; 175 ScopPrinter() : DOTGraphTraitsPrinter<ScopDetection, false>("scops", ID) {} 176 }; 177 char ScopPrinter::ID = 0; 178 179 struct ScopOnlyPrinter : public DOTGraphTraitsPrinter<ScopDetection, true> { 180 static char ID; 181 ScopOnlyPrinter() 182 : DOTGraphTraitsPrinter<ScopDetection, true>("scopsonly", ID) {} 183 }; 184 char ScopOnlyPrinter::ID = 0; 185 186 static RegisterPass<ScopViewer> X("view-scops", 187 "Polly - View Scops of function"); 188 189 static RegisterPass<ScopOnlyViewer> 190 Y("view-scops-only", 191 "Polly - View Scops of function (with no function bodies)"); 192 193 static RegisterPass<ScopPrinter> M("dot-scops", 194 "Polly - Print Scops of function"); 195 196 static RegisterPass<ScopOnlyPrinter> 197 N("dot-scops-only", 198 "Polly - Print Scops of function (with no function bodies)"); 199 200 Pass *polly::createDOTViewerPass() { return new ScopViewer(); } 201 202 Pass *polly::createDOTOnlyViewerPass() { return new ScopOnlyViewer(); } 203 204 Pass *polly::createDOTPrinterPass() { return new ScopPrinter(); } 205 206 Pass *polly::createDOTOnlyPrinterPass() { return new ScopOnlyPrinter(); } 207