181ad6265SDimitry Andric //===-- BasicBlockSectionsProfileReader.cpp -------------------------------===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric // 981ad6265SDimitry Andric // Implementation of the basic block sections profile reader pass. It parses 1081ad6265SDimitry Andric // and stores the basic block sections profile file (which is specified via the 1181ad6265SDimitry Andric // `-basic-block-sections` flag). 1281ad6265SDimitry Andric // 1381ad6265SDimitry Andric //===----------------------------------------------------------------------===// 1481ad6265SDimitry Andric 1581ad6265SDimitry Andric #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h" 16c9157d92SDimitry Andric #include "llvm/ADT/DenseSet.h" 1781ad6265SDimitry Andric #include "llvm/ADT/SmallSet.h" 18fe013be4SDimitry Andric #include "llvm/ADT/SmallString.h" 1981ad6265SDimitry Andric #include "llvm/ADT/SmallVector.h" 2081ad6265SDimitry Andric #include "llvm/ADT/StringMap.h" 2181ad6265SDimitry Andric #include "llvm/ADT/StringRef.h" 22fe013be4SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 23c9157d92SDimitry Andric #include "llvm/Pass.h" 2481ad6265SDimitry Andric #include "llvm/Support/Error.h" 25c9157d92SDimitry Andric #include "llvm/Support/ErrorHandling.h" 2681ad6265SDimitry Andric #include "llvm/Support/LineIterator.h" 2781ad6265SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 28fe013be4SDimitry Andric #include "llvm/Support/Path.h" 29fe013be4SDimitry Andric #include <llvm/ADT/STLExtras.h> 3081ad6265SDimitry Andric 3181ad6265SDimitry Andric using namespace llvm; 3281ad6265SDimitry Andric 33*cdc20ff6SDimitry Andric char BasicBlockSectionsProfileReaderWrapperPass::ID = 0; 34*cdc20ff6SDimitry Andric INITIALIZE_PASS(BasicBlockSectionsProfileReaderWrapperPass, 35*cdc20ff6SDimitry Andric "bbsections-profile-reader", 3681ad6265SDimitry Andric "Reads and parses a basic block sections profile.", false, 3781ad6265SDimitry Andric false) 3881ad6265SDimitry Andric 39c9157d92SDimitry Andric Expected<UniqueBBID> 40c9157d92SDimitry Andric BasicBlockSectionsProfileReader::parseUniqueBBID(StringRef S) const { 41c9157d92SDimitry Andric SmallVector<StringRef, 2> Parts; 42c9157d92SDimitry Andric S.split(Parts, '.'); 43c9157d92SDimitry Andric if (Parts.size() > 2) 44c9157d92SDimitry Andric return createProfileParseError(Twine("unable to parse basic block id: '") + 45c9157d92SDimitry Andric S + "'"); 46c9157d92SDimitry Andric unsigned long long BaseBBID; 47c9157d92SDimitry Andric if (getAsUnsignedInteger(Parts[0], 10, BaseBBID)) 48c9157d92SDimitry Andric return createProfileParseError( 49c9157d92SDimitry Andric Twine("unable to parse BB id: '" + Parts[0]) + 50c9157d92SDimitry Andric "': unsigned integer expected"); 51c9157d92SDimitry Andric unsigned long long CloneID = 0; 52c9157d92SDimitry Andric if (Parts.size() > 1 && getAsUnsignedInteger(Parts[1], 10, CloneID)) 53c9157d92SDimitry Andric return createProfileParseError(Twine("unable to parse clone id: '") + 54c9157d92SDimitry Andric Parts[1] + "': unsigned integer expected"); 55c9157d92SDimitry Andric return UniqueBBID{static_cast<unsigned>(BaseBBID), 56c9157d92SDimitry Andric static_cast<unsigned>(CloneID)}; 57c9157d92SDimitry Andric } 58c9157d92SDimitry Andric 5981ad6265SDimitry Andric bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const { 60c9157d92SDimitry Andric return getClusterInfoForFunction(FuncName).first; 6181ad6265SDimitry Andric } 6281ad6265SDimitry Andric 6381ad6265SDimitry Andric std::pair<bool, SmallVector<BBClusterInfo>> 64c9157d92SDimitry Andric BasicBlockSectionsProfileReader::getClusterInfoForFunction( 6581ad6265SDimitry Andric StringRef FuncName) const { 66c9157d92SDimitry Andric auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName)); 67c9157d92SDimitry Andric return R != ProgramPathAndClusterInfo.end() 68c9157d92SDimitry Andric ? std::pair(true, R->second.ClusterInfo) 69c9157d92SDimitry Andric : std::pair(false, SmallVector<BBClusterInfo>()); 70c9157d92SDimitry Andric } 71c9157d92SDimitry Andric 72c9157d92SDimitry Andric SmallVector<SmallVector<unsigned>> 73c9157d92SDimitry Andric BasicBlockSectionsProfileReader::getClonePathsForFunction( 74c9157d92SDimitry Andric StringRef FuncName) const { 75c9157d92SDimitry Andric return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths; 76c9157d92SDimitry Andric } 77c9157d92SDimitry Andric 78c9157d92SDimitry Andric // Reads the version 1 basic block sections profile. Profile for each function 79c9157d92SDimitry Andric // is encoded as follows: 80c9157d92SDimitry Andric // m <module_name> 81c9157d92SDimitry Andric // f <function_name_1> <function_name_2> ... 82c9157d92SDimitry Andric // c <bb_id_1> <bb_id_2> <bb_id_3> 83c9157d92SDimitry Andric // c <bb_id_4> <bb_id_5> 84c9157d92SDimitry Andric // ... 85c9157d92SDimitry Andric // Module name specifier (starting with 'm') is optional and allows 86c9157d92SDimitry Andric // distinguishing profile for internal-linkage functions with the same name. If 87c9157d92SDimitry Andric // not specified, it will apply to any function with the same name. Function 88c9157d92SDimitry Andric // name specifier (starting with 'f') can specify multiple function name 89c9157d92SDimitry Andric // aliases. Basic block clusters are specified by 'c' and specify the cluster of 90c9157d92SDimitry Andric // basic blocks, and the internal order in which they must be placed in the same 91c9157d92SDimitry Andric // section. 92c9157d92SDimitry Andric // This profile can also specify cloning paths which instruct the compiler to 93c9157d92SDimitry Andric // clone basic blocks along a path. The cloned blocks are then specified in the 94c9157d92SDimitry Andric // cluster information. 95c9157d92SDimitry Andric // The following profile lists two cloning paths (starting with 'p') for 96c9157d92SDimitry Andric // function bar and places the total 9 blocks within two clusters. The first two 97c9157d92SDimitry Andric // blocks of a cloning path specify the edge along which the path is cloned. For 98c9157d92SDimitry Andric // instance, path 1 (1 -> 3 -> 4) instructs that 3 and 4 must be cloned along 99c9157d92SDimitry Andric // the edge 1->3. Within the given clusters, each cloned block is identified by 100c9157d92SDimitry Andric // "<original block id>.<clone id>". For instance, 3.1 represents the first 101c9157d92SDimitry Andric // clone of block 3. Original blocks are specified just with their block ids. A 102c9157d92SDimitry Andric // block cloned multiple times appears with distinct clone ids. The CFG for bar 103c9157d92SDimitry Andric // is shown below before and after cloning with its final clusters labeled. 104c9157d92SDimitry Andric // 105c9157d92SDimitry Andric // f main 106c9157d92SDimitry Andric // f bar 107c9157d92SDimitry Andric // p 1 3 4 # cloning path 1 108c9157d92SDimitry Andric // p 4 2 # cloning path 2 109c9157d92SDimitry Andric // c 1 3.1 4.1 6 # basic block cluster 1 110c9157d92SDimitry Andric // c 0 2 3 4 2.1 5 # basic block cluster 2 111c9157d92SDimitry Andric // **************************************************************************** 112c9157d92SDimitry Andric // function bar before and after cloning with basic block clusters shown. 113c9157d92SDimitry Andric // **************************************************************************** 114c9157d92SDimitry Andric // .... .............. 115c9157d92SDimitry Andric // 0 -------+ : 0 :---->: 1 ---> 3.1 : 116c9157d92SDimitry Andric // | | : | : :........ | : 117c9157d92SDimitry Andric // v v : v : : v : 118c9157d92SDimitry Andric // +--> 2 --> 5 1 ~~~~~~> +---: 2 : : 4.1: clsuter 1 119c9157d92SDimitry Andric // | | | | : | : : | : 120c9157d92SDimitry Andric // | v | | : v ....... : v : 121c9157d92SDimitry Andric // | 3 <------+ | : 3 <--+ : : 6 : 122c9157d92SDimitry Andric // | | | : | | : :....: 123c9157d92SDimitry Andric // | v | : v | : 124c9157d92SDimitry Andric // +--- 4 ---> 6 | : 4 | : 125c9157d92SDimitry Andric // | : | | : 126c9157d92SDimitry Andric // | : v | : 127c9157d92SDimitry Andric // | :2.1---+ : cluster 2 128c9157d92SDimitry Andric // | : | ......: 129c9157d92SDimitry Andric // | : v : 130c9157d92SDimitry Andric // +-->: 5 : 131c9157d92SDimitry Andric // .... 132c9157d92SDimitry Andric // **************************************************************************** 133c9157d92SDimitry Andric Error BasicBlockSectionsProfileReader::ReadV1Profile() { 134c9157d92SDimitry Andric auto FI = ProgramPathAndClusterInfo.end(); 135c9157d92SDimitry Andric 136c9157d92SDimitry Andric // Current cluster ID corresponding to this function. 137c9157d92SDimitry Andric unsigned CurrentCluster = 0; 138c9157d92SDimitry Andric // Current position in the current cluster. 139c9157d92SDimitry Andric unsigned CurrentPosition = 0; 140c9157d92SDimitry Andric 141c9157d92SDimitry Andric // Temporary set to ensure every basic block ID appears once in the clusters 142c9157d92SDimitry Andric // of a function. 143c9157d92SDimitry Andric DenseSet<UniqueBBID> FuncBBIDs; 144c9157d92SDimitry Andric 145c9157d92SDimitry Andric // Debug-info-based module filename for the current function. Empty string 146c9157d92SDimitry Andric // means no filename. 147c9157d92SDimitry Andric StringRef DIFilename; 148c9157d92SDimitry Andric 149c9157d92SDimitry Andric for (; !LineIt.is_at_eof(); ++LineIt) { 150c9157d92SDimitry Andric StringRef S(*LineIt); 151c9157d92SDimitry Andric char Specifier = S[0]; 152c9157d92SDimitry Andric S = S.drop_front().trim(); 153c9157d92SDimitry Andric SmallVector<StringRef, 4> Values; 154c9157d92SDimitry Andric S.split(Values, ' '); 155c9157d92SDimitry Andric switch (Specifier) { 156c9157d92SDimitry Andric case '@': 157c9157d92SDimitry Andric continue; 158c9157d92SDimitry Andric case 'm': // Module name speicifer. 159c9157d92SDimitry Andric if (Values.size() != 1) { 160c9157d92SDimitry Andric return createProfileParseError(Twine("invalid module name value: '") + 161c9157d92SDimitry Andric S + "'"); 162c9157d92SDimitry Andric } 163c9157d92SDimitry Andric DIFilename = sys::path::remove_leading_dotslash(Values[0]); 164c9157d92SDimitry Andric continue; 165c9157d92SDimitry Andric case 'f': { // Function names specifier. 166c9157d92SDimitry Andric bool FunctionFound = any_of(Values, [&](StringRef Alias) { 167c9157d92SDimitry Andric auto It = FunctionNameToDIFilename.find(Alias); 168c9157d92SDimitry Andric // No match if this function name is not found in this module. 169c9157d92SDimitry Andric if (It == FunctionNameToDIFilename.end()) 170c9157d92SDimitry Andric return false; 171c9157d92SDimitry Andric // Return a match if debug-info-filename is not specified. Otherwise, 172c9157d92SDimitry Andric // check for equality. 173c9157d92SDimitry Andric return DIFilename.empty() || It->second.equals(DIFilename); 174c9157d92SDimitry Andric }); 175c9157d92SDimitry Andric if (!FunctionFound) { 176c9157d92SDimitry Andric // Skip the following profile by setting the profile iterator (FI) to 177c9157d92SDimitry Andric // the past-the-end element. 178c9157d92SDimitry Andric FI = ProgramPathAndClusterInfo.end(); 179c9157d92SDimitry Andric DIFilename = ""; 180c9157d92SDimitry Andric continue; 181c9157d92SDimitry Andric } 182c9157d92SDimitry Andric for (size_t i = 1; i < Values.size(); ++i) 183c9157d92SDimitry Andric FuncAliasMap.try_emplace(Values[i], Values.front()); 184c9157d92SDimitry Andric 185c9157d92SDimitry Andric // Prepare for parsing clusters of this function name. 186c9157d92SDimitry Andric // Start a new cluster map for this function name. 187c9157d92SDimitry Andric auto R = ProgramPathAndClusterInfo.try_emplace(Values.front()); 188c9157d92SDimitry Andric // Report error when multiple profiles have been specified for the same 189c9157d92SDimitry Andric // function. 190c9157d92SDimitry Andric if (!R.second) 191c9157d92SDimitry Andric return createProfileParseError("duplicate profile for function '" + 192c9157d92SDimitry Andric Values.front() + "'"); 193c9157d92SDimitry Andric FI = R.first; 194c9157d92SDimitry Andric CurrentCluster = 0; 195c9157d92SDimitry Andric FuncBBIDs.clear(); 196c9157d92SDimitry Andric // We won't need DIFilename anymore. Clean it up to avoid its application 197c9157d92SDimitry Andric // on the next function. 198c9157d92SDimitry Andric DIFilename = ""; 199c9157d92SDimitry Andric continue; 200c9157d92SDimitry Andric } 201c9157d92SDimitry Andric case 'c': // Basic block cluster specifier. 202c9157d92SDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the 203c9157d92SDimitry Andric // past-the-end element. 204c9157d92SDimitry Andric if (FI == ProgramPathAndClusterInfo.end()) 205c9157d92SDimitry Andric continue; 206c9157d92SDimitry Andric // Reset current cluster position. 207c9157d92SDimitry Andric CurrentPosition = 0; 208c9157d92SDimitry Andric for (auto BasicBlockIDStr : Values) { 209c9157d92SDimitry Andric auto BasicBlockID = parseUniqueBBID(BasicBlockIDStr); 210c9157d92SDimitry Andric if (!BasicBlockID) 211c9157d92SDimitry Andric return BasicBlockID.takeError(); 212c9157d92SDimitry Andric if (!FuncBBIDs.insert(*BasicBlockID).second) 213c9157d92SDimitry Andric return createProfileParseError( 214c9157d92SDimitry Andric Twine("duplicate basic block id found '") + BasicBlockIDStr + 215c9157d92SDimitry Andric "'"); 216c9157d92SDimitry Andric 217c9157d92SDimitry Andric if (!BasicBlockID->BaseID && CurrentPosition) 218c9157d92SDimitry Andric return createProfileParseError( 219c9157d92SDimitry Andric "entry BB (0) does not begin a cluster."); 220c9157d92SDimitry Andric 221c9157d92SDimitry Andric FI->second.ClusterInfo.emplace_back(BBClusterInfo{ 222c9157d92SDimitry Andric *std::move(BasicBlockID), CurrentCluster, CurrentPosition++}); 223c9157d92SDimitry Andric } 224c9157d92SDimitry Andric CurrentCluster++; 225c9157d92SDimitry Andric continue; 226c9157d92SDimitry Andric case 'p': { // Basic block cloning path specifier. 227c9157d92SDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the 228c9157d92SDimitry Andric // past-the-end element. 229c9157d92SDimitry Andric if (FI == ProgramPathAndClusterInfo.end()) 230c9157d92SDimitry Andric continue; 231c9157d92SDimitry Andric SmallSet<unsigned, 5> BBsInPath; 232c9157d92SDimitry Andric FI->second.ClonePaths.push_back({}); 233c9157d92SDimitry Andric for (size_t I = 0; I < Values.size(); ++I) { 234c9157d92SDimitry Andric auto BaseBBIDStr = Values[I]; 235c9157d92SDimitry Andric unsigned long long BaseBBID = 0; 236c9157d92SDimitry Andric if (getAsUnsignedInteger(BaseBBIDStr, 10, BaseBBID)) 237c9157d92SDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") + 238c9157d92SDimitry Andric BaseBBIDStr + "'"); 239c9157d92SDimitry Andric if (I != 0 && !BBsInPath.insert(BaseBBID).second) 240c9157d92SDimitry Andric return createProfileParseError( 241c9157d92SDimitry Andric Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'"); 242c9157d92SDimitry Andric FI->second.ClonePaths.back().push_back(BaseBBID); 243c9157d92SDimitry Andric } 244c9157d92SDimitry Andric continue; 245c9157d92SDimitry Andric } 246c9157d92SDimitry Andric default: 247c9157d92SDimitry Andric return createProfileParseError(Twine("invalid specifier: '") + 248c9157d92SDimitry Andric Twine(Specifier) + "'"); 249c9157d92SDimitry Andric } 250c9157d92SDimitry Andric llvm_unreachable("should not break from this switch statement"); 251c9157d92SDimitry Andric } 252c9157d92SDimitry Andric return Error::success(); 253c9157d92SDimitry Andric } 254c9157d92SDimitry Andric 255c9157d92SDimitry Andric Error BasicBlockSectionsProfileReader::ReadV0Profile() { 256c9157d92SDimitry Andric auto FI = ProgramPathAndClusterInfo.end(); 257c9157d92SDimitry Andric // Current cluster ID corresponding to this function. 258c9157d92SDimitry Andric unsigned CurrentCluster = 0; 259c9157d92SDimitry Andric // Current position in the current cluster. 260c9157d92SDimitry Andric unsigned CurrentPosition = 0; 261c9157d92SDimitry Andric 262c9157d92SDimitry Andric // Temporary set to ensure every basic block ID appears once in the clusters 263c9157d92SDimitry Andric // of a function. 264c9157d92SDimitry Andric SmallSet<unsigned, 4> FuncBBIDs; 265c9157d92SDimitry Andric 266c9157d92SDimitry Andric for (; !LineIt.is_at_eof(); ++LineIt) { 267c9157d92SDimitry Andric StringRef S(*LineIt); 268c9157d92SDimitry Andric if (S[0] == '@') 269c9157d92SDimitry Andric continue; 270c9157d92SDimitry Andric // Check for the leading "!" 271c9157d92SDimitry Andric if (!S.consume_front("!") || S.empty()) 272c9157d92SDimitry Andric break; 273c9157d92SDimitry Andric // Check for second "!" which indicates a cluster of basic blocks. 274c9157d92SDimitry Andric if (S.consume_front("!")) { 275c9157d92SDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the 276c9157d92SDimitry Andric // past-the-end element. 277c9157d92SDimitry Andric if (FI == ProgramPathAndClusterInfo.end()) 278c9157d92SDimitry Andric continue; 279c9157d92SDimitry Andric SmallVector<StringRef, 4> BBIDs; 280c9157d92SDimitry Andric S.split(BBIDs, ' '); 281c9157d92SDimitry Andric // Reset current cluster position. 282c9157d92SDimitry Andric CurrentPosition = 0; 283c9157d92SDimitry Andric for (auto BBIDStr : BBIDs) { 284c9157d92SDimitry Andric unsigned long long BBID; 285c9157d92SDimitry Andric if (getAsUnsignedInteger(BBIDStr, 10, BBID)) 286c9157d92SDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") + 287c9157d92SDimitry Andric BBIDStr + "'"); 288c9157d92SDimitry Andric if (!FuncBBIDs.insert(BBID).second) 289c9157d92SDimitry Andric return createProfileParseError( 290c9157d92SDimitry Andric Twine("duplicate basic block id found '") + BBIDStr + "'"); 291c9157d92SDimitry Andric if (BBID == 0 && CurrentPosition) 292c9157d92SDimitry Andric return createProfileParseError( 293c9157d92SDimitry Andric "entry BB (0) does not begin a cluster"); 294c9157d92SDimitry Andric 295c9157d92SDimitry Andric FI->second.ClusterInfo.emplace_back( 296c9157d92SDimitry Andric BBClusterInfo({{static_cast<unsigned>(BBID), 0}, 297c9157d92SDimitry Andric CurrentCluster, 298c9157d92SDimitry Andric CurrentPosition++})); 299c9157d92SDimitry Andric } 300c9157d92SDimitry Andric CurrentCluster++; 301c9157d92SDimitry Andric } else { 302c9157d92SDimitry Andric // This is a function name specifier. It may include a debug info filename 303c9157d92SDimitry Andric // specifier starting with `M=`. 304c9157d92SDimitry Andric auto [AliasesStr, DIFilenameStr] = S.split(' '); 305c9157d92SDimitry Andric SmallString<128> DIFilename; 306c9157d92SDimitry Andric if (DIFilenameStr.starts_with("M=")) { 307c9157d92SDimitry Andric DIFilename = 308c9157d92SDimitry Andric sys::path::remove_leading_dotslash(DIFilenameStr.substr(2)); 309c9157d92SDimitry Andric if (DIFilename.empty()) 310c9157d92SDimitry Andric return createProfileParseError("empty module name specifier"); 311c9157d92SDimitry Andric } else if (!DIFilenameStr.empty()) { 312c9157d92SDimitry Andric return createProfileParseError("unknown string found: '" + 313c9157d92SDimitry Andric DIFilenameStr + "'"); 314c9157d92SDimitry Andric } 315c9157d92SDimitry Andric // Function aliases are separated using '/'. We use the first function 316c9157d92SDimitry Andric // name for the cluster info mapping and delegate all other aliases to 317c9157d92SDimitry Andric // this one. 318c9157d92SDimitry Andric SmallVector<StringRef, 4> Aliases; 319c9157d92SDimitry Andric AliasesStr.split(Aliases, '/'); 320c9157d92SDimitry Andric bool FunctionFound = any_of(Aliases, [&](StringRef Alias) { 321c9157d92SDimitry Andric auto It = FunctionNameToDIFilename.find(Alias); 322c9157d92SDimitry Andric // No match if this function name is not found in this module. 323c9157d92SDimitry Andric if (It == FunctionNameToDIFilename.end()) 324c9157d92SDimitry Andric return false; 325c9157d92SDimitry Andric // Return a match if debug-info-filename is not specified. Otherwise, 326c9157d92SDimitry Andric // check for equality. 327c9157d92SDimitry Andric return DIFilename.empty() || It->second.equals(DIFilename); 328c9157d92SDimitry Andric }); 329c9157d92SDimitry Andric if (!FunctionFound) { 330c9157d92SDimitry Andric // Skip the following profile by setting the profile iterator (FI) to 331c9157d92SDimitry Andric // the past-the-end element. 332c9157d92SDimitry Andric FI = ProgramPathAndClusterInfo.end(); 333c9157d92SDimitry Andric continue; 334c9157d92SDimitry Andric } 335c9157d92SDimitry Andric for (size_t i = 1; i < Aliases.size(); ++i) 336c9157d92SDimitry Andric FuncAliasMap.try_emplace(Aliases[i], Aliases.front()); 337c9157d92SDimitry Andric 338c9157d92SDimitry Andric // Prepare for parsing clusters of this function name. 339c9157d92SDimitry Andric // Start a new cluster map for this function name. 340c9157d92SDimitry Andric auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front()); 341c9157d92SDimitry Andric // Report error when multiple profiles have been specified for the same 342c9157d92SDimitry Andric // function. 343c9157d92SDimitry Andric if (!R.second) 344c9157d92SDimitry Andric return createProfileParseError("duplicate profile for function '" + 345c9157d92SDimitry Andric Aliases.front() + "'"); 346c9157d92SDimitry Andric FI = R.first; 347c9157d92SDimitry Andric CurrentCluster = 0; 348c9157d92SDimitry Andric FuncBBIDs.clear(); 349c9157d92SDimitry Andric } 350c9157d92SDimitry Andric } 351c9157d92SDimitry Andric return Error::success(); 35281ad6265SDimitry Andric } 35381ad6265SDimitry Andric 35481ad6265SDimitry Andric // Basic Block Sections can be enabled for a subset of machine basic blocks. 35581ad6265SDimitry Andric // This is done by passing a file containing names of functions for which basic 35681ad6265SDimitry Andric // block sections are desired. Additionally, machine basic block ids of the 35781ad6265SDimitry Andric // functions can also be specified for a finer granularity. Moreover, a cluster 35881ad6265SDimitry Andric // of basic blocks could be assigned to the same section. 359fe013be4SDimitry Andric // Optionally, a debug-info filename can be specified for each function to allow 360fe013be4SDimitry Andric // distinguishing internal-linkage functions of the same name. 36181ad6265SDimitry Andric // A file with basic block sections for all of function main and three blocks 36281ad6265SDimitry Andric // for function foo (of which 1 and 2 are placed in a cluster) looks like this: 363fe013be4SDimitry Andric // (Profile for function foo is only loaded when its debug-info filename 364fe013be4SDimitry Andric // matches 'path/to/foo_file.cc'). 36581ad6265SDimitry Andric // ---------------------------- 36681ad6265SDimitry Andric // list.txt: 36781ad6265SDimitry Andric // !main 368fe013be4SDimitry Andric // !foo M=path/to/foo_file.cc 36981ad6265SDimitry Andric // !!1 2 37081ad6265SDimitry Andric // !!4 371fe013be4SDimitry Andric Error BasicBlockSectionsProfileReader::ReadProfile() { 37281ad6265SDimitry Andric assert(MBuf); 37381ad6265SDimitry Andric 374c9157d92SDimitry Andric unsigned long long Version = 0; 375c9157d92SDimitry Andric StringRef FirstLine(*LineIt); 376c9157d92SDimitry Andric if (FirstLine.consume_front("v")) { 377c9157d92SDimitry Andric if (getAsUnsignedInteger(FirstLine, 10, Version)) { 378c9157d92SDimitry Andric return createProfileParseError(Twine("version number expected: '") + 379c9157d92SDimitry Andric FirstLine + "'"); 38081ad6265SDimitry Andric } 381c9157d92SDimitry Andric if (Version > 1) { 382c9157d92SDimitry Andric return createProfileParseError(Twine("invalid profile version: ") + 383c9157d92SDimitry Andric Twine(Version)); 384fe013be4SDimitry Andric } 385c9157d92SDimitry Andric ++LineIt; 386fe013be4SDimitry Andric } 38781ad6265SDimitry Andric 388c9157d92SDimitry Andric switch (Version) { 389c9157d92SDimitry Andric case 0: 390c9157d92SDimitry Andric // TODO: Deprecate V0 once V1 is fully integrated downstream. 391c9157d92SDimitry Andric return ReadV0Profile(); 392c9157d92SDimitry Andric case 1: 393c9157d92SDimitry Andric return ReadV1Profile(); 394c9157d92SDimitry Andric default: 395c9157d92SDimitry Andric llvm_unreachable("Invalid profile version."); 39681ad6265SDimitry Andric } 39781ad6265SDimitry Andric } 39881ad6265SDimitry Andric 399*cdc20ff6SDimitry Andric bool BasicBlockSectionsProfileReaderWrapperPass::doInitialization(Module &M) { 400*cdc20ff6SDimitry Andric if (!BBSPR.MBuf) 401fe013be4SDimitry Andric return false; 402fe013be4SDimitry Andric // Get the function name to debug info filename mapping. 403*cdc20ff6SDimitry Andric BBSPR.FunctionNameToDIFilename.clear(); 404fe013be4SDimitry Andric for (const Function &F : M) { 405fe013be4SDimitry Andric SmallString<128> DIFilename; 406fe013be4SDimitry Andric if (F.isDeclaration()) 407fe013be4SDimitry Andric continue; 408fe013be4SDimitry Andric DISubprogram *Subprogram = F.getSubprogram(); 409fe013be4SDimitry Andric if (Subprogram) { 410fe013be4SDimitry Andric llvm::DICompileUnit *CU = Subprogram->getUnit(); 411fe013be4SDimitry Andric if (CU) 412fe013be4SDimitry Andric DIFilename = sys::path::remove_leading_dotslash(CU->getFilename()); 413fe013be4SDimitry Andric } 414fe013be4SDimitry Andric [[maybe_unused]] bool inserted = 415*cdc20ff6SDimitry Andric BBSPR.FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename) 416*cdc20ff6SDimitry Andric .second; 417fe013be4SDimitry Andric assert(inserted); 418fe013be4SDimitry Andric } 419*cdc20ff6SDimitry Andric if (auto Err = BBSPR.ReadProfile()) 42081ad6265SDimitry Andric report_fatal_error(std::move(Err)); 421fe013be4SDimitry Andric return false; 42281ad6265SDimitry Andric } 42381ad6265SDimitry Andric 424*cdc20ff6SDimitry Andric AnalysisKey BasicBlockSectionsProfileReaderAnalysis::Key; 425*cdc20ff6SDimitry Andric 426*cdc20ff6SDimitry Andric BasicBlockSectionsProfileReader 427*cdc20ff6SDimitry Andric BasicBlockSectionsProfileReaderAnalysis::run(Function &F, 428*cdc20ff6SDimitry Andric FunctionAnalysisManager &AM) { 429*cdc20ff6SDimitry Andric return BasicBlockSectionsProfileReader(TM->getBBSectionsFuncListBuf()); 430*cdc20ff6SDimitry Andric } 431*cdc20ff6SDimitry Andric 432*cdc20ff6SDimitry Andric bool BasicBlockSectionsProfileReaderWrapperPass::isFunctionHot( 433*cdc20ff6SDimitry Andric StringRef FuncName) const { 434*cdc20ff6SDimitry Andric return BBSPR.isFunctionHot(FuncName); 435*cdc20ff6SDimitry Andric } 436*cdc20ff6SDimitry Andric 437*cdc20ff6SDimitry Andric std::pair<bool, SmallVector<BBClusterInfo>> 438*cdc20ff6SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getClusterInfoForFunction( 439*cdc20ff6SDimitry Andric StringRef FuncName) const { 440*cdc20ff6SDimitry Andric return BBSPR.getClusterInfoForFunction(FuncName); 441*cdc20ff6SDimitry Andric } 442*cdc20ff6SDimitry Andric 443*cdc20ff6SDimitry Andric SmallVector<SmallVector<unsigned>> 444*cdc20ff6SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction( 445*cdc20ff6SDimitry Andric StringRef FuncName) const { 446*cdc20ff6SDimitry Andric return BBSPR.getClonePathsForFunction(FuncName); 447*cdc20ff6SDimitry Andric } 448*cdc20ff6SDimitry Andric 449*cdc20ff6SDimitry Andric BasicBlockSectionsProfileReader & 450*cdc20ff6SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() { 451*cdc20ff6SDimitry Andric return BBSPR; 452*cdc20ff6SDimitry Andric } 453*cdc20ff6SDimitry Andric 454*cdc20ff6SDimitry Andric ImmutablePass *llvm::createBasicBlockSectionsProfileReaderWrapperPass( 455*cdc20ff6SDimitry Andric const MemoryBuffer *Buf) { 456*cdc20ff6SDimitry Andric return new BasicBlockSectionsProfileReaderWrapperPass(Buf); 45781ad6265SDimitry Andric } 458