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" 16*5f757f3fSDimitry Andric #include "llvm/ADT/DenseSet.h" 1781ad6265SDimitry Andric #include "llvm/ADT/SmallSet.h" 1806c3fb27SDimitry 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" 2206c3fb27SDimitry Andric #include "llvm/IR/DebugInfoMetadata.h" 23*5f757f3fSDimitry Andric #include "llvm/Pass.h" 2481ad6265SDimitry Andric #include "llvm/Support/Error.h" 25*5f757f3fSDimitry Andric #include "llvm/Support/ErrorHandling.h" 2681ad6265SDimitry Andric #include "llvm/Support/LineIterator.h" 2781ad6265SDimitry Andric #include "llvm/Support/MemoryBuffer.h" 2806c3fb27SDimitry Andric #include "llvm/Support/Path.h" 2906c3fb27SDimitry Andric #include <llvm/ADT/STLExtras.h> 3081ad6265SDimitry Andric 3181ad6265SDimitry Andric using namespace llvm; 3281ad6265SDimitry Andric 3381ad6265SDimitry Andric char BasicBlockSectionsProfileReader::ID = 0; 3481ad6265SDimitry Andric INITIALIZE_PASS(BasicBlockSectionsProfileReader, "bbsections-profile-reader", 3581ad6265SDimitry Andric "Reads and parses a basic block sections profile.", false, 3681ad6265SDimitry Andric false) 3781ad6265SDimitry Andric 38*5f757f3fSDimitry Andric Expected<UniqueBBID> 39*5f757f3fSDimitry Andric BasicBlockSectionsProfileReader::parseUniqueBBID(StringRef S) const { 40*5f757f3fSDimitry Andric SmallVector<StringRef, 2> Parts; 41*5f757f3fSDimitry Andric S.split(Parts, '.'); 42*5f757f3fSDimitry Andric if (Parts.size() > 2) 43*5f757f3fSDimitry Andric return createProfileParseError(Twine("unable to parse basic block id: '") + 44*5f757f3fSDimitry Andric S + "'"); 45*5f757f3fSDimitry Andric unsigned long long BaseBBID; 46*5f757f3fSDimitry Andric if (getAsUnsignedInteger(Parts[0], 10, BaseBBID)) 47*5f757f3fSDimitry Andric return createProfileParseError( 48*5f757f3fSDimitry Andric Twine("unable to parse BB id: '" + Parts[0]) + 49*5f757f3fSDimitry Andric "': unsigned integer expected"); 50*5f757f3fSDimitry Andric unsigned long long CloneID = 0; 51*5f757f3fSDimitry Andric if (Parts.size() > 1 && getAsUnsignedInteger(Parts[1], 10, CloneID)) 52*5f757f3fSDimitry Andric return createProfileParseError(Twine("unable to parse clone id: '") + 53*5f757f3fSDimitry Andric Parts[1] + "': unsigned integer expected"); 54*5f757f3fSDimitry Andric return UniqueBBID{static_cast<unsigned>(BaseBBID), 55*5f757f3fSDimitry Andric static_cast<unsigned>(CloneID)}; 56*5f757f3fSDimitry Andric } 57*5f757f3fSDimitry Andric 5881ad6265SDimitry Andric bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const { 59*5f757f3fSDimitry Andric return getClusterInfoForFunction(FuncName).first; 6081ad6265SDimitry Andric } 6181ad6265SDimitry Andric 6281ad6265SDimitry Andric std::pair<bool, SmallVector<BBClusterInfo>> 63*5f757f3fSDimitry Andric BasicBlockSectionsProfileReader::getClusterInfoForFunction( 6481ad6265SDimitry Andric StringRef FuncName) const { 65*5f757f3fSDimitry Andric auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName)); 66*5f757f3fSDimitry Andric return R != ProgramPathAndClusterInfo.end() 67*5f757f3fSDimitry Andric ? std::pair(true, R->second.ClusterInfo) 68*5f757f3fSDimitry Andric : std::pair(false, SmallVector<BBClusterInfo>()); 69*5f757f3fSDimitry Andric } 70*5f757f3fSDimitry Andric 71*5f757f3fSDimitry Andric SmallVector<SmallVector<unsigned>> 72*5f757f3fSDimitry Andric BasicBlockSectionsProfileReader::getClonePathsForFunction( 73*5f757f3fSDimitry Andric StringRef FuncName) const { 74*5f757f3fSDimitry Andric return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths; 75*5f757f3fSDimitry Andric } 76*5f757f3fSDimitry Andric 77*5f757f3fSDimitry Andric // Reads the version 1 basic block sections profile. Profile for each function 78*5f757f3fSDimitry Andric // is encoded as follows: 79*5f757f3fSDimitry Andric // m <module_name> 80*5f757f3fSDimitry Andric // f <function_name_1> <function_name_2> ... 81*5f757f3fSDimitry Andric // c <bb_id_1> <bb_id_2> <bb_id_3> 82*5f757f3fSDimitry Andric // c <bb_id_4> <bb_id_5> 83*5f757f3fSDimitry Andric // ... 84*5f757f3fSDimitry Andric // Module name specifier (starting with 'm') is optional and allows 85*5f757f3fSDimitry Andric // distinguishing profile for internal-linkage functions with the same name. If 86*5f757f3fSDimitry Andric // not specified, it will apply to any function with the same name. Function 87*5f757f3fSDimitry Andric // name specifier (starting with 'f') can specify multiple function name 88*5f757f3fSDimitry Andric // aliases. Basic block clusters are specified by 'c' and specify the cluster of 89*5f757f3fSDimitry Andric // basic blocks, and the internal order in which they must be placed in the same 90*5f757f3fSDimitry Andric // section. 91*5f757f3fSDimitry Andric // This profile can also specify cloning paths which instruct the compiler to 92*5f757f3fSDimitry Andric // clone basic blocks along a path. The cloned blocks are then specified in the 93*5f757f3fSDimitry Andric // cluster information. 94*5f757f3fSDimitry Andric // The following profile lists two cloning paths (starting with 'p') for 95*5f757f3fSDimitry Andric // function bar and places the total 9 blocks within two clusters. The first two 96*5f757f3fSDimitry Andric // blocks of a cloning path specify the edge along which the path is cloned. For 97*5f757f3fSDimitry Andric // instance, path 1 (1 -> 3 -> 4) instructs that 3 and 4 must be cloned along 98*5f757f3fSDimitry Andric // the edge 1->3. Within the given clusters, each cloned block is identified by 99*5f757f3fSDimitry Andric // "<original block id>.<clone id>". For instance, 3.1 represents the first 100*5f757f3fSDimitry Andric // clone of block 3. Original blocks are specified just with their block ids. A 101*5f757f3fSDimitry Andric // block cloned multiple times appears with distinct clone ids. The CFG for bar 102*5f757f3fSDimitry Andric // is shown below before and after cloning with its final clusters labeled. 103*5f757f3fSDimitry Andric // 104*5f757f3fSDimitry Andric // f main 105*5f757f3fSDimitry Andric // f bar 106*5f757f3fSDimitry Andric // p 1 3 4 # cloning path 1 107*5f757f3fSDimitry Andric // p 4 2 # cloning path 2 108*5f757f3fSDimitry Andric // c 1 3.1 4.1 6 # basic block cluster 1 109*5f757f3fSDimitry Andric // c 0 2 3 4 2.1 5 # basic block cluster 2 110*5f757f3fSDimitry Andric // **************************************************************************** 111*5f757f3fSDimitry Andric // function bar before and after cloning with basic block clusters shown. 112*5f757f3fSDimitry Andric // **************************************************************************** 113*5f757f3fSDimitry Andric // .... .............. 114*5f757f3fSDimitry Andric // 0 -------+ : 0 :---->: 1 ---> 3.1 : 115*5f757f3fSDimitry Andric // | | : | : :........ | : 116*5f757f3fSDimitry Andric // v v : v : : v : 117*5f757f3fSDimitry Andric // +--> 2 --> 5 1 ~~~~~~> +---: 2 : : 4.1: clsuter 1 118*5f757f3fSDimitry Andric // | | | | : | : : | : 119*5f757f3fSDimitry Andric // | v | | : v ....... : v : 120*5f757f3fSDimitry Andric // | 3 <------+ | : 3 <--+ : : 6 : 121*5f757f3fSDimitry Andric // | | | : | | : :....: 122*5f757f3fSDimitry Andric // | v | : v | : 123*5f757f3fSDimitry Andric // +--- 4 ---> 6 | : 4 | : 124*5f757f3fSDimitry Andric // | : | | : 125*5f757f3fSDimitry Andric // | : v | : 126*5f757f3fSDimitry Andric // | :2.1---+ : cluster 2 127*5f757f3fSDimitry Andric // | : | ......: 128*5f757f3fSDimitry Andric // | : v : 129*5f757f3fSDimitry Andric // +-->: 5 : 130*5f757f3fSDimitry Andric // .... 131*5f757f3fSDimitry Andric // **************************************************************************** 132*5f757f3fSDimitry Andric Error BasicBlockSectionsProfileReader::ReadV1Profile() { 133*5f757f3fSDimitry Andric auto FI = ProgramPathAndClusterInfo.end(); 134*5f757f3fSDimitry Andric 135*5f757f3fSDimitry Andric // Current cluster ID corresponding to this function. 136*5f757f3fSDimitry Andric unsigned CurrentCluster = 0; 137*5f757f3fSDimitry Andric // Current position in the current cluster. 138*5f757f3fSDimitry Andric unsigned CurrentPosition = 0; 139*5f757f3fSDimitry Andric 140*5f757f3fSDimitry Andric // Temporary set to ensure every basic block ID appears once in the clusters 141*5f757f3fSDimitry Andric // of a function. 142*5f757f3fSDimitry Andric DenseSet<UniqueBBID> FuncBBIDs; 143*5f757f3fSDimitry Andric 144*5f757f3fSDimitry Andric // Debug-info-based module filename for the current function. Empty string 145*5f757f3fSDimitry Andric // means no filename. 146*5f757f3fSDimitry Andric StringRef DIFilename; 147*5f757f3fSDimitry Andric 148*5f757f3fSDimitry Andric for (; !LineIt.is_at_eof(); ++LineIt) { 149*5f757f3fSDimitry Andric StringRef S(*LineIt); 150*5f757f3fSDimitry Andric char Specifier = S[0]; 151*5f757f3fSDimitry Andric S = S.drop_front().trim(); 152*5f757f3fSDimitry Andric SmallVector<StringRef, 4> Values; 153*5f757f3fSDimitry Andric S.split(Values, ' '); 154*5f757f3fSDimitry Andric switch (Specifier) { 155*5f757f3fSDimitry Andric case '@': 156*5f757f3fSDimitry Andric continue; 157*5f757f3fSDimitry Andric case 'm': // Module name speicifer. 158*5f757f3fSDimitry Andric if (Values.size() != 1) { 159*5f757f3fSDimitry Andric return createProfileParseError(Twine("invalid module name value: '") + 160*5f757f3fSDimitry Andric S + "'"); 161*5f757f3fSDimitry Andric } 162*5f757f3fSDimitry Andric DIFilename = sys::path::remove_leading_dotslash(Values[0]); 163*5f757f3fSDimitry Andric continue; 164*5f757f3fSDimitry Andric case 'f': { // Function names specifier. 165*5f757f3fSDimitry Andric bool FunctionFound = any_of(Values, [&](StringRef Alias) { 166*5f757f3fSDimitry Andric auto It = FunctionNameToDIFilename.find(Alias); 167*5f757f3fSDimitry Andric // No match if this function name is not found in this module. 168*5f757f3fSDimitry Andric if (It == FunctionNameToDIFilename.end()) 169*5f757f3fSDimitry Andric return false; 170*5f757f3fSDimitry Andric // Return a match if debug-info-filename is not specified. Otherwise, 171*5f757f3fSDimitry Andric // check for equality. 172*5f757f3fSDimitry Andric return DIFilename.empty() || It->second.equals(DIFilename); 173*5f757f3fSDimitry Andric }); 174*5f757f3fSDimitry Andric if (!FunctionFound) { 175*5f757f3fSDimitry Andric // Skip the following profile by setting the profile iterator (FI) to 176*5f757f3fSDimitry Andric // the past-the-end element. 177*5f757f3fSDimitry Andric FI = ProgramPathAndClusterInfo.end(); 178*5f757f3fSDimitry Andric DIFilename = ""; 179*5f757f3fSDimitry Andric continue; 180*5f757f3fSDimitry Andric } 181*5f757f3fSDimitry Andric for (size_t i = 1; i < Values.size(); ++i) 182*5f757f3fSDimitry Andric FuncAliasMap.try_emplace(Values[i], Values.front()); 183*5f757f3fSDimitry Andric 184*5f757f3fSDimitry Andric // Prepare for parsing clusters of this function name. 185*5f757f3fSDimitry Andric // Start a new cluster map for this function name. 186*5f757f3fSDimitry Andric auto R = ProgramPathAndClusterInfo.try_emplace(Values.front()); 187*5f757f3fSDimitry Andric // Report error when multiple profiles have been specified for the same 188*5f757f3fSDimitry Andric // function. 189*5f757f3fSDimitry Andric if (!R.second) 190*5f757f3fSDimitry Andric return createProfileParseError("duplicate profile for function '" + 191*5f757f3fSDimitry Andric Values.front() + "'"); 192*5f757f3fSDimitry Andric FI = R.first; 193*5f757f3fSDimitry Andric CurrentCluster = 0; 194*5f757f3fSDimitry Andric FuncBBIDs.clear(); 195*5f757f3fSDimitry Andric // We won't need DIFilename anymore. Clean it up to avoid its application 196*5f757f3fSDimitry Andric // on the next function. 197*5f757f3fSDimitry Andric DIFilename = ""; 198*5f757f3fSDimitry Andric continue; 199*5f757f3fSDimitry Andric } 200*5f757f3fSDimitry Andric case 'c': // Basic block cluster specifier. 201*5f757f3fSDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the 202*5f757f3fSDimitry Andric // past-the-end element. 203*5f757f3fSDimitry Andric if (FI == ProgramPathAndClusterInfo.end()) 204*5f757f3fSDimitry Andric continue; 205*5f757f3fSDimitry Andric // Reset current cluster position. 206*5f757f3fSDimitry Andric CurrentPosition = 0; 207*5f757f3fSDimitry Andric for (auto BasicBlockIDStr : Values) { 208*5f757f3fSDimitry Andric auto BasicBlockID = parseUniqueBBID(BasicBlockIDStr); 209*5f757f3fSDimitry Andric if (!BasicBlockID) 210*5f757f3fSDimitry Andric return BasicBlockID.takeError(); 211*5f757f3fSDimitry Andric if (!FuncBBIDs.insert(*BasicBlockID).second) 212*5f757f3fSDimitry Andric return createProfileParseError( 213*5f757f3fSDimitry Andric Twine("duplicate basic block id found '") + BasicBlockIDStr + 214*5f757f3fSDimitry Andric "'"); 215*5f757f3fSDimitry Andric 216*5f757f3fSDimitry Andric if (!BasicBlockID->BaseID && CurrentPosition) 217*5f757f3fSDimitry Andric return createProfileParseError( 218*5f757f3fSDimitry Andric "entry BB (0) does not begin a cluster."); 219*5f757f3fSDimitry Andric 220*5f757f3fSDimitry Andric FI->second.ClusterInfo.emplace_back(BBClusterInfo{ 221*5f757f3fSDimitry Andric *std::move(BasicBlockID), CurrentCluster, CurrentPosition++}); 222*5f757f3fSDimitry Andric } 223*5f757f3fSDimitry Andric CurrentCluster++; 224*5f757f3fSDimitry Andric continue; 225*5f757f3fSDimitry Andric case 'p': { // Basic block cloning path specifier. 226*5f757f3fSDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the 227*5f757f3fSDimitry Andric // past-the-end element. 228*5f757f3fSDimitry Andric if (FI == ProgramPathAndClusterInfo.end()) 229*5f757f3fSDimitry Andric continue; 230*5f757f3fSDimitry Andric SmallSet<unsigned, 5> BBsInPath; 231*5f757f3fSDimitry Andric FI->second.ClonePaths.push_back({}); 232*5f757f3fSDimitry Andric for (size_t I = 0; I < Values.size(); ++I) { 233*5f757f3fSDimitry Andric auto BaseBBIDStr = Values[I]; 234*5f757f3fSDimitry Andric unsigned long long BaseBBID = 0; 235*5f757f3fSDimitry Andric if (getAsUnsignedInteger(BaseBBIDStr, 10, BaseBBID)) 236*5f757f3fSDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") + 237*5f757f3fSDimitry Andric BaseBBIDStr + "'"); 238*5f757f3fSDimitry Andric if (I != 0 && !BBsInPath.insert(BaseBBID).second) 239*5f757f3fSDimitry Andric return createProfileParseError( 240*5f757f3fSDimitry Andric Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'"); 241*5f757f3fSDimitry Andric FI->second.ClonePaths.back().push_back(BaseBBID); 242*5f757f3fSDimitry Andric } 243*5f757f3fSDimitry Andric continue; 244*5f757f3fSDimitry Andric } 245*5f757f3fSDimitry Andric default: 246*5f757f3fSDimitry Andric return createProfileParseError(Twine("invalid specifier: '") + 247*5f757f3fSDimitry Andric Twine(Specifier) + "'"); 248*5f757f3fSDimitry Andric } 249*5f757f3fSDimitry Andric llvm_unreachable("should not break from this switch statement"); 250*5f757f3fSDimitry Andric } 251*5f757f3fSDimitry Andric return Error::success(); 252*5f757f3fSDimitry Andric } 253*5f757f3fSDimitry Andric 254*5f757f3fSDimitry Andric Error BasicBlockSectionsProfileReader::ReadV0Profile() { 255*5f757f3fSDimitry Andric auto FI = ProgramPathAndClusterInfo.end(); 256*5f757f3fSDimitry Andric // Current cluster ID corresponding to this function. 257*5f757f3fSDimitry Andric unsigned CurrentCluster = 0; 258*5f757f3fSDimitry Andric // Current position in the current cluster. 259*5f757f3fSDimitry Andric unsigned CurrentPosition = 0; 260*5f757f3fSDimitry Andric 261*5f757f3fSDimitry Andric // Temporary set to ensure every basic block ID appears once in the clusters 262*5f757f3fSDimitry Andric // of a function. 263*5f757f3fSDimitry Andric SmallSet<unsigned, 4> FuncBBIDs; 264*5f757f3fSDimitry Andric 265*5f757f3fSDimitry Andric for (; !LineIt.is_at_eof(); ++LineIt) { 266*5f757f3fSDimitry Andric StringRef S(*LineIt); 267*5f757f3fSDimitry Andric if (S[0] == '@') 268*5f757f3fSDimitry Andric continue; 269*5f757f3fSDimitry Andric // Check for the leading "!" 270*5f757f3fSDimitry Andric if (!S.consume_front("!") || S.empty()) 271*5f757f3fSDimitry Andric break; 272*5f757f3fSDimitry Andric // Check for second "!" which indicates a cluster of basic blocks. 273*5f757f3fSDimitry Andric if (S.consume_front("!")) { 274*5f757f3fSDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the 275*5f757f3fSDimitry Andric // past-the-end element. 276*5f757f3fSDimitry Andric if (FI == ProgramPathAndClusterInfo.end()) 277*5f757f3fSDimitry Andric continue; 278*5f757f3fSDimitry Andric SmallVector<StringRef, 4> BBIDs; 279*5f757f3fSDimitry Andric S.split(BBIDs, ' '); 280*5f757f3fSDimitry Andric // Reset current cluster position. 281*5f757f3fSDimitry Andric CurrentPosition = 0; 282*5f757f3fSDimitry Andric for (auto BBIDStr : BBIDs) { 283*5f757f3fSDimitry Andric unsigned long long BBID; 284*5f757f3fSDimitry Andric if (getAsUnsignedInteger(BBIDStr, 10, BBID)) 285*5f757f3fSDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") + 286*5f757f3fSDimitry Andric BBIDStr + "'"); 287*5f757f3fSDimitry Andric if (!FuncBBIDs.insert(BBID).second) 288*5f757f3fSDimitry Andric return createProfileParseError( 289*5f757f3fSDimitry Andric Twine("duplicate basic block id found '") + BBIDStr + "'"); 290*5f757f3fSDimitry Andric if (BBID == 0 && CurrentPosition) 291*5f757f3fSDimitry Andric return createProfileParseError( 292*5f757f3fSDimitry Andric "entry BB (0) does not begin a cluster"); 293*5f757f3fSDimitry Andric 294*5f757f3fSDimitry Andric FI->second.ClusterInfo.emplace_back( 295*5f757f3fSDimitry Andric BBClusterInfo({{static_cast<unsigned>(BBID), 0}, 296*5f757f3fSDimitry Andric CurrentCluster, 297*5f757f3fSDimitry Andric CurrentPosition++})); 298*5f757f3fSDimitry Andric } 299*5f757f3fSDimitry Andric CurrentCluster++; 300*5f757f3fSDimitry Andric } else { 301*5f757f3fSDimitry Andric // This is a function name specifier. It may include a debug info filename 302*5f757f3fSDimitry Andric // specifier starting with `M=`. 303*5f757f3fSDimitry Andric auto [AliasesStr, DIFilenameStr] = S.split(' '); 304*5f757f3fSDimitry Andric SmallString<128> DIFilename; 305*5f757f3fSDimitry Andric if (DIFilenameStr.starts_with("M=")) { 306*5f757f3fSDimitry Andric DIFilename = 307*5f757f3fSDimitry Andric sys::path::remove_leading_dotslash(DIFilenameStr.substr(2)); 308*5f757f3fSDimitry Andric if (DIFilename.empty()) 309*5f757f3fSDimitry Andric return createProfileParseError("empty module name specifier"); 310*5f757f3fSDimitry Andric } else if (!DIFilenameStr.empty()) { 311*5f757f3fSDimitry Andric return createProfileParseError("unknown string found: '" + 312*5f757f3fSDimitry Andric DIFilenameStr + "'"); 313*5f757f3fSDimitry Andric } 314*5f757f3fSDimitry Andric // Function aliases are separated using '/'. We use the first function 315*5f757f3fSDimitry Andric // name for the cluster info mapping and delegate all other aliases to 316*5f757f3fSDimitry Andric // this one. 317*5f757f3fSDimitry Andric SmallVector<StringRef, 4> Aliases; 318*5f757f3fSDimitry Andric AliasesStr.split(Aliases, '/'); 319*5f757f3fSDimitry Andric bool FunctionFound = any_of(Aliases, [&](StringRef Alias) { 320*5f757f3fSDimitry Andric auto It = FunctionNameToDIFilename.find(Alias); 321*5f757f3fSDimitry Andric // No match if this function name is not found in this module. 322*5f757f3fSDimitry Andric if (It == FunctionNameToDIFilename.end()) 323*5f757f3fSDimitry Andric return false; 324*5f757f3fSDimitry Andric // Return a match if debug-info-filename is not specified. Otherwise, 325*5f757f3fSDimitry Andric // check for equality. 326*5f757f3fSDimitry Andric return DIFilename.empty() || It->second.equals(DIFilename); 327*5f757f3fSDimitry Andric }); 328*5f757f3fSDimitry Andric if (!FunctionFound) { 329*5f757f3fSDimitry Andric // Skip the following profile by setting the profile iterator (FI) to 330*5f757f3fSDimitry Andric // the past-the-end element. 331*5f757f3fSDimitry Andric FI = ProgramPathAndClusterInfo.end(); 332*5f757f3fSDimitry Andric continue; 333*5f757f3fSDimitry Andric } 334*5f757f3fSDimitry Andric for (size_t i = 1; i < Aliases.size(); ++i) 335*5f757f3fSDimitry Andric FuncAliasMap.try_emplace(Aliases[i], Aliases.front()); 336*5f757f3fSDimitry Andric 337*5f757f3fSDimitry Andric // Prepare for parsing clusters of this function name. 338*5f757f3fSDimitry Andric // Start a new cluster map for this function name. 339*5f757f3fSDimitry Andric auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front()); 340*5f757f3fSDimitry Andric // Report error when multiple profiles have been specified for the same 341*5f757f3fSDimitry Andric // function. 342*5f757f3fSDimitry Andric if (!R.second) 343*5f757f3fSDimitry Andric return createProfileParseError("duplicate profile for function '" + 344*5f757f3fSDimitry Andric Aliases.front() + "'"); 345*5f757f3fSDimitry Andric FI = R.first; 346*5f757f3fSDimitry Andric CurrentCluster = 0; 347*5f757f3fSDimitry Andric FuncBBIDs.clear(); 348*5f757f3fSDimitry Andric } 349*5f757f3fSDimitry Andric } 350*5f757f3fSDimitry Andric return Error::success(); 35181ad6265SDimitry Andric } 35281ad6265SDimitry Andric 35381ad6265SDimitry Andric // Basic Block Sections can be enabled for a subset of machine basic blocks. 35481ad6265SDimitry Andric // This is done by passing a file containing names of functions for which basic 35581ad6265SDimitry Andric // block sections are desired. Additionally, machine basic block ids of the 35681ad6265SDimitry Andric // functions can also be specified for a finer granularity. Moreover, a cluster 35781ad6265SDimitry Andric // of basic blocks could be assigned to the same section. 35806c3fb27SDimitry Andric // Optionally, a debug-info filename can be specified for each function to allow 35906c3fb27SDimitry Andric // distinguishing internal-linkage functions of the same name. 36081ad6265SDimitry Andric // A file with basic block sections for all of function main and three blocks 36181ad6265SDimitry Andric // for function foo (of which 1 and 2 are placed in a cluster) looks like this: 36206c3fb27SDimitry Andric // (Profile for function foo is only loaded when its debug-info filename 36306c3fb27SDimitry Andric // matches 'path/to/foo_file.cc'). 36481ad6265SDimitry Andric // ---------------------------- 36581ad6265SDimitry Andric // list.txt: 36681ad6265SDimitry Andric // !main 36706c3fb27SDimitry Andric // !foo M=path/to/foo_file.cc 36881ad6265SDimitry Andric // !!1 2 36981ad6265SDimitry Andric // !!4 37006c3fb27SDimitry Andric Error BasicBlockSectionsProfileReader::ReadProfile() { 37181ad6265SDimitry Andric assert(MBuf); 37281ad6265SDimitry Andric 373*5f757f3fSDimitry Andric unsigned long long Version = 0; 374*5f757f3fSDimitry Andric StringRef FirstLine(*LineIt); 375*5f757f3fSDimitry Andric if (FirstLine.consume_front("v")) { 376*5f757f3fSDimitry Andric if (getAsUnsignedInteger(FirstLine, 10, Version)) { 377*5f757f3fSDimitry Andric return createProfileParseError(Twine("version number expected: '") + 378*5f757f3fSDimitry Andric FirstLine + "'"); 37981ad6265SDimitry Andric } 380*5f757f3fSDimitry Andric if (Version > 1) { 381*5f757f3fSDimitry Andric return createProfileParseError(Twine("invalid profile version: ") + 382*5f757f3fSDimitry Andric Twine(Version)); 38306c3fb27SDimitry Andric } 384*5f757f3fSDimitry Andric ++LineIt; 38506c3fb27SDimitry Andric } 38681ad6265SDimitry Andric 387*5f757f3fSDimitry Andric switch (Version) { 388*5f757f3fSDimitry Andric case 0: 389*5f757f3fSDimitry Andric // TODO: Deprecate V0 once V1 is fully integrated downstream. 390*5f757f3fSDimitry Andric return ReadV0Profile(); 391*5f757f3fSDimitry Andric case 1: 392*5f757f3fSDimitry Andric return ReadV1Profile(); 393*5f757f3fSDimitry Andric default: 394*5f757f3fSDimitry Andric llvm_unreachable("Invalid profile version."); 39581ad6265SDimitry Andric } 39681ad6265SDimitry Andric } 39781ad6265SDimitry Andric 39806c3fb27SDimitry Andric bool BasicBlockSectionsProfileReader::doInitialization(Module &M) { 39981ad6265SDimitry Andric if (!MBuf) 40006c3fb27SDimitry Andric return false; 40106c3fb27SDimitry Andric // Get the function name to debug info filename mapping. 40206c3fb27SDimitry Andric FunctionNameToDIFilename.clear(); 40306c3fb27SDimitry Andric for (const Function &F : M) { 40406c3fb27SDimitry Andric SmallString<128> DIFilename; 40506c3fb27SDimitry Andric if (F.isDeclaration()) 40606c3fb27SDimitry Andric continue; 40706c3fb27SDimitry Andric DISubprogram *Subprogram = F.getSubprogram(); 40806c3fb27SDimitry Andric if (Subprogram) { 40906c3fb27SDimitry Andric llvm::DICompileUnit *CU = Subprogram->getUnit(); 41006c3fb27SDimitry Andric if (CU) 41106c3fb27SDimitry Andric DIFilename = sys::path::remove_leading_dotslash(CU->getFilename()); 41206c3fb27SDimitry Andric } 41306c3fb27SDimitry Andric [[maybe_unused]] bool inserted = 41406c3fb27SDimitry Andric FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename).second; 41506c3fb27SDimitry Andric assert(inserted); 41606c3fb27SDimitry Andric } 41706c3fb27SDimitry Andric if (auto Err = ReadProfile()) 41881ad6265SDimitry Andric report_fatal_error(std::move(Err)); 41906c3fb27SDimitry Andric return false; 42081ad6265SDimitry Andric } 42181ad6265SDimitry Andric 42281ad6265SDimitry Andric ImmutablePass * 42381ad6265SDimitry Andric llvm::createBasicBlockSectionsProfileReaderPass(const MemoryBuffer *Buf) { 42481ad6265SDimitry Andric return new BasicBlockSectionsProfileReader(Buf); 42581ad6265SDimitry Andric } 426