15 #ifndef LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H 16 #define LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H 48 #define DEBUG_TYPE "block-freq" 52 class BranchProbabilityInfo;
56 class MachineBasicBlock;
57 class MachineBranchProbabilityInfo;
58 class MachineFunction;
60 class MachineLoopInfo;
62 namespace bfi_detail {
107 uint64_t Sum = Mass + X.Mass;
117 uint64_t Diff = Mass - X.Mass;
118 Mass = Diff > Mass ? 0 : Diff;
123 Mass = P.
scale(Mass);
164 static const bool value =
true;
202 bool isValid()
const {
return Index <= getMaxIndex(); }
225 bool IsPackaged =
false;
234 : Parent(Parent), Nodes(1, Header), BackedgeMass(1) {}
236 template <
class It1,
class It2>
239 : Parent(Parent), Nodes(FirstHeader, LastHeader) {
240 NumHeaders = Nodes.
size();
241 Nodes.
insert(Nodes.
end(), FirstOther, LastOther);
242 BackedgeMass.
resize(NumHeaders);
247 return std::binary_search(Nodes.
begin(), Nodes.
begin() + NumHeaders,
249 return Node == Nodes[0];
256 assert(isHeader(B) &&
"this is only valid on loop header blocks");
264 return Nodes.
begin() + NumHeaders;
269 return make_range(members_begin(), members_end());
291 if (!isDoubleLoopHeader())
310 auto L = getPackagedLoop();
311 return L ? L->getHeader() : Node;
318 while (L->Parent && L->Parent->IsPackaged)
331 if (!isADoublePackage())
337 bool isPackaged()
const {
return getResolvedNode() != Node; }
369 : Type(Type), TargetNode(TargetNode), Amount(Amount) {}
385 bool DidOverflow =
false;
390 add(Node, Amount, Weight::Local);
394 add(Node, Amount, Weight::Exit);
398 add(Node, Amount, Weight::Backedge);
457 return *Working[Head.
Index].Loop;
469 std::list<LoopData>::iterator Insert);
477 void updateLoopWithIrreducible(
LoopData &OuterLoop);
499 void adjustLoopHeaderMass(
LoopData &Loop);
513 void finalizeMetrics();
519 std::string getLoopName(
const LoopData &Loop)
const;
530 uint64_t Freq)
const;
531 bool isIrrLoopHeader(
const BlockNode &Node);
533 void setBlockFreq(
const BlockNode &Node, uint64_t Freq);
541 return Freqs[0].Integer;
545 namespace bfi_detail {
571 assert(BB &&
"Unexpected nullptr");
572 auto MachineName =
"BB" +
Twine(BB->getNumber());
573 if (BB->getBasicBlock())
574 return (MachineName +
"[" + BB->getName() +
"]").str();
575 return MachineName.
str();
579 assert(BB &&
"Unexpected nullptr");
610 using iterator = std::deque<const IrrNode *>::const_iterator;
631 template <
class BlockEdgesAdder>
637 template <
class BlockEdgesAdder>
641 void addNodesInFunction();
644 Nodes.emplace_back(Node);
649 template <
class BlockEdgesAdder>
656 template <
class BlockEdgesAdder>
660 addNodesInLoop(*OuterLoop);
661 for (
auto N : OuterLoop->
Nodes)
662 addEdges(
N, OuterLoop, addBlockEdges);
664 addNodesInFunction();
666 addEdges(
Index, OuterLoop, addBlockEdges);
668 StartIrr =
Lookup[Start.Index];
671 template <
class BlockEdgesAdder>
679 const auto &Working =
BFI.Working[Node.
Index];
681 if (Working.isAPackage())
682 for (
const auto &
I : Working.Loop->Exits)
685 addBlockEdges(*
this, Irr, OuterLoop);
849 using BranchProbabilityInfoT =
856 const BranchProbabilityInfoT *BPI =
nullptr;
857 const LoopInfoT *LI =
nullptr;
858 const FunctionT *
F =
nullptr;
861 std::vector<const BlockT *> RPOT;
864 using rpot_iterator =
typename std::vector<const BlockT *>::const_iterator;
866 rpot_iterator rpot_begin()
const {
return RPOT.
begin(); }
867 rpot_iterator rpot_end()
const {
return RPOT.end(); }
869 size_t getIndex(
const rpot_iterator &
I)
const {
return I - rpot_begin(); }
871 BlockNode getNode(
const rpot_iterator &
I)
const {
876 const BlockT *getBlock(
const BlockNode &Node)
const {
878 return RPOT[Node.
Index];
884 void initializeRPOT();
893 void initializeLoops();
921 bool tryToComputeMassInFunction();
935 void computeIrreducibleMass(
LoopData *OuterLoop,
936 std::list<LoopData>::iterator Insert);
947 void computeMassInLoops();
955 void computeMassInFunction();
966 void calculate(
const FunctionT &F,
const BranchProbabilityInfoT &BPI,
967 const LoopInfoT &LI);
976 const BlockT *BB)
const {
981 uint64_t Freq)
const {
989 void setBlockFreq(
const BlockT *BB, uint64_t Freq);
995 const BranchProbabilityInfoT &
getBPI()
const {
return *BPI; }
1020 const BranchProbabilityInfoT &BPI,
1021 const LoopInfoT &LI) {
1034 <<
"\n=================" 1035 << std::string(F.getName().size(),
'=') <<
"\n");
1041 computeMassInLoops();
1042 computeMassInFunction();
1049 if (Nodes.
count(BB))
1056 Nodes[BB] = NewNode;
1057 Freqs.emplace_back();
1063 const BlockT *Entry = &F->front();
1064 RPOT.reserve(F->size());
1068 assert(RPOT.size() - 1 <= BlockNode::getMaxIndex() &&
1069 "More nodes in function than Block Frequency Info supports");
1072 for (rpot_iterator I = rpot_begin(),
E = rpot_end(); I !=
E; ++
I) {
1079 Working.reserve(RPOT.size());
1081 Working.emplace_back(
Index);
1082 Freqs.resize(RPOT.size());
1091 std::deque<std::pair<const LoopT *, LoopData *>> Q;
1092 for (
const LoopT *L : *LI)
1093 Q.emplace_back(L,
nullptr);
1094 while (!Q.empty()) {
1095 const LoopT *
Loop = Q.front().first;
1096 LoopData *Parent = Q.front().second;
1099 BlockNode Header = getNode(Loop->getHeader());
1102 Loops.emplace_back(Parent, Header);
1106 for (
const LoopT *L : *Loop)
1107 Q.emplace_back(L, &
Loops.back());
1114 if (Working[
Index].isLoopHeader()) {
1115 LoopData *ContainingLoop = Working[
Index].getContainingLoop();
1121 const LoopT *
Loop = LI->getLoopFor(RPOT[
Index]);
1126 BlockNode Header = getNode(Loop->getHeader());
1128 const auto &HeaderData = Working[Header.
Index];
1129 assert(HeaderData.isLoopHeader());
1131 Working[
Index].Loop = HeaderData.Loop;
1132 HeaderData.Loop->Nodes.push_back(Index);
1140 for (
auto L =
Loops.rbegin(),
E =
Loops.rend(); L !=
E; ++L) {
1141 if (computeMassInLoop(*L))
1143 auto Next = std::next(L);
1144 computeIrreducibleMass(&*L, L.base());
1145 L = std::prev(Next);
1146 if (computeMassInLoop(*L))
1155 LLVM_DEBUG(
dbgs() <<
"compute-mass-in-loop: " << getLoopName(Loop) <<
"\n");
1160 unsigned NumHeadersWithWeight = 0;
1165 auto &HeaderNode = Loop.
Nodes[
H];
1166 const BlockT *Block = getBlock(HeaderNode);
1167 IsIrrLoopHeader.set(Loop.
Nodes[
H].Index);
1169 if (!HeaderWeight) {
1172 HeadersWithoutWeight.
insert(
H);
1176 <<
" has irr loop header weight " 1177 << HeaderWeight.
getValue() <<
"\n");
1178 NumHeadersWithWeight++;
1179 uint64_t HeaderWeightValue = HeaderWeight.
getValue();
1180 if (!MinHeaderWeight || HeaderWeightValue < MinHeaderWeight)
1181 MinHeaderWeight = HeaderWeightValue;
1182 if (HeaderWeightValue) {
1183 Dist.
addLocal(HeaderNode, HeaderWeightValue);
1192 if (!MinHeaderWeight)
1193 MinHeaderWeight = 1;
1194 for (
uint32_t H : HeadersWithoutWeight) {
1195 auto &HeaderNode = Loop.
Nodes[
H];
1196 assert(!getBlock(HeaderNode)->getIrrLoopHeaderWeight() &&
1197 "Shouldn't have a weight metadata");
1198 uint64_t MinWeight = MinHeaderWeight.
getValue();
1202 Dist.
addLocal(HeaderNode, MinWeight);
1204 distributeIrrLoopHeaderMass(Dist);
1206 if (!propagateMassToSuccessors(&Loop, M))
1208 if (NumHeadersWithWeight == 0)
1210 adjustLoopHeaderMass(Loop);
1213 if (!propagateMassToSuccessors(&Loop, Loop.
getHeader()))
1216 if (!propagateMassToSuccessors(&Loop, M))
1221 computeLoopScale(Loop);
1230 assert(!Working.empty() &&
"no blocks in function");
1231 assert(!Working[0].isLoopHeader() &&
"entry block is a loop header");
1234 for (rpot_iterator I = rpot_begin(),
IE = rpot_end(); I !=
IE; ++
I) {
1237 if (Working[Node.
Index].isPackaged())
1240 if (!propagateMassToSuccessors(
nullptr, Node))
1247 if (tryToComputeMassInFunction())
1249 computeIrreducibleMass(
nullptr,
Loops.begin());
1250 if (tryToComputeMassInFunction())
1256 namespace bfi_detail {
1258 template <
class BT>
struct BlockEdgesAdder {
1270 const BlockT *BB = BFI.RPOT[Irr.
Node.
Index];
1271 for (
const auto Succ : children<const BlockT *>(BB))
1272 G.
addEdge(Irr, BFI.getNode(Succ), OuterLoop);
1280 LoopData *OuterLoop, std::list<LoopData>::iterator Insert) {
1282 if (OuterLoop)
dbgs()
1283 <<
"loop: " << getLoopName(*OuterLoop) <<
"\n";
1284 else dbgs() <<
"function\n");
1286 using namespace bfi_detail;
1293 for (
auto &L : analyzeIrreducible(G, OuterLoop, Insert))
1294 computeMassInLoop(L);
1298 updateLoopWithIrreducible(*OuterLoop);
1309 const BlockNode &Node) {
1313 if (
auto *Loop = Working[Node.Index].getPackagedLoop()) {
1314 assert(Loop != OuterLoop &&
"Cannot propagate mass in a packaged loop");
1315 if (!addLoopSuccessorsToDist(OuterLoop, *Loop, Dist))
1319 const BlockT *BB = getBlock(Node);
1324 Dist, OuterLoop, Node, getNode(*
SI),
1332 distributeMass(Node, OuterLoop, Dist);
1340 OS <<
"block-frequency-info: " << F->getName() <<
"\n";
1341 for (
const BlockT &BB : *F) {
1343 getFloatingBlockFreq(&BB).print(OS, 5)
1344 <<
", int = " << getBlockFreq(&BB).getFrequency();
1347 F->getFunction(), getNode(&BB)))
1350 BB.getIrrLoopHeaderWeight())
1351 OS <<
", irr_loop_header_weight = " << IrrLoopHeaderWeight.getValue();
1365 template <
class BlockFrequencyInfoT,
class BranchProbabilityInfoT>
1372 uint64_t MaxFrequency = 0;
1378 return G->getFunction()->getName();
1382 unsigned HotPercentThreshold = 0) {
1384 if (!HotPercentThreshold)
1388 if (!MaxFrequency) {
1389 for (
NodeIter I = GTraits::nodes_begin(Graph),
1390 E = GTraits::nodes_end(Graph);
1394 std::max(MaxFrequency, Graph->getBlockFreq(N).getFrequency());
1406 OS <<
"color=\"red\"";
1412 GVDAGType GType,
int layout_order = -1) {
1416 if (layout_order != -1)
1417 OS << Node->getName() <<
"[" << layout_order <<
"] : ";
1419 OS << Node->getName() <<
" : ";
1422 Graph->printBlockFreq(OS, Node);
1425 OS << Graph->getBlockFreq(Node).getFrequency();
1428 auto Count = Graph->getBlockProfileCount(Node);
1430 OS << Count.getValue();
1437 "never reach this point.");
1443 const BlockFrequencyInfoT *
BFI,
1444 const BranchProbabilityInfoT *BPI,
1445 unsigned HotPercentThreshold = 0) {
1455 OS <<
format(
"label=\"%.1f%%\"", Percent);
1457 if (HotPercentThreshold) {
1462 if (EFreq >= HotFreq) {
1463 OS <<
",color=\"red\"";
1476 #endif // LLVM_ANALYSIS_BLOCKFREQUENCYINFOIMPL_H BlockMass operator+(BlockMass L, BlockMass R)
bool operator!=(const BlockNode &X) const
void setBlockFreq(const BlockT *BB, uint64_t Freq)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang", "erlang-compatible garbage collector")
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
bool IsPackaged
Whether this has been packaged.
LLVM_NODISCARD std::string str() const
str - Get the contents as an std::string.
bool operator<=(BlockMass X) const
typename SuperClass::const_iterator const_iterator
This class represents lattice values for constants.
Scaled64 getFloatingBlockFreq(const BlockT *BB) const
bool isIrrLoopHeader(const BlockT *BB)
LoopData(LoopData *Parent, It1 FirstHeader, It1 LastHeader, It2 FirstOther, It2 LastOther)
void push_back(const T &Elt)
NodeList::const_iterator members_begin() const
This provides a very simple, boring adaptor for a begin and end iterator into a range type...
Index of loop information.
iterator succ_begin() const
Stats about a block itself.
raw_ostream & printBlockFreq(raw_ostream &OS, const BlockNode &Node) const
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
static std::string getGraphName(const BlockFrequencyInfoT *G)
BlockFrequency getBlockFreq(const BlockT *BB) const
Optional< uint64_t > getBlockProfileCount(const Function &F, const BlockT *BB) const
raw_ostream & print(raw_ostream &OS) const
const BranchProbabilityInfoT & getBPI() const
void addLocal(const BlockNode &Node, uint64_t Amount)
SmallDenseMap< uint32_t, IrrNode *, 4 > Lookup
LoopData * Parent
The parent loop.
BlockNode getHeader() const
uint32_t NumHeaders
Number of headers.
IrreducibleGraph(BFIBase &BFI, const BFIBase::LoopData *OuterLoop, BlockEdgesAdder addBlockEdges)
Construct an explicit graph containing irreducible control flow.
const BlockFrequencyInfoImpl< BT > & BFI
void setBlockFreq(const BlockNode &Node, uint64_t Freq)
WorkingData(const BlockNode &Node)
BFIDOTGraphTraitsBase(bool isSimple=false)
SparseBitVector IsIrrLoopHeader
Whether each block is an irreducible loop header.
iterator succ_end() const
bool operator<(const BlockNode &X) const
void operator()(IrreducibleGraph &G, IrreducibleGraph::IrrNode &Irr, const LoopData *OuterLoop)
Weight(DistType Type, BlockNode TargetNode, uint64_t Amount)
NodeList::const_iterator members_end() const
uint32_t getWeightFromBranchProb(const BranchProbability Prob)
BlockMass & getMass()
Get the appropriate mass for a node.
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Scaled64 getFloatingBlockFreq(const BlockNode &Node) const
static int Lookup(ArrayRef< TableEntry > Table, unsigned Opcode)
bool isAPackage() const
Has Loop been packaged up?
virtual raw_ostream & print(raw_ostream &OS) const
std::string getNodeLabel(NodeRef Node, const BlockFrequencyInfoT *Graph, GVDAGType GType, int layout_order=-1)
void addEdge(IrrNode &Irr, const BlockNode &Succ, const BFIBase::LoopData *OuterLoop)
BlockMass & operator*=(BranchProbability P)
bool operator>=(BlockMass X) const
LoopData * getContainingLoop() const
Interval::succ_iterator succ_begin(Interval *I)
succ_begin/succ_end - define methods so that Intervals may be used just like BasicBlocks can with the...
static bool isSimple(Instruction *I)
auto reverse(ContainerTy &&C, typename std::enable_if< has_rbegin< ContainerTy >::value >::type *=nullptr) -> decltype(make_range(C.rbegin(), C.rend()))
bool operator==(BlockMass X) const
Graph of irreducible control flow.
const T & getValue() const LLVM_LVALUE_FUNCTION
bool operator>(const BlockNode &X) const
std::deque< const IrrNode * >::const_iterator iterator
bool operator>=(const BlockNode &X) const
IrrNode(const BlockNode &Node)
bool isLoopHeader() const
bool operator==(const BlockNode &X) const
auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range))
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
void calculate(const FunctionT &F, const BranchProbabilityInfoT &BPI, const LoopInfoT &LI)
static void addEdge(SmallVectorImpl< LazyCallGraph::Edge > &Edges, DenseMap< LazyCallGraph::Node *, int > &EdgeIndexMap, LazyCallGraph::Node &N, LazyCallGraph::Edge::Kind EK)
raw_ostream & print(raw_ostream &OS) const override
Print the frequencies for the current function.
void addBackedge(const BlockNode &Node, uint64_t Amount)
void initialize(const BFIBase::LoopData *OuterLoop, BlockEdgesAdder addBlockEdges)
bool isHeader(const BlockNode &Node) const
Optional< uint64_t > getProfileCountFromFreq(const Function &F, uint64_t Freq) const
bool isIrrLoopHeader(const BlockNode &Node)
std::vector< FrequencyData > Freqs
Data about each block. This is used downstream.
typename GraphType::UnknownGraphTypeError NodeRef
bool isIrreducible() const
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
LLVM Basic Block Representation.
The instances of the Type class are immutable: once they are created, they are never changed...
BlockMass & operator-=(BlockMass X)
Subtract another mass.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
BlockMass & operator+=(BlockMass X)
Add another mass.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Distribution of unscaled probability weight.
std::pair< iterator, bool > insert(const ValueT &V)
bool operator<=(const BlockNode &X) const
void addNode(const BlockNode &Node)
po_iterator< T > po_end(const T &G)
Optional< uint64_t > getProfileCountFromFreq(const Function &F, uint64_t Freq) const
BlockNode getResolvedNode() const
Resolve a node to its representative.
BlockMass Mass
Mass distribution from the entry block.
typename GTraits::NodeRef NodeRef
void clear()
Clear all memory.
BlockEdgesAdder(const BlockFrequencyInfoImpl< BT > &BFI)
BlockMass operator*(BlockMass L, BranchProbability R)
Class to represent profile counts.
std::string getEdgeAttributes(NodeRef Node, EdgeIter EI, const BlockFrequencyInfoT *BFI, const BranchProbabilityInfoT *BPI, unsigned HotPercentThreshold=0)
raw_ostream & operator<<(raw_ostream &OS, BlockMass X)
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
void addExit(const BlockNode &Node, uint64_t Amount)
BlockNode(IndexType Index)
std::string getNodeAttributes(NodeRef Node, const BlockFrequencyInfoT *Graph, unsigned HotPercentThreshold=0)
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
LoopData * getPackagedLoop() const
isPodLike - This is a type trait that is used to determine whether a given type can be copied around ...
static uint32_t getDenominator()
bool isADoublePackage() const
Has Loop been packaged up twice?
ExitMap Exits
Successor edges (and weights).
uint64_t getEntryFreq() const
static BranchProbability getBranchProbability(uint64_t Numerator, uint64_t Denominator)
bool isDoubleLoopHeader() const
BlockMass operator-(BlockMass L, BlockMass R)
uint64_t scale(uint64_t Num) const
Scale a large integer.
static GCRegistry::Add< StatepointGC > D("statepoint-example", "an example strategy for statepoint")
static BlockMass getEmpty()
ScaledNumber< uint64_t > toScaled() const
Convert to scaled number.
std::list< LoopData > Loops
Indexed information about loops.
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
A range adaptor for a pair of iterators.
std::string getBlockName(const BlockT *BB)
Get the name of a MachineBasicBlock.
static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, ArrayRef< StringRef > StandardNames)
Initialize the set of available library functions based on the specified target triple.
LoopData(LoopData *Parent, const BlockNode &Header)
static void clear(coro::Shape &Shape)
iterator insert(iterator I, T &&Elt)
iterator pred_end() const
Unscaled probability weight.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Analysis providing branch probability information.
iterator pred_begin() const
bool operator>(BlockMass X) const
void addEdges(const BlockNode &Node, const BFIBase::LoopData *OuterLoop, BlockEdgesAdder addBlockEdges)
Represents a single loop in the control flow graph.
raw_ostream & printBlockFreq(raw_ostream &OS, const BlockT *BB) const
StringRef getName() const
Return a constant reference to the value's name.
void reserve(size_t Size)
Grow the DenseSet so that it can contain at least NumEntries items before resizing again...
typename GTraits::ChildIteratorType EdgeIter
typename GTraits::nodes_iterator NodeIter
static BlockMass getFull()
size_type count(const_arg_type_t< KeyT > Val) const
Return 1 if the specified key is in the map, 0 otherwise.
std::string str() const
Return the twine contents as a std::string.
ValueT lookup(const_arg_type_t< KeyT > Val) const
lookup - Return the entry for the specified key, or a default constructed value if no such entry exis...
iterator_range< NodeList::const_iterator > members() const
bool operator!=(BlockMass X) const
NodeList Nodes
Header and the members of the loop.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
A raw_ostream that writes to an std::string.
bool operator<(BlockMass X) const
std::vector< WorkingData > Working
Loop data: see initializeLoops().
std::vector< IrrNode > Nodes
HeaderMassList BackedgeMass
Mass returned to each loop header.
This class implements an extremely fast bulk output stream that can only output to a stream...
DefaultDOTGraphTraits - This class provides the default implementations of all of the DOTGraphTraits ...
Optional< uint64_t > getBlockProfileCount(const Function &F, const BlockNode &Node) const
const FunctionT * getFunction() const
Shared implementation for block frequency analysis.
static size_t getMaxIndex()
BlockFrequency getBlockFreq(const BlockNode &Node) const
std::deque< const IrrNode * > Edges
Base class for BlockFrequencyInfoImpl.
OutputIt copy(R &&Range, OutputIt Out)
HeaderMassList::difference_type getHeaderIndex(const BlockNode &B)
LoopData & getLoopPackage(const BlockNode &Head)
uint32_t getNumerator() const
bool isPackaged() const
Has ContainingLoop been packaged up?
Representative of a block.
po_iterator< T > po_begin(const T &G)
WeightList Weights
Individual successor weights.