Expand Up
@@ -13,12 +13,9 @@
//
// ===----------------------------------------------------------------------===//
#include " polly/ScopGraphPrinter.h"
#include " polly/LinkAllPasses.h"
#include " polly/ScopDetection.h"
#include " polly/Support/ScopLocation.h"
#include " llvm/Analysis/DOTGraphTraitsPass.h"
#include " llvm/Analysis/RegionInfo.h"
#include " llvm/Analysis/RegionIterator.h"
#include " llvm/Support/CommandLine.h"
using namespace polly ;
Expand All
@@ -33,175 +30,126 @@ static cl::opt<bool> ViewAll("polly-view-all",
cl::Hidden, cl::init(false ), cl::ZeroOrMore);
namespace llvm {
template <>
struct GraphTraits <ScopDetection *> : public GraphTraits<RegionInfo *> {
static NodeRef getEntryNode (ScopDetection *SD) {
return GraphTraits<RegionInfo *>::getEntryNode (SD->getRI ());
}
static nodes_iterator nodes_begin (ScopDetection *SD) {
return nodes_iterator::begin (getEntryNode (SD));
}
static nodes_iterator nodes_end (ScopDetection *SD) {
return nodes_iterator::end (getEntryNode (SD));
}
};
template <>
struct GraphTraits <ScopDetectionWrapperPass *>
: public GraphTraits<ScopDetection *> {
static NodeRef getEntryNode (ScopDetectionWrapperPass *P) {
return GraphTraits<ScopDetection *>::getEntryNode (&P->getSD ());
}
static nodes_iterator nodes_begin (ScopDetectionWrapperPass *P) {
return nodes_iterator::begin (getEntryNode (P));
}
static nodes_iterator nodes_end (ScopDetectionWrapperPass *P) {
return nodes_iterator::end (getEntryNode (P));
}
};
template <> struct DOTGraphTraits <RegionNode *> : public DefaultDOTGraphTraits {
DOTGraphTraits (bool isSimple = false ) : DefaultDOTGraphTraits(isSimple) {}
std::string getNodeLabel (RegionNode *Node, RegionNode *Graph) {
if (!Node->isSubRegion ()) {
BasicBlock *BB = Node->getNodeAs <BasicBlock>();
if (isSimple ())
return DOTGraphTraits<DOTFuncInfo *>::getSimpleNodeLabel (BB, nullptr );
else
return DOTGraphTraits<DOTFuncInfo *>::getCompleteNodeLabel (BB, nullptr );
}
return " Not implemented" ;
}
};
std::string DOTGraphTraits<ScopDetection *>::getEdgeAttributes(
RegionNode *srcNode, GraphTraits<RegionInfo *>::ChildIteratorType CI,
ScopDetection *SD) {
RegionNode *destNode = *CI;
template <>
struct DOTGraphTraits <ScopDetectionWrapperPass *>
: public DOTGraphTraits<RegionNode *> {
DOTGraphTraits (bool isSimple = false )
: DOTGraphTraits<RegionNode *>(isSimple) {}
static std::string getGraphName (ScopDetectionWrapperPass *SD) {
return " Scop Graph" ;
}
if (srcNode->isSubRegion () || destNode->isSubRegion ())
return " " ;
std::string getEdgeAttributes (RegionNode *srcNode,
GraphTraits<RegionInfo *>::ChildIteratorType CI,
ScopDetectionWrapperPass *P) {
RegionNode *destNode = *CI;
auto *SD = &P->getSD ();
// 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>();
if (srcNode-> isSubRegion () || destNode-> isSubRegion ())
return " " ;
RegionInfo *RI = SD-> getRI ();
Region *R = RI-> getRegionFor (destBB) ;
// 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>();
while (R && R->getParent ())
if (R->getParent ()->getEntry () == destBB)
R = R->getParent ();
else
break ;
RegionInfo *RI = SD-> getRI ();
Region *R = RI-> getRegionFor (destBB) ;
if (R && R-> getEntry () == destBB && R-> contains (srcBB))
return " constraint=false " ;
while (R && R->getParent ())
if (R->getParent ()->getEntry () == destBB)
R = R->getParent ();
else
break ;
return " " ;
}
if (R && R->getEntry () == destBB && R->contains (srcBB))
return " constraint=false" ;
std::string
DOTGraphTraits<ScopDetection *>::escapeString(llvm::StringRef String) {
std::string Escaped;
return " " ;
}
for (const auto &C : String) {
if (C == ' "' )
Escaped += ' \\ ' ;
std::string getNodeLabel (RegionNode *Node, ScopDetectionWrapperPass *P) {
return DOTGraphTraits<RegionNode *>::getNodeLabel (
Node, reinterpret_cast <RegionNode *>(
P->getSD ().getRI ()->getTopLevelRegion ()));
Escaped += C;
}
static std::string escapeString (std::string String) {
std::string Escaped;
for (const auto &C : String) {
if (C == ' "' )
Escaped += ' \\ ' ;
Escaped += C;
}
return Escaped;
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 " );
}
// Print the cluster of the subregions. This groups the single basic blocks
// and adds a different background color for each group.
static void printRegionCluster (ScopDetection *SD, const Region *R,
raw_ostream &O, unsigned depth = 0 ) {
O.indent (2 * depth) << " subgraph cluster_" << static_cast <const void *>(R)
<< " {\n " ;
unsigned LineBegin, LineEnd;
std::string FileName;
std::string ErrorMessage = SD->regionIsInvalidBecause (R);
ErrorMessage = escapeString (ErrorMessage);
O.indent (2 * (depth + 1 ))
<< " label = \" " << Location << ErrorMessage << " \" ;\n " ;
getDebugLocation (R, LineBegin, LineEnd, FileName);
if (SD->isMaxRegionInScop (*R)) {
O.indent (2 * (depth + 1 )) << " style = filled;\n " ;
std::string Location;
if (LineBegin != (unsigned )-1 ) {
Location = escapeString (FileName + " :" + std::to_string (LineBegin) + " -" +
std::to_string (LineEnd) + " \n " );
}
// Set color to green.
O.indent (2 * (depth + 1 )) << " color = 3" ;
} else {
O.indent (2 * (depth + 1 )) << " style = solid;\n " ;
std::string ErrorMessage = SD->regionIsInvalidBecause (R);
ErrorMessage = escapeString (ErrorMessage);
O.indent (2 * (depth + 1 ))
<< " label = \" " << Location << ErrorMessage << " \" ;\n " ;
int color = (R->getDepth () * 2 % 12 ) + 1 ;
if (SD->isMaxRegionInScop (*R)) {
O.indent (2 * (depth + 1 )) << " style = filled;\n " ;
// We do not want green again.
if (color == 3 )
color = 6 ;
// Set color to green.
O.indent (2 * (depth + 1 )) << " color = 3" ;
} else {
O.indent (2 * (depth + 1 )) << " style = solid;\n " ;
O.indent (2 * (depth + 1 )) << " color = " << color << " \n " ;
}
int color = (R->getDepth () * 2 % 12 ) + 1 ;
for (const auto &SubRegion : *R)
printRegionCluster (SD, SubRegion.get (), O, depth + 1 );
// We do not want green again.
if (color == 3 )
color = 6 ;
RegionInfo *RI = R->getRegionInfo ();
O.indent (2 * (depth + 1 )) << " color = " << color << " \n " ;
}
for (BasicBlock *BB : R->blocks ())
if (RI->getRegionFor (BB) == R)
O.indent (2 * (depth + 1 ))
<< " Node"
<< static_cast <void *>(RI->getTopLevelRegion ()->getBBNode (BB))
<< " ;\n " ;
for ( const auto &SubRegion : *R)
printRegionCluster (SD, SubRegion. get (), O, depth + 1 );
O. indent ( 2 * depth) << " } \n " ;
}
RegionInfo *RI = R->getRegionInfo ();
void DOTGraphTraits<ScopDetection *>::addCustomGraphFeatures(
ScopDetection *SD, GraphWriter<ScopDetection *> &GW) {
raw_ostream &O = GW.getOStream ();
O << " \t colorscheme = \" paired12\"\n " ;
printRegionCluster (SD, SD->getRI ()->getTopLevelRegion (), O, 4 );
}
for (BasicBlock *BB : R->blocks ())
if (RI->getRegionFor (BB) == R)
O.indent (2 * (depth + 1 ))
<< " Node"
<< static_cast <void *>(RI->getTopLevelRegion ()->getBBNode (BB))
<< " ;\n " ;
} // namespace llvm
O.indent (2 * depth) << " }\n " ;
}
static void
addCustomGraphFeatures (const ScopDetectionWrapperPass *SD,
GraphWriter<ScopDetectionWrapperPass *> &GW) {
raw_ostream &O = GW.getOStream ();
O << " \t colorscheme = \" paired12\"\n " ;
printRegionCluster (&SD->getSD (), SD->getSD ().getRI ()->getTopLevelRegion (),
O, 4 );
struct ScopDetectionAnalysisGraphTraits {
static ScopDetection *getGraph (ScopDetectionWrapperPass *Analysis) {
return &Analysis->getSD ();
}
};
} // end namespace llvm
struct ScopViewer
: public DOTGraphTraitsViewer<ScopDetectionWrapperPass, false > {
struct ScopViewerWrapperPass
: public DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false ,
ScopDetection *,
ScopDetectionAnalysisGraphTraits> {
static char ID;
ScopViewer ()
: DOTGraphTraitsViewer<ScopDetectionWrapperPass, false >(" scops" , ID) {}
ScopViewerWrapperPass ()
: DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false ,
ScopDetection *,
ScopDetectionAnalysisGraphTraits>(
" scops" , ID) {}
bool processFunction (Function &F, ScopDetectionWrapperPass &SD) override {
if (ViewFilter != " " && !F.getName ().count (ViewFilter))
return false ;
Expand All
@@ -213,51 +161,84 @@ struct ScopViewer
return std::distance (SD.getSD ().begin (), SD.getSD ().end ()) > 0 ;
}
};
char ScopViewer ::ID = 0 ;
char ScopViewerWrapperPass ::ID = 0 ;
struct ScopOnlyViewer
: public DOTGraphTraitsViewer<ScopDetectionWrapperPass, true > {
struct ScopOnlyViewerWrapperPass
: public DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false ,
ScopDetection *,
ScopDetectionAnalysisGraphTraits> {
static char ID;
ScopOnlyViewer ()
: DOTGraphTraitsViewer<ScopDetectionWrapperPass, true >(" scopsonly" , ID) {}
ScopOnlyViewerWrapperPass ()
: DOTGraphTraitsViewerWrapperPass<ScopDetectionWrapperPass, false ,
ScopDetection *,
ScopDetectionAnalysisGraphTraits>(
" scopsonly" , ID) {}
};
char ScopOnlyViewer ::ID = 0 ;
char ScopOnlyViewerWrapperPass ::ID = 0 ;
struct ScopPrinter
: public DOTGraphTraitsPrinter<ScopDetectionWrapperPass, false > {
struct ScopPrinterWrapperPass
: public DOTGraphTraitsPrinterWrapperPass<
ScopDetectionWrapperPass, false , ScopDetection *,
ScopDetectionAnalysisGraphTraits> {
static char ID;
ScopPrinter ()
: DOTGraphTraitsPrinter<ScopDetectionWrapperPass, false >(" scops" , ID) {}
ScopPrinterWrapperPass ()
: DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, false ,
ScopDetection *,
ScopDetectionAnalysisGraphTraits>(
" scops" , ID) {}
};
char ScopPrinter ::ID = 0 ;
char ScopPrinterWrapperPass ::ID = 0 ;
struct ScopOnlyPrinter
: public DOTGraphTraitsPrinter<ScopDetectionWrapperPass, true > {
struct ScopOnlyPrinterWrapperPass
: public DOTGraphTraitsPrinterWrapperPass<
ScopDetectionWrapperPass, true , ScopDetection *,
ScopDetectionAnalysisGraphTraits> {
static char ID;
ScopOnlyPrinter ()
: DOTGraphTraitsPrinter<ScopDetectionWrapperPass, true >(" scopsonly" , ID) {
}
ScopOnlyPrinterWrapperPass ()
: DOTGraphTraitsPrinterWrapperPass<ScopDetectionWrapperPass, true ,
ScopDetection *,
ScopDetectionAnalysisGraphTraits>(
" scopsonly" , ID) {}
};
char ScopOnlyPrinter ::ID = 0 ;
char ScopOnlyPrinterWrapperPass ::ID = 0 ;
static RegisterPass<ScopViewer > X (" view-scops" ,
" Polly - View Scops of function" );
static RegisterPass<ScopViewerWrapperPass > X (" view-scops" ,
" Polly - View Scops of function" );
static RegisterPass<ScopOnlyViewer >
static RegisterPass<ScopOnlyViewerWrapperPass >
Y (" view-scops-only" ,
" Polly - View Scops of function (with no function bodies)" );
static RegisterPass<ScopPrinter> M ( " dot-scops " ,
" Polly - Print Scops of function" );
static RegisterPass<ScopPrinterWrapperPass>
M ( " dot-scops " , " Polly - Print Scops of function" );
static RegisterPass<ScopOnlyPrinter >
static RegisterPass<ScopOnlyPrinterWrapperPass >
N (" dot-scops-only" ,
" Polly - Print Scops of function (with no function bodies)" );
Pass *polly::createDOTViewerPass () { return new ScopViewer (); }
Pass *polly::createDOTViewerWrapperPass () {
return new ScopViewerWrapperPass ();
}
Pass *polly::createDOTOnlyViewerWrapperPass () {
return new ScopOnlyViewerWrapperPass ();
}
Pass *polly::createDOTPrinterWrapperPass () {
return new ScopPrinterWrapperPass ();
}
Pass *polly::createDOTOnlyPrinterWrapperPass () {
return new ScopOnlyPrinterWrapperPass ();
}
Pass *polly::createDOTOnlyViewerPass () { return new ScopOnlyViewer (); }
bool ScopViewer::processFunction (Function &F, const ScopDetection &SD) {
if (ViewFilter != " " && !F.getName ().count (ViewFilter))
return false ;
Pass *polly::createDOTPrinterPass () { return new ScopPrinter (); }
if (ViewAll)
return true ;
Pass *polly::createDOTOnlyPrinterPass () { return new ScopOnlyPrinter (); }
// Check that at least one scop was detected.
return std::distance (SD.begin (), SD.end ()) > 0 ;
}