diff --git a/llvm/include/llvm/ProfileData/SampleProf.h b/llvm/include/llvm/ProfileData/SampleProf.h index 11b160fc3ac6..18a0989ae537 100644 --- a/llvm/include/llvm/ProfileData/SampleProf.h +++ b/llvm/include/llvm/ProfileData/SampleProf.h @@ -177,7 +177,10 @@ enum class SecNameTableFlags : uint32_t { SecFlagMD5Name = (1 << 0), // Store MD5 in fixed length instead of ULEB128 so NameTable can be // accessed like an array. - SecFlagFixedLengthMD5 = (1 << 1) + SecFlagFixedLengthMD5 = (1 << 1), + // Profile contains ".__uniq." suffix name. Compiler shouldn't strip + // the suffix when doing profile matching when seeing the flag. + SecFlagUniqSuffix = (1 << 2) }; enum class SecProfSummaryFlags : uint32_t { SecFlagInValid = 0, @@ -728,13 +731,14 @@ public: /// GUID to \p S. Also traverse the BodySamples to add hot CallTarget's GUID /// to \p S. void findInlinedFunctions(DenseSet &S, const Module *M, + const StringMap &SymbolMap, uint64_t Threshold) const { if (TotalSamples <= Threshold) return; auto isDeclaration = [](const Function *F) { return !F || F->isDeclaration(); }; - if (isDeclaration(M->getFunction(getFuncName()))) { + if (isDeclaration(SymbolMap.lookup(getFuncName()))) { // Add to the import list only when it's defined out of module. S.insert(getGUID(Name)); } @@ -743,13 +747,13 @@ public: for (const auto &BS : BodySamples) for (const auto &TS : BS.second.getCallTargets()) if (TS.getValue() > Threshold) { - const Function *Callee = M->getFunction(getFuncName(TS.getKey())); + const Function *Callee = SymbolMap.lookup(getFuncName(TS.getKey())); if (isDeclaration(Callee)) S.insert(getGUID(TS.getKey())); } for (const auto &CS : CallsiteSamples) for (const auto &NameFS : CS.second) - NameFS.second.findInlinedFunctions(S, M, Threshold); + NameFS.second.findInlinedFunctions(S, M, SymbolMap, Threshold); } /// Set the name of the function. @@ -780,17 +784,31 @@ public: return getCanonicalFnName(F.getName(), Attr); } - static StringRef getCanonicalFnName(StringRef FnName, StringRef Attr = "") { - static const char *knownSuffixes[] = { ".llvm.", ".part." }; + /// Name suffixes which canonicalization should handle to avoid + /// profile mismatch. + static constexpr const char *LLVMSuffix = ".llvm."; + static constexpr const char *PartSuffix = ".part."; + static constexpr const char *UniqSuffix = ".__uniq."; + + static StringRef getCanonicalFnName(StringRef FnName, + StringRef Attr = "selected") { + // Note the sequence of the suffixes in the knownSuffixes array matters. + // If suffix "A" is appended after the suffix "B", "A" should be in front + // of "B" in knownSuffixes. + const char *knownSuffixes[] = {LLVMSuffix, PartSuffix, UniqSuffix}; if (Attr == "" || Attr == "all") { return FnName.split('.').first; } else if (Attr == "selected") { StringRef Cand(FnName); for (const auto &Suf : knownSuffixes) { StringRef Suffix(Suf); + // If the profile contains ".__uniq." suffix, don't strip the + // suffix for names in the IR. + if (Suffix == UniqSuffix && FunctionSamples::HasUniqSuffix) + continue; auto It = Cand.rfind(Suffix); if (It == StringRef::npos) - return Cand; + continue; auto Dit = Cand.rfind('.'); if (Dit == It + Suffix.size() - 1) Cand = Cand.substr(0, It); @@ -861,6 +879,9 @@ public: /// Whether the profile uses MD5 to represent string. static bool UseMD5; + /// Whether the profile contains any ".__uniq." suffix in a name. + static bool HasUniqSuffix; + /// GUIDToFuncNameMap saves the mapping from GUID to the symbol name, for /// all the function symbols defined or declared in current module. DenseMap *GUIDToFuncNameMap = nullptr; diff --git a/llvm/include/llvm/ProfileData/SampleProfReader.h b/llvm/include/llvm/ProfileData/SampleProfReader.h index 999e75eddffa..db1ec6869724 100644 --- a/llvm/include/llvm/ProfileData/SampleProfReader.h +++ b/llvm/include/llvm/ProfileData/SampleProfReader.h @@ -363,7 +363,11 @@ public: /// Print the profile for \p FName on stream \p OS. void dumpFunctionProfile(StringRef FName, raw_ostream &OS = dbgs()); - virtual void collectFuncsFrom(const Module &M) {} + /// Collect functions with definitions in Module M. For reader which + /// support loading function profiles on demand, return true when the + /// reader has been given a module. Always return false for reader + /// which doesn't support loading function profiles on demand. + virtual bool collectFuncsFromModule() { return false; } /// Print all the profiles on stream \p OS. void dump(raw_ostream &OS = dbgs()); @@ -454,9 +458,13 @@ public: /// Don't read profile without context if the flag is set. This is only meaningful /// for ExtBinary format. virtual void setSkipFlatProf(bool Skip) {} + /// Return whether any name in the profile contains ".__uniq." suffix. + virtual bool hasUniqSuffix() { return false; } SampleProfileReaderItaniumRemapper *getRemapper() { return Remapper.get(); } + void setModule(const Module *Mod) { M = Mod; } + protected: /// Map every function to its associated profile. /// @@ -496,6 +504,11 @@ protected: /// \brief The format of sample. SampleProfileFormat Format = SPF_None; + + /// \brief The current module being compiled if SampleProfileReader + /// is used by compiler. If SampleProfileReader is used by other + /// tools which are not compiler, M is usually nullptr. + const Module *M = nullptr; }; class SampleProfileReaderText : public SampleProfileReader { @@ -656,8 +669,6 @@ protected: DenseMap FuncOffsetTable; /// The set containing the functions to use when compiling a module. DenseSet FuncsToUse; - /// Use all functions from the input profile. - bool UseAllFuncs = true; /// Use fixed length MD5 instead of ULEB128 encoding so NameTable doesn't /// need to be read in up front and can be directly accessed using index. @@ -692,8 +703,9 @@ public: uint64_t getFileSize(); virtual bool dumpSectionInfo(raw_ostream &OS = dbgs()) override; - /// Collect functions with definitions in Module \p M. - void collectFuncsFrom(const Module &M) override; + /// Collect functions with definitions in Module M. Return true if + /// the reader has been given a module. + bool collectFuncsFromModule() override; /// Return whether names in the profile are all MD5 numbers. virtual bool useMD5() override { return MD5StringBuf.get(); } @@ -731,8 +743,6 @@ private: DenseMap FuncOffsetTable; /// The set containing the functions to use when compiling a module. DenseSet FuncsToUse; - /// Use all functions from the input profile. - bool UseAllFuncs = true; virtual std::error_code verifySPMagic(uint64_t Magic) override; virtual std::error_code readNameTable() override; /// Read a string indirectly via the name table. @@ -751,8 +761,9 @@ public: /// Read samples only for functions to use. std::error_code readImpl() override; - /// Collect functions to be used when compiling Module \p M. - void collectFuncsFrom(const Module &M) override; + /// Collect functions with definitions in Module M. Return true if + /// the reader has been given a module. + bool collectFuncsFromModule() override; /// Return whether names in the profile are all MD5 numbers. virtual bool useMD5() override { return true; } diff --git a/llvm/lib/ProfileData/SampleProf.cpp b/llvm/lib/ProfileData/SampleProf.cpp index a429e53a0adb..6647b2637341 100644 --- a/llvm/lib/ProfileData/SampleProf.cpp +++ b/llvm/lib/ProfileData/SampleProf.cpp @@ -40,7 +40,8 @@ namespace sampleprof { SampleProfileFormat FunctionSamples::Format; bool FunctionSamples::ProfileIsProbeBased = false; bool FunctionSamples::ProfileIsCS = false; -bool FunctionSamples::UseMD5; +bool FunctionSamples::UseMD5 = false; +bool FunctionSamples::HasUniqSuffix = true; } // namespace sampleprof } // namespace llvm @@ -262,6 +263,8 @@ void FunctionSamples::findAllNames(DenseSet &NameSet) const { const FunctionSamples *FunctionSamples::findFunctionSamplesAt( const LineLocation &Loc, StringRef CalleeName, SampleProfileReaderItaniumRemapper *Remapper) const { + CalleeName = getCanonicalFnName(CalleeName); + std::string CalleeGUID; CalleeName = getRepInFormat(CalleeName, UseMD5, CalleeGUID); diff --git a/llvm/lib/ProfileData/SampleProfReader.cpp b/llvm/lib/ProfileData/SampleProfReader.cpp index 38cbca844c87..089ad7bcac0d 100644 --- a/llvm/lib/ProfileData/SampleProfReader.cpp +++ b/llvm/lib/ProfileData/SampleProfReader.cpp @@ -584,6 +584,8 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection( bool UseMD5 = hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name); assert((!FixedLengthMD5 || UseMD5) && "If FixedLengthMD5 is true, UseMD5 has to be true"); + FunctionSamples::HasUniqSuffix = + hasSecFlag(Entry, SecNameTableFlags::SecFlagUniqSuffix); if (std::error_code EC = readNameTableSec(UseMD5)) return EC; break; @@ -615,11 +617,13 @@ std::error_code SampleProfileReaderExtBinaryBase::readOneSection( return sampleprof_error::success; } -void SampleProfileReaderExtBinaryBase::collectFuncsFrom(const Module &M) { - UseAllFuncs = false; +bool SampleProfileReaderExtBinaryBase::collectFuncsFromModule() { + if (!M) + return false; FuncsToUse.clear(); - for (auto &F : M) + for (auto &F : *M) FuncsToUse.insert(FunctionSamples::getCanonicalFnName(F)); + return true; } std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() { @@ -648,14 +652,24 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncOffsetTable() { } std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() { + // Collect functions used by current module if the Reader has been + // given a module. + // collectFuncsFromModule uses FunctionSamples::getCanonicalFnName + // which will query FunctionSamples::HasUniqSuffix, so it has to be + // called after FunctionSamples::HasUniqSuffix is set, i.e. after + // NameTable section is read. + bool LoadFuncsToBeUsed = collectFuncsFromModule(); + + // When LoadFuncsToBeUsed is false, load all the function profiles. const uint8_t *Start = Data; - if (UseAllFuncs) { + if (!LoadFuncsToBeUsed) { while (Data < End) { if (std::error_code EC = readFuncProfile(Data)) return EC; } assert(Data == End && "More data is read than expected"); } else { + // Load function profiles on demand. if (Remapper) { for (auto Name : FuncsToUse) { Remapper->insert(Name); @@ -688,7 +702,6 @@ std::error_code SampleProfileReaderExtBinaryBase::readFuncProfiles() { } Data = End; } - assert((CSProfileCount == 0 || CSProfileCount == Profiles.size()) && "Cannot have both context-sensitive and regular profile"); ProfileIsCS = (CSProfileCount > 0); @@ -783,13 +796,18 @@ std::error_code SampleProfileReaderExtBinaryBase::readImpl() { } std::error_code SampleProfileReaderCompactBinary::readImpl() { + // Collect functions used by current module if the Reader has been + // given a module. + bool LoadFuncsToBeUsed = collectFuncsFromModule(); + std::vector OffsetsToUse; - if (UseAllFuncs) { + if (!LoadFuncsToBeUsed) { + // load all the function profiles. for (auto FuncEntry : FuncOffsetTable) { OffsetsToUse.push_back(FuncEntry.second); } - } - else { + } else { + // load function profiles on demand. for (auto Name : FuncsToUse) { auto GUID = std::to_string(MD5Hash(Name)); auto iter = FuncOffsetTable.find(StringRef(GUID)); @@ -1010,6 +1028,8 @@ static std::string getSecFlagsStr(const SecHdrTableEntry &Entry) { Flags.append("fixlenmd5,"); else if (hasSecFlag(Entry, SecNameTableFlags::SecFlagMD5Name)) Flags.append("md5,"); + if (hasSecFlag(Entry, SecNameTableFlags::SecFlagUniqSuffix)) + Flags.append("uniq,"); break; case SecProfSummary: if (hasSecFlag(Entry, SecProfSummaryFlags::SecFlagPartial)) @@ -1117,11 +1137,13 @@ std::error_code SampleProfileReaderCompactBinary::readFuncOffsetTable() { return sampleprof_error::success; } -void SampleProfileReaderCompactBinary::collectFuncsFrom(const Module &M) { - UseAllFuncs = false; +bool SampleProfileReaderCompactBinary::collectFuncsFromModule() { + if (!M) + return false; FuncsToUse.clear(); - for (auto &F : M) + for (auto &F : *M) FuncsToUse.insert(FunctionSamples::getCanonicalFnName(F)); + return true; } std::error_code SampleProfileReaderBinary::readSummaryEntry( diff --git a/llvm/lib/ProfileData/SampleProfWriter.cpp b/llvm/lib/ProfileData/SampleProfWriter.cpp index 8017f2a82804..8939d3a84596 100644 --- a/llvm/lib/ProfileData/SampleProfWriter.cpp +++ b/llvm/lib/ProfileData/SampleProfWriter.cpp @@ -204,6 +204,17 @@ std::error_code SampleProfileWriterExtBinaryBase::writeNameTableSection( addName(I.first()); addNames(I.second); } + + // If NameTable contains ".__uniq." suffix, set SecFlagUniqSuffix flag + // so compiler won't strip the suffix during profile matching after + // seeing the flag in the profile. + for (const auto &I : NameTable) { + if (I.first.find(FunctionSamples::UniqSuffix) != StringRef::npos) { + addSectionFlag(SecNameTable, SecNameTableFlags::SecFlagUniqSuffix); + break; + } + } + if (auto EC = writeNameTable()) return EC; return sampleprof_error::success; diff --git a/llvm/lib/Transforms/IPO/SampleContextTracker.cpp b/llvm/lib/Transforms/IPO/SampleContextTracker.cpp index ac593f71be91..9b7af455e69d 100644 --- a/llvm/lib/Transforms/IPO/SampleContextTracker.cpp +++ b/llvm/lib/Transforms/IPO/SampleContextTracker.cpp @@ -199,6 +199,8 @@ SampleContextTracker::getCalleeContextSamplesFor(const CallBase &Inst, if (!DIL) return nullptr; + CalleeName = FunctionSamples::getCanonicalFnName(CalleeName); + // For indirect call, CalleeName will be empty, in which case the context // profile for callee with largest total samples will be returned. ContextTrieNode *CalleeContext = getCalleeContextFor(DIL, CalleeName); diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp index 5ab11368d2e0..22fd951c5c9d 100644 --- a/llvm/lib/Transforms/IPO/SampleProfile.cpp +++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp @@ -608,7 +608,7 @@ SampleProfileLoader::findCalleeFunctionSamples(const CallBase &Inst) const { StringRef CalleeName; if (Function *Callee = Inst.getCalledFunction()) - CalleeName = FunctionSamples::getCanonicalFnName(*Callee); + CalleeName = Callee->getName(); if (ProfileIsCS) return ContextTracker->getCalleeContextSamplesFor(Inst, CalleeName); @@ -994,7 +994,7 @@ bool SampleProfileLoader::inlineHotFunctions( for (const auto *FS : findIndirectCallFunctionSamples(*I, Sum)) { uint64_t SumOrigin = Sum; if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) { - FS->findInlinedFunctions(InlinedGUIDs, F.getParent(), + FS->findInlinedFunctions(InlinedGUIDs, F.getParent(), SymbolMap, PSI->getOrCompHotCountThreshold()); continue; } @@ -1015,7 +1015,8 @@ bool SampleProfileLoader::inlineHotFunctions( } } else if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) { findCalleeFunctionSamples(*I)->findInlinedFunctions( - InlinedGUIDs, F.getParent(), PSI->getOrCompHotCountThreshold()); + InlinedGUIDs, F.getParent(), SymbolMap, + PSI->getOrCompHotCountThreshold()); } } Changed |= LocalChanged; @@ -1266,7 +1267,7 @@ bool SampleProfileLoader::inlineHotFunctionsWithPriority( for (const auto *FS : CalleeSamples) { // TODO: Consider disable pre-lTO ICP for MonoLTO as well if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) { - FS->findInlinedFunctions(InlinedGUIDs, F.getParent(), + FS->findInlinedFunctions(InlinedGUIDs, F.getParent(), SymbolMap, PSI->getOrCompHotCountThreshold()); continue; } @@ -1313,7 +1314,8 @@ bool SampleProfileLoader::inlineHotFunctionsWithPriority( } } else if (LTOPhase == ThinOrFullLTOPhase::ThinLTOPreLink) { findCalleeFunctionSamples(*I)->findInlinedFunctions( - InlinedGUIDs, F.getParent(), PSI->getOrCompHotCountThreshold()); + InlinedGUIDs, F.getParent(), SymbolMap, + PSI->getOrCompHotCountThreshold()); } } @@ -1679,7 +1681,9 @@ bool SampleProfileLoader::doInitialization(Module &M, } Reader = std::move(ReaderOrErr.get()); Reader->setSkipFlatProf(LTOPhase == ThinOrFullLTOPhase::ThinLTOPostLink); - Reader->collectFuncsFrom(M); + // set module before reading the profile so reader may be able to only + // read the function profiles which are used by the current module. + Reader->setModule(&M); if (std::error_code EC = Reader->read()) { std::string Msg = "profile reading failed: " + EC.message(); Ctx.diagnose(DiagnosticInfoSampleProfile(Filename, Msg)); @@ -1763,12 +1767,11 @@ bool SampleProfileLoader::runOnModule(Module &M, ModuleAnalysisManager *AM, for (const auto &N_F : M.getValueSymbolTable()) { StringRef OrigName = N_F.getKey(); Function *F = dyn_cast(N_F.getValue()); - if (F == nullptr) + if (F == nullptr || OrigName.empty()) continue; SymbolMap[OrigName] = F; - auto pos = OrigName.find('.'); - if (pos != StringRef::npos) { - StringRef NewName = OrigName.substr(0, pos); + StringRef NewName = FunctionSamples::getCanonicalFnName(*F); + if (OrigName != NewName && !NewName.empty()) { auto r = SymbolMap.insert(std::make_pair(NewName, F)); // Failiing to insert means there is already an entry in SymbolMap, // thus there are multiple functions that are mapped to the same @@ -1781,12 +1784,13 @@ bool SampleProfileLoader::runOnModule(Module &M, ModuleAnalysisManager *AM, // Insert the remapped names into SymbolMap. if (Remapper) { if (auto MapName = Remapper->lookUpNameInProfile(OrigName)) { - if (*MapName == OrigName) - continue; - SymbolMap.insert(std::make_pair(*MapName, F)); + if (*MapName != OrigName && !MapName->empty()) + SymbolMap.insert(std::make_pair(*MapName, F)); } } } + assert(SymbolMap.count(StringRef()) == 0 && + "No empty StringRef should be added in SymbolMap"); bool retval = false; for (auto F : buildFunctionOrder(M, CG)) { diff --git a/llvm/test/Transforms/SampleProfile/Inputs/uniqname.nosuffix.afdo b/llvm/test/Transforms/SampleProfile/Inputs/uniqname.nosuffix.afdo new file mode 100644 index 000000000000..acbb31466698 Binary files /dev/null and b/llvm/test/Transforms/SampleProfile/Inputs/uniqname.nosuffix.afdo differ diff --git a/llvm/test/Transforms/SampleProfile/Inputs/uniqname.suffix.afdo b/llvm/test/Transforms/SampleProfile/Inputs/uniqname.suffix.afdo new file mode 100644 index 000000000000..145a318355db Binary files /dev/null and b/llvm/test/Transforms/SampleProfile/Inputs/uniqname.suffix.afdo differ diff --git a/llvm/test/Transforms/SampleProfile/Inputs/uniqname.suffix.prof b/llvm/test/Transforms/SampleProfile/Inputs/uniqname.suffix.prof new file mode 100644 index 000000000000..0cc18a7ed72a --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/Inputs/uniqname.suffix.prof @@ -0,0 +1,14 @@ +_Z3foov:225715:5930 + 2: 5553 + 3: 5391 + 3: _ZL3moov.__uniq.334154460836426447066042049082945760258:5860 + 1: 5279 _Z10moo_calleev:5279 + 2: 5279 + 3: 5000 + 3: _ZL3noov.__uniq.334154460836426447066042049082945760258:5860 + 1: 5000 + 2: 2000 _Z10noo_calleev:2000 +_ZL3goov.__uniq.334154460836426447066042049082945760258:5860:5860 + 1: 5279 + 1: _ZL3hoov.__uniq.334154460836426447066042049082945760258:5860 + 1: 5000 diff --git a/llvm/test/Transforms/SampleProfile/uniqname.ll b/llvm/test/Transforms/SampleProfile/uniqname.ll new file mode 100644 index 000000000000..1d304af85368 --- /dev/null +++ b/llvm/test/Transforms/SampleProfile/uniqname.ll @@ -0,0 +1,141 @@ +; Make sure profile matching is successful if both profile and IR contain +; ".__uniq." suffix, for text format or extbinary format profile. +; Make sure profile matching is successful if IR contains ".__uniq." suffix +; but profile doesn't contain the suffix, for extbinary format profile. +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/uniqname.suffix.prof -S | FileCheck %s +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/uniqname.suffix.afdo -S | FileCheck %s +; RUN: opt < %s -passes=sample-profile -sample-profile-file=%S/Inputs/uniqname.nosuffix.afdo -S | FileCheck %s + +target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-unknown-linux-gnu" + +@cond = dso_local global i8 0, align 1 +@p = dso_local global void ()* null, align 8 + +; Check the callsite in inlined function with uniq suffix is annotated with +; profile correctly. +; CHECK-LABEL: @_Z3foov( +; CHECK: call void @_Z10moo_calleev(), {{.*}} !prof ![[PROF_ID1:[0-9]+]] +; CHECK: call void @_Z10noo_calleev(), {{.*}} !prof ![[PROF_ID2:[0-9]+]] +; CHECK: ret void + +; Function Attrs: uwtable mustprogress +define dso_local void @_Z3foov() #0 !dbg !7 { +entry: + store void ()* @_ZL3hoov.__uniq.334154460836426447066042049082945760258, void ()** @p, align 8, !dbg !9, !tbaa !10 + call void @_ZL3goov.__uniq.334154460836426447066042049082945760258.llvm.4206369970847378271(), !dbg !14 + call void @_ZL3moov.__uniq.334154460836426447066042049082945760258(), !dbg !15 + ret void, !dbg !16 +} + +; Function Attrs: uwtable mustprogress +define internal void @_ZL3hoov.__uniq.334154460836426447066042049082945760258() #1 !dbg !17 { +entry: + call void @_Z10hoo_calleev(), !dbg !18 + ret void, !dbg !19 +} + +; Check the indirect call target with uniq suffix is promoted and the inlined +; body is annotated with profile. +; CHECK: define internal void @_ZL3goov.__uniq.334154460836426447066042049082945760258.llvm.4206369970847378271{{.*}} !prof ![[PROF_ID3:[0-9]+]] +; CHECK: icmp eq void ()* {{.*}} @_ZL3hoov.__uniq.334154460836426447066042049082945760258 +; CHECK: call void @_Z10hoo_calleev(), {{.*}} !prof ![[PROF_ID4:[0-9]+]] + +; Function Attrs: noinline uwtable mustprogress +define internal void @_ZL3goov.__uniq.334154460836426447066042049082945760258.llvm.4206369970847378271() #2 !dbg !20 { +entry: + %0 = load void ()*, void ()** @p, align 8, !dbg !21, !tbaa !10 + call void %0(), !dbg !22 + ret void, !dbg !23 +} + +; Function Attrs: uwtable mustprogress +define internal void @_ZL3moov.__uniq.334154460836426447066042049082945760258() #1 !dbg !24 { +entry: + call void @_Z10moo_calleev(), !dbg !25 + %0 = load volatile i8, i8* @cond, align 1, !dbg !26, !tbaa !27, !range !29 + %tobool.not = icmp eq i8 %0, 0, !dbg !26 + br i1 %tobool.not, label %if.end, label %if.then, !dbg !26 + +if.then: ; preds = %entry + call void @_ZL3noov.__uniq.334154460836426447066042049082945760258(), !dbg !30 + br label %if.end, !dbg !30 + +if.end: ; preds = %if.then, %entry + ret void, !dbg !31 +} + +declare !dbg !32 dso_local void @_Z10hoo_calleev() #3 + +declare !dbg !33 dso_local void @_Z10moo_calleev() #3 + +; Function Attrs: uwtable mustprogress +define internal void @_ZL3noov.__uniq.334154460836426447066042049082945760258() #1 !dbg !34 { +entry: + %0 = load volatile i8, i8* @cond, align 1, !dbg !35, !tbaa !27, !range !29 + %tobool.not = icmp eq i8 %0, 0, !dbg !35 + br i1 %tobool.not, label %if.end, label %if.then, !dbg !35 + +if.then: ; preds = %entry + call void @_Z10noo_calleev(), !dbg !36 + br label %if.end, !dbg !36 + +if.end: ; preds = %if.then, %entry + ret void, !dbg !37 +} + +declare !dbg !38 dso_local void @_Z10noo_calleev() #3 + +attributes #0 = { uwtable mustprogress "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-sample-profile" "use-soft-float"="false" } +attributes #1 = { uwtable mustprogress "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "sample-profile-suffix-elision-policy"="selected" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-sample-profile" "use-soft-float"="false" } +attributes #2 = { noinline uwtable mustprogress "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "sample-profile-suffix-elision-policy"="selected" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-sample-profile" "use-soft-float"="false" } +attributes #3 = { "disable-tail-calls"="false" "frame-pointer"="none" "less-precise-fpmad"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="true" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "tune-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } + +; CHECK: ![[PROF_ID1]] = !{!"branch_weights", i32 5931} +; CHECK: ![[PROF_ID2]] = !{!"branch_weights", i32 2000} +; CHECK: ![[PROF_ID3]] = !{!"function_entry_count", i64 5861} +; CHECK: ![[PROF_ID4]] = !{!"branch_weights", i32 5000} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C_plus_plus_14, file: !1, producer: "clang version 12.0.0 (https://github.com/llvm/llvm-project.git e42c17446a2e5cbf9eebc752beafadad3fac7f63)", isOptimized: true, runtimeVersion: 0, emissionKind: LineTablesOnly, enums: !2, splitDebugInlining: false, debugInfoForProfiling: true, nameTableKind: None) +!1 = !DIFile(filename: "1.cc", directory: "/usr/local/google/home/wmi/workarea/llvm/build/splitprofile") +!2 = !{} +!3 = !{i32 7, !"Dwarf Version", i32 4} +!4 = !{i32 2, !"Debug Info Version", i32 3} +!5 = !{i32 1, !"wchar_size", i32 4} +!6 = !{!"clang version 12.0.0 (https://github.com/llvm/llvm-project.git e42c17446a2e5cbf9eebc752beafadad3fac7f63)"} +!7 = distinct !DISubprogram(name: "foo", linkageName: "_Z3foov", scope: !1, file: !1, line: 28, type: !8, scopeLine: 28, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!8 = !DISubroutineType(types: !2) +!9 = !DILocation(line: 29, column: 5, scope: !7) +!10 = !{!11, !11, i64 0} +!11 = !{!"any pointer", !12, i64 0} +!12 = !{!"omnipotent char", !13, i64 0} +!13 = !{!"Simple C++ TBAA"} +!14 = !DILocation(line: 30, column: 3, scope: !7) +!15 = !DILocation(line: 31, column: 3, scope: !7) +!16 = !DILocation(line: 32, column: 3, scope: !7) +!17 = distinct !DISubprogram(name: "hoo", linkageName: "_ZL3hoov.__uniq.334154460836426447066042049082945760258", scope: !1, file: !1, line: 17, type: !8, scopeLine: 17, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!18 = !DILocation(line: 18, column: 3, scope: !17) +!19 = !DILocation(line: 19, column: 1, scope: !17) +!20 = distinct !DISubprogram(name: "goo", linkageName: "_ZL3goov.__uniq.334154460836426447066042049082945760258.llvm.4206369970847378271", scope: !1, file: !1, line: 24, type: !8, scopeLine: 24, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!21 = !DILocation(line: 25, column: 5, scope: !20) +!22 = !DILocation(line: 25, column: 3, scope: !20) +!23 = !DILocation(line: 26, column: 1, scope: !20) +!24 = distinct !DISubprogram(name: "moo", linkageName: "_ZL3moov.__uniq.334154460836426447066042049082945760258", scope: !1, file: !1, line: 11, type: !8, scopeLine: 11, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!25 = !DILocation(line: 12, column: 3, scope: !24) +!26 = !DILocation(line: 13, column: 7, scope: !24) +!27 = !{!28, !28, i64 0} +!28 = !{!"bool", !12, i64 0} +!29 = !{i8 0, i8 2} +!30 = !DILocation(line: 14, column: 5, scope: !24) +!31 = !DILocation(line: 15, column: 1, scope: !24) +!32 = !DISubprogram(name: "hoo_callee", linkageName: "_Z10hoo_calleev", scope: !1, file: !1, line: 3, type: !8, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!33 = !DISubprogram(name: "moo_callee", linkageName: "_Z10moo_calleev", scope: !1, file: !1, line: 2, type: !8, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) +!34 = distinct !DISubprogram(name: "noo", linkageName: "_ZL3noov.__uniq.334154460836426447066042049082945760258", scope: !1, file: !1, line: 6, type: !8, scopeLine: 6, flags: DIFlagPrototyped | DIFlagAllCallsDescribed, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !2) +!35 = !DILocation(line: 7, column: 7, scope: !34) +!36 = !DILocation(line: 8, column: 5, scope: !34) +!37 = !DILocation(line: 9, column: 1, scope: !34) +!38 = !DISubprogram(name: "noo_callee", linkageName: "_Z10noo_calleev", scope: !1, file: !1, line: 1, type: !8, flags: DIFlagPrototyped, spFlags: DISPFlagOptimized, retainedNodes: !2) diff --git a/llvm/unittests/ProfileData/SampleProfTest.cpp b/llvm/unittests/ProfileData/SampleProfTest.cpp index 8b81418a8506..ddb25a910110 100644 --- a/llvm/unittests/ProfileData/SampleProfTest.cpp +++ b/llvm/unittests/ProfileData/SampleProfTest.cpp @@ -60,7 +60,7 @@ struct SampleProfTest : ::testing::Test { std::string(Profile), Context, std::string(RemapFile)); ASSERT_TRUE(NoError(ReaderOrErr.getError())); Reader = std::move(ReaderOrErr.get()); - Reader->collectFuncsFrom(M); + Reader->setModule(&M); } TempFile createRemapFile() {