diff --git a/include/llvm/Analysis/CFGPrinter.h b/include/llvm/Analysis/CFGPrinter.h index b0c88f29625..80a26cd733f 100644 --- a/include/llvm/Analysis/CFGPrinter.h +++ b/include/llvm/Analysis/CFGPrinter.h @@ -18,11 +18,14 @@ #ifndef LLVM_ANALYSIS_CFGPRINTER_H #define LLVM_ANALYSIS_CFGPRINTER_H +#include "llvm/Analysis/BlockFrequencyInfo.h" +#include "llvm/Analysis/BranchProbabilityInfo.h" #include "llvm/IR/CFG.h" #include "llvm/IR/Constants.h" #include "llvm/IR/Function.h" #include "llvm/IR/Instructions.h" #include "llvm/IR/PassManager.h" +#include "llvm/Support/FormatVariadic.h" #include "llvm/Support/GraphWriter.h" namespace llvm { @@ -50,20 +53,61 @@ public: PreservedAnalyses run(Function &F, FunctionAnalysisManager &AM); }; -template<> -struct DOTGraphTraits : public DefaultDOTGraphTraits { +class DOTFuncInfo { +private: + const Function *F; + const BlockFrequencyInfo *BFI; + const BranchProbabilityInfo *BPI; + +public: + DOTFuncInfo(const Function *F) : DOTFuncInfo(F, nullptr, nullptr) {} + + DOTFuncInfo(const Function *F, const BlockFrequencyInfo *BFI, + BranchProbabilityInfo *BPI) + : F(F), BFI(BFI), BPI(BPI) { + } + + const BlockFrequencyInfo *getBFI() { return BFI; } + + const BranchProbabilityInfo *getBPI() { return BPI; } + + const Function *getFunction() { return this->F; } +}; + +template <> +struct GraphTraits : public GraphTraits { + static NodeRef getEntryNode(DOTFuncInfo *CFGInfo) { + return &(CFGInfo->getFunction()->getEntryBlock()); + } + + // nodes_iterator/begin/end - Allow iteration over all nodes in the graph + using nodes_iterator = pointer_iterator; + + static nodes_iterator nodes_begin(DOTFuncInfo *CFGInfo) { + return nodes_iterator(CFGInfo->getFunction()->begin()); + } + + static nodes_iterator nodes_end(DOTFuncInfo *CFGInfo) { + return nodes_iterator(CFGInfo->getFunction()->end()); + } + + static size_t size(DOTFuncInfo *CFGInfo) { + return CFGInfo->getFunction()->size(); + } +}; + +template <> struct DOTGraphTraits : public DefaultDOTGraphTraits { // Cache for is hidden property llvm::DenseMap isHiddenBasicBlock; DOTGraphTraits (bool isSimple=false) : DefaultDOTGraphTraits(isSimple) {} - static std::string getGraphName(const Function *F) { - return "CFG for '" + F->getName().str() + "' function"; + static std::string getGraphName(DOTFuncInfo *CFGInfo) { + return "CFG for '" + CFGInfo->getFunction()->getName().str() + "' function"; } - static std::string getSimpleNodeLabel(const BasicBlock *Node, - const Function *) { + static std::string getSimpleNodeLabel(const BasicBlock *Node, DOTFuncInfo *) { if (!Node->getName().empty()) return Node->getName().str(); @@ -75,7 +119,7 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { } static std::string getCompleteNodeLabel(const BasicBlock *Node, - const Function *) { + DOTFuncInfo *) { enum { MaxColumns = 80 }; std::string Str; raw_string_ostream OS(Str); @@ -120,11 +164,12 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { } std::string getNodeLabel(const BasicBlock *Node, - const Function *Graph) { + DOTFuncInfo *CFGInfo) { + if (isSimple()) - return getSimpleNodeLabel(Node, Graph); + return getSimpleNodeLabel(Node, CFGInfo); else - return getCompleteNodeLabel(Node, Graph); + return getCompleteNodeLabel(Node, CFGInfo); } static std::string getEdgeSourceLabel(const BasicBlock *Node, @@ -151,11 +196,10 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { /// Display the raw branch weights from PGO. std::string getEdgeAttributes(const BasicBlock *Node, const_succ_iterator I, - const Function *F) { + DOTFuncInfo *CFGInfo) { const Instruction *TI = Node->getTerminator(); if (TI->getNumSuccessors() == 1) return ""; - MDNode *WeightsNode = TI->getMetadata(LLVMContext::MD_prof); if (!WeightsNode) return ""; @@ -163,7 +207,6 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { MDString *MDName = cast(WeightsNode->getOperand(0)); if (MDName->getString() != "branch_weights") return ""; - unsigned OpNo = I.getSuccessorIndex() + 1; if (OpNo >= WeightsNode->getNumOperands()) return ""; diff --git a/lib/Analysis/CFGPrinter.cpp b/lib/Analysis/CFGPrinter.cpp index 4a708b4981a..295d936c026 100644 --- a/lib/Analysis/CFGPrinter.cpp +++ b/lib/Analysis/CFGPrinter.cpp @@ -42,6 +42,31 @@ static cl::opt HideUnreachablePaths("cfg-hide-unreachable-paths", static cl::opt HideDeoptimizePaths("cfg-hide-deoptimize-paths", cl::init(false)); +static void writeCFGToDotFile(Function &F, BlockFrequencyInfo *BFI, + BranchProbabilityInfo *BPI, + bool isSimple) { + std::string Filename = + (CFGDotFilenamePrefix + "." + F.getName() + ".dot").str(); + errs() << "Writing '" << Filename << "'..."; + + std::error_code EC; + raw_fd_ostream File(Filename, EC, sys::fs::F_Text); + + DOTFuncInfo CFGInfo(&F, BFI, BPI); + if (!EC) + WriteGraph(File, &CFGInfo, isSimple); + else + errs() << " error opening file for writing!"; + errs() << "\n"; +} + +static void viewCFG(Function &F, BlockFrequencyInfo *BFI, + BranchProbabilityInfo *BPI, + bool isSimple) { + DOTFuncInfo CFGInfo(&F, BFI, BPI); + ViewGraph(&CFGInfo, "cfg." + F.getName(), isSimple); +} + namespace { struct CFGViewerLegacyPass : public FunctionPass { static char ID; // Pass identifcation, replacement for typeid @@ -50,13 +75,18 @@ namespace { } bool runOnFunction(Function &F) override { - F.viewCFG(); + auto *BPI = &getAnalysis().getBPI(); + auto *BFI = &getAnalysis().getBFI(); + viewCFG(F, BFI, BPI, /*isSimple=*/false); return false; } void print(raw_ostream &OS, const Module* = nullptr) const override {} void getAnalysisUsage(AnalysisUsage &AU) const override { + FunctionPass::getAnalysisUsage(AU); // Maybe Change to FunctionPass::... + AU.addRequired(); + AU.addRequired(); AU.setPreservesAll(); } }; @@ -67,7 +97,9 @@ INITIALIZE_PASS(CFGViewerLegacyPass, "view-cfg", "View CFG of function", false, PreservedAnalyses CFGViewerPass::run(Function &F, FunctionAnalysisManager &AM) { - F.viewCFG(); + auto *BFI = &AM.getResult(F); + auto *BPI = &AM.getResult(F); + viewCFG(F, BFI, BPI, /*isSimple=*/false); return PreservedAnalyses::all(); } @@ -80,13 +112,18 @@ namespace { } bool runOnFunction(Function &F) override { - F.viewCFGOnly(); + auto *BPI = &getAnalysis().getBPI(); + auto *BFI = &getAnalysis().getBFI(); + viewCFG(F, BFI, BPI, /*isSimple=*/false); return false; } void print(raw_ostream &OS, const Module* = nullptr) const override {} void getAnalysisUsage(AnalysisUsage &AU) const override { + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addRequired(); AU.setPreservesAll(); } }; @@ -98,27 +135,12 @@ INITIALIZE_PASS(CFGOnlyViewerLegacyPass, "view-cfg-only", PreservedAnalyses CFGOnlyViewerPass::run(Function &F, FunctionAnalysisManager &AM) { - F.viewCFGOnly(); + auto *BFI = &AM.getResult(F); + auto *BPI = &AM.getResult(F); + viewCFG(F, BFI, BPI, /*isSimple=*/false); return PreservedAnalyses::all(); } -static void writeCFGToDotFile(Function &F, bool CFGOnly = false) { - if (!CFGFuncName.empty() && !F.getName().contains(CFGFuncName)) - return; - std::string Filename = - (CFGDotFilenamePrefix + "." + F.getName() + ".dot").str(); - errs() << "Writing '" << Filename << "'..."; - - std::error_code EC; - raw_fd_ostream File(Filename, EC, sys::fs::OF_Text); - - if (!EC) - WriteGraph(File, (const Function*)&F, CFGOnly); - else - errs() << " error opening file for writing!"; - errs() << "\n"; -} - namespace { struct CFGPrinterLegacyPass : public FunctionPass { static char ID; // Pass identification, replacement for typeid @@ -127,13 +149,18 @@ namespace { } bool runOnFunction(Function &F) override { - writeCFGToDotFile(F); + auto *BPI = &getAnalysis().getBPI(); + auto *BFI = &getAnalysis().getBFI(); + writeCFGToDotFile(F, BFI, BPI, /*isSimple=*/false); return false; } void print(raw_ostream &OS, const Module* = nullptr) const override {} void getAnalysisUsage(AnalysisUsage &AU) const override { + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addRequired(); AU.setPreservesAll(); } }; @@ -145,7 +172,9 @@ INITIALIZE_PASS(CFGPrinterLegacyPass, "dot-cfg", "Print CFG of function to 'dot' PreservedAnalyses CFGPrinterPass::run(Function &F, FunctionAnalysisManager &AM) { - writeCFGToDotFile(F); + auto *BFI = &AM.getResult(F); + auto *BPI = &AM.getResult(F); + writeCFGToDotFile(F, BFI, BPI, /*isSimple=*/false); return PreservedAnalyses::all(); } @@ -157,12 +186,17 @@ namespace { } bool runOnFunction(Function &F) override { - writeCFGToDotFile(F, /*CFGOnly=*/true); + auto *BPI = &getAnalysis().getBPI(); + auto *BFI = &getAnalysis().getBFI(); + writeCFGToDotFile(F, BFI, BPI, /*isSimple=*/false); return false; } void print(raw_ostream &OS, const Module* = nullptr) const override {} void getAnalysisUsage(AnalysisUsage &AU) const override { + FunctionPass::getAnalysisUsage(AU); + AU.addRequired(); + AU.addRequired(); AU.setPreservesAll(); } }; @@ -175,7 +209,9 @@ INITIALIZE_PASS(CFGOnlyPrinterLegacyPass, "dot-cfg-only", PreservedAnalyses CFGOnlyPrinterPass::run(Function &F, FunctionAnalysisManager &AM) { - writeCFGToDotFile(F, /*CFGOnly=*/true); + auto *BFI = &AM.getResult(F); + auto *BPI = &AM.getResult(F); + writeCFGToDotFile(F, BFI, BPI, /*isSimple=*/false); return PreservedAnalyses::all(); } @@ -187,7 +223,8 @@ PreservedAnalyses CFGOnlyPrinterPass::run(Function &F, void Function::viewCFG() const { if (!CFGFuncName.empty() && !getName().contains(CFGFuncName)) return; - ViewGraph(this, "cfg" + getName()); + DOTFuncInfo CFGInfo(this); + ViewGraph(&CFGInfo, "cfg" + getName()); } /// viewCFGOnly - This function is meant for use from the debugger. It works @@ -198,7 +235,8 @@ void Function::viewCFG() const { void Function::viewCFGOnly() const { if (!CFGFuncName.empty() && !getName().contains(CFGFuncName)) return; - ViewGraph(this, "cfg" + getName(), true); + DOTFuncInfo CFGInfo(this); + ViewGraph(&CFGInfo, "cfg" + getName(), true); } FunctionPass *llvm::createCFGPrinterLegacyPassPass () { @@ -209,7 +247,7 @@ FunctionPass *llvm::createCFGOnlyPrinterLegacyPassPass () { return new CFGOnlyPrinterLegacyPass(); } -void DOTGraphTraits::computeHiddenNodes(const Function *F) { +void DOTGraphTraits::computeHiddenNodes(const Function *F) { auto evaluateBB = [&](const BasicBlock *Node) { if (succ_begin(Node) == succ_end(Node)) { const Instruction *TI = Node->getTerminator(); @@ -228,7 +266,7 @@ void DOTGraphTraits::computeHiddenNodes(const Function *F) { evaluateBB); } -bool DOTGraphTraits::isNodeHidden(const BasicBlock *Node) { +bool DOTGraphTraits::isNodeHidden(const BasicBlock *Node) { // If both restricting flags are false, all nodes are displayed. if (!HideUnreachablePaths && !HideDeoptimizePaths) return false; diff --git a/lib/Analysis/DomPrinter.cpp b/lib/Analysis/DomPrinter.cpp index 024a0fb4995..ebbe0d3e2c5 100644 --- a/lib/Analysis/DomPrinter.cpp +++ b/lib/Analysis/DomPrinter.cpp @@ -40,11 +40,11 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { if (isSimple()) - return DOTGraphTraits - ::getSimpleNodeLabel(BB, BB->getParent()); + return DOTGraphTraits + ::getSimpleNodeLabel(BB, nullptr); else - return DOTGraphTraits - ::getCompleteNodeLabel(BB, BB->getParent()); + return DOTGraphTraits + ::getCompleteNodeLabel(BB, nullptr); } }; diff --git a/lib/Analysis/RegionPrinter.cpp b/lib/Analysis/RegionPrinter.cpp index 020ff85d1b9..1fb5faaa6a7 100644 --- a/lib/Analysis/RegionPrinter.cpp +++ b/lib/Analysis/RegionPrinter.cpp @@ -47,11 +47,11 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { BasicBlock *BB = Node->getNodeAs(); if (isSimple()) - return DOTGraphTraits - ::getSimpleNodeLabel(BB, BB->getParent()); + return DOTGraphTraits + ::getSimpleNodeLabel(BB, nullptr); else - return DOTGraphTraits - ::getCompleteNodeLabel(BB, BB->getParent()); + return DOTGraphTraits + ::getCompleteNodeLabel(BB, nullptr); } return "Not implemented"; diff --git a/lib/Transforms/Scalar/NewGVN.cpp b/lib/Transforms/Scalar/NewGVN.cpp index b93a8bfeaa4..98c3304bf7b 100644 --- a/lib/Transforms/Scalar/NewGVN.cpp +++ b/lib/Transforms/Scalar/NewGVN.cpp @@ -898,7 +898,7 @@ bool NewGVN::isBackedge(BasicBlock *From, BasicBlock *To) const { #ifndef NDEBUG static std::string getBlockName(const BasicBlock *B) { - return DOTGraphTraits::getSimpleNodeLabel(B, nullptr); + return DOTGraphTraits::getSimpleNodeLabel(B, nullptr); } #endif