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" 165f757f3fSDimitry 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" 235f757f3fSDimitry Andric #include "llvm/Pass.h" 2481ad6265SDimitry Andric #include "llvm/Support/Error.h" 255f757f3fSDimitry 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 33*1db9f3b2SDimitry Andric char BasicBlockSectionsProfileReaderWrapperPass::ID = 0; 34*1db9f3b2SDimitry Andric INITIALIZE_PASS(BasicBlockSectionsProfileReaderWrapperPass, 35*1db9f3b2SDimitry Andric "bbsections-profile-reader", 3681ad6265SDimitry Andric "Reads and parses a basic block sections profile.", false, 3781ad6265SDimitry Andric false) 3881ad6265SDimitry Andric 395f757f3fSDimitry Andric Expected<UniqueBBID> 405f757f3fSDimitry Andric BasicBlockSectionsProfileReader::parseUniqueBBID(StringRef S) const { 415f757f3fSDimitry Andric SmallVector<StringRef, 2> Parts; 425f757f3fSDimitry Andric S.split(Parts, '.'); 435f757f3fSDimitry Andric if (Parts.size() > 2) 445f757f3fSDimitry Andric return createProfileParseError(Twine("unable to parse basic block id: '") + 455f757f3fSDimitry Andric S + "'"); 465f757f3fSDimitry Andric unsigned long long BaseBBID; 475f757f3fSDimitry Andric if (getAsUnsignedInteger(Parts[0], 10, BaseBBID)) 485f757f3fSDimitry Andric return createProfileParseError( 495f757f3fSDimitry Andric Twine("unable to parse BB id: '" + Parts[0]) + 505f757f3fSDimitry Andric "': unsigned integer expected"); 515f757f3fSDimitry Andric unsigned long long CloneID = 0; 525f757f3fSDimitry Andric if (Parts.size() > 1 && getAsUnsignedInteger(Parts[1], 10, CloneID)) 535f757f3fSDimitry Andric return createProfileParseError(Twine("unable to parse clone id: '") + 545f757f3fSDimitry Andric Parts[1] + "': unsigned integer expected"); 555f757f3fSDimitry Andric return UniqueBBID{static_cast<unsigned>(BaseBBID), 565f757f3fSDimitry Andric static_cast<unsigned>(CloneID)}; 575f757f3fSDimitry Andric } 585f757f3fSDimitry Andric 5981ad6265SDimitry Andric bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const { 605f757f3fSDimitry Andric return getClusterInfoForFunction(FuncName).first; 6181ad6265SDimitry Andric } 6281ad6265SDimitry Andric 6381ad6265SDimitry Andric std::pair<bool, SmallVector<BBClusterInfo>> 645f757f3fSDimitry Andric BasicBlockSectionsProfileReader::getClusterInfoForFunction( 6581ad6265SDimitry Andric StringRef FuncName) const { 665f757f3fSDimitry Andric auto R = ProgramPathAndClusterInfo.find(getAliasName(FuncName)); 675f757f3fSDimitry Andric return R != ProgramPathAndClusterInfo.end() 685f757f3fSDimitry Andric ? std::pair(true, R->second.ClusterInfo) 695f757f3fSDimitry Andric : std::pair(false, SmallVector<BBClusterInfo>()); 705f757f3fSDimitry Andric } 715f757f3fSDimitry Andric 725f757f3fSDimitry Andric SmallVector<SmallVector<unsigned>> 735f757f3fSDimitry Andric BasicBlockSectionsProfileReader::getClonePathsForFunction( 745f757f3fSDimitry Andric StringRef FuncName) const { 755f757f3fSDimitry Andric return ProgramPathAndClusterInfo.lookup(getAliasName(FuncName)).ClonePaths; 765f757f3fSDimitry Andric } 775f757f3fSDimitry Andric 785f757f3fSDimitry Andric // Reads the version 1 basic block sections profile. Profile for each function 795f757f3fSDimitry Andric // is encoded as follows: 805f757f3fSDimitry Andric // m <module_name> 815f757f3fSDimitry Andric // f <function_name_1> <function_name_2> ... 825f757f3fSDimitry Andric // c <bb_id_1> <bb_id_2> <bb_id_3> 835f757f3fSDimitry Andric // c <bb_id_4> <bb_id_5> 845f757f3fSDimitry Andric // ... 855f757f3fSDimitry Andric // Module name specifier (starting with 'm') is optional and allows 865f757f3fSDimitry Andric // distinguishing profile for internal-linkage functions with the same name. If 875f757f3fSDimitry Andric // not specified, it will apply to any function with the same name. Function 885f757f3fSDimitry Andric // name specifier (starting with 'f') can specify multiple function name 895f757f3fSDimitry Andric // aliases. Basic block clusters are specified by 'c' and specify the cluster of 905f757f3fSDimitry Andric // basic blocks, and the internal order in which they must be placed in the same 915f757f3fSDimitry Andric // section. 925f757f3fSDimitry Andric // This profile can also specify cloning paths which instruct the compiler to 935f757f3fSDimitry Andric // clone basic blocks along a path. The cloned blocks are then specified in the 945f757f3fSDimitry Andric // cluster information. 955f757f3fSDimitry Andric // The following profile lists two cloning paths (starting with 'p') for 965f757f3fSDimitry Andric // function bar and places the total 9 blocks within two clusters. The first two 975f757f3fSDimitry Andric // blocks of a cloning path specify the edge along which the path is cloned. For 985f757f3fSDimitry Andric // instance, path 1 (1 -> 3 -> 4) instructs that 3 and 4 must be cloned along 995f757f3fSDimitry Andric // the edge 1->3. Within the given clusters, each cloned block is identified by 1005f757f3fSDimitry Andric // "<original block id>.<clone id>". For instance, 3.1 represents the first 1015f757f3fSDimitry Andric // clone of block 3. Original blocks are specified just with their block ids. A 1025f757f3fSDimitry Andric // block cloned multiple times appears with distinct clone ids. The CFG for bar 1035f757f3fSDimitry Andric // is shown below before and after cloning with its final clusters labeled. 1045f757f3fSDimitry Andric // 1055f757f3fSDimitry Andric // f main 1065f757f3fSDimitry Andric // f bar 1075f757f3fSDimitry Andric // p 1 3 4 # cloning path 1 1085f757f3fSDimitry Andric // p 4 2 # cloning path 2 1095f757f3fSDimitry Andric // c 1 3.1 4.1 6 # basic block cluster 1 1105f757f3fSDimitry Andric // c 0 2 3 4 2.1 5 # basic block cluster 2 1115f757f3fSDimitry Andric // **************************************************************************** 1125f757f3fSDimitry Andric // function bar before and after cloning with basic block clusters shown. 1135f757f3fSDimitry Andric // **************************************************************************** 1145f757f3fSDimitry Andric // .... .............. 1155f757f3fSDimitry Andric // 0 -------+ : 0 :---->: 1 ---> 3.1 : 1165f757f3fSDimitry Andric // | | : | : :........ | : 1175f757f3fSDimitry Andric // v v : v : : v : 1185f757f3fSDimitry Andric // +--> 2 --> 5 1 ~~~~~~> +---: 2 : : 4.1: clsuter 1 1195f757f3fSDimitry Andric // | | | | : | : : | : 1205f757f3fSDimitry Andric // | v | | : v ....... : v : 1215f757f3fSDimitry Andric // | 3 <------+ | : 3 <--+ : : 6 : 1225f757f3fSDimitry Andric // | | | : | | : :....: 1235f757f3fSDimitry Andric // | v | : v | : 1245f757f3fSDimitry Andric // +--- 4 ---> 6 | : 4 | : 1255f757f3fSDimitry Andric // | : | | : 1265f757f3fSDimitry Andric // | : v | : 1275f757f3fSDimitry Andric // | :2.1---+ : cluster 2 1285f757f3fSDimitry Andric // | : | ......: 1295f757f3fSDimitry Andric // | : v : 1305f757f3fSDimitry Andric // +-->: 5 : 1315f757f3fSDimitry Andric // .... 1325f757f3fSDimitry Andric // **************************************************************************** 1335f757f3fSDimitry Andric Error BasicBlockSectionsProfileReader::ReadV1Profile() { 1345f757f3fSDimitry Andric auto FI = ProgramPathAndClusterInfo.end(); 1355f757f3fSDimitry Andric 1365f757f3fSDimitry Andric // Current cluster ID corresponding to this function. 1375f757f3fSDimitry Andric unsigned CurrentCluster = 0; 1385f757f3fSDimitry Andric // Current position in the current cluster. 1395f757f3fSDimitry Andric unsigned CurrentPosition = 0; 1405f757f3fSDimitry Andric 1415f757f3fSDimitry Andric // Temporary set to ensure every basic block ID appears once in the clusters 1425f757f3fSDimitry Andric // of a function. 1435f757f3fSDimitry Andric DenseSet<UniqueBBID> FuncBBIDs; 1445f757f3fSDimitry Andric 1455f757f3fSDimitry Andric // Debug-info-based module filename for the current function. Empty string 1465f757f3fSDimitry Andric // means no filename. 1475f757f3fSDimitry Andric StringRef DIFilename; 1485f757f3fSDimitry Andric 1495f757f3fSDimitry Andric for (; !LineIt.is_at_eof(); ++LineIt) { 1505f757f3fSDimitry Andric StringRef S(*LineIt); 1515f757f3fSDimitry Andric char Specifier = S[0]; 1525f757f3fSDimitry Andric S = S.drop_front().trim(); 1535f757f3fSDimitry Andric SmallVector<StringRef, 4> Values; 1545f757f3fSDimitry Andric S.split(Values, ' '); 1555f757f3fSDimitry Andric switch (Specifier) { 1565f757f3fSDimitry Andric case '@': 1575f757f3fSDimitry Andric continue; 1585f757f3fSDimitry Andric case 'm': // Module name speicifer. 1595f757f3fSDimitry Andric if (Values.size() != 1) { 1605f757f3fSDimitry Andric return createProfileParseError(Twine("invalid module name value: '") + 1615f757f3fSDimitry Andric S + "'"); 1625f757f3fSDimitry Andric } 1635f757f3fSDimitry Andric DIFilename = sys::path::remove_leading_dotslash(Values[0]); 1645f757f3fSDimitry Andric continue; 1655f757f3fSDimitry Andric case 'f': { // Function names specifier. 1665f757f3fSDimitry Andric bool FunctionFound = any_of(Values, [&](StringRef Alias) { 1675f757f3fSDimitry Andric auto It = FunctionNameToDIFilename.find(Alias); 1685f757f3fSDimitry Andric // No match if this function name is not found in this module. 1695f757f3fSDimitry Andric if (It == FunctionNameToDIFilename.end()) 1705f757f3fSDimitry Andric return false; 1715f757f3fSDimitry Andric // Return a match if debug-info-filename is not specified. Otherwise, 1725f757f3fSDimitry Andric // check for equality. 1735f757f3fSDimitry Andric return DIFilename.empty() || It->second.equals(DIFilename); 1745f757f3fSDimitry Andric }); 1755f757f3fSDimitry Andric if (!FunctionFound) { 1765f757f3fSDimitry Andric // Skip the following profile by setting the profile iterator (FI) to 1775f757f3fSDimitry Andric // the past-the-end element. 1785f757f3fSDimitry Andric FI = ProgramPathAndClusterInfo.end(); 1795f757f3fSDimitry Andric DIFilename = ""; 1805f757f3fSDimitry Andric continue; 1815f757f3fSDimitry Andric } 1825f757f3fSDimitry Andric for (size_t i = 1; i < Values.size(); ++i) 1835f757f3fSDimitry Andric FuncAliasMap.try_emplace(Values[i], Values.front()); 1845f757f3fSDimitry Andric 1855f757f3fSDimitry Andric // Prepare for parsing clusters of this function name. 1865f757f3fSDimitry Andric // Start a new cluster map for this function name. 1875f757f3fSDimitry Andric auto R = ProgramPathAndClusterInfo.try_emplace(Values.front()); 1885f757f3fSDimitry Andric // Report error when multiple profiles have been specified for the same 1895f757f3fSDimitry Andric // function. 1905f757f3fSDimitry Andric if (!R.second) 1915f757f3fSDimitry Andric return createProfileParseError("duplicate profile for function '" + 1925f757f3fSDimitry Andric Values.front() + "'"); 1935f757f3fSDimitry Andric FI = R.first; 1945f757f3fSDimitry Andric CurrentCluster = 0; 1955f757f3fSDimitry Andric FuncBBIDs.clear(); 1965f757f3fSDimitry Andric // We won't need DIFilename anymore. Clean it up to avoid its application 1975f757f3fSDimitry Andric // on the next function. 1985f757f3fSDimitry Andric DIFilename = ""; 1995f757f3fSDimitry Andric continue; 2005f757f3fSDimitry Andric } 2015f757f3fSDimitry Andric case 'c': // Basic block cluster specifier. 2025f757f3fSDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the 2035f757f3fSDimitry Andric // past-the-end element. 2045f757f3fSDimitry Andric if (FI == ProgramPathAndClusterInfo.end()) 2055f757f3fSDimitry Andric continue; 2065f757f3fSDimitry Andric // Reset current cluster position. 2075f757f3fSDimitry Andric CurrentPosition = 0; 2085f757f3fSDimitry Andric for (auto BasicBlockIDStr : Values) { 2095f757f3fSDimitry Andric auto BasicBlockID = parseUniqueBBID(BasicBlockIDStr); 2105f757f3fSDimitry Andric if (!BasicBlockID) 2115f757f3fSDimitry Andric return BasicBlockID.takeError(); 2125f757f3fSDimitry Andric if (!FuncBBIDs.insert(*BasicBlockID).second) 2135f757f3fSDimitry Andric return createProfileParseError( 2145f757f3fSDimitry Andric Twine("duplicate basic block id found '") + BasicBlockIDStr + 2155f757f3fSDimitry Andric "'"); 2165f757f3fSDimitry Andric 2175f757f3fSDimitry Andric if (!BasicBlockID->BaseID && CurrentPosition) 2185f757f3fSDimitry Andric return createProfileParseError( 2195f757f3fSDimitry Andric "entry BB (0) does not begin a cluster."); 2205f757f3fSDimitry Andric 2215f757f3fSDimitry Andric FI->second.ClusterInfo.emplace_back(BBClusterInfo{ 2225f757f3fSDimitry Andric *std::move(BasicBlockID), CurrentCluster, CurrentPosition++}); 2235f757f3fSDimitry Andric } 2245f757f3fSDimitry Andric CurrentCluster++; 2255f757f3fSDimitry Andric continue; 2265f757f3fSDimitry Andric case 'p': { // Basic block cloning path specifier. 2275f757f3fSDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the 2285f757f3fSDimitry Andric // past-the-end element. 2295f757f3fSDimitry Andric if (FI == ProgramPathAndClusterInfo.end()) 2305f757f3fSDimitry Andric continue; 2315f757f3fSDimitry Andric SmallSet<unsigned, 5> BBsInPath; 2325f757f3fSDimitry Andric FI->second.ClonePaths.push_back({}); 2335f757f3fSDimitry Andric for (size_t I = 0; I < Values.size(); ++I) { 2345f757f3fSDimitry Andric auto BaseBBIDStr = Values[I]; 2355f757f3fSDimitry Andric unsigned long long BaseBBID = 0; 2365f757f3fSDimitry Andric if (getAsUnsignedInteger(BaseBBIDStr, 10, BaseBBID)) 2375f757f3fSDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") + 2385f757f3fSDimitry Andric BaseBBIDStr + "'"); 2395f757f3fSDimitry Andric if (I != 0 && !BBsInPath.insert(BaseBBID).second) 2405f757f3fSDimitry Andric return createProfileParseError( 2415f757f3fSDimitry Andric Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'"); 2425f757f3fSDimitry Andric FI->second.ClonePaths.back().push_back(BaseBBID); 2435f757f3fSDimitry Andric } 2445f757f3fSDimitry Andric continue; 2455f757f3fSDimitry Andric } 2465f757f3fSDimitry Andric default: 2475f757f3fSDimitry Andric return createProfileParseError(Twine("invalid specifier: '") + 2485f757f3fSDimitry Andric Twine(Specifier) + "'"); 2495f757f3fSDimitry Andric } 2505f757f3fSDimitry Andric llvm_unreachable("should not break from this switch statement"); 2515f757f3fSDimitry Andric } 2525f757f3fSDimitry Andric return Error::success(); 2535f757f3fSDimitry Andric } 2545f757f3fSDimitry Andric 2555f757f3fSDimitry Andric Error BasicBlockSectionsProfileReader::ReadV0Profile() { 2565f757f3fSDimitry Andric auto FI = ProgramPathAndClusterInfo.end(); 2575f757f3fSDimitry Andric // Current cluster ID corresponding to this function. 2585f757f3fSDimitry Andric unsigned CurrentCluster = 0; 2595f757f3fSDimitry Andric // Current position in the current cluster. 2605f757f3fSDimitry Andric unsigned CurrentPosition = 0; 2615f757f3fSDimitry Andric 2625f757f3fSDimitry Andric // Temporary set to ensure every basic block ID appears once in the clusters 2635f757f3fSDimitry Andric // of a function. 2645f757f3fSDimitry Andric SmallSet<unsigned, 4> FuncBBIDs; 2655f757f3fSDimitry Andric 2665f757f3fSDimitry Andric for (; !LineIt.is_at_eof(); ++LineIt) { 2675f757f3fSDimitry Andric StringRef S(*LineIt); 2685f757f3fSDimitry Andric if (S[0] == '@') 2695f757f3fSDimitry Andric continue; 2705f757f3fSDimitry Andric // Check for the leading "!" 2715f757f3fSDimitry Andric if (!S.consume_front("!") || S.empty()) 2725f757f3fSDimitry Andric break; 2735f757f3fSDimitry Andric // Check for second "!" which indicates a cluster of basic blocks. 2745f757f3fSDimitry Andric if (S.consume_front("!")) { 2755f757f3fSDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the 2765f757f3fSDimitry Andric // past-the-end element. 2775f757f3fSDimitry Andric if (FI == ProgramPathAndClusterInfo.end()) 2785f757f3fSDimitry Andric continue; 2795f757f3fSDimitry Andric SmallVector<StringRef, 4> BBIDs; 2805f757f3fSDimitry Andric S.split(BBIDs, ' '); 2815f757f3fSDimitry Andric // Reset current cluster position. 2825f757f3fSDimitry Andric CurrentPosition = 0; 2835f757f3fSDimitry Andric for (auto BBIDStr : BBIDs) { 2845f757f3fSDimitry Andric unsigned long long BBID; 2855f757f3fSDimitry Andric if (getAsUnsignedInteger(BBIDStr, 10, BBID)) 2865f757f3fSDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") + 2875f757f3fSDimitry Andric BBIDStr + "'"); 2885f757f3fSDimitry Andric if (!FuncBBIDs.insert(BBID).second) 2895f757f3fSDimitry Andric return createProfileParseError( 2905f757f3fSDimitry Andric Twine("duplicate basic block id found '") + BBIDStr + "'"); 2915f757f3fSDimitry Andric if (BBID == 0 && CurrentPosition) 2925f757f3fSDimitry Andric return createProfileParseError( 2935f757f3fSDimitry Andric "entry BB (0) does not begin a cluster"); 2945f757f3fSDimitry Andric 2955f757f3fSDimitry Andric FI->second.ClusterInfo.emplace_back( 2965f757f3fSDimitry Andric BBClusterInfo({{static_cast<unsigned>(BBID), 0}, 2975f757f3fSDimitry Andric CurrentCluster, 2985f757f3fSDimitry Andric CurrentPosition++})); 2995f757f3fSDimitry Andric } 3005f757f3fSDimitry Andric CurrentCluster++; 3015f757f3fSDimitry Andric } else { 3025f757f3fSDimitry Andric // This is a function name specifier. It may include a debug info filename 3035f757f3fSDimitry Andric // specifier starting with `M=`. 3045f757f3fSDimitry Andric auto [AliasesStr, DIFilenameStr] = S.split(' '); 3055f757f3fSDimitry Andric SmallString<128> DIFilename; 3065f757f3fSDimitry Andric if (DIFilenameStr.starts_with("M=")) { 3075f757f3fSDimitry Andric DIFilename = 3085f757f3fSDimitry Andric sys::path::remove_leading_dotslash(DIFilenameStr.substr(2)); 3095f757f3fSDimitry Andric if (DIFilename.empty()) 3105f757f3fSDimitry Andric return createProfileParseError("empty module name specifier"); 3115f757f3fSDimitry Andric } else if (!DIFilenameStr.empty()) { 3125f757f3fSDimitry Andric return createProfileParseError("unknown string found: '" + 3135f757f3fSDimitry Andric DIFilenameStr + "'"); 3145f757f3fSDimitry Andric } 3155f757f3fSDimitry Andric // Function aliases are separated using '/'. We use the first function 3165f757f3fSDimitry Andric // name for the cluster info mapping and delegate all other aliases to 3175f757f3fSDimitry Andric // this one. 3185f757f3fSDimitry Andric SmallVector<StringRef, 4> Aliases; 3195f757f3fSDimitry Andric AliasesStr.split(Aliases, '/'); 3205f757f3fSDimitry Andric bool FunctionFound = any_of(Aliases, [&](StringRef Alias) { 3215f757f3fSDimitry Andric auto It = FunctionNameToDIFilename.find(Alias); 3225f757f3fSDimitry Andric // No match if this function name is not found in this module. 3235f757f3fSDimitry Andric if (It == FunctionNameToDIFilename.end()) 3245f757f3fSDimitry Andric return false; 3255f757f3fSDimitry Andric // Return a match if debug-info-filename is not specified. Otherwise, 3265f757f3fSDimitry Andric // check for equality. 3275f757f3fSDimitry Andric return DIFilename.empty() || It->second.equals(DIFilename); 3285f757f3fSDimitry Andric }); 3295f757f3fSDimitry Andric if (!FunctionFound) { 3305f757f3fSDimitry Andric // Skip the following profile by setting the profile iterator (FI) to 3315f757f3fSDimitry Andric // the past-the-end element. 3325f757f3fSDimitry Andric FI = ProgramPathAndClusterInfo.end(); 3335f757f3fSDimitry Andric continue; 3345f757f3fSDimitry Andric } 3355f757f3fSDimitry Andric for (size_t i = 1; i < Aliases.size(); ++i) 3365f757f3fSDimitry Andric FuncAliasMap.try_emplace(Aliases[i], Aliases.front()); 3375f757f3fSDimitry Andric 3385f757f3fSDimitry Andric // Prepare for parsing clusters of this function name. 3395f757f3fSDimitry Andric // Start a new cluster map for this function name. 3405f757f3fSDimitry Andric auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front()); 3415f757f3fSDimitry Andric // Report error when multiple profiles have been specified for the same 3425f757f3fSDimitry Andric // function. 3435f757f3fSDimitry Andric if (!R.second) 3445f757f3fSDimitry Andric return createProfileParseError("duplicate profile for function '" + 3455f757f3fSDimitry Andric Aliases.front() + "'"); 3465f757f3fSDimitry Andric FI = R.first; 3475f757f3fSDimitry Andric CurrentCluster = 0; 3485f757f3fSDimitry Andric FuncBBIDs.clear(); 3495f757f3fSDimitry Andric } 3505f757f3fSDimitry Andric } 3515f757f3fSDimitry 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. 35906c3fb27SDimitry Andric // Optionally, a debug-info filename can be specified for each function to allow 36006c3fb27SDimitry 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: 36306c3fb27SDimitry Andric // (Profile for function foo is only loaded when its debug-info filename 36406c3fb27SDimitry Andric // matches 'path/to/foo_file.cc'). 36581ad6265SDimitry Andric // ---------------------------- 36681ad6265SDimitry Andric // list.txt: 36781ad6265SDimitry Andric // !main 36806c3fb27SDimitry Andric // !foo M=path/to/foo_file.cc 36981ad6265SDimitry Andric // !!1 2 37081ad6265SDimitry Andric // !!4 37106c3fb27SDimitry Andric Error BasicBlockSectionsProfileReader::ReadProfile() { 37281ad6265SDimitry Andric assert(MBuf); 37381ad6265SDimitry Andric 3745f757f3fSDimitry Andric unsigned long long Version = 0; 3755f757f3fSDimitry Andric StringRef FirstLine(*LineIt); 3765f757f3fSDimitry Andric if (FirstLine.consume_front("v")) { 3775f757f3fSDimitry Andric if (getAsUnsignedInteger(FirstLine, 10, Version)) { 3785f757f3fSDimitry Andric return createProfileParseError(Twine("version number expected: '") + 3795f757f3fSDimitry Andric FirstLine + "'"); 38081ad6265SDimitry Andric } 3815f757f3fSDimitry Andric if (Version > 1) { 3825f757f3fSDimitry Andric return createProfileParseError(Twine("invalid profile version: ") + 3835f757f3fSDimitry Andric Twine(Version)); 38406c3fb27SDimitry Andric } 3855f757f3fSDimitry Andric ++LineIt; 38606c3fb27SDimitry Andric } 38781ad6265SDimitry Andric 3885f757f3fSDimitry Andric switch (Version) { 3895f757f3fSDimitry Andric case 0: 3905f757f3fSDimitry Andric // TODO: Deprecate V0 once V1 is fully integrated downstream. 3915f757f3fSDimitry Andric return ReadV0Profile(); 3925f757f3fSDimitry Andric case 1: 3935f757f3fSDimitry Andric return ReadV1Profile(); 3945f757f3fSDimitry Andric default: 3955f757f3fSDimitry Andric llvm_unreachable("Invalid profile version."); 39681ad6265SDimitry Andric } 39781ad6265SDimitry Andric } 39881ad6265SDimitry Andric 399*1db9f3b2SDimitry Andric bool BasicBlockSectionsProfileReaderWrapperPass::doInitialization(Module &M) { 400*1db9f3b2SDimitry Andric if (!BBSPR.MBuf) 40106c3fb27SDimitry Andric return false; 40206c3fb27SDimitry Andric // Get the function name to debug info filename mapping. 403*1db9f3b2SDimitry Andric BBSPR.FunctionNameToDIFilename.clear(); 40406c3fb27SDimitry Andric for (const Function &F : M) { 40506c3fb27SDimitry Andric SmallString<128> DIFilename; 40606c3fb27SDimitry Andric if (F.isDeclaration()) 40706c3fb27SDimitry Andric continue; 40806c3fb27SDimitry Andric DISubprogram *Subprogram = F.getSubprogram(); 40906c3fb27SDimitry Andric if (Subprogram) { 41006c3fb27SDimitry Andric llvm::DICompileUnit *CU = Subprogram->getUnit(); 41106c3fb27SDimitry Andric if (CU) 41206c3fb27SDimitry Andric DIFilename = sys::path::remove_leading_dotslash(CU->getFilename()); 41306c3fb27SDimitry Andric } 41406c3fb27SDimitry Andric [[maybe_unused]] bool inserted = 415*1db9f3b2SDimitry Andric BBSPR.FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename) 416*1db9f3b2SDimitry Andric .second; 41706c3fb27SDimitry Andric assert(inserted); 41806c3fb27SDimitry Andric } 419*1db9f3b2SDimitry Andric if (auto Err = BBSPR.ReadProfile()) 42081ad6265SDimitry Andric report_fatal_error(std::move(Err)); 42106c3fb27SDimitry Andric return false; 42281ad6265SDimitry Andric } 42381ad6265SDimitry Andric 424*1db9f3b2SDimitry Andric AnalysisKey BasicBlockSectionsProfileReaderAnalysis::Key; 425*1db9f3b2SDimitry Andric 426*1db9f3b2SDimitry Andric BasicBlockSectionsProfileReader 427*1db9f3b2SDimitry Andric BasicBlockSectionsProfileReaderAnalysis::run(Function &F, 428*1db9f3b2SDimitry Andric FunctionAnalysisManager &AM) { 429*1db9f3b2SDimitry Andric return BasicBlockSectionsProfileReader(TM->getBBSectionsFuncListBuf()); 430*1db9f3b2SDimitry Andric } 431*1db9f3b2SDimitry Andric 432*1db9f3b2SDimitry Andric bool BasicBlockSectionsProfileReaderWrapperPass::isFunctionHot( 433*1db9f3b2SDimitry Andric StringRef FuncName) const { 434*1db9f3b2SDimitry Andric return BBSPR.isFunctionHot(FuncName); 435*1db9f3b2SDimitry Andric } 436*1db9f3b2SDimitry Andric 437*1db9f3b2SDimitry Andric std::pair<bool, SmallVector<BBClusterInfo>> 438*1db9f3b2SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getClusterInfoForFunction( 439*1db9f3b2SDimitry Andric StringRef FuncName) const { 440*1db9f3b2SDimitry Andric return BBSPR.getClusterInfoForFunction(FuncName); 441*1db9f3b2SDimitry Andric } 442*1db9f3b2SDimitry Andric 443*1db9f3b2SDimitry Andric SmallVector<SmallVector<unsigned>> 444*1db9f3b2SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction( 445*1db9f3b2SDimitry Andric StringRef FuncName) const { 446*1db9f3b2SDimitry Andric return BBSPR.getClonePathsForFunction(FuncName); 447*1db9f3b2SDimitry Andric } 448*1db9f3b2SDimitry Andric 449*1db9f3b2SDimitry Andric BasicBlockSectionsProfileReader & 450*1db9f3b2SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() { 451*1db9f3b2SDimitry Andric return BBSPR; 452*1db9f3b2SDimitry Andric } 453*1db9f3b2SDimitry Andric 454*1db9f3b2SDimitry Andric ImmutablePass *llvm::createBasicBlockSectionsProfileReaderWrapperPass( 455*1db9f3b2SDimitry Andric const MemoryBuffer *Buf) { 456*1db9f3b2SDimitry Andric return new BasicBlockSectionsProfileReaderWrapperPass(Buf); 45781ad6265SDimitry Andric } 458