-
Notifications
You must be signed in to change notification settings - Fork 10.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[MemProf] Expand optimization scope to internal linkage function #73236
Conversation
@llvm/pr-subscribers-pgo @llvm/pr-subscribers-clang Author: None (lifengxiang1025) ChangesNow MemProf can't do IR annotation right in the local linkage function and global initial function __cxx_global_var_init. In llvm-profdata which convert raw memory profile to memory profile, it uses function name in dwarf to create GUID. But when llvm consumes memory profile, it use Full diff: https://github.com/llvm/llvm-project/pull/73236.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index e08a1e5f42df20c..ae45c23c9e6811c 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -538,6 +538,9 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
{
llvm::raw_svector_ostream Out(FnName);
getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out);
+ if (getCodeGenOpts().UniqueInternalLinkageNames) {
+ Out << getModuleNameHash();
+ }
}
// Create a variable initialization function.
diff --git a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
index c6134ce77136364..97db0122be7c8e7 100644
--- a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
@@ -677,24 +677,10 @@ static void readMemprof(Module &M, Function &F,
const TargetLibraryInfo &TLI) {
auto &Ctx = M.getContext();
- auto FuncName = getIRPGOFuncName(F);
+ auto FuncName = F.getName();
auto FuncGUID = Function::getGUID(FuncName);
std::optional<memprof::MemProfRecord> MemProfRec;
auto Err = MemProfReader->getMemProfRecord(FuncGUID).moveInto(MemProfRec);
- if (Err) {
- // If we don't find getIRPGOFuncName(), try getPGOFuncName() to handle
- // profiles built by older compilers
- Err = handleErrors(std::move(Err), [&](const InstrProfError &IE) -> Error {
- if (IE.get() != instrprof_error::unknown_function)
- return make_error<InstrProfError>(IE);
- auto FuncName = getPGOFuncName(F);
- auto FuncGUID = Function::getGUID(FuncName);
- if (auto Err =
- MemProfReader->getMemProfRecord(FuncGUID).moveInto(MemProfRec))
- return Err;
- return Error::success();
- });
- }
if (Err) {
handleAllErrors(std::move(Err), [&](const InstrProfError &IPE) {
auto Err = IPE.get();
|
@llvm/pr-subscribers-llvm-transforms Author: None (lifengxiang1025) ChangesNow MemProf can't do IR annotation right in the local linkage function and global initial function __cxx_global_var_init. In llvm-profdata which convert raw memory profile to memory profile, it uses function name in dwarf to create GUID. But when llvm consumes memory profile, it use Full diff: https://github.com/llvm/llvm-project/pull/73236.diff 2 Files Affected:
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index e08a1e5f42df20c..ae45c23c9e6811c 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -538,6 +538,9 @@ CodeGenModule::EmitCXXGlobalVarDeclInitFunc(const VarDecl *D,
{
llvm::raw_svector_ostream Out(FnName);
getCXXABI().getMangleContext().mangleDynamicInitializer(D, Out);
+ if (getCodeGenOpts().UniqueInternalLinkageNames) {
+ Out << getModuleNameHash();
+ }
}
// Create a variable initialization function.
diff --git a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
index c6134ce77136364..97db0122be7c8e7 100644
--- a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
@@ -677,24 +677,10 @@ static void readMemprof(Module &M, Function &F,
const TargetLibraryInfo &TLI) {
auto &Ctx = M.getContext();
- auto FuncName = getIRPGOFuncName(F);
+ auto FuncName = F.getName();
auto FuncGUID = Function::getGUID(FuncName);
std::optional<memprof::MemProfRecord> MemProfRec;
auto Err = MemProfReader->getMemProfRecord(FuncGUID).moveInto(MemProfRec);
- if (Err) {
- // If we don't find getIRPGOFuncName(), try getPGOFuncName() to handle
- // profiles built by older compilers
- Err = handleErrors(std::move(Err), [&](const InstrProfError &IE) -> Error {
- if (IE.get() != instrprof_error::unknown_function)
- return make_error<InstrProfError>(IE);
- auto FuncName = getPGOFuncName(F);
- auto FuncGUID = Function::getGUID(FuncName);
- if (auto Err =
- MemProfReader->getMemProfRecord(FuncGUID).moveInto(MemProfRec))
- return Err;
- return Error::success();
- });
- }
if (Err) {
handleAllErrors(std::move(Err), [&](const InstrProfError &IPE) {
auto Err = IPE.get();
|
9dd4626
to
fdce130
Compare
@teresajohnson Can you take a look and provide your insights? |
fdce130
to
82cebba
Compare
@snehasish can you take a look at the issue described here? Should we be doing something different in llvm-profdata? |
@lifengxiang1025 thanks for flagging this issue. I think it's best to not rely on unique-internal-linkage-name here. Instead we should extend the logic in RawMemProfReader.cpp to include "filename;" if the function is internal linkage as expected by IRPGOFuncName. Can you try this approach? llvm-project/llvm/lib/ProfileData/RawMemProfReader.cpp Lines 509 to 510 in c0fe071
|
I don't think we want to change the name in the frames themselves, as the names in the debug info when matching don't contain this prefix. Although I suppose we could modify the matcher to add the prefixes when matching frames too. I.e. here:
It sounds like the issue is that the names used to index the memprof records do not use the PGOFuncName scheme and therefore we never find any memprof records for an internal linkage function during matching. I.e. the GUID passed to InstrProfWriter::addMemProfRecord. Unfortunately, looking at RawMemProfReader.cpp it does look like that eventually gets populated out of the Function (GUID) field from same Frame setup code. So we'd either need to do some extra handling in that code so that the prefix is only used for the record entry, or change the matcher (the latter may be the easiest). |
I don't find how to get linkage type in dwarf. It seems dwarf don't record linkage type. And the linkage type between thin compile and link step can change also. |
My response assumed that it was already using the IRPGOFuncName for matching. Yes, I think we should make the switch then.
Yes, you're right. As an alternative can we use the symbol table and find |
If we choose this method. I think we can't deal with the situation which one symbol is not local linkage type in thin compile, but will be converted to local linkage after thin backend by thinlto's internalization. In this situation function name in llvm-profdata will have prefix with file name. But when llvm consumes memory profile, PGOFuncName won't return function name with prefix. |
If I understand the issue you are describing, that would only occur if the instrumentation build also used ThinLTO. Is that a typical use case for you? |
@snehasish and I chatted more about this offline. Using the dwarf info to figure out the right source name prefix during indexing is not straightforward. The source file name used as the prefix in the compiler for the IRPGOName is that of the TU. The source file of the line in the dwarf info may be a header. It could be possible to walk up the profiled inline frames to find a source file, but that is error prone in certain circumstances (e.g. if the profiled binary had thinlto cross module inlining, and if it isn't obvious which source file name is a non-included TU). I think your change to the matching is almost strictly better than the complete non-matching we get currently for local functions. It would even work in many cases without uniq suffixes, but uniq suffixes will make that work even better. So let's go ahead with that change. However, we'd like to request that you split the __cxx_global_var_init change into a separate patch, as it is somewhat orthogonal to the matching change, and in case there are unexpected issues with that change. Can you split that out and make the test case here for matching of a non __cxx_global_var_init function? Thanks! |
f91e72a
to
3e50c55
Compare
Thanks for your reply. I have removed the __cxx_global_var_init change. Please review again. |
llvm/test/Transforms/PGOProfile/Inputs/update_memprof_inputs.sh
Outdated
Show resolved
Hide resolved
3e50c55
to
fd0f4ff
Compare
also s/linakge/linkage/ in commit message and PR title. |
fd0f4ff
to
1425bf3
Compare
Now MemProf can't do IR annotation right in the local linkage function and global initial function __cxx_global_var_init. In llvm-profdata which convert raw memory profile to memory profile, it uses function name in dwarf to create GUID. But when llvm consumes memory profile, it use
getIRPGOFuncName
orgetPGOFuncName
which returns local linkage function asFileName;FunctionName
orFileName:FunctionName
to get function name and create GUID. So profile creator's GUID is not same as profile consumer.So I think MemProf should be used with
unique-internal-linkage-names
and don't use PGOFuncName.__cxx_global_var_init is created later than where UniqueInternalLinkageNames works. So I add uniq suffix to __cxx_global_var_init additionally.