aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2023-09-02 21:17:18 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-12-08 17:34:50 +0000
commit06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e (patch)
tree62f873df87c7c675557a179e0c4c83fe9f3087bc /contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp
parentcf037972ea8863e2bab7461d77345367d2c1e054 (diff)
parent7fa27ce4a07f19b07799a767fc29416f3b625afb (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/CodeGen/BasicBlockSectionsProfileReader.cpp92
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 *