Skip to content

[Profile] Refactor profile correlation. #70856

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

Merged
merged 4 commits into from
Nov 1, 2023

Conversation

ZequanWu
Copy link
Contributor

Refactor some code from #69493.

#70712 was reverted due to linking failures. So, I removed -profile-correlate= flag and kept -debug-info-correlate in this change.

@ZequanWu ZequanWu requested a review from ellishg October 31, 2023 20:39
@llvmbot llvmbot added compiler-rt PGO Profile Guided Optimizations labels Oct 31, 2023
@llvmbot
Copy link
Member

llvmbot commented Oct 31, 2023

@llvm/pr-subscribers-pgo

Author: Zequan Wu (ZequanWu)

Changes

Refactor some code from #69493.

#70712 was reverted due to linking failures. So, I removed -profile-correlate= flag and kept -debug-info-correlate in this change.


Patch is 21.43 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/70856.diff

11 Files Affected:

  • (modified) compiler-rt/lib/profile/InstrProfiling.c (+4)
  • (modified) compiler-rt/lib/profile/InstrProfiling.h (+6)
  • (modified) compiler-rt/lib/profile/InstrProfilingBuffer.c (+11)
  • (modified) compiler-rt/lib/profile/InstrProfilingMerge.c (+6-5)
  • (modified) compiler-rt/lib/profile/InstrProfilingWriter.c (+10-11)
  • (modified) compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c (+1-1)
  • (modified) llvm/include/llvm/ProfileData/InstrProfCorrelator.h (+10-3)
  • (modified) llvm/include/llvm/ProfileData/InstrProfReader.h (+2)
  • (modified) llvm/lib/ProfileData/InstrProfCorrelator.cpp (+63-37)
  • (modified) llvm/lib/ProfileData/InstrProfReader.cpp (+2-2)
  • (modified) llvm/tools/llvm-profdata/llvm-profdata.cpp (+6-3)
diff --git a/compiler-rt/lib/profile/InstrProfiling.c b/compiler-rt/lib/profile/InstrProfiling.c
index da04d8ebdec95bb..7d69e37815c948f 100644
--- a/compiler-rt/lib/profile/InstrProfiling.c
+++ b/compiler-rt/lib/profile/InstrProfiling.c
@@ -89,3 +89,7 @@ COMPILER_RT_VISIBILITY void __llvm_profile_reset_counters(void) {
   }
   lprofSetProfileDumped(0);
 }
+
+inline int hasCorrelation() {
+  return (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) != 0ULL;
+}
diff --git a/compiler-rt/lib/profile/InstrProfiling.h b/compiler-rt/lib/profile/InstrProfiling.h
index e143149fca82707..b8104af5f12b910 100644
--- a/compiler-rt/lib/profile/InstrProfiling.h
+++ b/compiler-rt/lib/profile/InstrProfiling.h
@@ -261,6 +261,9 @@ uint64_t __llvm_profile_get_magic(void);
 /*! \brief Get the version of the file format. */
 uint64_t __llvm_profile_get_version(void);
 
+/*! \brief If the binary is compiled with profile correlation. */
+int hasCorrelation();
+
 /*! \brief Get the number of entries in the profile data section. */
 uint64_t __llvm_profile_get_num_data(const __llvm_profile_data *Begin,
                                      const __llvm_profile_data *End);
@@ -282,6 +285,9 @@ uint64_t __llvm_profile_get_counters_size(const char *Begin, const char *End);
 uint64_t __llvm_profile_get_num_bitmap_bytes(const char *Begin,
                                              const char *End);
 
+/*! \brief Get the size of the profile name section in bytes. */
+uint64_t __llvm_profile_get_name_size(const char *Begin, const char *End);
+
 /* ! \brief Given the sizes of the data and counter information, return the
  * number of padding bytes before and after the counters, and after the names,
  * in the raw profile.
diff --git a/compiler-rt/lib/profile/InstrProfilingBuffer.c b/compiler-rt/lib/profile/InstrProfilingBuffer.c
index c7217b2dfef8a97..69965142d978746 100644
--- a/compiler-rt/lib/profile/InstrProfilingBuffer.c
+++ b/compiler-rt/lib/profile/InstrProfilingBuffer.c
@@ -56,6 +56,8 @@ uint64_t __llvm_profile_get_size_for_buffer(void) {
 COMPILER_RT_VISIBILITY
 uint64_t __llvm_profile_get_num_data(const __llvm_profile_data *Begin,
                                      const __llvm_profile_data *End) {
+  if (hasCorrelation())
+    return 0;
   intptr_t BeginI = (intptr_t)Begin, EndI = (intptr_t)End;
   return ((EndI + sizeof(__llvm_profile_data) - 1) - BeginI) /
          sizeof(__llvm_profile_data);
@@ -64,6 +66,8 @@ uint64_t __llvm_profile_get_num_data(const __llvm_profile_data *Begin,
 COMPILER_RT_VISIBILITY
 uint64_t __llvm_profile_get_data_size(const __llvm_profile_data *Begin,
                                       const __llvm_profile_data *End) {
+  if (hasCorrelation())
+    return 0;
   return __llvm_profile_get_num_data(Begin, End) * sizeof(__llvm_profile_data);
 }
 
@@ -92,6 +96,13 @@ uint64_t __llvm_profile_get_num_bitmap_bytes(const char *Begin,
   return (End - Begin);
 }
 
+COMPILER_RT_VISIBILITY
+uint64_t __llvm_profile_get_name_size(const char *Begin, const char *End) {
+  if (hasCorrelation())
+    return 0;
+  return End - Begin;
+}
+
 /// Calculate the number of padding bytes needed to add to \p Offset in order
 /// for (\p Offset + Padding) to be page-aligned.
 static uint64_t calculateBytesNeededToPageAlign(uint64_t Offset) {
diff --git a/compiler-rt/lib/profile/InstrProfilingMerge.c b/compiler-rt/lib/profile/InstrProfilingMerge.c
index c5f168bf7517718..b08973debda94f3 100644
--- a/compiler-rt/lib/profile/InstrProfilingMerge.c
+++ b/compiler-rt/lib/profile/InstrProfilingMerge.c
@@ -69,8 +69,9 @@ int __llvm_profile_check_compatibility(const char *ProfileData,
       Header->NumBitmapBytes !=
           __llvm_profile_get_num_bitmap_bytes(__llvm_profile_begin_bitmap(),
                                               __llvm_profile_end_bitmap()) ||
-      Header->NamesSize != (uint64_t)(__llvm_profile_end_names() -
-                                      __llvm_profile_begin_names()) ||
+      Header->NamesSize !=
+          __llvm_profile_get_name_size(__llvm_profile_begin_names(),
+                                       __llvm_profile_end_names()) ||
       Header->ValueKindLast != IPVK_Last)
     return 1;
 
@@ -138,9 +139,9 @@ int __llvm_profile_merge_from_buffer(const char *ProfileData,
   if (SrcNameStart < SrcCountersStart || SrcNameStart < SrcBitmapStart)
     return 1;
 
-  // Merge counters by iterating the entire counter section when debug info
-  // correlation is enabled.
-  if (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) {
+  // Merge counters by iterating the entire counter section when correlation is
+  // enabled.
+  if (hasCorrelation()) {
     for (SrcCounter = SrcCountersStart,
         DstCounter = __llvm_profile_begin_counters();
          SrcCounter < SrcCountersEnd;) {
diff --git a/compiler-rt/lib/profile/InstrProfilingWriter.c b/compiler-rt/lib/profile/InstrProfilingWriter.c
index 3b61f3def9f6ef0..d35ee6b20504f3e 100644
--- a/compiler-rt/lib/profile/InstrProfilingWriter.c
+++ b/compiler-rt/lib/profile/InstrProfilingWriter.c
@@ -262,21 +262,19 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
                    const char *BitmapBegin, const char *BitmapEnd,
                    VPDataReaderType *VPDataReader, const char *NamesBegin,
                    const char *NamesEnd, int SkipNameDataWrite) {
-  int DebugInfoCorrelate =
-      (__llvm_profile_get_version() & VARIANT_MASK_DBG_CORRELATE) != 0ULL;
+  int ProfileCorrelation = hasCorrelation();
 
   /* Calculate size of sections. */
   const uint64_t DataSectionSize =
-      DebugInfoCorrelate ? 0 : __llvm_profile_get_data_size(DataBegin, DataEnd);
-  const uint64_t NumData =
-      DebugInfoCorrelate ? 0 : __llvm_profile_get_num_data(DataBegin, DataEnd);
+      __llvm_profile_get_data_size(DataBegin, DataEnd);
+  const uint64_t NumData = __llvm_profile_get_num_data(DataBegin, DataEnd);
   const uint64_t CountersSectionSize =
       __llvm_profile_get_counters_size(CountersBegin, CountersEnd);
   const uint64_t NumCounters =
       __llvm_profile_get_num_counters(CountersBegin, CountersEnd);
   const uint64_t NumBitmapBytes =
       __llvm_profile_get_num_bitmap_bytes(BitmapBegin, BitmapEnd);
-  const uint64_t NamesSize = DebugInfoCorrelate ? 0 : NamesEnd - NamesBegin;
+  const uint64_t NamesSize = __llvm_profile_get_name_size(NamesBegin, NamesEnd);
 
   /* Create the header. */
   __llvm_profile_header Header;
@@ -304,7 +302,7 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
 #endif
 
   /* The data and names sections are omitted in lightweight mode. */
-  if (DebugInfoCorrelate) {
+  if (ProfileCorrelation) {
     Header.CountersDelta = 0;
     Header.NamesDelta = 0;
   }
@@ -320,21 +318,22 @@ lprofWriteDataImpl(ProfDataWriter *Writer, const __llvm_profile_data *DataBegin,
 
   /* Write the profile data. */
   ProfDataIOVec IOVecData[] = {
-      {DebugInfoCorrelate ? NULL : DataBegin, sizeof(uint8_t), DataSectionSize,
+      {ProfileCorrelation ? NULL : DataBegin, sizeof(uint8_t), DataSectionSize,
        0},
       {NULL, sizeof(uint8_t), PaddingBytesBeforeCounters, 1},
       {CountersBegin, sizeof(uint8_t), CountersSectionSize, 0},
       {NULL, sizeof(uint8_t), PaddingBytesAfterCounters, 1},
       {BitmapBegin, sizeof(uint8_t), NumBitmapBytes, 0},
       {NULL, sizeof(uint8_t), PaddingBytesAfterBitmapBytes, 1},
-      {(SkipNameDataWrite || DebugInfoCorrelate) ? NULL : NamesBegin,
+      {(SkipNameDataWrite || ProfileCorrelation) ? NULL : NamesBegin,
        sizeof(uint8_t), NamesSize, 0},
       {NULL, sizeof(uint8_t), PaddingBytesAfterNames, 1}};
   if (Writer->Write(Writer, IOVecData, sizeof(IOVecData) / sizeof(*IOVecData)))
     return -1;
 
-  /* Value profiling is not yet supported in continuous mode. */
-  if (__llvm_profile_is_continuous_mode_enabled())
+  /* Value profiling is not yet supported in continuous mode and profile
+   * correlation mode. */
+  if (__llvm_profile_is_continuous_mode_enabled() || ProfileCorrelation)
     return 0;
 
   return writeValueProfData(Writer, VPDataReader, DataBegin, DataEnd);
diff --git a/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c b/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c
index 226d678aca347a4..245dc798910425b 100644
--- a/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c
+++ b/compiler-rt/test/profile/Linux/instrprof-show-debug-info-correlation.c
@@ -4,7 +4,7 @@
 
 // RUN: %clang_pgogen -o %t.no.dbg -mllvm --debug-info-correlate -mllvm --disable-vp=true %s
 // RUN: not llvm-profdata show --debug-info=%t.no.dbg 2>&1 | FileCheck %s --check-prefix NO-DBG
-// NO-DBG: unable to correlate profile: could not find any profile metadata in debug info
+// NO-DBG: unable to correlate profile: could not find any profile data metadata in correlated file
 
 // YAML: Probes:
 // YAML:   - Function Name:   a
diff --git a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
index dd062951f277c1c..a3a0805a294a20c 100644
--- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
+++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
@@ -31,8 +31,11 @@ class ObjectFile;
 /// to their functions.
 class InstrProfCorrelator {
 public:
+  /// Indicate which kind correlator to use.
+  enum ProfCorrelatorKind { NONE, DEBUG_INFO };
+
   static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
-  get(StringRef DebugInfoFilename);
+  get(StringRef Filename, ProfCorrelatorKind FileKind);
 
   /// Construct a ProfileData vector used to correlate raw instrumentation data
   /// to their functions.
@@ -104,7 +107,7 @@ class InstrProfCorrelator {
 
 private:
   static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
-  get(std::unique_ptr<MemoryBuffer> Buffer);
+  get(std::unique_ptr<MemoryBuffer> Buffer, ProfCorrelatorKind FileKind);
 
   const InstrProfCorrelatorKind Kind;
 };
@@ -128,7 +131,7 @@ class InstrProfCorrelatorImpl : public InstrProfCorrelator {
 
   static llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
   get(std::unique_ptr<InstrProfCorrelator::Context> Ctx,
-      const object::ObjectFile &Obj);
+      const object::ObjectFile &Obj, ProfCorrelatorKind FileKind);
 
 protected:
   std::vector<RawInstrProf::ProfileData<IntPtrT>> Data;
@@ -138,6 +141,8 @@ class InstrProfCorrelatorImpl : public InstrProfCorrelator {
       int MaxWarnings,
       InstrProfCorrelator::CorrelationData *Data = nullptr) = 0;
 
+  virtual Error correlateProfileNameImpl() = 0;
+
   Error dumpYaml(int MaxWarnings, raw_ostream &OS) override;
 
   void addProbe(StringRef FunctionName, uint64_t CFGHash, IntPtrT CounterOffset,
@@ -205,6 +210,8 @@ class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
   void correlateProfileDataImpl(
       int MaxWarnings,
       InstrProfCorrelator::CorrelationData *Data = nullptr) override;
+
+  Error correlateProfileNameImpl() override;
 };
 
 } // end namespace llvm
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index cf6429a324d36b3..1084a58eb098d12 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -377,6 +377,8 @@ class RawInstrProfReader : public InstrProfReader {
     return (Version & VARIANT_MASK_DBG_CORRELATE) != 0;
   }
 
+  bool useCorrelate() const { return useDebugInfoCorrelate(); }
+
   bool hasSingleByteCoverage() const override {
     return (Version & VARIANT_MASK_BYTE_COVERAGE) != 0;
   }
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
index 2138368500bed09..e429b9f1da54cba 100644
--- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -24,15 +24,20 @@
 
 using namespace llvm;
 
-/// Get the __llvm_prf_cnts section.
-Expected<object::SectionRef> getCountersSection(const object::ObjectFile &Obj) {
+/// Get profile section.
+Expected<object::SectionRef> getInstrProfSection(const object::ObjectFile &Obj,
+                                                 InstrProfSectKind IPSK) {
+  Triple::ObjectFormatType ObjFormat = Obj.getTripleObjectFormat();
+  std::string ExpectedSectionName =
+      getInstrProfSectionName(IPSK, ObjFormat,
+                              /*AddSegmentInfo=*/false);
   for (auto &Section : Obj.sections())
     if (auto SectionName = Section.getName())
-      if (SectionName.get() == INSTR_PROF_CNTS_SECT_NAME)
+      if (SectionName.get() == ExpectedSectionName)
         return Section;
   return make_error<InstrProfError>(
       instrprof_error::unable_to_correlate_profile,
-      "could not find counter section (" INSTR_PROF_CNTS_SECT_NAME ")");
+      "could not find section (" + Twine(ExpectedSectionName) + ")");
 }
 
 const char *InstrProfCorrelator::FunctionNameAttributeName = "Function Name";
@@ -42,7 +47,7 @@ const char *InstrProfCorrelator::NumCountersAttributeName = "Num Counters";
 llvm::Expected<std::unique_ptr<InstrProfCorrelator::Context>>
 InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
                                   const object::ObjectFile &Obj) {
-  auto CountersSection = getCountersSection(Obj);
+  auto CountersSection = getInstrProfSection(Obj, IPSK_cnts);
   if (auto Err = CountersSection.takeError())
     return std::move(Err);
   auto C = std::make_unique<Context>();
@@ -54,30 +59,32 @@ InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
 }
 
 llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
-InstrProfCorrelator::get(StringRef DebugInfoFilename) {
-  auto DsymObjectsOrErr =
-      object::MachOObjectFile::findDsymObjectMembers(DebugInfoFilename);
-  if (auto Err = DsymObjectsOrErr.takeError())
-    return std::move(Err);
-  if (!DsymObjectsOrErr->empty()) {
-    // TODO: Enable profile correlation when there are multiple objects in a
-    // dSYM bundle.
-    if (DsymObjectsOrErr->size() > 1)
-      return make_error<InstrProfError>(
-          instrprof_error::unable_to_correlate_profile,
-          "using multiple objects is not yet supported");
-    DebugInfoFilename = *DsymObjectsOrErr->begin();
+InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind) {
+  if (FileKind == DEBUG_INFO) {
+    auto DsymObjectsOrErr =
+        object::MachOObjectFile::findDsymObjectMembers(Filename);
+    if (auto Err = DsymObjectsOrErr.takeError())
+      return std::move(Err);
+    if (!DsymObjectsOrErr->empty()) {
+      // TODO: Enable profile correlation when there are multiple objects in a
+      // dSYM bundle.
+      if (DsymObjectsOrErr->size() > 1)
+        return make_error<InstrProfError>(
+            instrprof_error::unable_to_correlate_profile,
+            "using multiple objects is not yet supported");
+      Filename = *DsymObjectsOrErr->begin();
+    }
   }
-  auto BufferOrErr =
-      errorOrToExpected(MemoryBuffer::getFile(DebugInfoFilename));
+  auto BufferOrErr = errorOrToExpected(MemoryBuffer::getFile(Filename));
   if (auto Err = BufferOrErr.takeError())
     return std::move(Err);
 
-  return get(std::move(*BufferOrErr));
+  return get(std::move(*BufferOrErr), FileKind);
 }
 
 llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
-InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer) {
+InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer,
+                         ProfCorrelatorKind FileKind) {
   auto BinOrErr = object::createBinary(*Buffer);
   if (auto Err = BinOrErr.takeError())
     return std::move(Err);
@@ -88,9 +95,11 @@ InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer) {
       return std::move(Err);
     auto T = Obj->makeTriple();
     if (T.isArch64Bit())
-      return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj);
+      return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj,
+                                                    FileKind);
     if (T.isArch32Bit())
-      return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj);
+      return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj,
+                                                    FileKind);
   }
   return make_error<InstrProfError>(
       instrprof_error::unable_to_correlate_profile, "not an object file");
@@ -132,29 +141,33 @@ template <class IntPtrT>
 llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
 InstrProfCorrelatorImpl<IntPtrT>::get(
     std::unique_ptr<InstrProfCorrelator::Context> Ctx,
-    const object::ObjectFile &Obj) {
-  if (Obj.isELF() || Obj.isMachO()) {
-    auto DICtx = DWARFContext::create(Obj);
-    return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>(std::move(DICtx),
-                                                               std::move(Ctx));
+    const object::ObjectFile &Obj, ProfCorrelatorKind FileKind) {
+  if (FileKind == DEBUG_INFO) {
+    if (Obj.isELF() || Obj.isMachO()) {
+      auto DICtx = DWARFContext::create(Obj);
+      return std::make_unique<DwarfInstrProfCorrelator<IntPtrT>>(
+          std::move(DICtx), std::move(Ctx));
+    }
+    return make_error<InstrProfError>(
+        instrprof_error::unable_to_correlate_profile,
+        "unsupported debug info format (only DWARF is supported)");
   }
   return make_error<InstrProfError>(
       instrprof_error::unable_to_correlate_profile,
-      "unsupported debug info format (only DWARF is supported)");
+      "unsupported correlation file type (only DWARF is supported)");
 }
 
 template <class IntPtrT>
 Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData(int MaxWarnings) {
   assert(Data.empty() && Names.empty() && NamesVec.empty());
   correlateProfileDataImpl(MaxWarnings);
-  if (Data.empty() || NamesVec.empty())
+  if (this->Data.empty())
     return make_error<InstrProfError>(
         instrprof_error::unable_to_correlate_profile,
-        "could not find any profile metadata in debug info");
-  auto Result =
-      collectGlobalObjectNameStrings(NamesVec, /*doCompression=*/false, Names);
-  CounterOffsets.clear();
-  NamesVec.clear();
+        "could not find any profile data metadata in correlated file");
+  Error Result = correlateProfileNameImpl();
+  this->CounterOffsets.clear();
+  this->NamesVec.clear();
   return Result;
 }
 
@@ -189,7 +202,7 @@ Error InstrProfCorrelatorImpl<IntPtrT>::dumpYaml(int MaxWarnings,
   if (Data.Probes.empty())
     return make_error<InstrProfError>(
         instrprof_error::unable_to_correlate_profile,
-        "could not find any profile metadata in debug info");
+        "could not find any profile data metadata in debug info");
   yaml::Output YamlOS(OS);
   YamlOS << Data;
   return Error::success();
@@ -365,3 +378,16 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
     WithColor::warning() << format("Suppressed %d additional warnings\n",
                                    NumSuppressedWarnings);
 }
+
+template <class IntPtrT>
+Error DwarfInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() {
+  if (this->NamesVec.empty()) {
+    return make_error<InstrProfError>(
+        instrprof_error::unable_to_correlate_profile,
+        "could not find any profile name metadata in debug info");
+  }
+  auto Result =
+      collectGlobalObjectNameStrings(this->NamesVec,
+                                     /*doCompression=*/false, this->Names);
+  return Result;
+}
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 31d3ff2bcbf6ca7..dd66f4247ec73ea 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -563,9 +563,9 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
                   "\nPLEASE update this tool to version in the raw profile, or "
                   "regenerate raw profile with expected version.")
                      .str());
-  if (useDebugInfoCorrelate() && !Correlator)
+  if (useCorrelate() && !Correlator)
     return error(instrprof_error::missing_debug_info_for_correlation);
-  if (!useDebugInfoCorrelate() && Correlator)
+  if (!useCorrelate() && Correlator)
     return error(instrprof_error::unexpected_debug_info_for_correlation);
 
   BinaryIdsSize = swap(Header.BinaryIdsSize);
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profda...
[truncated]

@ZequanWu
Copy link
Contributor Author

Sorry for so many noise regarding this change.

Copy link
Contributor

@ellishg ellishg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds fine to me, but I guess I don't understand why -profile-correlate= doesn't work. Do you still plan to add the flag later?

@ZequanWu
Copy link
Contributor Author

ZequanWu commented Nov 1, 2023

Sounds fine to me, but I guess I don't understand why -profile-correlate= doesn't work. Do you still plan to add the flag later?

I haven't found a way to share information (whether of not binary correlation is enabled) between CodeGen(TargetLoweringObjectFileImpl.cpp) and Instrumentation(InstrProfiling.cpp) components. The explanation is
here: https://discourse.llvm.org/t/rfc-add-binary-profile-correlation-to-not-load-profile-metadata-sections-into-memory-at-runtime/74565#use-temporary-section-names-6.

@ZequanWu ZequanWu merged commit 3c97c8b into llvm:main Nov 1, 2023
@ZequanWu ZequanWu deleted the refactor-profile-cor branch November 1, 2023 18:31
@dtellenbach
Copy link
Member

@ZequanWu this seems to cause issues on macOS: https://green.lab.llvm.org/green/job/clang-stage1-RA/36184/console

Profile-x86_64 :: Darwin/instrprof-debug-info-correlate.c
Profile-x86_64 :: instrprof-darwin-
Profile-x86_64h :: Darwin/instrprof-debug-info-correlate.c
Profile-x86_64h :: instrprof-darwin-exports.c

are failing, could you please take a look or revert?

@ZequanWu
Copy link
Contributor Author

ZequanWu commented Nov 2, 2023

@ZequanWu this seems to cause issues on macOS: https://green.lab.llvm.org/green/job/clang-stage1-RA/36184/console

Profile-x86_64 :: Darwin/instrprof-debug-info-correlate.c
Profile-x86_64 :: instrprof-darwin-
Profile-x86_64h :: Darwin/instrprof-debug-info-correlate.c
Profile-x86_64h :: instrprof-darwin-exports.c

are failing, could you please take a look or revert?

It should be fixed by 56e205a.

@dtellenbach
Copy link
Member

It should be fixed by 56e205a.

Thank you!

@ZequanWu
Copy link
Contributor Author

ZequanWu commented Nov 2, 2023

Sounds fine to me, but I guess I don't understand why -profile-correlate= doesn't work. Do you still plan to add the flag later?

I haven't found a way to share information (whether of not binary correlation is enabled) between CodeGen(TargetLoweringObjectFileImpl.cpp) and Instrumentation(InstrProfiling.cpp) components. The explanation is here: https://discourse.llvm.org/t/rfc-add-binary-profile-correlation-to-not-load-profile-metadata-sections-into-memory-at-runtime/74565#use-temporary-section-names-6.

Oh, actually, we can have -profile-correlate flag just need to define it at InstrProfCorrelator.cpp (ProfileData component), which is less desired but working as discussed at #69656 (comment).

@petrhosek
Copy link
Member

I'm a bit concerned about the use of hasCorrelation. We require the runtime to check the flag and omit the data and names section if set which introduces a potential issue: since we emit the version in every TU and u se COMDAT to deduplicate them, but that means that if you link together TUs compiled with and without -debug-info-correlate/-profile-correlate= (that is having different flags), you would end up with different results depending on which section was selected by the linker. This may not be an issue if you always compile all code yourself using the same set of flags, but might be an issue when you combine libraries coming from different sources.

What I think would be a better design is to just omit the respective sections altogether when -debug-info-correlate/-profile-correlate= is enabled. Then in llvm-profdata we would use the correlation as a fallback mechanism, that is if the data or names are present in the profile, just use it, otherwise fallback either to debug info or unstripped file (you could even support a combination of both). That way we wouldn't even need flags like VARIANT_MASK_DBG_CORRELATE.

@ZequanWu
Copy link
Contributor Author

ZequanWu commented Nov 2, 2023

I'm a bit concerned about the use of hasCorrelation. We require the runtime to check the flag and omit the data and names section if set which introduces a potential issue: since we emit the version in every TU and u se COMDAT to deduplicate them, but that means that if you link together TUs compiled with and without -debug-info-correlate/-profile-correlate= (that is having different flags), you would end up with different results depending on which section was selected by the linker. This may not be an issue if you always compile all code yourself using the same set of flags, but might be an issue when you combine libraries coming from different sources.

I understand your concern. I think that's the limitation of these modes. You need to either compile all code with -debug-info-correlate/-profile-correlate= consistently or not. So, these modes are not suitable for projects which link with libraries compiled without the flags.

What I think would be a better design is to just omit the respective sections altogether when -debug-info-correlate/-profile-correlate= is enabled.

I don't understand how this solves the problem you described above. Can you elaborate a bit more? We still need to decide if we need to omit data and names sections at runtime right?

@petrhosek
Copy link
Member

What I think would be a better design is to just omit the respective sections altogether when -debug-info-correlate/-profile-correlate= is enabled.

I don't understand how this solves the problem you described above. Can you elaborate a bit more? We still need to decide if we need to omit data and names sections at runtime right?

If you omit the data and names sections from the object files, then __llvm_profile_end_data() - __llvm_profile_begin_data() and __llvm_profile_end_names() - __llvm_profile_begin_names() are both 0 and there's no need for special casing this in the runtime. When linking together objects complied with different flags, sizes of those sections would correspond only to object files compiled without correlation. For example, if linking together a.o compiled with debug info correlation and b.o compiled without, the profile would only contain data and names from b.o.

This approach would require slightly more complex logic in the correlator. Currently, we either read the data and names from the profile or from DWARF (depending on the flag), there's no in-between state. With the approach I'm proposing, we would need to combine data from different sources: read the data and names in the profile and combine them with the data and names in the DWARF and/or the unstripped file.

@ZequanWu
Copy link
Contributor Author

ZequanWu commented Nov 8, 2023

If you omit the data and names sections from the object files, then __llvm_profile_end_data() - __llvm_profile_begin_data() and __llvm_profile_end_names() - __llvm_profile_begin_names() are both 0 and there's no need for special casing this in the runtime.

From my experiments on linux, I found that for debug info correlation __llvm_profile_end_data() - __llvm_profile_begin_data() and __llvm_profile_end_names() - __llvm_profile_begin_names() are both 0 at runtime because {__start_/__stop_}{__llvm_prf_names/data} symbols are null if there is no __llvm_prf_names/data.

But for binary correlation, even though __llvm_prf_names/data don't have SHF_ALLOC flag so they are not loaded into memory, __llvm_profile_end_data() - __llvm_profile_begin_data() and __llvm_profile_end_names() - __llvm_profile_begin_names() still produces the size of name and data sections, that's why we need a bit in the global profile version variable to indicate they are empty at runtime. I feel like this is a bug in lld as _start/_stop symbols for non allocated sections should be null. Even if we have a way to fix that, we still need the mode bit at llvm-profile merging step to indicate if the raw profile need debug info/binary to correlate. However, we can get ride of the runtime checking __llvm_profile_has_correlation to allow code compiled w/wo debug-info linked together works well.

@MaskRay
Copy link
Member

MaskRay commented Nov 10, 2023

I am nervous with new if (hasCorrelation()) conditions as well.

If you use the same name for a non-SHF_ALLOC section and a SHF_ALLOC section, the linked output has the SHF_ALLOC flag and you cannot tell what components were non-SHF_ALLOC.

.section aa,"",@progbits,unique,1
.quad 0

.section aa,"a",@progbits,unique,2
.quad 0

Usually, the better idea is to use different section names. It may require some trial and error to see how much complexity this scheme will bring. llvm/include/llvm/ProfileData/InstrProfData.inc

I feel like this is a bug in lld as _start/_stop symbols for non allocated sections should be null.

It isn't. This is "undefined behavior, no diagnostic required".

For

extern char __start___llvm_covfun __attribute__((weak));
extern char __stop___llvm_covfun __attribute__((weak));

int main() {
  printf("%p, %p\n", &__start___llvm_covfun, &__stop___llvm_covfun);
  return 0;
}

The program is ill-formed when __llvm_covfun does not have the SHF_ALLOC flag.
__start_/__stop_ symbols were not designed to be used with non-SHF_ALLOC output sections.
It's invalid to reference a non-SHF_ALLOC section from SHF_ALLOC code. The regular undefined weak rule (handwavy "Unresolved weak symbols have a zero value." in the specification) does not necessarily apply.

I noticed that GNU ld defines __start_/__stop_ for the non-SHF_ALLOC output section just like lld, and its output a.out prints non-zero addresses.

ZequanWu added a commit to ZequanWu/llvm-project that referenced this pull request Nov 10, 2023
As discussed in llvm#70856 (comment) and llvm#70856 (comment), it's better not to do runtime check for VARIANT_MASK_DBG_CORRELATE bit in __llvm_profile_raw_version when deciding if profile data/name sections should be dropped or not.
@ZequanWu
Copy link
Contributor Author

Chatted with @MaskRay offline, we come to an agreement that it's not good to use relying on the bit in __llvm_profile_raw_version to decide whether or not to dump data/name sections at runtime for the reasons mentioned above. Sent a PR: #71996

Even if we have a way to fix that, we still need the mode bit at llvm-profile merging step to indicate if the raw profile need debug info/binary to correlate. However, we can get ride of the runtime checking __llvm_profile_has_correlation to allow code compiled w/wo debug-info linked together works well.

I take back this word. When we do llvm-profdata merge, we use -debug-info to provide debug info file for correlation and the same could apply to binary correlation, a different flag. So, we know which correlation mode we are using.

ZequanWu added a commit that referenced this pull request Nov 14, 2023
As discussed in
#70856 (comment)
and
#70856 (comment),
it's better not to do runtime check for VARIANT_MASK_DBG_CORRELATE bit
in __llvm_profile_raw_version when deciding if profile data/name
sections should be dropped or not.
zahiraam pushed a commit to zahiraam/llvm-project that referenced this pull request Nov 20, 2023
As discussed in
llvm#70856 (comment)
and
llvm#70856 (comment),
it's better not to do runtime check for VARIANT_MASK_DBG_CORRELATE bit
in __llvm_profile_raw_version when deciding if profile data/name
sections should be dropped or not.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler-rt PGO Profile Guided Optimizations
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants