1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +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:
Kirill Naumov 2020-04-06 16:53:10 +00:00
parent 64d224eff5
commit ed0b96189b
5 changed files with 132 additions and 51 deletions

View File

@ -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 "";

View File

@ -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;

View File

@ -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);
}
};

View File

@ -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";

View File

@ -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