diff --git a/llvm/include/llvm/ProfileData/InstrProf.h b/llvm/include/llvm/ProfileData/InstrProf.h index f59ddc3e5932..f742476ac854 100644 --- a/llvm/include/llvm/ProfileData/InstrProf.h +++ b/llvm/include/llvm/ProfileData/InstrProf.h @@ -506,9 +506,9 @@ class InstrProfSymtab { public: using AddrHashMap = std::vector>; - // Returns the canonical name of the given PGOName. In a canonical name, all - // suffixes that begins with "." except ".__uniq." are stripped. - // FIXME: Unify this with `FunctionSamples::getCanonicalFnName`. + // Returns the canonical name of the given PGOName. This shares the same + // logic of FunctionSamples::getCanonicalFnName() but only strips ".llvm." + // and ".part", and leaves out ".__uniq.". LLVM_ABI static StringRef getCanonicalName(StringRef PGOName); private: @@ -761,7 +761,7 @@ void InstrProfSymtab::finalizeSymtab() const { if (Sorted) return; llvm::sort(MD5NameMap, less_first()); - llvm::sort(MD5FuncMap, less_first()); + llvm::stable_sort(MD5FuncMap, less_first()); llvm::sort(AddrToMD5Map, less_first()); AddrToMD5Map.erase(llvm::unique(AddrToMD5Map), AddrToMD5Map.end()); Sorted = true; diff --git a/llvm/lib/ProfileData/InstrProf.cpp b/llvm/lib/ProfileData/InstrProf.cpp index 54987872f2d8..82469481881c 100644 --- a/llvm/lib/ProfileData/InstrProf.cpp +++ b/llvm/lib/ProfileData/InstrProf.cpp @@ -30,6 +30,7 @@ #include "llvm/IR/ProfDataUtils.h" #include "llvm/IR/Type.h" #include "llvm/ProfileData/InstrProfReader.h" +#include "llvm/ProfileData/SampleProf.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Compiler.h" @@ -531,11 +532,14 @@ Error InstrProfSymtab::create(Module &M, bool InLTO, bool AddCanonical) { // Ignore in this case. if (!F.hasName()) continue; - if (Error E = addFuncWithName(F, getIRPGOFuncName(F, InLTO), AddCanonical)) + auto IRPGOFuncName = getIRPGOFuncName(F, InLTO); + if (Error E = addFuncWithName(F, IRPGOFuncName, AddCanonical)) return E; // Also use getPGOFuncName() so that we can find records from older profiles - if (Error E = addFuncWithName(F, getPGOFuncName(F, InLTO), AddCanonical)) - return E; + auto PGOFuncName = getPGOFuncName(F, InLTO); + if (PGOFuncName != IRPGOFuncName) + if (Error E = addFuncWithName(F, PGOFuncName, AddCanonical)) + return E; } for (GlobalVariable &G : M.globals()) { @@ -645,22 +649,20 @@ StringRef InstrProfSymtab::getCanonicalName(StringRef PGOName) { // // ".__uniq." suffix is used to differentiate internal linkage functions in // different modules and should be kept. This is the only suffix with the - // pattern ".xxx" which is kept before matching, other suffixes similar as - // ".llvm." will be stripped. - const std::string UniqSuffix = ".__uniq."; - size_t Pos = PGOName.find(UniqSuffix); - if (Pos != StringRef::npos) - Pos += UniqSuffix.length(); - else - Pos = 0; - - // Search '.' after ".__uniq." if ".__uniq." exists, otherwise search '.' from - // the beginning. - Pos = PGOName.find('.', Pos); - if (Pos != StringRef::npos && Pos != 0) - return PGOName.substr(0, Pos); - - return PGOName; + // pattern ".xxx" which is kept before matching, other suffixes ".llvm." and + // ".part" will be stripped. + // + // Leverage the common canonicalization logic from FunctionSamples. Instead of + // removing all suffixes except ".__uniq.", explicitly specify the ones to be + // removed. This avoids the issue of colliding the canonical names of + // coroutine function with its await suspend wrappers or with its post-split + // clones. i.e. coro function foo, its wrappers + // (foo.__await_suspend_wrapper__init, and foo.__await_suspend_wrapper__final) + // and its post-split clones (foo.resume, foo.cleanup) are all canonicalized + // to "foo" otherwise, which can make the symtab lookup return unexpected + // result. + const SmallVector SuffixesToRemove{".llvm.", ".part."}; + return FunctionSamples::getCanonicalFnName(PGOName, SuffixesToRemove); } Error InstrProfSymtab::addFuncWithName(Function &F, StringRef PGOFuncName, diff --git a/llvm/test/Transforms/PGOProfile/indirect_call_promotion_unique.ll b/llvm/test/Transforms/PGOProfile/indirect_call_promotion_unique.ll index 2c51d6a47b65..d20c7ee6c2a1 100644 --- a/llvm/test/Transforms/PGOProfile/indirect_call_promotion_unique.ll +++ b/llvm/test/Transforms/PGOProfile/indirect_call_promotion_unique.ll @@ -89,13 +89,37 @@ entry: ret i32 3 } +; IR has coro function "func7" and await suspend wrapper "func7.__await_suspend_wrapper__init", +; Profile only has the coro function name func7. +; func7.__await_suspend_wrapper__init is defined before func7 to be matched first. +; Note: ignore the incomplete function body, we only care about the names for test purpose. +define i32 @func7.__await_suspend_wrapper__init() { +entry: + ret i32 3 +} + +define i32 @func7() { +entry: + ret i32 3 +} + +define i32 @bar7() { +entry: + %tmp5 = load ptr, ptr @foo, align 8 +; CHECK: icmp eq ptr %tmp5, @func7{{$}} + %call = call i32 %tmp5(), !prof !6 + ret i32 %call +} + ; GUID of "func1" is -2545542355363006406. ; GUID of "func2" is -4377547752858689819. ; GUID of "func3.__uniq.258901567653530696343884446915951489119" is 8271224222042874235. ; GUID of "func4.__uniq.140291095734751150107370763113257199296" is 1491826207425861106. ; GUID of "func5.__uniq.127882361580787111523790444488985774976" is -4238550483433487304. +; GUID of "func7" is 4143431755475214830. !1 = !{!"VP", i32 0, i64 1600, i64 -2545542355363006406, i64 1600} !2 = !{!"VP", i32 0, i64 1600, i64 -4377547752858689819, i64 1600} !3 = !{!"VP", i32 0, i64 1600, i64 8271224222042874235, i64 1600} !4 = !{!"VP", i32 0, i64 1600, i64 1491826207425861106, i64 1600} !5 = !{!"VP", i32 0, i64 1600, i64 -4238550483433487304, i64 1600} +!6 = !{!"VP", i32 0, i64 1600, i64 4143431755475214830, i64 1600}