xref: /llvm-project/llvm/lib/CGData/OutlinedHashTree.cpp (revision e4e3ff5adc8b374be0620223ea2b654adde038ea)
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