Path: blob/main/contrib/llvm-project/llvm/lib/CodeGenData/OutlinedHashTree.cpp
35232 views
//===-- OutlinedHashTree.cpp ----------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// An OutlinedHashTree is a Trie that contains sequences of stable hash values9// of instructions that have been outlined. This OutlinedHashTree can be used10// to understand the outlined instruction sequences collected across modules.11//12//===----------------------------------------------------------------------===//1314#include "llvm/CodeGenData/OutlinedHashTree.h"1516#define DEBUG_TYPE "outlined-hash-tree"1718using namespace llvm;1920void OutlinedHashTree::walkGraph(NodeCallbackFn CallbackNode,21EdgeCallbackFn CallbackEdge,22bool SortedWalk) const {23SmallVector<const HashNode *> Stack;24Stack.emplace_back(getRoot());2526while (!Stack.empty()) {27const auto *Current = Stack.pop_back_val();28if (CallbackNode)29CallbackNode(Current);3031auto HandleNext = [&](const HashNode *Next) {32if (CallbackEdge)33CallbackEdge(Current, Next);34Stack.emplace_back(Next);35};36if (SortedWalk) {37SmallVector<std::pair<stable_hash, const HashNode *>> SortedSuccessors;38for (const auto &[Hash, Successor] : Current->Successors)39SortedSuccessors.emplace_back(Hash, Successor.get());40llvm::sort(SortedSuccessors);41for (const auto &P : SortedSuccessors)42HandleNext(P.second);43} else {44for (const auto &P : Current->Successors)45HandleNext(P.second.get());46}47}48}4950size_t OutlinedHashTree::size(bool GetTerminalCountOnly) const {51size_t Size = 0;52walkGraph([&Size, GetTerminalCountOnly](const HashNode *N) {53Size += (N && (!GetTerminalCountOnly || N->Terminals));54});55return Size;56}5758size_t OutlinedHashTree::depth() const {59size_t Size = 0;60DenseMap<const HashNode *, size_t> DepthMap;61walkGraph([&Size, &DepthMap](62const HashNode *N) { Size = std::max(Size, DepthMap[N]); },63[&DepthMap](const HashNode *Src, const HashNode *Dst) {64size_t Depth = DepthMap[Src];65DepthMap[Dst] = Depth + 1;66});67return Size;68}6970void OutlinedHashTree::insert(const HashSequencePair &SequencePair) {71auto &[Sequence, Count] = SequencePair;72HashNode *Current = getRoot();7374for (stable_hash StableHash : Sequence) {75auto I = Current->Successors.find(StableHash);76if (I == Current->Successors.end()) {77std::unique_ptr<HashNode> Next = std::make_unique<HashNode>();78HashNode *NextPtr = Next.get();79NextPtr->Hash = StableHash;80Current->Successors.emplace(StableHash, std::move(Next));81Current = NextPtr;82} else83Current = I->second.get();84}85if (Count)86Current->Terminals = (Current->Terminals ? *Current->Terminals : 0) + Count;87}8889void OutlinedHashTree::merge(const OutlinedHashTree *Tree) {90HashNode *Dst = getRoot();91const HashNode *Src = Tree->getRoot();92SmallVector<std::pair<HashNode *, const HashNode *>> Stack;93Stack.emplace_back(Dst, Src);9495while (!Stack.empty()) {96auto [DstNode, SrcNode] = Stack.pop_back_val();97if (!SrcNode)98continue;99if (SrcNode->Terminals)100DstNode->Terminals =101(DstNode->Terminals ? *DstNode->Terminals : 0) + *SrcNode->Terminals;102for (auto &[Hash, NextSrcNode] : SrcNode->Successors) {103HashNode *NextDstNode;104auto I = DstNode->Successors.find(Hash);105if (I == DstNode->Successors.end()) {106auto NextDst = std::make_unique<HashNode>();107NextDstNode = NextDst.get();108NextDstNode->Hash = Hash;109DstNode->Successors.emplace(Hash, std::move(NextDst));110} else111NextDstNode = I->second.get();112113Stack.emplace_back(NextDstNode, NextSrcNode.get());114}115}116}117118std::optional<unsigned>119OutlinedHashTree::find(const HashSequence &Sequence) const {120const HashNode *Current = getRoot();121for (stable_hash StableHash : Sequence) {122const auto I = Current->Successors.find(StableHash);123if (I == Current->Successors.end())124return 0;125Current = I->second.get();126}127return Current->Terminals;128}129130131