19bb55568SKyungwoo Lee //===-- OutlinedHashTree.cpp ----------------------------------------------===// 29bb55568SKyungwoo Lee // 39bb55568SKyungwoo Lee // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 49bb55568SKyungwoo Lee // See https://llvm.org/LICENSE.txt for license information. 59bb55568SKyungwoo Lee // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 69bb55568SKyungwoo Lee // 79bb55568SKyungwoo Lee //===----------------------------------------------------------------------===// 89bb55568SKyungwoo Lee // 99bb55568SKyungwoo Lee // An OutlinedHashTree is a Trie that contains sequences of stable hash values 109bb55568SKyungwoo Lee // of instructions that have been outlined. This OutlinedHashTree can be used 119bb55568SKyungwoo Lee // to understand the outlined instruction sequences collected across modules. 129bb55568SKyungwoo Lee // 139bb55568SKyungwoo Lee //===----------------------------------------------------------------------===// 149bb55568SKyungwoo Lee 159bb55568SKyungwoo Lee #include "llvm/CGData/OutlinedHashTree.h" 169bb55568SKyungwoo Lee 179bb55568SKyungwoo Lee #define DEBUG_TYPE "outlined-hash-tree" 189bb55568SKyungwoo Lee 199bb55568SKyungwoo Lee using namespace llvm; 209bb55568SKyungwoo Lee 219bb55568SKyungwoo Lee void OutlinedHashTree::walkGraph(NodeCallbackFn CallbackNode, 229bb55568SKyungwoo Lee EdgeCallbackFn CallbackEdge, 239bb55568SKyungwoo Lee bool SortedWalk) const { 249bb55568SKyungwoo Lee SmallVector<const HashNode *> Stack; 259bb55568SKyungwoo Lee Stack.emplace_back(getRoot()); 269bb55568SKyungwoo Lee 279bb55568SKyungwoo Lee while (!Stack.empty()) { 289bb55568SKyungwoo Lee const auto *Current = Stack.pop_back_val(); 299bb55568SKyungwoo Lee if (CallbackNode) 309bb55568SKyungwoo Lee CallbackNode(Current); 319bb55568SKyungwoo Lee 329bb55568SKyungwoo Lee auto HandleNext = [&](const HashNode *Next) { 339bb55568SKyungwoo Lee if (CallbackEdge) 349bb55568SKyungwoo Lee CallbackEdge(Current, Next); 359bb55568SKyungwoo Lee Stack.emplace_back(Next); 369bb55568SKyungwoo Lee }; 379bb55568SKyungwoo Lee if (SortedWalk) { 389bb55568SKyungwoo Lee SmallVector<std::pair<stable_hash, const HashNode *>> SortedSuccessors; 399bb55568SKyungwoo Lee for (const auto &[Hash, Successor] : Current->Successors) 409bb55568SKyungwoo Lee SortedSuccessors.emplace_back(Hash, Successor.get()); 419bb55568SKyungwoo Lee llvm::sort(SortedSuccessors); 429bb55568SKyungwoo Lee for (const auto &P : SortedSuccessors) 439bb55568SKyungwoo Lee HandleNext(P.second); 449bb55568SKyungwoo Lee } else { 459bb55568SKyungwoo Lee for (const auto &P : Current->Successors) 469bb55568SKyungwoo Lee HandleNext(P.second.get()); 479bb55568SKyungwoo Lee } 489bb55568SKyungwoo Lee } 499bb55568SKyungwoo Lee } 509bb55568SKyungwoo Lee 519bb55568SKyungwoo Lee size_t OutlinedHashTree::size(bool GetTerminalCountOnly) const { 529bb55568SKyungwoo Lee size_t Size = 0; 539bb55568SKyungwoo Lee walkGraph([&Size, GetTerminalCountOnly](const HashNode *N) { 549bb55568SKyungwoo Lee Size += (N && (!GetTerminalCountOnly || N->Terminals)); 559bb55568SKyungwoo Lee }); 569bb55568SKyungwoo Lee return Size; 579bb55568SKyungwoo Lee } 589bb55568SKyungwoo Lee 599bb55568SKyungwoo Lee size_t OutlinedHashTree::depth() const { 609bb55568SKyungwoo Lee size_t Size = 0; 619bb55568SKyungwoo Lee DenseMap<const HashNode *, size_t> DepthMap; 629bb55568SKyungwoo Lee walkGraph([&Size, &DepthMap]( 639bb55568SKyungwoo Lee const HashNode *N) { Size = std::max(Size, DepthMap[N]); }, 649bb55568SKyungwoo Lee [&DepthMap](const HashNode *Src, const HashNode *Dst) { 659bb55568SKyungwoo Lee size_t Depth = DepthMap[Src]; 669bb55568SKyungwoo Lee DepthMap[Dst] = Depth + 1; 679bb55568SKyungwoo Lee }); 689bb55568SKyungwoo Lee return Size; 699bb55568SKyungwoo Lee } 709bb55568SKyungwoo Lee 719bb55568SKyungwoo Lee void OutlinedHashTree::insert(const HashSequencePair &SequencePair) { 729bb55568SKyungwoo Lee auto &[Sequence, Count] = SequencePair; 739bb55568SKyungwoo Lee HashNode *Current = getRoot(); 749bb55568SKyungwoo Lee 759bb55568SKyungwoo Lee for (stable_hash StableHash : Sequence) { 769bb55568SKyungwoo Lee auto I = Current->Successors.find(StableHash); 779bb55568SKyungwoo Lee if (I == Current->Successors.end()) { 789bb55568SKyungwoo Lee std::unique_ptr<HashNode> Next = std::make_unique<HashNode>(); 799bb55568SKyungwoo Lee HashNode *NextPtr = Next.get(); 809bb55568SKyungwoo Lee NextPtr->Hash = StableHash; 819bb55568SKyungwoo Lee Current->Successors.emplace(StableHash, std::move(Next)); 829bb55568SKyungwoo Lee Current = NextPtr; 839bb55568SKyungwoo Lee } else 849bb55568SKyungwoo Lee Current = I->second.get(); 859bb55568SKyungwoo Lee } 869bb55568SKyungwoo Lee if (Count) 87*e4e3ff5aSKazu Hirata Current->Terminals = Current->Terminals.value_or(0) + Count; 889bb55568SKyungwoo Lee } 899bb55568SKyungwoo Lee 909bb55568SKyungwoo Lee void OutlinedHashTree::merge(const OutlinedHashTree *Tree) { 919bb55568SKyungwoo Lee HashNode *Dst = getRoot(); 929bb55568SKyungwoo Lee const HashNode *Src = Tree->getRoot(); 939bb55568SKyungwoo Lee SmallVector<std::pair<HashNode *, const HashNode *>> Stack; 949bb55568SKyungwoo Lee Stack.emplace_back(Dst, Src); 959bb55568SKyungwoo Lee 969bb55568SKyungwoo Lee while (!Stack.empty()) { 979bb55568SKyungwoo Lee auto [DstNode, SrcNode] = Stack.pop_back_val(); 989bb55568SKyungwoo Lee if (!SrcNode) 999bb55568SKyungwoo Lee continue; 1009bb55568SKyungwoo Lee if (SrcNode->Terminals) 101*e4e3ff5aSKazu Hirata DstNode->Terminals = DstNode->Terminals.value_or(0) + *SrcNode->Terminals; 1029bb55568SKyungwoo Lee for (auto &[Hash, NextSrcNode] : SrcNode->Successors) { 1039bb55568SKyungwoo Lee HashNode *NextDstNode; 1049bb55568SKyungwoo Lee auto I = DstNode->Successors.find(Hash); 1059bb55568SKyungwoo Lee if (I == DstNode->Successors.end()) { 1069bb55568SKyungwoo Lee auto NextDst = std::make_unique<HashNode>(); 1079bb55568SKyungwoo Lee NextDstNode = NextDst.get(); 1089bb55568SKyungwoo Lee NextDstNode->Hash = Hash; 1099bb55568SKyungwoo Lee DstNode->Successors.emplace(Hash, std::move(NextDst)); 1109bb55568SKyungwoo Lee } else 1119bb55568SKyungwoo Lee NextDstNode = I->second.get(); 1129bb55568SKyungwoo Lee 1139bb55568SKyungwoo Lee Stack.emplace_back(NextDstNode, NextSrcNode.get()); 1149bb55568SKyungwoo Lee } 1159bb55568SKyungwoo Lee } 1169bb55568SKyungwoo Lee } 1179bb55568SKyungwoo Lee 1189bb55568SKyungwoo Lee std::optional<unsigned> 1199bb55568SKyungwoo Lee OutlinedHashTree::find(const HashSequence &Sequence) const { 1209bb55568SKyungwoo Lee const HashNode *Current = getRoot(); 1219bb55568SKyungwoo Lee for (stable_hash StableHash : Sequence) { 1229bb55568SKyungwoo Lee const auto I = Current->Successors.find(StableHash); 1239bb55568SKyungwoo Lee if (I == Current->Successors.end()) 1249bb55568SKyungwoo Lee return 0; 1259bb55568SKyungwoo Lee Current = I->second.get(); 1269bb55568SKyungwoo Lee } 1279bb55568SKyungwoo Lee return Current->Terminals; 1289bb55568SKyungwoo Lee } 129