Skip to content

Commit 594e11c

Browse files
[MemProf] Avoid incorrect ICP symtab canonicalization (#115419)
ICP builds a symtab from the symbols in the module allowing mapping from the VP metadata GUIDs to the Function. MemProf uses this same symtab handling for its ICP during cloning. When symbols are added to the symtab, the handling adds both a GUID computed from the function name, or from the attached PGOFuncName metadata for locals, as well as a GUID computed from the "canonicalized" name, which strips all "." suffixes other than ".__uniq". This was originally meant to remove the ".llvm.*" suffix added to promoted locals (done earlier in the ThinLTO backend). In theory, it should no longer be needed as locals should have PGOFuncName metadata. However, this was causing a linker unsat, in code that used coroutines. For an original coroutine function, there were several additional functions created that had the same name, but different "." suffixes. Therefore the canonical name for these additional functions had the same GUID as that of the original function, leading to extra entries in the symtab, and to selecting the wrong function for promotion. For regular ICP this can happen, but is just a performance issue. However, for memprof the promoted direct call calls a memprof clone, and because we called the wrong function, in this case it didn't have a memprof clone and we got a linker unsat. We may be able to remove the canonical name handling for ICP in general, but for now disable it for MemProf. At worst this could lead to not finding a GUID in the symtab and not performing an ICP, so should be conservatively correct.
1 parent bfa3ffb commit 594e11c

File tree

4 files changed

+35
-7
lines changed

4 files changed

+35
-7
lines changed

llvm/include/llvm/ProfileData/InstrProf.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,8 @@ class InstrProfSymtab {
504504
// name-set = {PGOFuncName} union {getCanonicalName(PGOFuncName)}
505505
// - In MD5NameMap: <MD5Hash(name), name> for name in name-set
506506
// - In MD5FuncMap: <MD5Hash(name), &F> for name in name-set
507-
Error addFuncWithName(Function &F, StringRef PGOFuncName);
507+
// The canonical name is only added if \c AddCanonical is true.
508+
Error addFuncWithName(Function &F, StringRef PGOFuncName, bool AddCanonical);
508509

509510
// Add the vtable into the symbol table, by creating the following
510511
// map entries:
@@ -560,7 +561,9 @@ class InstrProfSymtab {
560561
/// decls from module \c M. This interface is used by transformation
561562
/// passes such as indirect function call promotion. Variable \c InLTO
562563
/// indicates if this is called from LTO optimization passes.
563-
Error create(Module &M, bool InLTO = false);
564+
/// A canonical name, removing non-__uniq suffixes, is added if
565+
/// \c AddCanonical is true.
566+
Error create(Module &M, bool InLTO = false, bool AddCanonical = true);
564567

565568
/// Create InstrProfSymtab from a set of names iteratable from
566569
/// \p IterRange. This interface is used by IndexedProfReader.

llvm/lib/ProfileData/InstrProf.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -483,16 +483,16 @@ GlobalVariable *createPGOFuncNameVar(Function &F, StringRef PGOFuncName) {
483483
return createPGOFuncNameVar(*F.getParent(), F.getLinkage(), PGOFuncName);
484484
}
485485

486-
Error InstrProfSymtab::create(Module &M, bool InLTO) {
486+
Error InstrProfSymtab::create(Module &M, bool InLTO, bool AddCanonical) {
487487
for (Function &F : M) {
488488
// Function may not have a name: like using asm("") to overwrite the name.
489489
// Ignore in this case.
490490
if (!F.hasName())
491491
continue;
492-
if (Error E = addFuncWithName(F, getIRPGOFuncName(F, InLTO)))
492+
if (Error E = addFuncWithName(F, getIRPGOFuncName(F, InLTO), AddCanonical))
493493
return E;
494494
// Also use getPGOFuncName() so that we can find records from older profiles
495-
if (Error E = addFuncWithName(F, getPGOFuncName(F, InLTO)))
495+
if (Error E = addFuncWithName(F, getPGOFuncName(F, InLTO), AddCanonical))
496496
return E;
497497
}
498498

@@ -630,7 +630,8 @@ StringRef InstrProfSymtab::getCanonicalName(StringRef PGOName) {
630630
return PGOName;
631631
}
632632

633-
Error InstrProfSymtab::addFuncWithName(Function &F, StringRef PGOFuncName) {
633+
Error InstrProfSymtab::addFuncWithName(Function &F, StringRef PGOFuncName,
634+
bool AddCanonical) {
634635
auto NameToGUIDMap = [&](StringRef Name) -> Error {
635636
if (Error E = addFuncName(Name))
636637
return E;
@@ -640,6 +641,9 @@ Error InstrProfSymtab::addFuncWithName(Function &F, StringRef PGOFuncName) {
640641
if (Error E = NameToGUIDMap(PGOFuncName))
641642
return E;
642643

644+
if (!AddCanonical)
645+
return Error::success();
646+
643647
StringRef CanonicalFuncName = getCanonicalName(PGOFuncName);
644648
if (CanonicalFuncName != PGOFuncName)
645649
return NameToGUIDMap(CanonicalFuncName);

llvm/lib/Transforms/IPO/MemProfContextDisambiguation.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4143,7 +4143,17 @@ bool MemProfContextDisambiguation::initializeIndirectCallPromotionInfo(
41434143
Module &M) {
41444144
ICallAnalysis = std::make_unique<ICallPromotionAnalysis>();
41454145
Symtab = std::make_unique<InstrProfSymtab>();
4146-
if (Error E = Symtab->create(M, /*InLTO=*/true)) {
4146+
// Don't add canonical names, to avoid multiple functions to the symtab
4147+
// when they both have the same root name with "." suffixes stripped.
4148+
// If we pick the wrong one then this could lead to incorrect ICP and calling
4149+
// a memprof clone that we don't actually create (resulting in linker unsats).
4150+
// What this means is that the GUID of the function (or its PGOFuncName
4151+
// metadata) *must* match that in the VP metadata to allow promotion.
4152+
// In practice this should not be a limitation, since local functions should
4153+
// have PGOFuncName metadata and global function names shouldn't need any
4154+
// special handling (they should not get the ".llvm.*" suffix that the
4155+
// canonicalization handling is attempting to strip).
4156+
if (Error E = Symtab->create(M, /*InLTO=*/true, /*AddCanonical=*/false)) {
41474157
std::string SymtabFailure = toString(std::move(E));
41484158
M.getContext().emitError("Failed to create symtab: " + SymtabFailure);
41494159
return false;

llvm/test/ThinLTO/X86/memprof-icp.ll

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
; RUN: -enable-memprof-indirect-call-support=true \
9292
; RUN: -supports-hot-cold-new \
9393
; RUN: -r=%t/foo.o,_Z3fooR2B0j,plx \
94+
; RUN: -r=%t/foo.o,_ZN2B03barEj.abc,plx \
9495
; RUN: -r=%t/foo.o,_Z3xyzR2B0j, \
9596
; RUN: -r=%t/main.o,_Z3fooR2B0j, \
9697
; RUN: -r=%t/main.o,_Znwm, \
@@ -121,6 +122,7 @@
121122
; RUN: -supports-hot-cold-new \
122123
; RUN: -thinlto-distributed-indexes \
123124
; RUN: -r=%t/foo.o,_Z3fooR2B0j,plx \
125+
; RUN: -r=%t/foo.o,_ZN2B03barEj.abc,plx \
124126
; RUN: -r=%t/foo.o,_Z3xyzR2B0j, \
125127
; RUN: -r=%t/main.o,_Z3fooR2B0j, \
126128
; RUN: -r=%t/main.o,_Znwm, \
@@ -155,6 +157,7 @@
155157
; RUN: -enable-memprof-indirect-call-support=false \
156158
; RUN: -supports-hot-cold-new \
157159
; RUN: -r=%t/foo.noicp.o,_Z3fooR2B0j,plx \
160+
; RUN: -r=%t/foo.noicp.o,_ZN2B03barEj.abc,plx \
158161
; RUN: -r=%t/foo.noicp.o,_Z3xyzR2B0j, \
159162
; RUN: -r=%t/main.o,_Z3fooR2B0j, \
160163
; RUN: -r=%t/main.o,_Znwm, \
@@ -261,6 +264,14 @@ target triple = "x86_64-unknown-linux-gnu"
261264

262265
declare i32 @_Z3xyzR2B0j(ptr %b)
263266

267+
;; Add a function that has the same name as one of the indirect callees, but
268+
;; with a suffix, to make sure we don't incorrectly pick the wrong one as the
269+
;; promoted target (which happens if we attempt to canonicalize the names
270+
;; when building the ICP symtab).
271+
define i32 @_ZN2B03barEj.abc(ptr %this, i32 %s) {
272+
ret i32 0
273+
}
274+
264275
define i32 @_Z3fooR2B0j(ptr %b) {
265276
entry:
266277
%0 = load ptr, ptr %b, align 8

0 commit comments

Comments
 (0)