brintos

brintos / llvm-project-archived public Read only

0
0
Text · 8.2 KiB · 33e073b Raw
249 lines · cpp
1//===- RegionPrinter.cpp - Print regions tree pass ------------------------===//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// Print out the region tree of a function using dotty/graphviz.9//===----------------------------------------------------------------------===//10 11#include "llvm/Analysis/RegionPrinter.h"12#include "llvm/Analysis/DOTGraphTraitsPass.h"13#include "llvm/Analysis/RegionInfo.h"14#include "llvm/Analysis/RegionIterator.h"15#include "llvm/InitializePasses.h"16#include "llvm/Support/CommandLine.h"17#include "llvm/Support/raw_ostream.h"18#ifndef NDEBUG19#include "llvm/IR/LegacyPassManager.h"20#endif21 22using namespace llvm;23 24//===----------------------------------------------------------------------===//25/// onlySimpleRegion - Show only the simple regions in the RegionViewer.26static cl::opt<bool>27onlySimpleRegions("only-simple-regions",28                  cl::desc("Show only simple regions in the graphviz viewer"),29                  cl::Hidden,30                  cl::init(false));31 32std::string33llvm::DOTGraphTraits<RegionNode *>::getNodeLabel(RegionNode *Node,34                                                 RegionNode *Graph) {35  if (!Node->isSubRegion()) {36    BasicBlock *BB = Node->getNodeAs<BasicBlock>();37 38    if (isSimple())39      return DOTGraphTraits<DOTFuncInfo *>::getSimpleNodeLabel(BB, nullptr);40    else41      return DOTGraphTraits<DOTFuncInfo *>::getCompleteNodeLabel(BB, nullptr);42  }43 44  return "Not implemented";45}46 47template <>48struct llvm::DOTGraphTraits<RegionInfo *>49    : public llvm::DOTGraphTraits<RegionNode *> {50 51  DOTGraphTraits (bool isSimple = false)52    : DOTGraphTraits<RegionNode*>(isSimple) {}53 54  static std::string getGraphName(const RegionInfo *) { return "Region Graph"; }55 56  std::string getNodeLabel(RegionNode *Node, RegionInfo *G) {57    return DOTGraphTraits<RegionNode *>::getNodeLabel(58        Node, reinterpret_cast<RegionNode *>(G->getTopLevelRegion()));59  }60 61  std::string getEdgeAttributes(RegionNode *srcNode,62                                GraphTraits<RegionInfo *>::ChildIteratorType CI,63                                RegionInfo *G) {64    RegionNode *destNode = *CI;65 66    if (srcNode->isSubRegion() || destNode->isSubRegion())67      return "";68 69    // In case of a backedge, do not use it to define the layout of the nodes.70    BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>();71    BasicBlock *destBB = destNode->getNodeAs<BasicBlock>();72 73    Region *R = G->getRegionFor(destBB);74 75    while (R && R->getParent())76      if (R->getParent()->getEntry() == destBB)77        R = R->getParent();78      else79        break;80 81    if (R && R->getEntry() == destBB && R->contains(srcBB))82      return "constraint=false";83 84    return "";85  }86 87  // Print the cluster of the subregions. This groups the single basic blocks88  // and adds a different background color for each group.89  static void printRegionCluster(const Region &R, GraphWriter<RegionInfo *> &GW,90                                 unsigned depth = 0) {91    raw_ostream &O = GW.getOStream();92    O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(&R)93      << " {\n";94    O.indent(2 * (depth + 1)) << "label = \"\";\n";95 96    if (!onlySimpleRegions || R.isSimple()) {97      O.indent(2 * (depth + 1)) << "style = filled;\n";98      O.indent(2 * (depth + 1)) << "color = "99        << ((R.getDepth() * 2 % 12) + 1) << "\n";100 101    } else {102      O.indent(2 * (depth + 1)) << "style = solid;\n";103      O.indent(2 * (depth + 1)) << "color = "104        << ((R.getDepth() * 2 % 12) + 2) << "\n";105    }106 107    for (const auto &RI : R)108      printRegionCluster(*RI, GW, depth + 1);109 110    const RegionInfo &RI = *static_cast<const RegionInfo*>(R.getRegionInfo());111 112    for (auto *BB : R.blocks())113      if (RI.getRegionFor(BB) == &R)114        O.indent(2 * (depth + 1)) << "Node"115          << static_cast<const void*>(RI.getTopLevelRegion()->getBBNode(BB))116          << ";\n";117 118    O.indent(2 * depth) << "}\n";119  }120 121  static void addCustomGraphFeatures(const RegionInfo *G,122                                     GraphWriter<RegionInfo *> &GW) {123    raw_ostream &O = GW.getOStream();124    O << "\tcolorscheme = \"paired12\"\n";125    printRegionCluster(*G->getTopLevelRegion(), GW, 4);126  }127};128 129namespace {130 131struct RegionInfoPassGraphTraits {132  static RegionInfo *getGraph(RegionInfoPass *RIP) {133    return &RIP->getRegionInfo();134  }135};136 137struct RegionPrinter138    : public DOTGraphTraitsPrinterWrapperPass<139          RegionInfoPass, false, RegionInfo *, RegionInfoPassGraphTraits> {140  static char ID;141  RegionPrinter()142      : DOTGraphTraitsPrinterWrapperPass<RegionInfoPass, false, RegionInfo *,143                                         RegionInfoPassGraphTraits>("reg", ID) {144  }145};146char RegionPrinter::ID = 0;147 148struct RegionOnlyPrinter149    : public DOTGraphTraitsPrinterWrapperPass<150          RegionInfoPass, true, RegionInfo *, RegionInfoPassGraphTraits> {151  static char ID;152  RegionOnlyPrinter()153      : DOTGraphTraitsPrinterWrapperPass<RegionInfoPass, true, RegionInfo *,154                                         RegionInfoPassGraphTraits>("reg", ID) {155  }156};157char RegionOnlyPrinter::ID = 0;158 159struct RegionViewer160    : public DOTGraphTraitsViewerWrapperPass<161          RegionInfoPass, false, RegionInfo *, RegionInfoPassGraphTraits> {162  static char ID;163  RegionViewer()164      : DOTGraphTraitsViewerWrapperPass<RegionInfoPass, false, RegionInfo *,165                                        RegionInfoPassGraphTraits>("reg", ID) {}166};167char RegionViewer::ID = 0;168 169struct RegionOnlyViewer170    : public DOTGraphTraitsViewerWrapperPass<RegionInfoPass, true, RegionInfo *,171                                             RegionInfoPassGraphTraits> {172  static char ID;173  RegionOnlyViewer()174      : DOTGraphTraitsViewerWrapperPass<RegionInfoPass, true, RegionInfo *,175                                        RegionInfoPassGraphTraits>("regonly",176                                                                   ID) {}177};178char RegionOnlyViewer::ID = 0;179 180} //end anonymous namespace181 182INITIALIZE_PASS(RegionPrinter, "dot-regions",183                "Print regions of function to 'dot' file", true, true)184 185INITIALIZE_PASS(186    RegionOnlyPrinter, "dot-regions-only",187    "Print regions of function to 'dot' file (with no function bodies)", true,188    true)189 190INITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function",191                true, true)192 193INITIALIZE_PASS(RegionOnlyViewer, "view-regions-only",194                "View regions of function (with no function bodies)",195                true, true)196 197FunctionPass *llvm::createRegionPrinterPass() { return new RegionPrinter(); }198 199FunctionPass *llvm::createRegionOnlyPrinterPass() {200  return new RegionOnlyPrinter();201}202 203FunctionPass* llvm::createRegionViewerPass() {204  return new RegionViewer();205}206 207FunctionPass* llvm::createRegionOnlyViewerPass() {208  return new RegionOnlyViewer();209}210 211#ifndef NDEBUG212static void viewRegionInfo(RegionInfo *RI, bool ShortNames) {213  assert(RI && "Argument must be non-null");214 215  llvm::Function *F = RI->getTopLevelRegion()->getEntry()->getParent();216  std::string GraphName = DOTGraphTraits<RegionInfo *>::getGraphName(RI);217 218  llvm::ViewGraph(RI, "reg", ShortNames,219                  Twine(GraphName) + " for '" + F->getName() + "' function");220}221 222static void invokeFunctionPass(const Function *F, FunctionPass *ViewerPass) {223  assert(F && "Argument must be non-null");224  assert(!F->isDeclaration() && "Function must have an implementation");225 226  // The viewer and analysis passes do not modify anything, so we can safely227  // remove the const qualifier228  auto NonConstF = const_cast<Function *>(F);229 230  llvm::legacy::FunctionPassManager FPM(NonConstF->getParent());231  FPM.add(ViewerPass);232  FPM.doInitialization();233  FPM.run(*NonConstF);234  FPM.doFinalization();235}236 237void llvm::viewRegion(RegionInfo *RI) { viewRegionInfo(RI, false); }238 239void llvm::viewRegion(const Function *F) {240  invokeFunctionPass(F, createRegionViewerPass());241}242 243void llvm::viewRegionOnly(RegionInfo *RI) { viewRegionInfo(RI, true); }244 245void llvm::viewRegionOnly(const Function *F) {246  invokeFunctionPass(F, createRegionOnlyViewerPass());247}248#endif249