1f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser//===- RegionPrinter.cpp - Print regions tree pass ------------------------===// 2f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser// 3f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser// The LLVM Compiler Infrastructure 4f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser// 5f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser// This file is distributed under the University of Illinois Open Source 6f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser// License. See LICENSE.TXT for details. 7f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser// 8f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser//===----------------------------------------------------------------------===// 9f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser// Print out the region tree of a function using dotty/graphviz. 10f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser//===----------------------------------------------------------------------===// 11f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 12d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Analysis/Passes.h" 13d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/DepthFirstIterator.h" 14d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/PostOrderIterator.h" 15d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/ADT/Statistic.h" 16d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Analysis/DOTGraphTraitsPass.h" 17f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser#include "llvm/Analysis/RegionInfo.h" 18f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser#include "llvm/Analysis/RegionIterator.h" 19f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser#include "llvm/Analysis/RegionPrinter.h" 20f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser#include "llvm/Support/CommandLine.h" 21d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth#include "llvm/Support/Debug.h" 22f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser#include "llvm/Support/raw_ostream.h" 23f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 24f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserusing namespace llvm; 25f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 26f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser//===----------------------------------------------------------------------===// 27f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser/// onlySimpleRegion - Show only the simple regions in the RegionViewer. 28f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserstatic cl::opt<bool> 29f96b0063674e6bf72da5429bd49097e33c2325c7Tobias GrosseronlySimpleRegions("only-simple-regions", 30f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser cl::desc("Show only simple regions in the graphviz viewer"), 31f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser cl::Hidden, 32f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser cl::init(false)); 33f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 34f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grossernamespace llvm { 35f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grossertemplate<> 36f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserstruct DOTGraphTraits<RegionNode*> : public DefaultDOTGraphTraits { 37f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 38f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser DOTGraphTraits (bool isSimple=false) 39f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser : DefaultDOTGraphTraits(isSimple) {} 40f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 41f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser std::string getNodeLabel(RegionNode *Node, RegionNode *Graph) { 42f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 43f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser if (!Node->isSubRegion()) { 44f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser BasicBlock *BB = Node->getNodeAs<BasicBlock>(); 45f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 46f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser if (isSimple()) 47f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return DOTGraphTraits<const Function*> 48f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser ::getSimpleNodeLabel(BB, BB->getParent()); 49f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser else 50f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return DOTGraphTraits<const Function*> 51f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser ::getCompleteNodeLabel(BB, BB->getParent()); 52f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser } 53f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 54f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return "Not implemented"; 55f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser } 56f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser}; 57f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 58f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grossertemplate<> 59f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserstruct DOTGraphTraits<RegionInfo*> : public DOTGraphTraits<RegionNode*> { 60f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 61f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser DOTGraphTraits (bool isSimple=false) 62f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser : DOTGraphTraits<RegionNode*>(isSimple) {} 63f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 64f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser static std::string getGraphName(RegionInfo *DT) { 65f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return "Region Graph"; 66f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser } 67f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 68f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser std::string getNodeLabel(RegionNode *Node, RegionInfo *G) { 69f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return DOTGraphTraits<RegionNode*>::getNodeLabel(Node, 70f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser G->getTopLevelRegion()); 71f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser } 72f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 733091c92eedfbaeec352413b34f78f48889960361Tobias Grosser std::string getEdgeAttributes(RegionNode *srcNode, 743091c92eedfbaeec352413b34f78f48889960361Tobias Grosser GraphTraits<RegionInfo*>::ChildIteratorType CI, RegionInfo *RI) { 753091c92eedfbaeec352413b34f78f48889960361Tobias Grosser 763091c92eedfbaeec352413b34f78f48889960361Tobias Grosser RegionNode *destNode = *CI; 773091c92eedfbaeec352413b34f78f48889960361Tobias Grosser 783091c92eedfbaeec352413b34f78f48889960361Tobias Grosser if (srcNode->isSubRegion() || destNode->isSubRegion()) 793091c92eedfbaeec352413b34f78f48889960361Tobias Grosser return ""; 803091c92eedfbaeec352413b34f78f48889960361Tobias Grosser 813091c92eedfbaeec352413b34f78f48889960361Tobias Grosser // In case of a backedge, do not use it to define the layout of the nodes. 823091c92eedfbaeec352413b34f78f48889960361Tobias Grosser BasicBlock *srcBB = srcNode->getNodeAs<BasicBlock>(); 833091c92eedfbaeec352413b34f78f48889960361Tobias Grosser BasicBlock *destBB = destNode->getNodeAs<BasicBlock>(); 843091c92eedfbaeec352413b34f78f48889960361Tobias Grosser 853091c92eedfbaeec352413b34f78f48889960361Tobias Grosser Region *R = RI->getRegionFor(destBB); 863091c92eedfbaeec352413b34f78f48889960361Tobias Grosser 873091c92eedfbaeec352413b34f78f48889960361Tobias Grosser while (R && R->getParent()) 883091c92eedfbaeec352413b34f78f48889960361Tobias Grosser if (R->getParent()->getEntry() == destBB) 893091c92eedfbaeec352413b34f78f48889960361Tobias Grosser R = R->getParent(); 903091c92eedfbaeec352413b34f78f48889960361Tobias Grosser else 913091c92eedfbaeec352413b34f78f48889960361Tobias Grosser break; 923091c92eedfbaeec352413b34f78f48889960361Tobias Grosser 933091c92eedfbaeec352413b34f78f48889960361Tobias Grosser if (R->getEntry() == destBB && R->contains(srcBB)) 943091c92eedfbaeec352413b34f78f48889960361Tobias Grosser return "constraint=false"; 953091c92eedfbaeec352413b34f78f48889960361Tobias Grosser 963091c92eedfbaeec352413b34f78f48889960361Tobias Grosser return ""; 973091c92eedfbaeec352413b34f78f48889960361Tobias Grosser } 983091c92eedfbaeec352413b34f78f48889960361Tobias Grosser 99f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser // Print the cluster of the subregions. This groups the single basic blocks 100f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser // and adds a different background color for each group. 101f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser static void printRegionCluster(const Region *R, GraphWriter<RegionInfo*> &GW, 102f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser unsigned depth = 0) { 103f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser raw_ostream &O = GW.getOStream(); 104f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser O.indent(2 * depth) << "subgraph cluster_" << static_cast<const void*>(R) 105f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser << " {\n"; 106f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser O.indent(2 * (depth + 1)) << "label = \"\";\n"; 107f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 108f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser if (!onlySimpleRegions || R->isSimple()) { 109f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser O.indent(2 * (depth + 1)) << "style = filled;\n"; 110f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser O.indent(2 * (depth + 1)) << "color = " 111f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser << ((R->getDepth() * 2 % 12) + 1) << "\n"; 112f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 113f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser } else { 114f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser O.indent(2 * (depth + 1)) << "style = solid;\n"; 115f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser O.indent(2 * (depth + 1)) << "color = " 116f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser << ((R->getDepth() * 2 % 12) + 2) << "\n"; 117f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser } 118f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 119f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser for (Region::const_iterator RI = R->begin(), RE = R->end(); RI != RE; ++RI) 120f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser printRegionCluster(*RI, GW, depth + 1); 121f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 122f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser RegionInfo *RI = R->getRegionInfo(); 123f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 124f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser for (Region::const_block_iterator BI = R->block_begin(), 1257c52c97a2232756bbcc2fb4e664892bdb8b2d90cChandler Carruth BE = R->block_end(); BI != BE; ++BI) 1267c52c97a2232756bbcc2fb4e664892bdb8b2d90cChandler Carruth if (RI->getRegionFor(*BI) == R) 127f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser O.indent(2 * (depth + 1)) << "Node" 1287c52c97a2232756bbcc2fb4e664892bdb8b2d90cChandler Carruth << static_cast<const void*>(RI->getTopLevelRegion()->getBBNode(*BI)) 129f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser << ";\n"; 130f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 131f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser O.indent(2 * depth) << "}\n"; 132f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser } 133f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 134f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser static void addCustomGraphFeatures(const RegionInfo* RI, 135f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser GraphWriter<RegionInfo*> &GW) { 136f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser raw_ostream &O = GW.getOStream(); 137f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser O << "\tcolorscheme = \"paired12\"\n"; 138f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser printRegionCluster(RI->getTopLevelRegion(), GW, 4); 139f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser } 140f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser}; 141f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser} //end namespace llvm 142f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 143f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grossernamespace { 144f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 145f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserstruct RegionViewer 146f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser : public DOTGraphTraitsViewer<RegionInfo, false> { 147f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser static char ID; 148081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson RegionViewer() : DOTGraphTraitsViewer<RegionInfo, false>("reg", ID){ 149081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson initializeRegionViewerPass(*PassRegistry::getPassRegistry()); 150081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson } 151f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser}; 152f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserchar RegionViewer::ID = 0; 153f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 154f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserstruct RegionOnlyViewer 155f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser : public DOTGraphTraitsViewer<RegionInfo, true> { 156f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser static char ID; 157081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson RegionOnlyViewer() : DOTGraphTraitsViewer<RegionInfo, true>("regonly", ID) { 158081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson initializeRegionOnlyViewerPass(*PassRegistry::getPassRegistry()); 159081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson } 160f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser}; 161f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserchar RegionOnlyViewer::ID = 0; 162f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 163f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserstruct RegionPrinter 164f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser : public DOTGraphTraitsPrinter<RegionInfo, false> { 165f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser static char ID; 166f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser RegionPrinter() : 167081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson DOTGraphTraitsPrinter<RegionInfo, false>("reg", ID) { 168081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson initializeRegionPrinterPass(*PassRegistry::getPassRegistry()); 169081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson } 170f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser}; 17171802344fcb224a89e4e636c1ec47f3730969be7Owen Andersonchar RegionPrinter::ID = 0; 172f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser} //end anonymous namespace 173f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 174f96b0063674e6bf72da5429bd49097e33c2325c7Tobias GrosserINITIALIZE_PASS(RegionPrinter, "dot-regions", 175ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson "Print regions of function to 'dot' file", true, true) 176f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 17771802344fcb224a89e4e636c1ec47f3730969be7Owen AndersonINITIALIZE_PASS(RegionViewer, "view-regions", "View regions of function", 178ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson true, true) 17971802344fcb224a89e4e636c1ec47f3730969be7Owen Anderson 18071802344fcb224a89e4e636c1ec47f3730969be7Owen AndersonINITIALIZE_PASS(RegionOnlyViewer, "view-regions-only", 18171802344fcb224a89e4e636c1ec47f3730969be7Owen Anderson "View regions of function (with no function bodies)", 182ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson true, true) 18371802344fcb224a89e4e636c1ec47f3730969be7Owen Anderson 184811edc1f1a0672d28cd7c938e478a92543e68a51Dan Gohmannamespace { 185811edc1f1a0672d28cd7c938e478a92543e68a51Dan Gohman 186f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserstruct RegionOnlyPrinter 187f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser : public DOTGraphTraitsPrinter<RegionInfo, true> { 188f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser static char ID; 189f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser RegionOnlyPrinter() : 190081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson DOTGraphTraitsPrinter<RegionInfo, true>("reg", ID) { 191081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson initializeRegionOnlyPrinterPass(*PassRegistry::getPassRegistry()); 192081c34b725980f995be9080eaec24cd3dfaaf065Owen Anderson } 193f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser}; 194f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 195811edc1f1a0672d28cd7c938e478a92543e68a51Dan Gohman} 196811edc1f1a0672d28cd7c938e478a92543e68a51Dan Gohman 197f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosserchar RegionOnlyPrinter::ID = 0; 198f96b0063674e6bf72da5429bd49097e33c2325c7Tobias GrosserINITIALIZE_PASS(RegionOnlyPrinter, "dot-regions-only", 199f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser "Print regions of function to 'dot' file " 200f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser "(with no function bodies)", 201ce665bd2e2b581ab0858d1afe359192bac96b868Owen Anderson true, true) 202f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 203f96b0063674e6bf72da5429bd49097e33c2325c7Tobias GrosserFunctionPass* llvm::createRegionViewerPass() { 204f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return new RegionViewer(); 205f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser} 206f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 207f96b0063674e6bf72da5429bd49097e33c2325c7Tobias GrosserFunctionPass* llvm::createRegionOnlyViewerPass() { 208f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return new RegionOnlyViewer(); 209f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser} 210f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 211f96b0063674e6bf72da5429bd49097e33c2325c7Tobias GrosserFunctionPass* llvm::createRegionPrinterPass() { 212f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return new RegionPrinter(); 213f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser} 214f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 215f96b0063674e6bf72da5429bd49097e33c2325c7Tobias GrosserFunctionPass* llvm::createRegionOnlyPrinterPass() { 216f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser return new RegionOnlyPrinter(); 217f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser} 218f96b0063674e6bf72da5429bd49097e33c2325c7Tobias Grosser 219