2014-04-12 07:20:58 +08:00
|
|
|
//===- BlockFrequencyInfo.cpp - Block Frequency Analysis ------------------===//
|
2011-06-24 05:56:59 +08:00
|
|
|
//
|
|
|
|
// The LLVM Compiler Infrastructure
|
|
|
|
//
|
|
|
|
// This file is distributed under the University of Illinois Open Source
|
|
|
|
// License. See LICENSE.TXT for details.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// Loops should be simplified before this analysis.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2011-07-26 03:25:40 +08:00
|
|
|
#include "llvm/Analysis/BlockFrequencyInfo.h"
|
2014-04-12 07:20:58 +08:00
|
|
|
#include "llvm/Analysis/BlockFrequencyInfoImpl.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/Analysis/BranchProbabilityInfo.h"
|
2011-06-24 05:56:59 +08:00
|
|
|
#include "llvm/Analysis/LoopInfo.h"
|
|
|
|
#include "llvm/Analysis/Passes.h"
|
2014-03-04 19:45:46 +08:00
|
|
|
#include "llvm/IR/CFG.h"
|
2012-12-04 00:50:05 +08:00
|
|
|
#include "llvm/InitializePasses.h"
|
2013-11-14 10:27:46 +08:00
|
|
|
#include "llvm/Support/CommandLine.h"
|
|
|
|
#include "llvm/Support/Debug.h"
|
|
|
|
#include "llvm/Support/GraphWriter.h"
|
2011-06-24 05:56:59 +08:00
|
|
|
|
|
|
|
using namespace llvm;
|
|
|
|
|
2014-04-22 10:48:03 +08:00
|
|
|
#define DEBUG_TYPE "block-freq"
|
|
|
|
|
2013-11-14 10:27:46 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
enum GVDAGType {
|
|
|
|
GVDT_None,
|
|
|
|
GVDT_Fraction,
|
|
|
|
GVDT_Integer
|
|
|
|
};
|
|
|
|
|
|
|
|
static cl::opt<GVDAGType>
|
|
|
|
ViewBlockFreqPropagationDAG("view-block-freq-propagation-dags", cl::Hidden,
|
|
|
|
cl::desc("Pop up a window to show a dag displaying how block "
|
|
|
|
"frequencies propagation through the CFG."),
|
|
|
|
cl::values(
|
|
|
|
clEnumValN(GVDT_None, "none",
|
|
|
|
"do not display graphs."),
|
|
|
|
clEnumValN(GVDT_Fraction, "fraction", "display a graph using the "
|
|
|
|
"fractional block frequency representation."),
|
|
|
|
clEnumValN(GVDT_Integer, "integer", "display a graph using the raw "
|
|
|
|
"integer fractional block frequency representation."),
|
|
|
|
clEnumValEnd));
|
|
|
|
|
|
|
|
namespace llvm {
|
|
|
|
|
|
|
|
template <>
|
|
|
|
struct GraphTraits<BlockFrequencyInfo *> {
|
|
|
|
typedef const BasicBlock NodeType;
|
|
|
|
typedef succ_const_iterator ChildIteratorType;
|
|
|
|
typedef Function::const_iterator nodes_iterator;
|
|
|
|
|
|
|
|
static inline const NodeType *getEntryNode(const BlockFrequencyInfo *G) {
|
Analysis: Remove implicit ilist iterator conversions
Remove implicit ilist iterator conversions from LLVMAnalysis.
I came across something really scary in `llvm::isKnownNotFullPoison()`
which relied on `Instruction::getNextNode()` being completely broken
(not surprising, but scary nevertheless). This function is documented
(and coded to) return `nullptr` when it gets to the sentinel, but with
an `ilist_half_node` as a sentinel, the sentinel check looks into some
other memory and we don't recognize we've hit the end.
Rooting out these scary cases is the reason I'm removing the implicit
conversions before doing anything else with `ilist`; I'm not at all
surprised that clients rely on badness.
I found another scary case -- this time, not relying on badness, just
bad (but I guess getting lucky so far) -- in
`ObjectSizeOffsetEvaluator::compute_()`. Here, we save out the
insertion point, do some things, and then restore it. Previously, we
let the iterator auto-convert to `Instruction*`, and then set it back
using the `Instruction*` version:
Instruction *PrevInsertPoint = Builder.GetInsertPoint();
/* Logic that may change insert point */
if (PrevInsertPoint)
Builder.SetInsertPoint(PrevInsertPoint);
The check for `PrevInsertPoint` doesn't protect correctly against bad
accesses. If the insertion point has been set to the end of a basic
block (i.e., `SetInsertPoint(SomeBB)`), then `GetInsertPoint()` returns
an iterator pointing at the list sentinel. The version of
`SetInsertPoint()` that's getting called will then call
`PrevInsertPoint->getParent()`, which explodes horribly. The only
reason this hasn't blown up is that it's fairly unlikely the builder is
adding to the end of the block; usually, we're adding instructions
somewhere before the terminator.
llvm-svn: 249925
2015-10-10 08:53:03 +08:00
|
|
|
return &G->getFunction()->front();
|
2013-11-14 10:27:46 +08:00
|
|
|
}
|
|
|
|
static ChildIteratorType child_begin(const NodeType *N) {
|
|
|
|
return succ_begin(N);
|
|
|
|
}
|
|
|
|
static ChildIteratorType child_end(const NodeType *N) {
|
|
|
|
return succ_end(N);
|
|
|
|
}
|
|
|
|
static nodes_iterator nodes_begin(const BlockFrequencyInfo *G) {
|
|
|
|
return G->getFunction()->begin();
|
|
|
|
}
|
|
|
|
static nodes_iterator nodes_end(const BlockFrequencyInfo *G) {
|
|
|
|
return G->getFunction()->end();
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct DOTGraphTraits<BlockFrequencyInfo*> : public DefaultDOTGraphTraits {
|
|
|
|
explicit DOTGraphTraits(bool isSimple=false) :
|
|
|
|
DefaultDOTGraphTraits(isSimple) {}
|
|
|
|
|
|
|
|
static std::string getGraphName(const BlockFrequencyInfo *G) {
|
|
|
|
return G->getFunction()->getName();
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string getNodeLabel(const BasicBlock *Node,
|
|
|
|
const BlockFrequencyInfo *Graph) {
|
2014-06-27 06:52:05 +08:00
|
|
|
std::string Result;
|
|
|
|
raw_string_ostream OS(Result);
|
2013-11-14 10:27:46 +08:00
|
|
|
|
2015-03-28 01:51:30 +08:00
|
|
|
OS << Node->getName() << ":";
|
2013-11-14 10:27:46 +08:00
|
|
|
switch (ViewBlockFreqPropagationDAG) {
|
|
|
|
case GVDT_Fraction:
|
2013-12-14 08:25:42 +08:00
|
|
|
Graph->printBlockFreq(OS, Node);
|
2013-11-14 10:27:46 +08:00
|
|
|
break;
|
|
|
|
case GVDT_Integer:
|
|
|
|
OS << Graph->getBlockFreq(Node).getFrequency();
|
|
|
|
break;
|
|
|
|
case GVDT_None:
|
|
|
|
llvm_unreachable("If we are not supposed to render a graph we should "
|
|
|
|
"never reach this point.");
|
|
|
|
}
|
|
|
|
|
2014-06-27 06:52:05 +08:00
|
|
|
return Result;
|
2013-11-14 10:27:46 +08:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // end namespace llvm
|
|
|
|
#endif
|
|
|
|
|
2015-07-17 07:23:35 +08:00
|
|
|
BlockFrequencyInfo::BlockFrequencyInfo() {}
|
|
|
|
|
|
|
|
BlockFrequencyInfo::BlockFrequencyInfo(const Function &F,
|
|
|
|
const BranchProbabilityInfo &BPI,
|
|
|
|
const LoopInfo &LI) {
|
|
|
|
calculate(F, BPI, LI);
|
|
|
|
}
|
|
|
|
|
2016-05-06 05:13:27 +08:00
|
|
|
BlockFrequencyInfo::BlockFrequencyInfo(BlockFrequencyInfo &&Arg)
|
|
|
|
: BFI(std::move(Arg.BFI)) {}
|
|
|
|
|
|
|
|
BlockFrequencyInfo &BlockFrequencyInfo::operator=(BlockFrequencyInfo &&RHS) {
|
|
|
|
releaseMemory();
|
|
|
|
BFI = std::move(RHS.BFI);
|
|
|
|
return *this;
|
|
|
|
}
|
|
|
|
|
2015-07-15 07:40:50 +08:00
|
|
|
void BlockFrequencyInfo::calculate(const Function &F,
|
|
|
|
const BranchProbabilityInfo &BPI,
|
|
|
|
const LoopInfo &LI) {
|
2014-03-26 02:01:38 +08:00
|
|
|
if (!BFI)
|
|
|
|
BFI.reset(new ImplType);
|
2015-07-16 03:58:26 +08:00
|
|
|
BFI->calculate(F, BPI, LI);
|
2013-11-14 10:27:46 +08:00
|
|
|
#ifndef NDEBUG
|
|
|
|
if (ViewBlockFreqPropagationDAG != GVDT_None)
|
|
|
|
view();
|
|
|
|
#endif
|
2011-10-19 18:12:41 +08:00
|
|
|
}
|
|
|
|
|
2011-12-21 04:03:10 +08:00
|
|
|
BlockFrequency BlockFrequencyInfo::getBlockFreq(const BasicBlock *BB) const {
|
2014-03-26 02:01:38 +08:00
|
|
|
return BFI ? BFI->getBlockFreq(BB) : 0;
|
2011-06-24 05:56:59 +08:00
|
|
|
}
|
2013-11-14 10:27:46 +08:00
|
|
|
|
2016-03-24 02:18:26 +08:00
|
|
|
Optional<uint64_t>
|
|
|
|
BlockFrequencyInfo::getBlockProfileCount(const BasicBlock *BB) const {
|
|
|
|
auto EntryCount = getFunction()->getEntryCount();
|
|
|
|
if (!EntryCount)
|
|
|
|
return None;
|
|
|
|
// Use 128 bit APInt to do the arithmetic to avoid overflow.
|
|
|
|
APInt BlockCount(128, EntryCount.getValue());
|
|
|
|
APInt BlockFreq(128, getBlockFreq(BB).getFrequency());
|
|
|
|
APInt EntryFreq(128, getEntryFreq());
|
|
|
|
BlockCount *= BlockFreq;
|
|
|
|
BlockCount = BlockCount.udiv(EntryFreq);
|
|
|
|
return BlockCount.getLimitedValue();
|
|
|
|
}
|
|
|
|
|
2015-10-15 22:59:40 +08:00
|
|
|
void BlockFrequencyInfo::setBlockFreq(const BasicBlock *BB,
|
|
|
|
uint64_t Freq) {
|
|
|
|
assert(BFI && "Expected analysis to be available");
|
|
|
|
BFI->setBlockFreq(BB, Freq);
|
|
|
|
}
|
|
|
|
|
2013-11-14 10:27:46 +08:00
|
|
|
/// Pop up a ghostview window with the current block frequency propagation
|
|
|
|
/// rendered using dot.
|
|
|
|
void BlockFrequencyInfo::view() const {
|
|
|
|
// This code is only for debugging.
|
|
|
|
#ifndef NDEBUG
|
|
|
|
ViewGraph(const_cast<BlockFrequencyInfo *>(this), "BlockFrequencyDAGs");
|
|
|
|
#else
|
|
|
|
errs() << "BlockFrequencyInfo::view is only available in debug builds on "
|
|
|
|
"systems with Graphviz or gv!\n";
|
|
|
|
#endif // NDEBUG
|
|
|
|
}
|
|
|
|
|
|
|
|
const Function *BlockFrequencyInfo::getFunction() const {
|
2014-04-22 01:57:07 +08:00
|
|
|
return BFI ? BFI->getFunction() : nullptr;
|
2013-11-14 10:27:46 +08:00
|
|
|
}
|
2013-12-14 08:06:03 +08:00
|
|
|
|
|
|
|
raw_ostream &BlockFrequencyInfo::
|
|
|
|
printBlockFreq(raw_ostream &OS, const BlockFrequency Freq) const {
|
2014-03-26 02:01:38 +08:00
|
|
|
return BFI ? BFI->printBlockFreq(OS, Freq) : OS;
|
2013-12-14 08:06:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
raw_ostream &
|
|
|
|
BlockFrequencyInfo::printBlockFreq(raw_ostream &OS,
|
|
|
|
const BasicBlock *BB) const {
|
2014-03-26 02:01:38 +08:00
|
|
|
return BFI ? BFI->printBlockFreq(OS, BB) : OS;
|
2013-12-14 08:06:03 +08:00
|
|
|
}
|
2013-12-21 06:11:11 +08:00
|
|
|
|
|
|
|
uint64_t BlockFrequencyInfo::getEntryFreq() const {
|
2014-03-26 02:01:38 +08:00
|
|
|
return BFI ? BFI->getEntryFreq() : 0;
|
2013-12-21 06:11:11 +08:00
|
|
|
}
|
2015-07-15 07:40:50 +08:00
|
|
|
|
|
|
|
void BlockFrequencyInfo::releaseMemory() { BFI.reset(); }
|
|
|
|
|
|
|
|
void BlockFrequencyInfo::print(raw_ostream &OS) const {
|
|
|
|
if (BFI)
|
|
|
|
BFI->print(OS);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
INITIALIZE_PASS_BEGIN(BlockFrequencyInfoWrapperPass, "block-freq",
|
|
|
|
"Block Frequency Analysis", true, true)
|
2015-07-16 06:48:29 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(BranchProbabilityInfoWrapperPass)
|
2015-07-15 07:40:50 +08:00
|
|
|
INITIALIZE_PASS_DEPENDENCY(LoopInfoWrapperPass)
|
|
|
|
INITIALIZE_PASS_END(BlockFrequencyInfoWrapperPass, "block-freq",
|
|
|
|
"Block Frequency Analysis", true, true)
|
|
|
|
|
|
|
|
char BlockFrequencyInfoWrapperPass::ID = 0;
|
|
|
|
|
|
|
|
|
|
|
|
BlockFrequencyInfoWrapperPass::BlockFrequencyInfoWrapperPass()
|
|
|
|
: FunctionPass(ID) {
|
|
|
|
initializeBlockFrequencyInfoWrapperPassPass(*PassRegistry::getPassRegistry());
|
|
|
|
}
|
|
|
|
|
|
|
|
BlockFrequencyInfoWrapperPass::~BlockFrequencyInfoWrapperPass() {}
|
|
|
|
|
|
|
|
void BlockFrequencyInfoWrapperPass::print(raw_ostream &OS,
|
|
|
|
const Module *) const {
|
|
|
|
BFI.print(OS);
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlockFrequencyInfoWrapperPass::getAnalysisUsage(AnalysisUsage &AU) const {
|
2015-07-16 06:48:29 +08:00
|
|
|
AU.addRequired<BranchProbabilityInfoWrapperPass>();
|
2015-07-15 07:40:50 +08:00
|
|
|
AU.addRequired<LoopInfoWrapperPass>();
|
|
|
|
AU.setPreservesAll();
|
|
|
|
}
|
|
|
|
|
|
|
|
void BlockFrequencyInfoWrapperPass::releaseMemory() { BFI.releaseMemory(); }
|
|
|
|
|
|
|
|
bool BlockFrequencyInfoWrapperPass::runOnFunction(Function &F) {
|
2015-07-16 06:48:29 +08:00
|
|
|
BranchProbabilityInfo &BPI =
|
|
|
|
getAnalysis<BranchProbabilityInfoWrapperPass>().getBPI();
|
2015-07-15 07:40:50 +08:00
|
|
|
LoopInfo &LI = getAnalysis<LoopInfoWrapperPass>().getLoopInfo();
|
|
|
|
BFI.calculate(F, BPI, LI);
|
|
|
|
return false;
|
|
|
|
}
|
2016-05-06 05:13:27 +08:00
|
|
|
|
|
|
|
char BlockFrequencyAnalysis::PassID;
|
|
|
|
BlockFrequencyInfo BlockFrequencyAnalysis::run(Function &F,
|
|
|
|
AnalysisManager<Function> &AM) {
|
|
|
|
BlockFrequencyInfo BFI;
|
|
|
|
BFI.calculate(F, AM.getResult<BranchProbabilityAnalysis>(F),
|
|
|
|
AM.getResult<LoopAnalysis>(F));
|
|
|
|
return BFI;
|
|
|
|
}
|
|
|
|
|
|
|
|
PreservedAnalyses
|
|
|
|
BlockFrequencyPrinterPass::run(Function &F, AnalysisManager<Function> &AM) {
|
|
|
|
OS << "Printing analysis results of BFI for function "
|
|
|
|
<< "'" << F.getName() << "':"
|
|
|
|
<< "\n";
|
|
|
|
AM.getResult<BlockFrequencyAnalysis>(F).print(OS);
|
|
|
|
return PreservedAnalyses::all();
|
|
|
|
}
|