BlockFrequencyInfoImpl.h [plain text]
#ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H
#define LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/PostOrderIterator.h"
#include "llvm/ADT/iterator_range.h"
#include "llvm/IR/BasicBlock.h"
#include "llvm/Support/BlockFrequency.h"
#include "llvm/Support/BranchProbability.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/ScaledNumber.h"
#include "llvm/Support/raw_ostream.h"
#include <deque>
#include <list>
#include <string>
#include <vector>
#define DEBUG_TYPE "block-freq"
namespace llvm {
class BasicBlock;
class BranchProbabilityInfo;
class Function;
class Loop;
class LoopInfo;
class MachineBasicBlock;
class MachineBranchProbabilityInfo;
class MachineFunction;
class MachineLoop;
class MachineLoopInfo;
namespace bfi_detail {
struct IrreducibleGraph;
template <class BT> struct BlockEdgesAdder;
class BlockMass {
uint64_t Mass;
public:
BlockMass() : Mass(0) {}
explicit BlockMass(uint64_t Mass) : Mass(Mass) {}
static BlockMass getEmpty() { return BlockMass(); }
static BlockMass getFull() { return BlockMass(UINT64_MAX); }
uint64_t getMass() const { return Mass; }
bool isFull() const { return Mass == UINT64_MAX; }
bool isEmpty() const { return !Mass; }
bool operator!() const { return isEmpty(); }
BlockMass &operator+=(const BlockMass &X) {
uint64_t Sum = Mass + X.Mass;
Mass = Sum < Mass ? UINT64_MAX : Sum;
return *this;
}
BlockMass &operator-=(const BlockMass &X) {
uint64_t Diff = Mass - X.Mass;
Mass = Diff > Mass ? 0 : Diff;
return *this;
}
BlockMass &operator*=(const BranchProbability &P) {
Mass = P.scale(Mass);
return *this;
}
bool operator==(const BlockMass &X) const { return Mass == X.Mass; }
bool operator!=(const BlockMass &X) const { return Mass != X.Mass; }
bool operator<=(const BlockMass &X) const { return Mass <= X.Mass; }
bool operator>=(const BlockMass &X) const { return Mass >= X.Mass; }
bool operator<(const BlockMass &X) const { return Mass < X.Mass; }
bool operator>(const BlockMass &X) const { return Mass > X.Mass; }
ScaledNumber<uint64_t> toScaled() const;
void dump() const;
raw_ostream &print(raw_ostream &OS) const;
};
inline BlockMass operator+(const BlockMass &L, const BlockMass &R) {
return BlockMass(L) += R;
}
inline BlockMass operator-(const BlockMass &L, const BlockMass &R) {
return BlockMass(L) -= R;
}
inline BlockMass operator*(const BlockMass &L, const BranchProbability &R) {
return BlockMass(L) *= R;
}
inline BlockMass operator*(const BranchProbability &L, const BlockMass &R) {
return BlockMass(R) *= L;
}
inline raw_ostream &operator<<(raw_ostream &OS, const BlockMass &X) {
return X.print(OS);
}
}
template <> struct isPodLike<bfi_detail::BlockMass> {
static const bool value = true;
};
class BlockFrequencyInfoImplBase {
public:
typedef ScaledNumber<uint64_t> Scaled64;
typedef bfi_detail::BlockMass BlockMass;
struct BlockNode {
typedef uint32_t IndexType;
IndexType Index;
bool operator==(const BlockNode &X) const { return Index == X.Index; }
bool operator!=(const BlockNode &X) const { return Index != X.Index; }
bool operator<=(const BlockNode &X) const { return Index <= X.Index; }
bool operator>=(const BlockNode &X) const { return Index >= X.Index; }
bool operator<(const BlockNode &X) const { return Index < X.Index; }
bool operator>(const BlockNode &X) const { return Index > X.Index; }
BlockNode() : Index(UINT32_MAX) {}
BlockNode(IndexType Index) : Index(Index) {}
bool isValid() const { return Index <= getMaxIndex(); }
static size_t getMaxIndex() { return UINT32_MAX - 1; }
};
struct FrequencyData {
Scaled64 Scaled;
uint64_t Integer;
};
struct LoopData {
typedef SmallVector<std::pair<BlockNode, BlockMass>, 4> ExitMap;
typedef SmallVector<BlockNode, 4> NodeList;
LoopData *Parent; bool IsPackaged; uint32_t NumHeaders; ExitMap Exits; NodeList Nodes; BlockMass BackedgeMass; BlockMass Mass;
Scaled64 Scale;
LoopData(LoopData *Parent, const BlockNode &Header)
: Parent(Parent), IsPackaged(false), NumHeaders(1), Nodes(1, Header) {}
template <class It1, class It2>
LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther,
It2 LastOther)
: Parent(Parent), IsPackaged(false), Nodes(FirstHeader, LastHeader) {
NumHeaders = Nodes.size();
Nodes.insert(Nodes.end(), FirstOther, LastOther);
}
bool isHeader(const BlockNode &Node) const {
if (isIrreducible())
return std::binary_search(Nodes.begin(), Nodes.begin() + NumHeaders,
Node);
return Node == Nodes[0];
}
BlockNode getHeader() const { return Nodes[0]; }
bool isIrreducible() const { return NumHeaders > 1; }
NodeList::const_iterator members_begin() const {
return Nodes.begin() + NumHeaders;
}
NodeList::const_iterator members_end() const { return Nodes.end(); }
iterator_range<NodeList::const_iterator> members() const {
return make_range(members_begin(), members_end());
}
};
struct WorkingData {
BlockNode Node; LoopData *Loop; BlockMass Mass;
WorkingData(const BlockNode &Node) : Node(Node), Loop(nullptr) {}
bool isLoopHeader() const { return Loop && Loop->isHeader(Node); }
bool isDoubleLoopHeader() const {
return isLoopHeader() && Loop->Parent && Loop->Parent->isIrreducible() &&
Loop->Parent->isHeader(Node);
}
LoopData *getContainingLoop() const {
if (!isLoopHeader())
return Loop;
if (!isDoubleLoopHeader())
return Loop->Parent;
return Loop->Parent->Parent;
}
BlockNode getResolvedNode() const {
auto L = getPackagedLoop();
return L ? L->getHeader() : Node;
}
LoopData *getPackagedLoop() const {
if (!Loop || !Loop->IsPackaged)
return nullptr;
auto L = Loop;
while (L->Parent && L->Parent->IsPackaged)
L = L->Parent;
return L;
}
BlockMass &getMass() {
if (!isAPackage())
return Mass;
if (!isADoublePackage())
return Loop->Mass;
return Loop->Parent->Mass;
}
bool isPackaged() const { return getResolvedNode() != Node; }
bool isAPackage() const { return isLoopHeader() && Loop->IsPackaged; }
bool isADoublePackage() const {
return isDoubleLoopHeader() && Loop->Parent->IsPackaged;
}
};
struct Weight {
enum DistType { Local, Exit, Backedge };
DistType Type;
BlockNode TargetNode;
uint64_t Amount;
Weight() : Type(Local), Amount(0) {}
Weight(DistType Type, BlockNode TargetNode, uint64_t Amount)
: Type(Type), TargetNode(TargetNode), Amount(Amount) {}
};
struct Distribution {
typedef SmallVector<Weight, 4> WeightList;
WeightList Weights; uint64_t Total; bool DidOverflow;
Distribution() : Total(0), DidOverflow(false) {}
void addLocal(const BlockNode &Node, uint64_t Amount) {
add(Node, Amount, Weight::Local);
}
void addExit(const BlockNode &Node, uint64_t Amount) {
add(Node, Amount, Weight::Exit);
}
void addBackedge(const BlockNode &Node, uint64_t Amount) {
add(Node, Amount, Weight::Backedge);
}
void normalize();
private:
void add(const BlockNode &Node, uint64_t Amount, Weight::DistType Type);
};
std::vector<FrequencyData> Freqs;
std::vector<WorkingData> Working;
std::list<LoopData> Loops;
bool addLoopSuccessorsToDist(const LoopData *OuterLoop, LoopData &Loop,
Distribution &Dist);
bool addToDist(Distribution &Dist, const LoopData *OuterLoop,
const BlockNode &Pred, const BlockNode &Succ, uint64_t Weight);
LoopData &getLoopPackage(const BlockNode &Head) {
assert(Head.Index < Working.size());
assert(Working[Head.Index].isLoopHeader());
return *Working[Head.Index].Loop;
}
iterator_range<std::list<LoopData>::iterator>
analyzeIrreducible(const bfi_detail::IrreducibleGraph &G, LoopData *OuterLoop,
std::list<LoopData>::iterator Insert);
void updateLoopWithIrreducible(LoopData &OuterLoop);
void distributeMass(const BlockNode &Source, LoopData *OuterLoop,
Distribution &Dist);
void computeLoopScale(LoopData &Loop);
void packageLoop(LoopData &Loop);
void unwrapLoops();
void finalizeMetrics();
void clear();
virtual std::string getBlockName(const BlockNode &Node) const;
std::string getLoopName(const LoopData &Loop) const;
virtual raw_ostream &print(raw_ostream &OS) const { return OS; }
void dump() const { print(dbgs()); }
Scaled64 getFloatingBlockFreq(const BlockNode &Node) const;
BlockFrequency getBlockFreq(const BlockNode &Node) const;
raw_ostream &printBlockFreq(raw_ostream &OS, const BlockNode &Node) const;
raw_ostream &printBlockFreq(raw_ostream &OS,
const BlockFrequency &Freq) const;
uint64_t getEntryFreq() const {
assert(!Freqs.empty());
return Freqs[0].Integer;
}
virtual ~BlockFrequencyInfoImplBase() {}
};
namespace bfi_detail {
template <class BlockT> struct TypeMap {};
template <> struct TypeMap<BasicBlock> {
typedef BasicBlock BlockT;
typedef Function FunctionT;
typedef BranchProbabilityInfo BranchProbabilityInfoT;
typedef Loop LoopT;
typedef LoopInfo LoopInfoT;
};
template <> struct TypeMap<MachineBasicBlock> {
typedef MachineBasicBlock BlockT;
typedef MachineFunction FunctionT;
typedef MachineBranchProbabilityInfo BranchProbabilityInfoT;
typedef MachineLoop LoopT;
typedef MachineLoopInfo LoopInfoT;
};
template <class BlockT> std::string getBlockName(const BlockT *BB) {
assert(BB && "Unexpected nullptr");
auto MachineName = "BB" + Twine(BB->getNumber());
if (BB->getBasicBlock())
return (MachineName + "[" + BB->getName() + "]").str();
return MachineName.str();
}
template <> inline std::string getBlockName(const BasicBlock *BB) {
assert(BB && "Unexpected nullptr");
return BB->getName().str();
}
struct IrreducibleGraph {
typedef BlockFrequencyInfoImplBase BFIBase;
BFIBase &BFI;
typedef BFIBase::BlockNode BlockNode;
struct IrrNode {
BlockNode Node;
unsigned NumIn;
std::deque<const IrrNode *> Edges;
IrrNode(const BlockNode &Node) : Node(Node), NumIn(0) {}
typedef std::deque<const IrrNode *>::const_iterator iterator;
iterator pred_begin() const { return Edges.begin(); }
iterator succ_begin() const { return Edges.begin() + NumIn; }
iterator pred_end() const { return succ_begin(); }
iterator succ_end() const { return Edges.end(); }
};
BlockNode Start;
const IrrNode *StartIrr;
std::vector<IrrNode> Nodes;
SmallDenseMap<uint32_t, IrrNode *, 4> Lookup;
template <class BlockEdgesAdder>
IrreducibleGraph(BFIBase &BFI, const BFIBase::LoopData *OuterLoop,
BlockEdgesAdder addBlockEdges)
: BFI(BFI), StartIrr(nullptr) {
initialize(OuterLoop, addBlockEdges);
}
template <class BlockEdgesAdder>
void initialize(const BFIBase::LoopData *OuterLoop,
BlockEdgesAdder addBlockEdges);
void addNodesInLoop(const BFIBase::LoopData &OuterLoop);
void addNodesInFunction();
void addNode(const BlockNode &Node) {
Nodes.emplace_back(Node);
BFI.Working[Node.Index].getMass() = BlockMass::getEmpty();
}
void indexNodes();
template <class BlockEdgesAdder>
void addEdges(const BlockNode &Node, const BFIBase::LoopData *OuterLoop,
BlockEdgesAdder addBlockEdges);
void addEdge(IrrNode &Irr, const BlockNode &Succ,
const BFIBase::LoopData *OuterLoop);
};
template <class BlockEdgesAdder>
void IrreducibleGraph::initialize(const BFIBase::LoopData *OuterLoop,
BlockEdgesAdder addBlockEdges) {
if (OuterLoop) {
addNodesInLoop(*OuterLoop);
for (auto N : OuterLoop->Nodes)
addEdges(N, OuterLoop, addBlockEdges);
} else {
addNodesInFunction();
for (uint32_t Index = 0; Index < BFI.Working.size(); ++Index)
addEdges(Index, OuterLoop, addBlockEdges);
}
StartIrr = Lookup[Start.Index];
}
template <class BlockEdgesAdder>
void IrreducibleGraph::addEdges(const BlockNode &Node,
const BFIBase::LoopData *OuterLoop,
BlockEdgesAdder addBlockEdges) {
auto L = Lookup.find(Node.Index);
if (L == Lookup.end())
return;
IrrNode &Irr = *L->second;
const auto &Working = BFI.Working[Node.Index];
if (Working.isAPackage())
for (const auto &I : Working.Loop->Exits)
addEdge(Irr, I.first, OuterLoop);
else
addBlockEdges(*this, Irr, OuterLoop);
}
}
template <class BT> class BlockFrequencyInfoImpl : BlockFrequencyInfoImplBase {
typedef typename bfi_detail::TypeMap<BT>::BlockT BlockT;
typedef typename bfi_detail::TypeMap<BT>::FunctionT FunctionT;
typedef typename bfi_detail::TypeMap<BT>::BranchProbabilityInfoT
BranchProbabilityInfoT;
typedef typename bfi_detail::TypeMap<BT>::LoopT LoopT;
typedef typename bfi_detail::TypeMap<BT>::LoopInfoT LoopInfoT;
friend struct bfi_detail::BlockEdgesAdder<BT>;
typedef GraphTraits<const BlockT *> Successor;
typedef GraphTraits<Inverse<const BlockT *>> Predecessor;
const BranchProbabilityInfoT *BPI;
const LoopInfoT *LI;
const FunctionT *F;
std::vector<const BlockT *> RPOT;
DenseMap<const BlockT *, BlockNode> Nodes;
typedef typename std::vector<const BlockT *>::const_iterator rpot_iterator;
rpot_iterator rpot_begin() const { return RPOT.begin(); }
rpot_iterator rpot_end() const { return RPOT.end(); }
size_t getIndex(const rpot_iterator &I) const { return I - rpot_begin(); }
BlockNode getNode(const rpot_iterator &I) const {
return BlockNode(getIndex(I));
}
BlockNode getNode(const BlockT *BB) const { return Nodes.lookup(BB); }
const BlockT *getBlock(const BlockNode &Node) const {
assert(Node.Index < RPOT.size());
return RPOT[Node.Index];
}
void initializeRPOT();
void initializeLoops();
bool propagateMassToSuccessors(LoopData *OuterLoop, const BlockNode &Node);
bool computeMassInLoop(LoopData &Loop);
bool tryToComputeMassInFunction();
void computeIrreducibleMass(LoopData *OuterLoop,
std::list<LoopData>::iterator Insert);
void computeMassInLoops();
void computeMassInFunction();
std::string getBlockName(const BlockNode &Node) const override {
return bfi_detail::getBlockName(getBlock(Node));
}
public:
const FunctionT *getFunction() const { return F; }
void doFunction(const FunctionT *F, const BranchProbabilityInfoT *BPI,
const LoopInfoT *LI);
BlockFrequencyInfoImpl() : BPI(nullptr), LI(nullptr), F(nullptr) {}
using BlockFrequencyInfoImplBase::getEntryFreq;
BlockFrequency getBlockFreq(const BlockT *BB) const {
return BlockFrequencyInfoImplBase::getBlockFreq(getNode(BB));
}
Scaled64 getFloatingBlockFreq(const BlockT *BB) const {
return BlockFrequencyInfoImplBase::getFloatingBlockFreq(getNode(BB));
}
raw_ostream &print(raw_ostream &OS) const override;
using BlockFrequencyInfoImplBase::dump;
using BlockFrequencyInfoImplBase::printBlockFreq;
raw_ostream &printBlockFreq(raw_ostream &OS, const BlockT *BB) const {
return BlockFrequencyInfoImplBase::printBlockFreq(OS, getNode(BB));
}
};
template <class BT>
void BlockFrequencyInfoImpl<BT>::doFunction(const FunctionT *F,
const BranchProbabilityInfoT *BPI,
const LoopInfoT *LI) {
this->BPI = BPI;
this->LI = LI;
this->F = F;
BlockFrequencyInfoImplBase::clear();
RPOT.clear();
Nodes.clear();
DEBUG(dbgs() << "\nblock-frequency: " << F->getName() << "\n================="
<< std::string(F->getName().size(), '=') << "\n");
initializeRPOT();
initializeLoops();
computeMassInLoops();
computeMassInFunction();
unwrapLoops();
finalizeMetrics();
}
template <class BT> void BlockFrequencyInfoImpl<BT>::initializeRPOT() {
const BlockT *Entry = F->begin();
RPOT.reserve(F->size());
std::copy(po_begin(Entry), po_end(Entry), std::back_inserter(RPOT));
std::reverse(RPOT.begin(), RPOT.end());
assert(RPOT.size() - 1 <= BlockNode::getMaxIndex() &&
"More nodes in function than Block Frequency Info supports");
DEBUG(dbgs() << "reverse-post-order-traversal\n");
for (rpot_iterator I = rpot_begin(), E = rpot_end(); I != E; ++I) {
BlockNode Node = getNode(I);
DEBUG(dbgs() << " - " << getIndex(I) << ": " << getBlockName(Node) << "\n");
Nodes[*I] = Node;
}
Working.reserve(RPOT.size());
for (size_t Index = 0; Index < RPOT.size(); ++Index)
Working.emplace_back(Index);
Freqs.resize(RPOT.size());
}
template <class BT> void BlockFrequencyInfoImpl<BT>::initializeLoops() {
DEBUG(dbgs() << "loop-detection\n");
if (LI->empty())
return;
std::deque<std::pair<const LoopT *, LoopData *>> Q;
for (const LoopT *L : *LI)
Q.emplace_back(L, nullptr);
while (!Q.empty()) {
const LoopT *Loop = Q.front().first;
LoopData *Parent = Q.front().second;
Q.pop_front();
BlockNode Header = getNode(Loop->getHeader());
assert(Header.isValid());
Loops.emplace_back(Parent, Header);
Working[Header.Index].Loop = &Loops.back();
DEBUG(dbgs() << " - loop = " << getBlockName(Header) << "\n");
for (const LoopT *L : *Loop)
Q.emplace_back(L, &Loops.back());
}
for (size_t Index = 0; Index < RPOT.size(); ++Index) {
if (Working[Index].isLoopHeader()) {
LoopData *ContainingLoop = Working[Index].getContainingLoop();
if (ContainingLoop)
ContainingLoop->Nodes.push_back(Index);
continue;
}
const LoopT *Loop = LI->getLoopFor(RPOT[Index]);
if (!Loop)
continue;
BlockNode Header = getNode(Loop->getHeader());
assert(Header.isValid());
const auto &HeaderData = Working[Header.Index];
assert(HeaderData.isLoopHeader());
Working[Index].Loop = HeaderData.Loop;
HeaderData.Loop->Nodes.push_back(Index);
DEBUG(dbgs() << " - loop = " << getBlockName(Header)
<< ": member = " << getBlockName(Index) << "\n");
}
}
template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInLoops() {
for (auto L = Loops.rbegin(), E = Loops.rend(); L != E; ++L) {
if (computeMassInLoop(*L))
continue;
auto Next = std::next(L);
computeIrreducibleMass(&*L, L.base());
L = std::prev(Next);
if (computeMassInLoop(*L))
continue;
llvm_unreachable("unhandled irreducible control flow");
}
}
template <class BT>
bool BlockFrequencyInfoImpl<BT>::computeMassInLoop(LoopData &Loop) {
DEBUG(dbgs() << "compute-mass-in-loop: " << getLoopName(Loop) << "\n");
if (Loop.isIrreducible()) {
BlockMass Remaining = BlockMass::getFull();
for (uint32_t H = 0; H < Loop.NumHeaders; ++H) {
auto &Mass = Working[Loop.Nodes[H].Index].getMass();
Mass = Remaining * BranchProbability(1, Loop.NumHeaders - H);
Remaining -= Mass;
}
for (const BlockNode &M : Loop.Nodes)
if (!propagateMassToSuccessors(&Loop, M))
llvm_unreachable("unhandled irreducible control flow");
} else {
Working[Loop.getHeader().Index].getMass() = BlockMass::getFull();
if (!propagateMassToSuccessors(&Loop, Loop.getHeader()))
llvm_unreachable("irreducible control flow to loop header!?");
for (const BlockNode &M : Loop.members())
if (!propagateMassToSuccessors(&Loop, M))
return false;
}
computeLoopScale(Loop);
packageLoop(Loop);
return true;
}
template <class BT>
bool BlockFrequencyInfoImpl<BT>::tryToComputeMassInFunction() {
DEBUG(dbgs() << "compute-mass-in-function\n");
assert(!Working.empty() && "no blocks in function");
assert(!Working[0].isLoopHeader() && "entry block is a loop header");
Working[0].getMass() = BlockMass::getFull();
for (rpot_iterator I = rpot_begin(), IE = rpot_end(); I != IE; ++I) {
BlockNode Node = getNode(I);
if (Working[Node.Index].isPackaged())
continue;
if (!propagateMassToSuccessors(nullptr, Node))
return false;
}
return true;
}
template <class BT> void BlockFrequencyInfoImpl<BT>::computeMassInFunction() {
if (tryToComputeMassInFunction())
return;
computeIrreducibleMass(nullptr, Loops.begin());
if (tryToComputeMassInFunction())
return;
llvm_unreachable("unhandled irreducible control flow");
}
namespace bfi_detail {
template <class BT> struct BlockEdgesAdder {
typedef BT BlockT;
typedef BlockFrequencyInfoImplBase::LoopData LoopData;
typedef GraphTraits<const BlockT *> Successor;
const BlockFrequencyInfoImpl<BT> &BFI;
explicit BlockEdgesAdder(const BlockFrequencyInfoImpl<BT> &BFI)
: BFI(BFI) {}
void operator()(IrreducibleGraph &G, IrreducibleGraph::IrrNode &Irr,
const LoopData *OuterLoop) {
const BlockT *BB = BFI.RPOT[Irr.Node.Index];
for (auto I = Successor::child_begin(BB), E = Successor::child_end(BB);
I != E; ++I)
G.addEdge(Irr, BFI.getNode(*I), OuterLoop);
}
};
}
template <class BT>
void BlockFrequencyInfoImpl<BT>::computeIrreducibleMass(
LoopData *OuterLoop, std::list<LoopData>::iterator Insert) {
DEBUG(dbgs() << "analyze-irreducible-in-";
if (OuterLoop) dbgs() << "loop: " << getLoopName(*OuterLoop) << "\n";
else dbgs() << "function\n");
using namespace bfi_detail;
BlockEdgesAdder<BT> addBlockEdges(*this);
IrreducibleGraph G(*this, OuterLoop, addBlockEdges);
for (auto &L : analyzeIrreducible(G, OuterLoop, Insert))
computeMassInLoop(L);
if (!OuterLoop)
return;
updateLoopWithIrreducible(*OuterLoop);
}
template <class BT>
bool
BlockFrequencyInfoImpl<BT>::propagateMassToSuccessors(LoopData *OuterLoop,
const BlockNode &Node) {
DEBUG(dbgs() << " - node: " << getBlockName(Node) << "\n");
Distribution Dist;
if (auto *Loop = Working[Node.Index].getPackagedLoop()) {
assert(Loop != OuterLoop && "Cannot propagate mass in a packaged loop");
if (!addLoopSuccessorsToDist(OuterLoop, *Loop, Dist))
return false;
} else {
const BlockT *BB = getBlock(Node);
for (auto SI = Successor::child_begin(BB), SE = Successor::child_end(BB);
SI != SE; ++SI)
if (!addToDist(Dist, OuterLoop, Node, getNode(*SI),
BPI->getEdgeWeight(BB, SI)))
return false;
}
distributeMass(Node, OuterLoop, Dist);
return true;
}
template <class BT>
raw_ostream &BlockFrequencyInfoImpl<BT>::print(raw_ostream &OS) const {
if (!F)
return OS;
OS << "block-frequency-info: " << F->getName() << "\n";
for (const BlockT &BB : *F)
OS << " - " << bfi_detail::getBlockName(&BB)
<< ": float = " << getFloatingBlockFreq(&BB)
<< ", int = " << getBlockFreq(&BB).getFrequency() << "\n";
OS << "\n";
return OS;
}
}
#undef DEBUG_TYPE
#endif