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
331db9f3b2SDimitry Andric char BasicBlockSectionsProfileReaderWrapperPass::ID = 0;
341db9f3b2SDimitry Andric INITIALIZE_PASS(BasicBlockSectionsProfileReaderWrapperPass,
351db9f3b2SDimitry Andric "bbsections-profile-reader",
3681ad6265SDimitry Andric "Reads and parses a basic block sections profile.", false,
3781ad6265SDimitry Andric false)
3881ad6265SDimitry Andric
395f757f3fSDimitry Andric Expected<UniqueBBID>
parseUniqueBBID(StringRef S) const405f757f3fSDimitry 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
isFunctionHot(StringRef FuncName) const5981ad6265SDimitry Andric bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const {
605f757f3fSDimitry Andric return getClusterInfoForFunction(FuncName).first;
6181ad6265SDimitry Andric }
6281ad6265SDimitry Andric
6381ad6265SDimitry Andric std::pair<bool, SmallVector<BBClusterInfo>>
getClusterInfoForFunction(StringRef FuncName) const645f757f3fSDimitry 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>>
getClonePathsForFunction(StringRef FuncName) const735f757f3fSDimitry 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 // ****************************************************************************
ReadV1Profile()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.
173*0fca6ea1SDimitry Andric return DIFilename.empty() || It->second == 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 FI->second.ClusterInfo.emplace_back(BBClusterInfo{
2185f757f3fSDimitry Andric *std::move(BasicBlockID), CurrentCluster, CurrentPosition++});
2195f757f3fSDimitry Andric }
2205f757f3fSDimitry Andric CurrentCluster++;
2215f757f3fSDimitry Andric continue;
2225f757f3fSDimitry Andric case 'p': { // Basic block cloning path specifier.
2235f757f3fSDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the
2245f757f3fSDimitry Andric // past-the-end element.
2255f757f3fSDimitry Andric if (FI == ProgramPathAndClusterInfo.end())
2265f757f3fSDimitry Andric continue;
2275f757f3fSDimitry Andric SmallSet<unsigned, 5> BBsInPath;
2285f757f3fSDimitry Andric FI->second.ClonePaths.push_back({});
2295f757f3fSDimitry Andric for (size_t I = 0; I < Values.size(); ++I) {
2305f757f3fSDimitry Andric auto BaseBBIDStr = Values[I];
2315f757f3fSDimitry Andric unsigned long long BaseBBID = 0;
2325f757f3fSDimitry Andric if (getAsUnsignedInteger(BaseBBIDStr, 10, BaseBBID))
2335f757f3fSDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") +
2345f757f3fSDimitry Andric BaseBBIDStr + "'");
2355f757f3fSDimitry Andric if (I != 0 && !BBsInPath.insert(BaseBBID).second)
2365f757f3fSDimitry Andric return createProfileParseError(
2375f757f3fSDimitry Andric Twine("duplicate cloned block in path: '") + BaseBBIDStr + "'");
2385f757f3fSDimitry Andric FI->second.ClonePaths.back().push_back(BaseBBID);
2395f757f3fSDimitry Andric }
2405f757f3fSDimitry Andric continue;
2415f757f3fSDimitry Andric }
2425f757f3fSDimitry Andric default:
2435f757f3fSDimitry Andric return createProfileParseError(Twine("invalid specifier: '") +
2445f757f3fSDimitry Andric Twine(Specifier) + "'");
2455f757f3fSDimitry Andric }
2465f757f3fSDimitry Andric llvm_unreachable("should not break from this switch statement");
2475f757f3fSDimitry Andric }
2485f757f3fSDimitry Andric return Error::success();
2495f757f3fSDimitry Andric }
2505f757f3fSDimitry Andric
ReadV0Profile()2515f757f3fSDimitry Andric Error BasicBlockSectionsProfileReader::ReadV0Profile() {
2525f757f3fSDimitry Andric auto FI = ProgramPathAndClusterInfo.end();
2535f757f3fSDimitry Andric // Current cluster ID corresponding to this function.
2545f757f3fSDimitry Andric unsigned CurrentCluster = 0;
2555f757f3fSDimitry Andric // Current position in the current cluster.
2565f757f3fSDimitry Andric unsigned CurrentPosition = 0;
2575f757f3fSDimitry Andric
2585f757f3fSDimitry Andric // Temporary set to ensure every basic block ID appears once in the clusters
2595f757f3fSDimitry Andric // of a function.
2605f757f3fSDimitry Andric SmallSet<unsigned, 4> FuncBBIDs;
2615f757f3fSDimitry Andric
2625f757f3fSDimitry Andric for (; !LineIt.is_at_eof(); ++LineIt) {
2635f757f3fSDimitry Andric StringRef S(*LineIt);
2645f757f3fSDimitry Andric if (S[0] == '@')
2655f757f3fSDimitry Andric continue;
2665f757f3fSDimitry Andric // Check for the leading "!"
2675f757f3fSDimitry Andric if (!S.consume_front("!") || S.empty())
2685f757f3fSDimitry Andric break;
2695f757f3fSDimitry Andric // Check for second "!" which indicates a cluster of basic blocks.
2705f757f3fSDimitry Andric if (S.consume_front("!")) {
2715f757f3fSDimitry Andric // Skip the profile when we the profile iterator (FI) refers to the
2725f757f3fSDimitry Andric // past-the-end element.
2735f757f3fSDimitry Andric if (FI == ProgramPathAndClusterInfo.end())
2745f757f3fSDimitry Andric continue;
2755f757f3fSDimitry Andric SmallVector<StringRef, 4> BBIDs;
2765f757f3fSDimitry Andric S.split(BBIDs, ' ');
2775f757f3fSDimitry Andric // Reset current cluster position.
2785f757f3fSDimitry Andric CurrentPosition = 0;
2795f757f3fSDimitry Andric for (auto BBIDStr : BBIDs) {
2805f757f3fSDimitry Andric unsigned long long BBID;
2815f757f3fSDimitry Andric if (getAsUnsignedInteger(BBIDStr, 10, BBID))
2825f757f3fSDimitry Andric return createProfileParseError(Twine("unsigned integer expected: '") +
2835f757f3fSDimitry Andric BBIDStr + "'");
2845f757f3fSDimitry Andric if (!FuncBBIDs.insert(BBID).second)
2855f757f3fSDimitry Andric return createProfileParseError(
2865f757f3fSDimitry Andric Twine("duplicate basic block id found '") + BBIDStr + "'");
2875f757f3fSDimitry Andric
2885f757f3fSDimitry Andric FI->second.ClusterInfo.emplace_back(
2895f757f3fSDimitry Andric BBClusterInfo({{static_cast<unsigned>(BBID), 0},
2905f757f3fSDimitry Andric CurrentCluster,
2915f757f3fSDimitry Andric CurrentPosition++}));
2925f757f3fSDimitry Andric }
2935f757f3fSDimitry Andric CurrentCluster++;
2945f757f3fSDimitry Andric } else {
2955f757f3fSDimitry Andric // This is a function name specifier. It may include a debug info filename
2965f757f3fSDimitry Andric // specifier starting with `M=`.
2975f757f3fSDimitry Andric auto [AliasesStr, DIFilenameStr] = S.split(' ');
2985f757f3fSDimitry Andric SmallString<128> DIFilename;
2995f757f3fSDimitry Andric if (DIFilenameStr.starts_with("M=")) {
3005f757f3fSDimitry Andric DIFilename =
3015f757f3fSDimitry Andric sys::path::remove_leading_dotslash(DIFilenameStr.substr(2));
3025f757f3fSDimitry Andric if (DIFilename.empty())
3035f757f3fSDimitry Andric return createProfileParseError("empty module name specifier");
3045f757f3fSDimitry Andric } else if (!DIFilenameStr.empty()) {
3055f757f3fSDimitry Andric return createProfileParseError("unknown string found: '" +
3065f757f3fSDimitry Andric DIFilenameStr + "'");
3075f757f3fSDimitry Andric }
3085f757f3fSDimitry Andric // Function aliases are separated using '/'. We use the first function
3095f757f3fSDimitry Andric // name for the cluster info mapping and delegate all other aliases to
3105f757f3fSDimitry Andric // this one.
3115f757f3fSDimitry Andric SmallVector<StringRef, 4> Aliases;
3125f757f3fSDimitry Andric AliasesStr.split(Aliases, '/');
3135f757f3fSDimitry Andric bool FunctionFound = any_of(Aliases, [&](StringRef Alias) {
3145f757f3fSDimitry Andric auto It = FunctionNameToDIFilename.find(Alias);
3155f757f3fSDimitry Andric // No match if this function name is not found in this module.
3165f757f3fSDimitry Andric if (It == FunctionNameToDIFilename.end())
3175f757f3fSDimitry Andric return false;
3185f757f3fSDimitry Andric // Return a match if debug-info-filename is not specified. Otherwise,
3195f757f3fSDimitry Andric // check for equality.
320*0fca6ea1SDimitry Andric return DIFilename.empty() || It->second == DIFilename;
3215f757f3fSDimitry Andric });
3225f757f3fSDimitry Andric if (!FunctionFound) {
3235f757f3fSDimitry Andric // Skip the following profile by setting the profile iterator (FI) to
3245f757f3fSDimitry Andric // the past-the-end element.
3255f757f3fSDimitry Andric FI = ProgramPathAndClusterInfo.end();
3265f757f3fSDimitry Andric continue;
3275f757f3fSDimitry Andric }
3285f757f3fSDimitry Andric for (size_t i = 1; i < Aliases.size(); ++i)
3295f757f3fSDimitry Andric FuncAliasMap.try_emplace(Aliases[i], Aliases.front());
3305f757f3fSDimitry Andric
3315f757f3fSDimitry Andric // Prepare for parsing clusters of this function name.
3325f757f3fSDimitry Andric // Start a new cluster map for this function name.
3335f757f3fSDimitry Andric auto R = ProgramPathAndClusterInfo.try_emplace(Aliases.front());
3345f757f3fSDimitry Andric // Report error when multiple profiles have been specified for the same
3355f757f3fSDimitry Andric // function.
3365f757f3fSDimitry Andric if (!R.second)
3375f757f3fSDimitry Andric return createProfileParseError("duplicate profile for function '" +
3385f757f3fSDimitry Andric Aliases.front() + "'");
3395f757f3fSDimitry Andric FI = R.first;
3405f757f3fSDimitry Andric CurrentCluster = 0;
3415f757f3fSDimitry Andric FuncBBIDs.clear();
3425f757f3fSDimitry Andric }
3435f757f3fSDimitry Andric }
3445f757f3fSDimitry Andric return Error::success();
34581ad6265SDimitry Andric }
34681ad6265SDimitry Andric
34781ad6265SDimitry Andric // Basic Block Sections can be enabled for a subset of machine basic blocks.
34881ad6265SDimitry Andric // This is done by passing a file containing names of functions for which basic
34981ad6265SDimitry Andric // block sections are desired. Additionally, machine basic block ids of the
35081ad6265SDimitry Andric // functions can also be specified for a finer granularity. Moreover, a cluster
35181ad6265SDimitry Andric // of basic blocks could be assigned to the same section.
35206c3fb27SDimitry Andric // Optionally, a debug-info filename can be specified for each function to allow
35306c3fb27SDimitry Andric // distinguishing internal-linkage functions of the same name.
35481ad6265SDimitry Andric // A file with basic block sections for all of function main and three blocks
35581ad6265SDimitry Andric // for function foo (of which 1 and 2 are placed in a cluster) looks like this:
35606c3fb27SDimitry Andric // (Profile for function foo is only loaded when its debug-info filename
35706c3fb27SDimitry Andric // matches 'path/to/foo_file.cc').
35881ad6265SDimitry Andric // ----------------------------
35981ad6265SDimitry Andric // list.txt:
36081ad6265SDimitry Andric // !main
36106c3fb27SDimitry Andric // !foo M=path/to/foo_file.cc
36281ad6265SDimitry Andric // !!1 2
36381ad6265SDimitry Andric // !!4
ReadProfile()36406c3fb27SDimitry Andric Error BasicBlockSectionsProfileReader::ReadProfile() {
36581ad6265SDimitry Andric assert(MBuf);
36681ad6265SDimitry Andric
3675f757f3fSDimitry Andric unsigned long long Version = 0;
3685f757f3fSDimitry Andric StringRef FirstLine(*LineIt);
3695f757f3fSDimitry Andric if (FirstLine.consume_front("v")) {
3705f757f3fSDimitry Andric if (getAsUnsignedInteger(FirstLine, 10, Version)) {
3715f757f3fSDimitry Andric return createProfileParseError(Twine("version number expected: '") +
3725f757f3fSDimitry Andric FirstLine + "'");
37381ad6265SDimitry Andric }
3745f757f3fSDimitry Andric if (Version > 1) {
3755f757f3fSDimitry Andric return createProfileParseError(Twine("invalid profile version: ") +
3765f757f3fSDimitry Andric Twine(Version));
37706c3fb27SDimitry Andric }
3785f757f3fSDimitry Andric ++LineIt;
37906c3fb27SDimitry Andric }
38081ad6265SDimitry Andric
3815f757f3fSDimitry Andric switch (Version) {
3825f757f3fSDimitry Andric case 0:
3835f757f3fSDimitry Andric // TODO: Deprecate V0 once V1 is fully integrated downstream.
3845f757f3fSDimitry Andric return ReadV0Profile();
3855f757f3fSDimitry Andric case 1:
3865f757f3fSDimitry Andric return ReadV1Profile();
3875f757f3fSDimitry Andric default:
3885f757f3fSDimitry Andric llvm_unreachable("Invalid profile version.");
38981ad6265SDimitry Andric }
39081ad6265SDimitry Andric }
39181ad6265SDimitry Andric
doInitialization(Module & M)3921db9f3b2SDimitry Andric bool BasicBlockSectionsProfileReaderWrapperPass::doInitialization(Module &M) {
3931db9f3b2SDimitry Andric if (!BBSPR.MBuf)
39406c3fb27SDimitry Andric return false;
39506c3fb27SDimitry Andric // Get the function name to debug info filename mapping.
3961db9f3b2SDimitry Andric BBSPR.FunctionNameToDIFilename.clear();
39706c3fb27SDimitry Andric for (const Function &F : M) {
39806c3fb27SDimitry Andric SmallString<128> DIFilename;
39906c3fb27SDimitry Andric if (F.isDeclaration())
40006c3fb27SDimitry Andric continue;
40106c3fb27SDimitry Andric DISubprogram *Subprogram = F.getSubprogram();
40206c3fb27SDimitry Andric if (Subprogram) {
40306c3fb27SDimitry Andric llvm::DICompileUnit *CU = Subprogram->getUnit();
40406c3fb27SDimitry Andric if (CU)
40506c3fb27SDimitry Andric DIFilename = sys::path::remove_leading_dotslash(CU->getFilename());
40606c3fb27SDimitry Andric }
40706c3fb27SDimitry Andric [[maybe_unused]] bool inserted =
4081db9f3b2SDimitry Andric BBSPR.FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename)
4091db9f3b2SDimitry Andric .second;
41006c3fb27SDimitry Andric assert(inserted);
41106c3fb27SDimitry Andric }
4121db9f3b2SDimitry Andric if (auto Err = BBSPR.ReadProfile())
41381ad6265SDimitry Andric report_fatal_error(std::move(Err));
41406c3fb27SDimitry Andric return false;
41581ad6265SDimitry Andric }
41681ad6265SDimitry Andric
4171db9f3b2SDimitry Andric AnalysisKey BasicBlockSectionsProfileReaderAnalysis::Key;
4181db9f3b2SDimitry Andric
4191db9f3b2SDimitry Andric BasicBlockSectionsProfileReader
run(Function & F,FunctionAnalysisManager & AM)4201db9f3b2SDimitry Andric BasicBlockSectionsProfileReaderAnalysis::run(Function &F,
4211db9f3b2SDimitry Andric FunctionAnalysisManager &AM) {
4221db9f3b2SDimitry Andric return BasicBlockSectionsProfileReader(TM->getBBSectionsFuncListBuf());
4231db9f3b2SDimitry Andric }
4241db9f3b2SDimitry Andric
isFunctionHot(StringRef FuncName) const4251db9f3b2SDimitry Andric bool BasicBlockSectionsProfileReaderWrapperPass::isFunctionHot(
4261db9f3b2SDimitry Andric StringRef FuncName) const {
4271db9f3b2SDimitry Andric return BBSPR.isFunctionHot(FuncName);
4281db9f3b2SDimitry Andric }
4291db9f3b2SDimitry Andric
4301db9f3b2SDimitry Andric std::pair<bool, SmallVector<BBClusterInfo>>
getClusterInfoForFunction(StringRef FuncName) const4311db9f3b2SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getClusterInfoForFunction(
4321db9f3b2SDimitry Andric StringRef FuncName) const {
4331db9f3b2SDimitry Andric return BBSPR.getClusterInfoForFunction(FuncName);
4341db9f3b2SDimitry Andric }
4351db9f3b2SDimitry Andric
4361db9f3b2SDimitry Andric SmallVector<SmallVector<unsigned>>
getClonePathsForFunction(StringRef FuncName) const4371db9f3b2SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getClonePathsForFunction(
4381db9f3b2SDimitry Andric StringRef FuncName) const {
4391db9f3b2SDimitry Andric return BBSPR.getClonePathsForFunction(FuncName);
4401db9f3b2SDimitry Andric }
4411db9f3b2SDimitry Andric
4421db9f3b2SDimitry Andric BasicBlockSectionsProfileReader &
getBBSPR()4431db9f3b2SDimitry Andric BasicBlockSectionsProfileReaderWrapperPass::getBBSPR() {
4441db9f3b2SDimitry Andric return BBSPR;
4451db9f3b2SDimitry Andric }
4461db9f3b2SDimitry Andric
createBasicBlockSectionsProfileReaderWrapperPass(const MemoryBuffer * Buf)4471db9f3b2SDimitry Andric ImmutablePass *llvm::createBasicBlockSectionsProfileReaderWrapperPass(
4481db9f3b2SDimitry Andric const MemoryBuffer *Buf) {
4491db9f3b2SDimitry Andric return new BasicBlockSectionsProfileReaderWrapperPass(Buf);
45081ad6265SDimitry Andric }
451