diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2023-09-02 21:17:18 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2023-12-08 17:34:50 +0000 |
commit | 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch) | |
tree | 62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp | |
parent | cf037972ea8863e2bab7461d77345367d2c1e054 (diff) | |
parent | 7fa27ce4a07f19b07799a767fc29416f3b625afb (diff) |
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp')
-rw-r--r-- | contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp | 92 |
1 files changed, 74 insertions, 18 deletions
diff --git a/contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp b/contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp index 5bc8d82debc3..5dede452ec34 100644 --- a/contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp +++ b/contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp @@ -14,12 +14,17 @@ #include "llvm/CodeGen/BasicBlockSectionsProfileReader.h" #include "llvm/ADT/SmallSet.h" +#include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" #include "llvm/ADT/StringMap.h" #include "llvm/ADT/StringRef.h" +#include "llvm/CodeGen/Passes.h" +#include "llvm/IR/DebugInfoMetadata.h" #include "llvm/Support/Error.h" #include "llvm/Support/LineIterator.h" #include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/Path.h" +#include <llvm/ADT/STLExtras.h> using namespace llvm; @@ -35,13 +40,10 @@ bool BasicBlockSectionsProfileReader::isFunctionHot(StringRef FuncName) const { std::pair<bool, SmallVector<BBClusterInfo>> BasicBlockSectionsProfileReader::getBBClusterInfoForFunction( StringRef FuncName) const { - std::pair<bool, SmallVector<BBClusterInfo>> cluster_info(false, {}); auto R = ProgramBBClusterInfo.find(getAliasName(FuncName)); - if (R != ProgramBBClusterInfo.end()) { - cluster_info.second = R->second; - cluster_info.first = true; - } - return cluster_info; + return R != ProgramBBClusterInfo.end() + ? std::pair(true, R->second) + : std::pair(false, SmallVector<BBClusterInfo>{}); } // Basic Block Sections can be enabled for a subset of machine basic blocks. @@ -49,17 +51,19 @@ BasicBlockSectionsProfileReader::getBBClusterInfoForFunction( // block sections are desired. Additionally, machine basic block ids of the // functions can also be specified for a finer granularity. Moreover, a cluster // of basic blocks could be assigned to the same section. +// Optionally, a debug-info filename can be specified for each function to allow +// distinguishing internal-linkage functions of the same name. // A file with basic block sections for all of function main and three blocks // for function foo (of which 1 and 2 are placed in a cluster) looks like this: +// (Profile for function foo is only loaded when its debug-info filename +// matches 'path/to/foo_file.cc'). // ---------------------------- // list.txt: // !main -// !foo +// !foo M=path/to/foo_file.cc // !!1 2 // !!4 -static Error getBBClusterInfo(const MemoryBuffer *MBuf, - ProgramBBClusterInfoMapTy &ProgramBBClusterInfo, - StringMap<StringRef> &FuncAliasMap) { +Error BasicBlockSectionsProfileReader::ReadProfile() { assert(MBuf); line_iterator LineIt(*MBuf, /*SkipBlanks=*/true, /*CommentMarker=*/'#'); @@ -90,9 +94,10 @@ static Error getBBClusterInfo(const MemoryBuffer *MBuf, break; // Check for second "!" which indicates a cluster of basic blocks. if (S.consume_front("!")) { + // Skip the profile when we the profile iterator (FI) refers to the + // past-the-end element. if (FI == ProgramBBClusterInfo.end()) - return invalidProfileError( - "Cluster list does not follow a function name specifier."); + continue; SmallVector<StringRef, 4> BBIDs; S.split(BBIDs, ' '); // Reset current cluster position. @@ -112,18 +117,52 @@ static Error getBBClusterInfo(const MemoryBuffer *MBuf, BBClusterInfo{((unsigned)BBID), CurrentCluster, CurrentPosition++}); } CurrentCluster++; - } else { // This is a function name specifier. + } else { + // This is a function name specifier. It may include a debug info filename + // specifier starting with `M=`. + auto [AliasesStr, DIFilenameStr] = S.split(' '); + SmallString<128> DIFilename; + if (DIFilenameStr.startswith("M=")) { + DIFilename = + sys::path::remove_leading_dotslash(DIFilenameStr.substr(2)); + if (DIFilename.empty()) + return invalidProfileError("Empty module name specifier."); + } else if (!DIFilenameStr.empty()) { + return invalidProfileError("Unknown string found: '" + DIFilenameStr + + "'."); + } // Function aliases are separated using '/'. We use the first function // name for the cluster info mapping and delegate all other aliases to // this one. SmallVector<StringRef, 4> Aliases; - S.split(Aliases, '/'); + AliasesStr.split(Aliases, '/'); + bool FunctionFound = any_of(Aliases, [&](StringRef Alias) { + auto It = FunctionNameToDIFilename.find(Alias); + // No match if this function name is not found in this module. + if (It == FunctionNameToDIFilename.end()) + return false; + // Return a match if debug-info-filename is not specified. Otherwise, + // check for equality. + return DIFilename.empty() || It->second.equals(DIFilename); + }); + if (!FunctionFound) { + // Skip the following profile by setting the profile iterator (FI) to + // the past-the-end element. + FI = ProgramBBClusterInfo.end(); + continue; + } for (size_t i = 1; i < Aliases.size(); ++i) FuncAliasMap.try_emplace(Aliases[i], Aliases.front()); // Prepare for parsing clusters of this function name. // Start a new cluster map for this function name. - FI = ProgramBBClusterInfo.try_emplace(Aliases.front()).first; + auto R = ProgramBBClusterInfo.try_emplace(Aliases.front()); + // Report error when multiple profiles have been specified for the same + // function. + if (!R.second) + return invalidProfileError("Duplicate profile for function '" + + Aliases.front() + "'."); + FI = R.first; CurrentCluster = 0; FuncBBIDs.clear(); } @@ -131,11 +170,28 @@ static Error getBBClusterInfo(const MemoryBuffer *MBuf, return Error::success(); } -void BasicBlockSectionsProfileReader::initializePass() { +bool BasicBlockSectionsProfileReader::doInitialization(Module &M) { if (!MBuf) - return; - if (auto Err = getBBClusterInfo(MBuf, ProgramBBClusterInfo, FuncAliasMap)) + return false; + // Get the function name to debug info filename mapping. + FunctionNameToDIFilename.clear(); + for (const Function &F : M) { + SmallString<128> DIFilename; + if (F.isDeclaration()) + continue; + DISubprogram *Subprogram = F.getSubprogram(); + if (Subprogram) { + llvm::DICompileUnit *CU = Subprogram->getUnit(); + if (CU) + DIFilename = sys::path::remove_leading_dotslash(CU->getFilename()); + } + [[maybe_unused]] bool inserted = + FunctionNameToDIFilename.try_emplace(F.getName(), DIFilename).second; + assert(inserted); + } + if (auto Err = ReadProfile()) report_fatal_error(std::move(Err)); + return false; } ImmutablePass * |