xref: /llvm-project/llvm/lib/CGData/StableFunctionMap.cpp (revision 7ec26b23f27f2adfe6847bc69debb84efa34ed08)
1*7ec26b23SKyungwoo Lee //===-- StableFunctionMap.cpp ---------------------------------------------===//
2*7ec26b23SKyungwoo Lee //
3*7ec26b23SKyungwoo Lee // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*7ec26b23SKyungwoo Lee // See https://llvm.org/LICENSE.txt for license information.
5*7ec26b23SKyungwoo Lee // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*7ec26b23SKyungwoo Lee //
7*7ec26b23SKyungwoo Lee //===----------------------------------------------------------------------===//
8*7ec26b23SKyungwoo Lee //
9*7ec26b23SKyungwoo Lee // This implements the functionality for the StableFunctionMap class, which
10*7ec26b23SKyungwoo Lee // manages the mapping of stable function hashes to their metadata. It includes
11*7ec26b23SKyungwoo Lee // methods for inserting, merging, and finalizing function entries, as well as
12*7ec26b23SKyungwoo Lee // utilities for handling function names and IDs.
13*7ec26b23SKyungwoo Lee //
14*7ec26b23SKyungwoo Lee //===----------------------------------------------------------------------===//
15*7ec26b23SKyungwoo Lee 
16*7ec26b23SKyungwoo Lee #include "llvm/CGData/StableFunctionMap.h"
17*7ec26b23SKyungwoo Lee 
18*7ec26b23SKyungwoo Lee #define DEBUG_TYPE "stable-function-map"
19*7ec26b23SKyungwoo Lee 
20*7ec26b23SKyungwoo Lee using namespace llvm;
21*7ec26b23SKyungwoo Lee 
22*7ec26b23SKyungwoo Lee unsigned StableFunctionMap::getIdOrCreateForName(StringRef Name) {
23*7ec26b23SKyungwoo Lee   auto It = NameToId.find(Name);
24*7ec26b23SKyungwoo Lee   if (It != NameToId.end())
25*7ec26b23SKyungwoo Lee     return It->second;
26*7ec26b23SKyungwoo Lee   unsigned Id = IdToName.size();
27*7ec26b23SKyungwoo Lee   assert(Id == NameToId.size() && "ID collision");
28*7ec26b23SKyungwoo Lee   IdToName.emplace_back(Name.str());
29*7ec26b23SKyungwoo Lee   NameToId[IdToName.back()] = Id;
30*7ec26b23SKyungwoo Lee   return Id;
31*7ec26b23SKyungwoo Lee }
32*7ec26b23SKyungwoo Lee 
33*7ec26b23SKyungwoo Lee std::optional<std::string> StableFunctionMap::getNameForId(unsigned Id) const {
34*7ec26b23SKyungwoo Lee   if (Id >= IdToName.size())
35*7ec26b23SKyungwoo Lee     return std::nullopt;
36*7ec26b23SKyungwoo Lee   return IdToName[Id];
37*7ec26b23SKyungwoo Lee }
38*7ec26b23SKyungwoo Lee 
39*7ec26b23SKyungwoo Lee void StableFunctionMap::insert(const StableFunction &Func) {
40*7ec26b23SKyungwoo Lee   assert(!Finalized && "Cannot insert after finalization");
41*7ec26b23SKyungwoo Lee   auto FuncNameId = getIdOrCreateForName(Func.FunctionName);
42*7ec26b23SKyungwoo Lee   auto ModuleNameId = getIdOrCreateForName(Func.ModuleName);
43*7ec26b23SKyungwoo Lee   auto IndexOperandHashMap = std::make_unique<IndexOperandHashMapType>();
44*7ec26b23SKyungwoo Lee   for (auto &[Index, Hash] : Func.IndexOperandHashes)
45*7ec26b23SKyungwoo Lee     (*IndexOperandHashMap)[Index] = Hash;
46*7ec26b23SKyungwoo Lee   auto FuncEntry = std::make_unique<StableFunctionEntry>(
47*7ec26b23SKyungwoo Lee       Func.Hash, FuncNameId, ModuleNameId, Func.InstCount,
48*7ec26b23SKyungwoo Lee       std::move(IndexOperandHashMap));
49*7ec26b23SKyungwoo Lee   insert(std::move(FuncEntry));
50*7ec26b23SKyungwoo Lee }
51*7ec26b23SKyungwoo Lee 
52*7ec26b23SKyungwoo Lee void StableFunctionMap::merge(const StableFunctionMap &OtherMap) {
53*7ec26b23SKyungwoo Lee   assert(!Finalized && "Cannot merge after finalization");
54*7ec26b23SKyungwoo Lee   for (auto &[Hash, Funcs] : OtherMap.HashToFuncs) {
55*7ec26b23SKyungwoo Lee     auto &ThisFuncs = HashToFuncs[Hash];
56*7ec26b23SKyungwoo Lee     for (auto &Func : Funcs) {
57*7ec26b23SKyungwoo Lee       auto FuncNameId =
58*7ec26b23SKyungwoo Lee           getIdOrCreateForName(*OtherMap.getNameForId(Func->FunctionNameId));
59*7ec26b23SKyungwoo Lee       auto ModuleNameId =
60*7ec26b23SKyungwoo Lee           getIdOrCreateForName(*OtherMap.getNameForId(Func->ModuleNameId));
61*7ec26b23SKyungwoo Lee       auto ClonedIndexOperandHashMap =
62*7ec26b23SKyungwoo Lee           std::make_unique<IndexOperandHashMapType>(*Func->IndexOperandHashMap);
63*7ec26b23SKyungwoo Lee       ThisFuncs.emplace_back(std::make_unique<StableFunctionEntry>(
64*7ec26b23SKyungwoo Lee           Func->Hash, FuncNameId, ModuleNameId, Func->InstCount,
65*7ec26b23SKyungwoo Lee           std::move(ClonedIndexOperandHashMap)));
66*7ec26b23SKyungwoo Lee     }
67*7ec26b23SKyungwoo Lee   }
68*7ec26b23SKyungwoo Lee }
69*7ec26b23SKyungwoo Lee 
70*7ec26b23SKyungwoo Lee size_t StableFunctionMap::size(SizeType Type) const {
71*7ec26b23SKyungwoo Lee   switch (Type) {
72*7ec26b23SKyungwoo Lee   case UniqueHashCount:
73*7ec26b23SKyungwoo Lee     return HashToFuncs.size();
74*7ec26b23SKyungwoo Lee   case TotalFunctionCount: {
75*7ec26b23SKyungwoo Lee     size_t Count = 0;
76*7ec26b23SKyungwoo Lee     for (auto &Funcs : HashToFuncs)
77*7ec26b23SKyungwoo Lee       Count += Funcs.second.size();
78*7ec26b23SKyungwoo Lee     return Count;
79*7ec26b23SKyungwoo Lee   }
80*7ec26b23SKyungwoo Lee   case MergeableFunctionCount: {
81*7ec26b23SKyungwoo Lee     size_t Count = 0;
82*7ec26b23SKyungwoo Lee     for (auto &[Hash, Funcs] : HashToFuncs)
83*7ec26b23SKyungwoo Lee       if (Funcs.size() >= 2)
84*7ec26b23SKyungwoo Lee         Count += Funcs.size();
85*7ec26b23SKyungwoo Lee     return Count;
86*7ec26b23SKyungwoo Lee   }
87*7ec26b23SKyungwoo Lee   }
88*7ec26b23SKyungwoo Lee   llvm_unreachable("Unhandled size type");
89*7ec26b23SKyungwoo Lee }
90*7ec26b23SKyungwoo Lee 
91*7ec26b23SKyungwoo Lee using ParamLocs = SmallVector<IndexPair>;
92*7ec26b23SKyungwoo Lee static void removeIdenticalIndexPair(
93*7ec26b23SKyungwoo Lee     SmallVector<std::unique_ptr<StableFunctionMap::StableFunctionEntry>> &SFS) {
94*7ec26b23SKyungwoo Lee   auto &RSF = SFS[0];
95*7ec26b23SKyungwoo Lee   unsigned StableFunctionCount = SFS.size();
96*7ec26b23SKyungwoo Lee 
97*7ec26b23SKyungwoo Lee   SmallVector<IndexPair> ToDelete;
98*7ec26b23SKyungwoo Lee   for (auto &[Pair, Hash] : *(RSF->IndexOperandHashMap)) {
99*7ec26b23SKyungwoo Lee     bool Identical = true;
100*7ec26b23SKyungwoo Lee     for (unsigned J = 1; J < StableFunctionCount; ++J) {
101*7ec26b23SKyungwoo Lee       auto &SF = SFS[J];
102*7ec26b23SKyungwoo Lee       const auto &SHash = SF->IndexOperandHashMap->at(Pair);
103*7ec26b23SKyungwoo Lee       if (Hash != SHash) {
104*7ec26b23SKyungwoo Lee         Identical = false;
105*7ec26b23SKyungwoo Lee         break;
106*7ec26b23SKyungwoo Lee       }
107*7ec26b23SKyungwoo Lee     }
108*7ec26b23SKyungwoo Lee 
109*7ec26b23SKyungwoo Lee     // No need to parameterize them if the hashes are identical across stable
110*7ec26b23SKyungwoo Lee     // functions.
111*7ec26b23SKyungwoo Lee     if (Identical)
112*7ec26b23SKyungwoo Lee       ToDelete.emplace_back(Pair);
113*7ec26b23SKyungwoo Lee   }
114*7ec26b23SKyungwoo Lee 
115*7ec26b23SKyungwoo Lee   for (auto &Pair : ToDelete)
116*7ec26b23SKyungwoo Lee     for (auto &SF : SFS)
117*7ec26b23SKyungwoo Lee       SF->IndexOperandHashMap->erase(Pair);
118*7ec26b23SKyungwoo Lee }
119*7ec26b23SKyungwoo Lee 
120*7ec26b23SKyungwoo Lee void StableFunctionMap::finalize() {
121*7ec26b23SKyungwoo Lee   for (auto It = HashToFuncs.begin(); It != HashToFuncs.end(); ++It) {
122*7ec26b23SKyungwoo Lee     auto &[StableHash, SFS] = *It;
123*7ec26b23SKyungwoo Lee 
124*7ec26b23SKyungwoo Lee     // Group stable functions by ModuleIdentifier.
125*7ec26b23SKyungwoo Lee     std::stable_sort(SFS.begin(), SFS.end(),
126*7ec26b23SKyungwoo Lee                      [&](const std::unique_ptr<StableFunctionEntry> &L,
127*7ec26b23SKyungwoo Lee                          const std::unique_ptr<StableFunctionEntry> &R) {
128*7ec26b23SKyungwoo Lee                        return *getNameForId(L->ModuleNameId) <
129*7ec26b23SKyungwoo Lee                               *getNameForId(R->ModuleNameId);
130*7ec26b23SKyungwoo Lee                      });
131*7ec26b23SKyungwoo Lee 
132*7ec26b23SKyungwoo Lee     // Consider the first function as the root function.
133*7ec26b23SKyungwoo Lee     auto &RSF = SFS[0];
134*7ec26b23SKyungwoo Lee 
135*7ec26b23SKyungwoo Lee     bool Invalid = false;
136*7ec26b23SKyungwoo Lee     unsigned StableFunctionCount = SFS.size();
137*7ec26b23SKyungwoo Lee     for (unsigned I = 1; I < StableFunctionCount; ++I) {
138*7ec26b23SKyungwoo Lee       auto &SF = SFS[I];
139*7ec26b23SKyungwoo Lee       assert(RSF->Hash == SF->Hash);
140*7ec26b23SKyungwoo Lee       if (RSF->InstCount != SF->InstCount) {
141*7ec26b23SKyungwoo Lee         Invalid = true;
142*7ec26b23SKyungwoo Lee         break;
143*7ec26b23SKyungwoo Lee       }
144*7ec26b23SKyungwoo Lee       if (RSF->IndexOperandHashMap->size() != SF->IndexOperandHashMap->size()) {
145*7ec26b23SKyungwoo Lee         Invalid = true;
146*7ec26b23SKyungwoo Lee         break;
147*7ec26b23SKyungwoo Lee       }
148*7ec26b23SKyungwoo Lee       for (auto &P : *RSF->IndexOperandHashMap) {
149*7ec26b23SKyungwoo Lee         auto &InstOpndIndex = P.first;
150*7ec26b23SKyungwoo Lee         if (!SF->IndexOperandHashMap->count(InstOpndIndex)) {
151*7ec26b23SKyungwoo Lee           Invalid = true;
152*7ec26b23SKyungwoo Lee           break;
153*7ec26b23SKyungwoo Lee         }
154*7ec26b23SKyungwoo Lee       }
155*7ec26b23SKyungwoo Lee     }
156*7ec26b23SKyungwoo Lee     if (Invalid) {
157*7ec26b23SKyungwoo Lee       HashToFuncs.erase(It);
158*7ec26b23SKyungwoo Lee       continue;
159*7ec26b23SKyungwoo Lee     }
160*7ec26b23SKyungwoo Lee 
161*7ec26b23SKyungwoo Lee     // Trim the index pair that has the same operand hash across
162*7ec26b23SKyungwoo Lee     // stable functions.
163*7ec26b23SKyungwoo Lee     removeIdenticalIndexPair(SFS);
164*7ec26b23SKyungwoo Lee   }
165*7ec26b23SKyungwoo Lee 
166*7ec26b23SKyungwoo Lee   Finalized = true;
167*7ec26b23SKyungwoo Lee }
168