mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-21 18:22:53 +01:00
[CFGPrinter][CallPrinter][polly] Adding distinct structure for CFGDOTInfo
The patch introduces the system to distinctively store the information needed for the Control Flow Graph as well as the instrumentary needed for the follow-up changes: BlockFrequencyInfo and BranchProbabilityInfo. The patch is a part of sequence of three patches, related to graphs Heat Coloring. Reviewers: rcorcs, apilipenko, davidxl, sfertile, fedor.sergeev, eraman, bollu Differential Revision: https://reviews.llvm.org/D76820
This commit is contained in:
parent
64d224eff5
commit
ed0b96189b
@ -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<const Function*> : 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<DOTFuncInfo *> : public GraphTraits<const BasicBlock *> {
|
||||
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<Function::const_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<DOTFuncInfo *> : public DefaultDOTGraphTraits {
|
||||
|
||||
// Cache for is hidden property
|
||||
llvm::DenseMap <const BasicBlock *, bool> 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<const Function*> : 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<const Function*> : 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<const Function*> : 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<const Function*> : public DefaultDOTGraphTraits {
|
||||
MDString *MDName = cast<MDString>(WeightsNode->getOperand(0));
|
||||
if (MDName->getString() != "branch_weights")
|
||||
return "";
|
||||
|
||||
unsigned OpNo = I.getSuccessorIndex() + 1;
|
||||
if (OpNo >= WeightsNode->getNumOperands())
|
||||
return "";
|
||||
|
@ -42,6 +42,31 @@ static cl::opt<bool> HideUnreachablePaths("cfg-hide-unreachable-paths",
|
||||
static cl::opt<bool> 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<BranchProbabilityInfoWrapperPass>().getBPI();
|
||||
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().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<BlockFrequencyInfoWrapperPass>();
|
||||
AU.addRequired<BranchProbabilityInfoWrapperPass>();
|
||||
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<BlockFrequencyAnalysis>(F);
|
||||
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(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<BranchProbabilityInfoWrapperPass>().getBPI();
|
||||
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().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<BlockFrequencyInfoWrapperPass>();
|
||||
AU.addRequired<BranchProbabilityInfoWrapperPass>();
|
||||
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<BlockFrequencyAnalysis>(F);
|
||||
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(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<BranchProbabilityInfoWrapperPass>().getBPI();
|
||||
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().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<BlockFrequencyInfoWrapperPass>();
|
||||
AU.addRequired<BranchProbabilityInfoWrapperPass>();
|
||||
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<BlockFrequencyAnalysis>(F);
|
||||
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(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<BranchProbabilityInfoWrapperPass>().getBPI();
|
||||
auto *BFI = &getAnalysis<BlockFrequencyInfoWrapperPass>().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<BlockFrequencyInfoWrapperPass>();
|
||||
AU.addRequired<BranchProbabilityInfoWrapperPass>();
|
||||
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<BlockFrequencyAnalysis>(F);
|
||||
auto *BPI = &AM.getResult<BranchProbabilityAnalysis>(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<const Function *>::computeHiddenNodes(const Function *F) {
|
||||
void DOTGraphTraits<DOTFuncInfo *>::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<const Function *>::computeHiddenNodes(const Function *F) {
|
||||
evaluateBB);
|
||||
}
|
||||
|
||||
bool DOTGraphTraits<const Function *>::isNodeHidden(const BasicBlock *Node) {
|
||||
bool DOTGraphTraits<DOTFuncInfo *>::isNodeHidden(const BasicBlock *Node) {
|
||||
// If both restricting flags are false, all nodes are displayed.
|
||||
if (!HideUnreachablePaths && !HideDeoptimizePaths)
|
||||
return false;
|
||||
|
@ -40,11 +40,11 @@ struct DOTGraphTraits<DomTreeNode*> : public DefaultDOTGraphTraits {
|
||||
|
||||
|
||||
if (isSimple())
|
||||
return DOTGraphTraits<const Function*>
|
||||
::getSimpleNodeLabel(BB, BB->getParent());
|
||||
return DOTGraphTraits<DOTFuncInfo *>
|
||||
::getSimpleNodeLabel(BB, nullptr);
|
||||
else
|
||||
return DOTGraphTraits<const Function*>
|
||||
::getCompleteNodeLabel(BB, BB->getParent());
|
||||
return DOTGraphTraits<DOTFuncInfo *>
|
||||
::getCompleteNodeLabel(BB, nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -47,11 +47,11 @@ struct DOTGraphTraits<RegionNode*> : public DefaultDOTGraphTraits {
|
||||
BasicBlock *BB = Node->getNodeAs<BasicBlock>();
|
||||
|
||||
if (isSimple())
|
||||
return DOTGraphTraits<const Function*>
|
||||
::getSimpleNodeLabel(BB, BB->getParent());
|
||||
return DOTGraphTraits<DOTFuncInfo *>
|
||||
::getSimpleNodeLabel(BB, nullptr);
|
||||
else
|
||||
return DOTGraphTraits<const Function*>
|
||||
::getCompleteNodeLabel(BB, BB->getParent());
|
||||
return DOTGraphTraits<DOTFuncInfo *>
|
||||
::getCompleteNodeLabel(BB, nullptr);
|
||||
}
|
||||
|
||||
return "Not implemented";
|
||||
|
@ -898,7 +898,7 @@ bool NewGVN::isBackedge(BasicBlock *From, BasicBlock *To) const {
|
||||
|
||||
#ifndef NDEBUG
|
||||
static std::string getBlockName(const BasicBlock *B) {
|
||||
return DOTGraphTraits<const Function *>::getSimpleNodeLabel(B, nullptr);
|
||||
return DOTGraphTraits<DOTFuncInfo *>::getSimpleNodeLabel(B, nullptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user