[clang] [llvm] [compiler-rt] [clang-tools-extra] [Profile] Allow profile merging with multiple correlate files. (PR #75957)
Zequan Wu via cfe-commits
cfe-commits at lists.llvm.org
Wed Dec 20 10:20:25 PST 2023
https://github.com/ZequanWu updated https://github.com/llvm/llvm-project/pull/75957
>From d72f0e1ad7759bad81767418604d27f11d74d6de Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Tue, 19 Dec 2023 12:32:15 -0500
Subject: [PATCH 1/3] [Profile] Allow profile merging with multiple correlate
files.
---
.../Linux/instrprof-correlation-mixed.test | 33 ++++
.../Linux/instrprof-debug-info-correlate.c | 19 ++
.../llvm/ProfileData/InstrProfCorrelator.h | 124 ++++++++++---
.../llvm/ProfileData/InstrProfReader.h | 17 +-
llvm/lib/Object/BuildID.cpp | 18 ++
llvm/lib/ProfileData/InstrProfCorrelator.cpp | 164 +++++++++++++-----
llvm/lib/ProfileData/InstrProfReader.cpp | 26 ++-
llvm/tools/llvm-profdata/llvm-profdata.cpp | 84 +++++----
8 files changed, 358 insertions(+), 127 deletions(-)
create mode 100644 compiler-rt/test/profile/Linux/instrprof-correlation-mixed.test
diff --git a/compiler-rt/test/profile/Linux/instrprof-correlation-mixed.test b/compiler-rt/test/profile/Linux/instrprof-correlation-mixed.test
new file mode 100644
index 00000000000000..8cc4611eec4f0b
--- /dev/null
+++ b/compiler-rt/test/profile/Linux/instrprof-correlation-mixed.test
@@ -0,0 +1,33 @@
+// REQUIRES: lld-available
+// Test llvm-profdata merging with multiple correlation files mixing different correlation modes.
+
+// RUN: %clang_pgogen -o %t.normal -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.normal
+// RUN: llvm-profdata merge -o %t.normal.profdata %t.profraw
+
+// Compiling with differnt configs.
+// RUN: %clang_pgogen -o %t -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp -c -o %t-main.o
+// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp -c -o %t-main.debug.o
+// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -fpic -shared -Wl,--build-id -o %t-libfoo.debug.so
+// RUN: %clang_pgogen -o %t -mllvm -profile-correlate=binary -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -fpic -shared -Wl,--build-id -o %t-libfoo.binary.so
+
+// Test mixing default raw profile and lightweight raw profile generated with debug info correlate.
+// The raw profiles are mixed in %t.proflite.
+// RUN: %clang_pgogen -o %t %t-main.o %t-libfoo.debug.so -Wl,--build-id -o %t
+// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t-libfoo.debug.so %t.proflite
+// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
+// Two separate raw profiles.
+// RUN: rm -rf %t.dir && mkdir %t.dir
+// RUN: env LLVM_PROFILE_FILE=%t.dir/raw%m.proflite %run %t
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t-libfoo.debug.so %t.dir
+// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
+
+// Test lightweight raw profiles generated with debug info correlate and binary correlate.
+// Note we can not mix different correlation modes in static linking because when merging, the same correlate file can not be used for more than one correaltion mode.
+// Two separate lightweight raw profiles.
+// RUN: %clang_pgogen -o %t -g %t-main.debug.o %t-libfoo.binary.so -Wl,--build-id -o %t
+// RUN: rm -rf %t.dir && mkdir %t.dir
+// RUN: env LLVM_PROFILE_FILE=%t.dir/raw%m.proflite %run %t
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t --binary-file=%t-libfoo.binary.so %t.dir
+// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
index a918d7b6299005..47dbf3c87e68f1 100644
--- a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
+++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
@@ -25,6 +25,25 @@
// RUN: diff <(llvm-profdata show --all-functions --counts %t.cov.normal.profdata) <(llvm-profdata show --all-functions --counts %t.cov.profdata)
+// Test debug info correlate with build id.
+
+// Both binaries are built with build id.
+// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -c -fpic -shared -Wl,--build-id -o %t-libfoo.so
+// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %t-libfoo.so -Wl,--build-id -o %t
+// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.o %t.proflite
+// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
+
+// One binary is built without build id.
+// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %t-libfoo.so -o %t
+// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.o %t.proflite
+// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
+
+// Warning about multiple correlate files have the same build id.
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t,%t-libfoo.o %t.proflite 2>&1 >/dev/null | FileCheck %s --check-prefix=WARN
+// WARN: Duplicate build id ({{.*}}) found for {{.*}} and {{.*}}
+
// Test debug info correlate with online merging.
// RUN: env LLVM_PROFILE_FILE=%t-1.profraw %run %t.normal
diff --git a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
index c07c67d287e2ce..1b579e0ac2fd24 100644
--- a/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
+++ b/llvm/include/llvm/ProfileData/InstrProfCorrelator.h
@@ -13,6 +13,7 @@
#define LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
#include "llvm/ADT/DenseSet.h"
+#include "llvm/Object/BuildID.h"
#include "llvm/ProfileData/InstrProf.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/MemoryBuffer.h"
@@ -35,20 +36,33 @@ class InstrProfCorrelator {
/// correlate.
enum ProfCorrelatorKind { NONE, DEBUG_INFO, BINARY };
+ struct AtomicWarningCounter {
+ AtomicWarningCounter(uint64_t MaxWarnings)
+ : MaxWarnings(MaxWarnings), WarningCount(0){};
+ bool shouldEmitWarning();
+ ~AtomicWarningCounter();
+
+ private:
+ const uint64_t MaxWarnings;
+ std::atomic<uint64_t> WarningCount;
+ };
+
static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
- get(StringRef Filename, ProfCorrelatorKind FileKind);
+ get(StringRef Filename, ProfCorrelatorKind FileKind,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter);
/// Construct a ProfileData vector used to correlate raw instrumentation data
/// to their functions.
- /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit)
- virtual Error correlateProfileData(int MaxWarnings) = 0;
+ virtual Error correlateProfileData() = 0;
/// Process debug info and dump the correlation data.
- /// \param MaxWarnings the maximum number of warnings to emit (0 = no limit)
- virtual Error dumpYaml(int MaxWarnings, raw_ostream &OS) = 0;
+ virtual Error dumpYaml(raw_ostream &OS) = 0;
+
+ virtual const char *getDataPointer() const = 0;
/// Return the number of ProfileData elements.
- std::optional<size_t> getDataSize() const;
+ size_t getDataSize() const;
/// Return a pointer to the names string that this class constructs.
const char *getNamesPointer() const { return Names.c_str(); }
@@ -61,6 +75,8 @@ class InstrProfCorrelator {
return Ctx->CountersSectionEnd - Ctx->CountersSectionStart;
}
+ object::BuildIDRef getBuildID() const { return Ctx->BuildID; }
+
static const char *FunctionNameAttributeName;
static const char *CFGHashAttributeName;
static const char *NumCountersAttributeName;
@@ -84,16 +100,25 @@ class InstrProfCorrelator {
const char *DataEnd;
const char *NameStart;
size_t NameSize;
+ object::BuildIDRef BuildID;
/// True if target and host have different endian orders.
bool ShouldSwapBytes;
};
const std::unique_ptr<Context> Ctx;
- InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr<Context> Ctx)
- : Ctx(std::move(Ctx)), Kind(K) {}
+ InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr<Context> Ctx,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter)
+ : Ctx(std::move(Ctx)), IsCorrelated(false), CorrelateLock(CorrelateLock),
+ WarnLock(WarnLock), WarnCounter(WarnCounter), Kind(K) {}
std::string Names;
- std::vector<std::string> NamesVec;
+ /// True if correlation is already done.
+ bool IsCorrelated;
+ std::mutex &CorrelateLock;
+ std::mutex &WarnLock;
+
+ bool shouldEmitWarning();
struct Probe {
std::string FunctionName;
@@ -115,8 +140,11 @@ class InstrProfCorrelator {
private:
static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
- get(std::unique_ptr<MemoryBuffer> Buffer, ProfCorrelatorKind FileKind);
+ get(std::unique_ptr<MemoryBuffer> Buffer, ProfCorrelatorKind FileKind,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter);
+ AtomicWarningCounter *WarnCounter;
const InstrProfCorrelatorKind Kind;
};
@@ -125,13 +153,15 @@ class InstrProfCorrelator {
template <class IntPtrT>
class InstrProfCorrelatorImpl : public InstrProfCorrelator {
public:
- InstrProfCorrelatorImpl(std::unique_ptr<InstrProfCorrelator::Context> Ctx);
+ InstrProfCorrelatorImpl(std::unique_ptr<InstrProfCorrelator::Context> Ctx,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter);
static bool classof(const InstrProfCorrelator *C);
/// Return a pointer to the underlying ProfileData vector that this class
/// constructs.
- const RawInstrProf::ProfileData<IntPtrT> *getDataPointer() const {
- return Data.empty() ? nullptr : Data.data();
+ const char *getDataPointer() const override {
+ return Data.empty() ? nullptr : (const char *)Data.data();
}
/// Return the number of ProfileData elements.
@@ -139,19 +169,20 @@ class InstrProfCorrelatorImpl : public InstrProfCorrelator {
static llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
get(std::unique_ptr<InstrProfCorrelator::Context> Ctx,
- const object::ObjectFile &Obj, ProfCorrelatorKind FileKind);
+ const object::ObjectFile &Obj, ProfCorrelatorKind FileKind,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter);
protected:
std::vector<RawInstrProf::ProfileData<IntPtrT>> Data;
- Error correlateProfileData(int MaxWarnings) override;
+ Error correlateProfileData() override;
virtual void correlateProfileDataImpl(
- int MaxWarnings,
InstrProfCorrelator::CorrelationData *Data = nullptr) = 0;
virtual Error correlateProfileNameImpl() = 0;
- Error dumpYaml(int MaxWarnings, raw_ostream &OS) override;
+ Error dumpYaml(raw_ostream &OS) override;
void addDataProbe(uint64_t FunctionName, uint64_t CFGHash,
IntPtrT CounterOffset, IntPtrT FunctionPtr,
@@ -164,8 +195,11 @@ class InstrProfCorrelatorImpl : public InstrProfCorrelator {
private:
InstrProfCorrelatorImpl(InstrProfCorrelatorKind Kind,
- std::unique_ptr<InstrProfCorrelator::Context> Ctx)
- : InstrProfCorrelator(Kind, std::move(Ctx)){};
+ std::unique_ptr<InstrProfCorrelator::Context> Ctx,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter)
+ : InstrProfCorrelator(Kind, std::move(Ctx), CorrelateLock, WarnLock,
+ WarnCounter){};
llvm::DenseSet<IntPtrT> CounterOffsets;
};
@@ -174,13 +208,18 @@ class InstrProfCorrelatorImpl : public InstrProfCorrelator {
template <class IntPtrT>
class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
public:
- DwarfInstrProfCorrelator(std::unique_ptr<DWARFContext> DICtx,
- std::unique_ptr<InstrProfCorrelator::Context> Ctx)
- : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)),
+ DwarfInstrProfCorrelator(
+ std::unique_ptr<DWARFContext> DICtx,
+ std::unique_ptr<InstrProfCorrelator::Context> Ctx,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ InstrProfCorrelator::AtomicWarningCounter *WarnCounter)
+ : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx), CorrelateLock,
+ WarnLock, WarnCounter),
DICtx(std::move(DICtx)) {}
private:
std::unique_ptr<DWARFContext> DICtx;
+ std::vector<std::string> NamesVec;
/// Return the address of the object that the provided DIE symbolizes.
std::optional<uint64_t> getLocation(const DWARFDie &Die) const;
@@ -217,7 +256,6 @@ class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
/// \param MaxWarnings the maximum number of warnings to emit (0 = no limit)
/// \param Data if provided, populate with the correlation data found
void correlateProfileDataImpl(
- int MaxWarnings,
InstrProfCorrelator::CorrelationData *Data = nullptr) override;
Error correlateProfileNameImpl() override;
@@ -228,8 +266,12 @@ class DwarfInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
template <class IntPtrT>
class BinaryInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
public:
- BinaryInstrProfCorrelator(std::unique_ptr<InstrProfCorrelator::Context> Ctx)
- : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx)) {}
+ BinaryInstrProfCorrelator(
+ std::unique_ptr<InstrProfCorrelator::Context> Ctx,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ InstrProfCorrelator::AtomicWarningCounter *WarnCounter)
+ : InstrProfCorrelatorImpl<IntPtrT>(std::move(Ctx), CorrelateLock,
+ WarnLock, WarnCounter) {}
/// Return a pointer to the names string that this class constructs.
const char *getNamesPointer() const { return this->Ctx.NameStart; }
@@ -239,12 +281,42 @@ class BinaryInstrProfCorrelator : public InstrProfCorrelatorImpl<IntPtrT> {
private:
void correlateProfileDataImpl(
- int MaxWarnings,
InstrProfCorrelator::CorrelationData *Data = nullptr) override;
Error correlateProfileNameImpl() override;
};
+// InstrProfCorrelators contains a map from BuildID to InstrProfCorrelator and
+// correlate profile on-demand when users call getCorrelator.
+class InstrProfCorrelators {
+public:
+ static llvm::Expected<std::unique_ptr<InstrProfCorrelators>>
+ get(ArrayRef<std::pair<StringRef, InstrProfCorrelator::ProfCorrelatorKind>>
+ CorrelateInputs,
+ uint32_t MaxWarnings);
+
+ InstrProfCorrelators(
+ StringMap<std::unique_ptr<InstrProfCorrelator>> &&CorrelatorMap,
+ std::unique_ptr<std::mutex> CorrelateLock,
+ std::unique_ptr<std::mutex> WarnLock,
+ std::unique_ptr<InstrProfCorrelator::AtomicWarningCounter> WarnCounter)
+ : CorrelatorMap(std::move(CorrelatorMap)),
+ CorrelateLock(std::move(CorrelateLock)), WarnLock(std::move(WarnLock)),
+ WarnCounter(std::move(WarnCounter)) {}
+
+ llvm::Expected<const InstrProfCorrelator *>
+ getCorrelator(object::BuildIDRef BuildID) const;
+
+ bool empty() const { return CorrelatorMap.empty(); }
+ Error dumpYaml(raw_ostream &OS);
+
+private:
+ // A map from BuildID to correlator.
+ const StringMap<std::unique_ptr<InstrProfCorrelator>> CorrelatorMap;
+ std::unique_ptr<std::mutex> CorrelateLock;
+ std::unique_ptr<std::mutex> WarnLock;
+ std::unique_ptr<InstrProfCorrelator::AtomicWarningCounter> WarnCounter;
+};
} // end namespace llvm
#endif // LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
diff --git a/llvm/include/llvm/ProfileData/InstrProfReader.h b/llvm/include/llvm/ProfileData/InstrProfReader.h
index ff50dfde0e7938..c7810c8b1af50c 100644
--- a/llvm/include/llvm/ProfileData/InstrProfReader.h
+++ b/llvm/include/llvm/ProfileData/InstrProfReader.h
@@ -199,12 +199,12 @@ class InstrProfReader {
/// instrprof file.
static Expected<std::unique_ptr<InstrProfReader>>
create(const Twine &Path, vfs::FileSystem &FS,
- const InstrProfCorrelator *Correlator = nullptr,
+ const InstrProfCorrelators *Correlators = nullptr,
std::function<void(Error)> Warn = nullptr);
static Expected<std::unique_ptr<InstrProfReader>>
create(std::unique_ptr<MemoryBuffer> Buffer,
- const InstrProfCorrelator *Correlator = nullptr,
+ const InstrProfCorrelators *Correlators = nullptr,
std::function<void(Error)> Warn = nullptr);
/// \param Weight for raw profiles use this as the temporal profile trace
@@ -313,7 +313,8 @@ class RawInstrProfReader : public InstrProfReader {
std::unique_ptr<MemoryBuffer> DataBuffer;
/// If available, this hold the ProfileData array used to correlate raw
/// instrumentation data to their functions.
- const InstrProfCorrelatorImpl<IntPtrT> *Correlator;
+ const InstrProfCorrelators *Correlators;
+ bool IsCorrelatorUsed;
/// A list of timestamps paired with a function name reference.
std::vector<std::pair<uint64_t, uint64_t>> TemporalProfTimestamps;
bool ShouldSwapBytes;
@@ -346,11 +347,9 @@ class RawInstrProfReader : public InstrProfReader {
public:
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer,
- const InstrProfCorrelator *Correlator,
+ const InstrProfCorrelators *Correlator,
std::function<void(Error)> Warn)
- : DataBuffer(std::move(DataBuffer)),
- Correlator(dyn_cast_or_null<const InstrProfCorrelatorImpl<IntPtrT>>(
- Correlator)),
+ : DataBuffer(std::move(DataBuffer)), Correlators((Correlator)),
Warn(Warn) {}
RawInstrProfReader(const RawInstrProfReader &) = delete;
RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
@@ -434,8 +433,8 @@ class RawInstrProfReader : public InstrProfReader {
bool atEnd() const { return Data == DataEnd; }
void advanceData() {
- // `CountersDelta` is a constant zero when using debug info correlation.
- if (!Correlator) {
+ // `CountersDelta` is a constant zero when using correlation.
+ if (!IsCorrelatorUsed) {
// The initial CountersDelta is the in-memory address difference between
// the data and counts sections:
// start(__llvm_prf_cnts) - start(__llvm_prf_data)
diff --git a/llvm/lib/Object/BuildID.cpp b/llvm/lib/Object/BuildID.cpp
index ef21458060abd6..363d2d379e9aa3 100644
--- a/llvm/lib/Object/BuildID.cpp
+++ b/llvm/lib/Object/BuildID.cpp
@@ -14,6 +14,7 @@
#include "llvm/Object/BuildID.h"
+#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
@@ -42,6 +43,21 @@ template <typename ELFT> BuildIDRef getBuildID(const ELFFile<ELFT> &Obj) {
return {};
}
+BuildIDRef getBuildID(const COFFObjectFile *Obj) {
+ for (const debug_directory &D : Obj->debug_directories()) {
+ if (D.AddressOfRawData == 0 || D.Type != COFF::IMAGE_DEBUG_TYPE_CODEVIEW)
+ continue;
+ const codeview::DebugInfo *DebugInfo;
+ StringRef PDBFileName;
+ if (Error E = Obj->getDebugPDBInfo(&D, DebugInfo, PDBFileName))
+ consumeError(std::move(E));
+ if (DebugInfo->Signature.CVSignature == OMF::Signature::PDB70)
+ return ArrayRef(DebugInfo->PDB70.Signature,
+ sizeof(DebugInfo->PDB70.Signature));
+ }
+ return {};
+}
+
} // namespace
BuildID llvm::object::parseBuildID(StringRef Str) {
@@ -62,6 +78,8 @@ BuildIDRef llvm::object::getBuildID(const ObjectFile *Obj) {
return ::getBuildID(O->getELFFile());
if (auto *O = dyn_cast<ELFObjectFile<ELF64BE>>(Obj))
return ::getBuildID(O->getELFFile());
+ if (auto *O = dyn_cast<COFFObjectFile>(Obj))
+ return ::getBuildID(O);
return std::nullopt;
}
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
index cf80a58f43bd90..edd38fdcf9c446 100644
--- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -52,6 +52,18 @@ const char *InstrProfCorrelator::FunctionNameAttributeName = "Function Name";
const char *InstrProfCorrelator::CFGHashAttributeName = "CFG Hash";
const char *InstrProfCorrelator::NumCountersAttributeName = "Num Counters";
+bool InstrProfCorrelator::AtomicWarningCounter::shouldEmitWarning() {
+ return MaxWarnings == 0 ||
+ WarningCount.fetch_add(1, std::memory_order_relaxed) < MaxWarnings;
+}
+
+InstrProfCorrelator::AtomicWarningCounter::~AtomicWarningCounter() {
+ if (MaxWarnings > 0 && WarningCount > MaxWarnings) {
+ WithColor::warning() << format("Suppressed %d additional warnings\n",
+ WarningCount - MaxWarnings);
+ }
+}
+
llvm::Expected<std::unique_ptr<InstrProfCorrelator::Context>>
InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
const object::ObjectFile &Obj,
@@ -87,11 +99,14 @@ InstrProfCorrelator::Context::get(std::unique_ptr<MemoryBuffer> Buffer,
++C->CountersSectionStart;
C->ShouldSwapBytes = Obj.isLittleEndian() != sys::IsLittleEndianHost;
+ C->BuildID = object::getBuildID(&Obj);
return Expected<std::unique_ptr<Context>>(std::move(C));
}
llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
-InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind) {
+InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter) {
if (FileKind == DEBUG_INFO) {
auto DsymObjectsOrErr =
object::MachOObjectFile::findDsymObjectMembers(Filename);
@@ -110,14 +125,16 @@ InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind) {
if (auto Err = BufferOrErr.takeError())
return std::move(Err);
- return get(std::move(*BufferOrErr), FileKind);
+ return get(std::move(*BufferOrErr), FileKind, CorrelateLock, WarnLock,
+ WarnCounter);
}
if (FileKind == BINARY) {
auto BufferOrErr = errorOrToExpected(MemoryBuffer::getFile(Filename));
if (auto Err = BufferOrErr.takeError())
return std::move(Err);
- return get(std::move(*BufferOrErr), FileKind);
+ return get(std::move(*BufferOrErr), FileKind, CorrelateLock, WarnLock,
+ WarnCounter);
}
return make_error<InstrProfError>(
instrprof_error::unable_to_correlate_profile,
@@ -127,7 +144,9 @@ InstrProfCorrelator::get(StringRef Filename, ProfCorrelatorKind FileKind) {
llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer,
- ProfCorrelatorKind FileKind) {
+ ProfCorrelatorKind FileKind, std::mutex &CorrelateLock,
+ std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter) {
auto BinOrErr = object::createBinary(*Buffer);
if (auto Err = BinOrErr.takeError())
return std::move(Err);
@@ -139,36 +158,46 @@ InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer,
auto T = Obj->makeTriple();
if (T.isArch64Bit())
return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj,
- FileKind);
+ FileKind, CorrelateLock,
+ WarnLock, WarnCounter);
if (T.isArch32Bit())
return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj,
- FileKind);
+ FileKind, CorrelateLock,
+ WarnLock, WarnCounter);
}
return make_error<InstrProfError>(
instrprof_error::unable_to_correlate_profile, "not an object file");
}
-std::optional<size_t> InstrProfCorrelator::getDataSize() const {
+size_t InstrProfCorrelator::getDataSize() const {
if (auto *C = dyn_cast<InstrProfCorrelatorImpl<uint32_t>>(this)) {
return C->getDataSize();
} else if (auto *C = dyn_cast<InstrProfCorrelatorImpl<uint64_t>>(this)) {
return C->getDataSize();
}
- return {};
+ return 0;
+}
+
+bool InstrProfCorrelator::shouldEmitWarning() {
+ return WarnCounter && WarnCounter->shouldEmitWarning();
}
namespace llvm {
template <>
InstrProfCorrelatorImpl<uint32_t>::InstrProfCorrelatorImpl(
- std::unique_ptr<InstrProfCorrelator::Context> Ctx)
- : InstrProfCorrelatorImpl(InstrProfCorrelatorKind::CK_32Bit,
- std::move(Ctx)) {}
+ std::unique_ptr<InstrProfCorrelator::Context> Ctx,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter)
+ : InstrProfCorrelatorImpl(InstrProfCorrelatorKind::CK_32Bit, std::move(Ctx),
+ CorrelateLock, WarnLock, WarnCounter) {}
template <>
InstrProfCorrelatorImpl<uint64_t>::InstrProfCorrelatorImpl(
- std::unique_ptr<InstrProfCorrelator::Context> Ctx)
- : InstrProfCorrelatorImpl(InstrProfCorrelatorKind::CK_64Bit,
- std::move(Ctx)) {}
+ std::unique_ptr<InstrProfCorrelator::Context> Ctx,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter)
+ : InstrProfCorrelatorImpl(InstrProfCorrelatorKind::CK_64Bit, std::move(Ctx),
+ CorrelateLock, WarnLock, WarnCounter) {}
template <>
bool InstrProfCorrelatorImpl<uint32_t>::classof(const InstrProfCorrelator *C) {
return C->getKind() == InstrProfCorrelatorKind::CK_32Bit;
@@ -184,35 +213,42 @@ template <class IntPtrT>
llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
InstrProfCorrelatorImpl<IntPtrT>::get(
std::unique_ptr<InstrProfCorrelator::Context> Ctx,
- const object::ObjectFile &Obj, ProfCorrelatorKind FileKind) {
+ const object::ObjectFile &Obj, ProfCorrelatorKind FileKind,
+ std::mutex &CorrelateLock, std::mutex &WarnLock,
+ AtomicWarningCounter *WarnCounter) {
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));
+ std::move(DICtx), std::move(Ctx), CorrelateLock, WarnLock,
+ WarnCounter);
}
return make_error<InstrProfError>(
instrprof_error::unable_to_correlate_profile,
"unsupported debug info format (only DWARF is supported)");
}
if (Obj.isELF() || Obj.isCOFF())
- return std::make_unique<BinaryInstrProfCorrelator<IntPtrT>>(std::move(Ctx));
+ return std::make_unique<BinaryInstrProfCorrelator<IntPtrT>>(
+ std::move(Ctx), CorrelateLock, WarnLock, WarnCounter);
return make_error<InstrProfError>(
instrprof_error::unable_to_correlate_profile,
"unsupported binary format (only ELF and COFF are supported)");
}
template <class IntPtrT>
-Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData(int MaxWarnings) {
- assert(Data.empty() && Names.empty() && NamesVec.empty());
- correlateProfileDataImpl(MaxWarnings);
+Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData() {
+ std::lock_guard<std::mutex> Guard(this->CorrelateLock);
+ if (IsCorrelated)
+ return Error::success();
+ assert(Data.empty() && Names.empty());
+ correlateProfileDataImpl();
if (this->Data.empty())
return make_error<InstrProfError>(
instrprof_error::unable_to_correlate_profile,
"could not find any profile data metadata in correlated file");
Error Result = correlateProfileNameImpl();
- this->CounterOffsets.clear();
- this->NamesVec.clear();
+ CounterOffsets.clear();
+ IsCorrelated = true;
return Result;
}
@@ -240,10 +276,9 @@ template <> struct yaml::SequenceElementTraits<InstrProfCorrelator::Probe> {
};
template <class IntPtrT>
-Error InstrProfCorrelatorImpl<IntPtrT>::dumpYaml(int MaxWarnings,
- raw_ostream &OS) {
+Error InstrProfCorrelatorImpl<IntPtrT>::dumpYaml(raw_ostream &OS) {
InstrProfCorrelator::CorrelationData Data;
- correlateProfileDataImpl(MaxWarnings, &Data);
+ correlateProfileDataImpl(&Data);
if (Data.Probes.empty())
return make_error<InstrProfError>(
instrprof_error::unable_to_correlate_profile,
@@ -324,10 +359,7 @@ bool DwarfInstrProfCorrelator<IntPtrT>::isDIEOfProbe(const DWARFDie &Die) {
template <class IntPtrT>
void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
- int MaxWarnings, InstrProfCorrelator::CorrelationData *Data) {
- bool UnlimitedWarnings = (MaxWarnings == 0);
- // -N suppressed warnings means we can emit up to N (unsuppressed) warnings
- int NumSuppressedWarnings = -MaxWarnings;
+ InstrProfCorrelator::CorrelationData *Data) {
auto maybeAddProbe = [&](DWARFDie Die) {
if (!isDIEOfProbe(Die))
return;
@@ -364,7 +396,8 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
}
}
if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) {
- if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+ if (this->shouldEmitWarning()) {
+ std::lock_guard<std::mutex> Guard(this->WarnLock);
WithColor::warning()
<< "Incomplete DIE for function " << FunctionName
<< ": CFGHash=" << CFGHash << " CounterPtr=" << CounterPtr
@@ -376,7 +409,8 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
uint64_t CountersStart = this->Ctx->CountersSectionStart;
uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
if (*CounterPtr < CountersStart || *CounterPtr >= CountersEnd) {
- if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+ if (this->shouldEmitWarning()) {
+ std::lock_guard<std::mutex> Guard(this->WarnLock);
WithColor::warning()
<< format("CounterPtr out of range for function %s: Actual=0x%x "
"Expected=[0x%x, 0x%x)\n",
@@ -385,7 +419,8 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
}
return;
}
- if (!FunctionPtr && (UnlimitedWarnings || ++NumSuppressedWarnings < 1)) {
+ if (!FunctionPtr && this->shouldEmitWarning()) {
+ std::lock_guard<std::mutex> Guard(this->WarnLock);
WithColor::warning() << format("Could not find address of function %s\n",
*FunctionName);
LLVM_DEBUG(Die.dump(dbgs()));
@@ -411,7 +446,7 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
} else {
this->addDataProbe(IndexedInstrProf::ComputeHash(*FunctionName), *CFGHash,
CounterOffset, FunctionPtr.value_or(0), *NumCounters);
- this->NamesVec.push_back(*FunctionName);
+ NamesVec.push_back(*FunctionName);
}
};
for (auto &CU : DICtx->normal_units())
@@ -420,33 +455,25 @@ void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
for (auto &CU : DICtx->dwo_units())
for (const auto &Entry : CU->dies())
maybeAddProbe(DWARFDie(CU.get(), &Entry));
-
- if (!UnlimitedWarnings && NumSuppressedWarnings > 0)
- WithColor::warning() << format("Suppressed %d additional warnings\n",
- NumSuppressedWarnings);
}
template <class IntPtrT>
Error DwarfInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() {
- if (this->NamesVec.empty()) {
+ if (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,
+ collectGlobalObjectNameStrings(NamesVec,
/*doCompression=*/false, this->Names);
return Result;
}
template <class IntPtrT>
void BinaryInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
- int MaxWarnings, InstrProfCorrelator::CorrelationData *CorrelateData) {
+ InstrProfCorrelator::CorrelationData *CorrelateData) {
using RawProfData = RawInstrProf::ProfileData<IntPtrT>;
- bool UnlimitedWarnings = (MaxWarnings == 0);
- // -N suppressed warnings means we can emit up to N (unsuppressed) warnings
- int NumSuppressedWarnings = -MaxWarnings;
-
const RawProfData *DataStart = (const RawProfData *)this->Ctx->DataStart;
const RawProfData *DataEnd = (const RawProfData *)this->Ctx->DataEnd;
// We need to use < here because the last data record may have no padding.
@@ -455,7 +482,8 @@ void BinaryInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl(
uint64_t CountersStart = this->Ctx->CountersSectionStart;
uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
if (CounterPtr < CountersStart || CounterPtr >= CountersEnd) {
- if (UnlimitedWarnings || ++NumSuppressedWarnings < 1) {
+ if (this->shouldEmitWarning()) {
+ std::lock_guard<std::mutex> Guard(this->WarnLock);
WithColor::warning()
<< format("CounterPtr out of range for function: Actual=0x%x "
"Expected=[0x%x, 0x%x) at data offset=0x%x\n",
@@ -481,3 +509,49 @@ Error BinaryInstrProfCorrelator<IntPtrT>::correlateProfileNameImpl() {
this->Names.append(this->Ctx->NameStart, this->Ctx->NameSize);
return Error::success();
}
+
+llvm::Expected<std::unique_ptr<InstrProfCorrelators>> InstrProfCorrelators::get(
+ ArrayRef<std::pair<StringRef, InstrProfCorrelator::ProfCorrelatorKind>>
+ CorrelateInputs,
+ uint32_t MaxWarnings) {
+ StringMap<std::unique_ptr<InstrProfCorrelator>> CorrelatorMap;
+ StringMap<StringRef> FileMap;
+ auto WarnCounter =
+ std::make_unique<InstrProfCorrelator::AtomicWarningCounter>(MaxWarnings);
+ std::unique_ptr<std::mutex> CorrelateLock = std::make_unique<std::mutex>();
+ std::unique_ptr<std::mutex> WarnLock = std::make_unique<std::mutex>();
+ for (const auto &Input : CorrelateInputs) {
+ std::unique_ptr<InstrProfCorrelator> Correlator;
+ if (auto Err = InstrProfCorrelator::get(Input.first, Input.second,
+ *CorrelateLock.get(),
+ *WarnLock.get(), WarnCounter.get())
+ .moveInto(Correlator))
+ return Err;
+ std::string BuildID = toHex(Correlator->getBuildID());
+ FileMap.try_emplace(BuildID, Input.first);
+ bool Inserted =
+ CorrelatorMap.try_emplace(BuildID, std::move(Correlator)).second;
+ if (!Inserted && WarnCounter->shouldEmitWarning()) {
+ std::lock_guard<std::mutex> Guard(*WarnLock);
+ WithColor::warning() << format(
+ "Duplicate build id (%s) found for %s and %s\n", BuildID.c_str(),
+ FileMap[BuildID].str().c_str(), Input.first.str().c_str());
+ }
+ }
+ return std::make_unique<InstrProfCorrelators>(
+ std::move(CorrelatorMap), std::move(CorrelateLock), std::move(WarnLock),
+ std::move(WarnCounter));
+}
+
+llvm::Expected<const InstrProfCorrelator *>
+InstrProfCorrelators::getCorrelator(object::BuildIDRef BuildID) const {
+ std::string BuildIDStr = toHex(BuildID);
+ auto I = CorrelatorMap.find(BuildIDStr);
+ if (I == CorrelatorMap.end())
+ return make_error<InstrProfError>(
+ instrprof_error::unable_to_correlate_profile,
+ "missing correlator file with build id " + BuildIDStr + "\n");
+ if (auto Err = I->getValue()->correlateProfileData())
+ return Err;
+ return I->getValue().get();
+}
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index 068922d421f8b9..c135710961cd43 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -155,19 +155,19 @@ printBinaryIdsInternal(raw_ostream &OS,
Expected<std::unique_ptr<InstrProfReader>>
InstrProfReader::create(const Twine &Path, vfs::FileSystem &FS,
- const InstrProfCorrelator *Correlator,
+ const InstrProfCorrelators *Correlators,
std::function<void(Error)> Warn) {
// Set up the buffer to read.
auto BufferOrError = setupMemoryBuffer(Path, FS);
if (Error E = BufferOrError.takeError())
return std::move(E);
- return InstrProfReader::create(std::move(BufferOrError.get()), Correlator,
+ return InstrProfReader::create(std::move(BufferOrError.get()), Correlators,
Warn);
}
Expected<std::unique_ptr<InstrProfReader>>
InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
- const InstrProfCorrelator *Correlator,
+ const InstrProfCorrelators *Correlators,
std::function<void(Error)> Warn) {
if (Buffer->getBufferSize() == 0)
return make_error<InstrProfError>(instrprof_error::empty_raw_profile);
@@ -177,9 +177,9 @@ InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
if (IndexedInstrProfReader::hasFormat(*Buffer))
Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
else if (RawInstrProfReader64::hasFormat(*Buffer))
- Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlator, Warn));
+ Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlators, Warn));
else if (RawInstrProfReader32::hasFormat(*Buffer))
- Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator, Warn));
+ Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlators, Warn));
else if (TextInstrProfReader::hasFormat(*Buffer))
Result.reset(new TextInstrProfReader(std::move(Buffer)));
else
@@ -559,6 +559,7 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
uint64_t BinaryIdSize = swap(Header.BinaryIdsSize);
// Binary id start just after the header if exists.
+ object::BuildIDRef BinaryId;
const uint8_t *BinaryIdStart =
reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
const uint8_t *BinaryIdEnd = BinaryIdStart + BinaryIdSize;
@@ -570,6 +571,7 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
readBinaryIdsInternal(*DataBuffer, BinaryIdSize, BinaryIdStart,
BinaryIds, getDataEndianness()))
return Err;
+ BinaryId = BinaryIds.back();
}
CountersDelta = swap(Header.CountersDelta);
@@ -600,22 +602,28 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
return error(instrprof_error::bad_header);
- if (Correlator) {
+ if (DataSize == 0 && NamesSize == 0 && Correlators && !Correlators->empty()) {
// These sizes in the raw file are zero because we constructed them in the
// Correlator.
- if (!(DataSize == 0 && NamesSize == 0 && CountersDelta == 0 &&
- NamesDelta == 0))
+ if (!(CountersDelta == 0 && NamesDelta == 0))
return error(instrprof_error::unexpected_correlation_info);
- Data = Correlator->getDataPointer();
+ auto CorrelatorOrErr = Correlators->getCorrelator(BinaryId);
+ if (!CorrelatorOrErr)
+ return CorrelatorOrErr.takeError();
+ auto *Correlator = CorrelatorOrErr.get();
+ Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
+ Correlator->getDataPointer());
DataEnd = Data + Correlator->getDataSize();
NamesStart = Correlator->getNamesPointer();
NamesEnd = NamesStart + Correlator->getNamesSize();
+ IsCorrelatorUsed = true;
} else {
Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
Start + DataOffset);
DataEnd = Data + NumData;
NamesStart = Start + NamesOffset;
NamesEnd = NamesStart + NamesSize;
+ IsCorrelatorUsed = false;
}
CountersStart = Start + CountersOffset;
diff --git a/llvm/tools/llvm-profdata/llvm-profdata.cpp b/llvm/tools/llvm-profdata/llvm-profdata.cpp
index 322b7da2678f4f..05a7f79bd6d72e 100644
--- a/llvm/tools/llvm-profdata/llvm-profdata.cpp
+++ b/llvm/tools/llvm-profdata/llvm-profdata.cpp
@@ -118,18 +118,18 @@ cl::opt<std::string> ProfiledBinary(
"profiled-binary", cl::init(""),
cl::desc("Path to binary from which the profile was collected."),
cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
-cl::opt<std::string> DebugInfoFilename(
- "debug-info", cl::init(""),
+cl::list<std::string> DebugInfoFilenames(
+ "debug-info",
cl::desc(
"For show, read and extract profile metadata from debug info and show "
"the functions it found. For merge, use the provided debug info to "
"correlate the raw profile."),
cl::sub(ShowSubcommand), cl::sub(MergeSubcommand));
-cl::opt<std::string>
- BinaryFilename("binary-file", cl::init(""),
- cl::desc("For merge, use the provided unstripped bianry to "
- "correlate the raw profile."),
- cl::sub(MergeSubcommand));
+cl::list<std::string>
+ BinaryFilenames("binary-file",
+ cl::desc("For merge, use the provided unstripped bianry to "
+ "correlate the raw profile."),
+ cl::sub(MergeSubcommand));
cl::opt<std::string> FuncNameFilter(
"function",
cl::desc("Details for matching functions. For overlapping CSSPGO, this "
@@ -607,7 +607,7 @@ static void overlapInput(const std::string &BaseFilename,
/// Load an input into a writer context.
static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
- const InstrProfCorrelator *Correlator,
+ const InstrProfCorrelators *Correlators,
const StringRef ProfiledBinary, WriterContext *WC) {
std::unique_lock<std::mutex> CtxGuard{WC->Lock};
@@ -675,7 +675,7 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
ReaderWarning = {make_error<InstrProfError>(ErrCode, Msg), Filename};
};
auto ReaderOrErr =
- InstrProfReader::create(Input.Filename, *FS, Correlator, Warn);
+ InstrProfReader::create(Input.Filename, *FS, Correlators, Warn);
if (Error E = ReaderOrErr.takeError()) {
// Skip the empty profiles by returning silently.
auto [ErrCode, Msg] = InstrProfError::take(std::move(E));
@@ -793,28 +793,27 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
OutputFormat != PF_Text)
exitWithError("unknown format is specified");
- // TODO: Maybe we should support correlation with mixture of different
- // correlation modes(w/wo debug-info/object correlation).
- if (!DebugInfoFilename.empty() && !BinaryFilename.empty())
- exitWithError("Expected only one of -debug-info, -binary-file");
- std::string CorrelateFilename;
- ProfCorrelatorKind CorrelateKind = ProfCorrelatorKind::NONE;
- if (!DebugInfoFilename.empty()) {
- CorrelateFilename = DebugInfoFilename;
- CorrelateKind = ProfCorrelatorKind::DEBUG_INFO;
- } else if (!BinaryFilename.empty()) {
- CorrelateFilename = BinaryFilename;
- CorrelateKind = ProfCorrelatorKind::BINARY;
- }
+ std::unique_ptr<InstrProfCorrelators> Correlators;
+ SmallVector<std::pair<StringRef, InstrProfCorrelator::ProfCorrelatorKind>>
+ CorrelateInputs;
- std::unique_ptr<InstrProfCorrelator> Correlator;
- if (CorrelateKind != InstrProfCorrelator::NONE) {
- if (auto Err = InstrProfCorrelator::get(CorrelateFilename, CorrelateKind)
- .moveInto(Correlator))
- exitWithError(std::move(Err), CorrelateFilename);
- if (auto Err = Correlator->correlateProfileData(MaxDbgCorrelationWarnings))
- exitWithError(std::move(Err), CorrelateFilename);
+ for (StringRef Filenames : DebugInfoFilenames) {
+ SmallVector<StringRef, 1> FilenameVec;
+ Filenames.split(FilenameVec, ',');
+ for (StringRef Filename : FilenameVec)
+ CorrelateInputs.push_back({Filename, InstrProfCorrelator::DEBUG_INFO});
}
+ for (StringRef Filenames : BinaryFilenames) {
+ SmallVector<StringRef, 1> FilenameVec;
+ Filenames.split(FilenameVec, ',');
+ for (StringRef Filename : FilenameVec)
+ CorrelateInputs.push_back({Filename, InstrProfCorrelator::BINARY});
+ }
+ if (!CorrelateInputs.empty())
+ if (auto Err = InstrProfCorrelators::get(CorrelateInputs,
+ MaxDbgCorrelationWarnings)
+ .moveInto(Correlators))
+ exitWithError(std::move(Err));
std::mutex ErrorLock;
SmallSet<instrprof_error, 4> WriterErrorCodes;
@@ -833,7 +832,7 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
if (NumThreads == 1) {
for (const auto &Input : Inputs)
- loadInput(Input, Remapper, Correlator.get(), ProfiledBinary,
+ loadInput(Input, Remapper, Correlators.get(), ProfiledBinary,
Contexts[0].get());
} else {
ThreadPool Pool(hardware_concurrency(NumThreads));
@@ -841,7 +840,7 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
// Load the inputs in parallel (N/NumThreads serial steps).
unsigned Ctx = 0;
for (const auto &Input : Inputs) {
- Pool.async(loadInput, Input, Remapper, Correlator.get(), ProfiledBinary,
+ Pool.async(loadInput, Input, Remapper, Correlators.get(), ProfiledBinary,
Contexts[Ctx].get());
Ctx = (Ctx + 1) % NumThreads;
}
@@ -3077,17 +3076,22 @@ static int showDebugInfoCorrelation(const std::string &Filename,
if (SFormat == ShowFormat::Json)
exitWithError("JSON output is not supported for debug info correlation");
std::unique_ptr<InstrProfCorrelator> Correlator;
+ InstrProfCorrelator::AtomicWarningCounter WarnCounter(
+ MaxDbgCorrelationWarnings);
+ std::mutex CorrelateLock;
+ std::mutex WarnLock;
if (auto Err =
- InstrProfCorrelator::get(Filename, InstrProfCorrelator::DEBUG_INFO)
+ InstrProfCorrelator::get(Filename, InstrProfCorrelator::DEBUG_INFO,
+ CorrelateLock, WarnLock, &WarnCounter)
.moveInto(Correlator))
exitWithError(std::move(Err), Filename);
if (SFormat == ShowFormat::Yaml) {
- if (auto Err = Correlator->dumpYaml(MaxDbgCorrelationWarnings, OS))
+ if (auto Err = Correlator->dumpYaml(OS))
exitWithError(std::move(Err), Filename);
return 0;
}
- if (auto Err = Correlator->correlateProfileData(MaxDbgCorrelationWarnings))
+ if (auto Err = Correlator->correlateProfileData())
exitWithError(std::move(Err), Filename);
InstrProfSymtab Symtab;
@@ -3108,10 +3112,10 @@ static int showDebugInfoCorrelation(const std::string &Filename,
}
static int show_main(int argc, const char *argv[]) {
- if (Filename.empty() && DebugInfoFilename.empty())
+ if (Filename.empty() && DebugInfoFilenames.empty())
exitWithError(
"the positional argument '<profdata-file>' is required unless '--" +
- DebugInfoFilename.ArgStr + "' is provided");
+ DebugInfoFilenames.ArgStr + "' is provided");
if (Filename == OutputFilename) {
errs() << sys::path::filename(argv[0]) << " " << argv[1]
@@ -3129,8 +3133,12 @@ static int show_main(int argc, const char *argv[]) {
if (ShowAllFunctions && !FuncNameFilter.empty())
WithColor::warning() << "-function argument ignored: showing all functions\n";
- if (!DebugInfoFilename.empty())
- return showDebugInfoCorrelation(DebugInfoFilename, SFormat, OS);
+ if (!DebugInfoFilenames.empty()) {
+ if (DebugInfoFilenames.size() > 1)
+ exitWithError("'--" + DebugInfoFilenames.ArgStr +
+ "' only accept one argument in show subcommand");
+ return showDebugInfoCorrelation(DebugInfoFilenames[0], SFormat, OS);
+ }
if (ShowProfileKind == instr)
return showInstrProfile(SFormat, OS);
>From 3481cf6ddd3b7a9759c2a7b37cf288cc36e25847 Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Tue, 19 Dec 2023 12:36:32 -0500
Subject: [PATCH 2/3] fixup! [Profile] Allow profile merging with multiple
correlate files.
---
.../test/profile/Linux/instrprof-debug-info-correlate.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
index 47dbf3c87e68f1..af19101f91a2f1 100644
--- a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
+++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
@@ -31,13 +31,13 @@
// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -c -fpic -shared -Wl,--build-id -o %t-libfoo.so
// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %t-libfoo.so -Wl,--build-id -o %t
// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
-// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.o %t.proflite
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.so %t.proflite
// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
// One binary is built without build id.
// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %t-libfoo.so -o %t
// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
-// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.o %t.proflite
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.so %t.proflite
// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
// Warning about multiple correlate files have the same build id.
>From 5f90bc2f97df90766483657cfc7634cffc67caeb Mon Sep 17 00:00:00 2001
From: Zequan Wu <zequanwu at google.com>
Date: Wed, 20 Dec 2023 13:20:10 -0500
Subject: [PATCH 3/3] add windows binary id test and clean up.
---
.../Linux/instrprof-correlation-mixed.test | 5 +-
.../Linux/instrprof-debug-info-correlate.c | 62 +++++++++++--------
.../Windows/instrprof-binary-correlate.c | 41 ++++++++++++
.../test/profile/instrprof-binary-correlate.c | 2 -
llvm/lib/ProfileData/InstrProfCorrelator.cpp | 2 +-
llvm/lib/ProfileData/InstrProfReader.cpp | 6 +-
6 files changed, 85 insertions(+), 33 deletions(-)
create mode 100644 compiler-rt/test/profile/Windows/instrprof-binary-correlate.c
diff --git a/compiler-rt/test/profile/Linux/instrprof-correlation-mixed.test b/compiler-rt/test/profile/Linux/instrprof-correlation-mixed.test
index 8cc4611eec4f0b..60f167dee4a49c 100644
--- a/compiler-rt/test/profile/Linux/instrprof-correlation-mixed.test
+++ b/compiler-rt/test/profile/Linux/instrprof-correlation-mixed.test
@@ -7,8 +7,9 @@
// Compiling with differnt configs.
// RUN: %clang_pgogen -o %t -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp -c -o %t-main.o
-// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp -c -o %t-main.debug.o
-// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -fpic -shared -Wl,--build-id -o %t-libfoo.debug.so
+// RUN: %clang_pgogen -o %t -g -mllvm -profile-correlate=debug-info -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp -c -o %t-main.debug.o
+// RUN: %clang_pgogen -o %t -mllvm -profile-correlate=binary -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -c -o %t-foo.binary.o
+// RUN: %clang_pgogen -o %t -g -mllvm -profile-correlate=debug-info -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -fpic -shared -Wl,--build-id -o %t-libfoo.debug.so
// RUN: %clang_pgogen -o %t -mllvm -profile-correlate=binary -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -fpic -shared -Wl,--build-id -o %t-libfoo.binary.so
// Test mixing default raw profile and lightweight raw profile generated with debug info correlate.
diff --git a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
index af19101f91a2f1..fa2ab6fb2cd27d 100644
--- a/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
+++ b/compiler-rt/test/profile/Linux/instrprof-debug-info-correlate.c
@@ -7,13 +7,16 @@
// RUN: env LLVM_PROFILE_FILE=%t.d4.proflite %run %t.d4
// RUN: llvm-profdata merge -o %t.d4.profdata --debug-info=%t.d4 %t.d4.proflite
-// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.d4.profdata)
+// RUN: llvm-profdata show --all-functions --counts %t.normal.profdata > %t.normal.profdata.show
+// RUN: llvm-profdata show --all-functions --counts %t.d4.profdata > %t.d4.profdata.show
+// RUN: diff %t.normal.profdata.show %t.d4.profdata.show
// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t %t.proflite
-// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
+// RUN: llvm-profdata show --all-functions --counts %t.profdata > %t.profdata.show
+// RUN: diff %t.normal.profdata.show %t.profdata.show
// RUN: %clang_pgogen -o %t.cov -g -mllvm --debug-info-correlate -mllvm -pgo-function-entry-coverage -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %S/../Inputs/instrprof-debug-info-correlate-foo.cpp
// RUN: env LLVM_PROFILE_FILE=%t.cov.proflite %run %t.cov
@@ -23,43 +26,50 @@
// RUN: env LLVM_PROFILE_FILE=%t.cov.profraw %run %t.cov.normal
// RUN: llvm-profdata merge -o %t.cov.normal.profdata %t.cov.profraw
-// RUN: diff <(llvm-profdata show --all-functions --counts %t.cov.normal.profdata) <(llvm-profdata show --all-functions --counts %t.cov.profdata)
-
-// Test debug info correlate with build id.
-
-// Both binaries are built with build id.
-// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -c -fpic -shared -Wl,--build-id -o %t-libfoo.so
-// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %t-libfoo.so -Wl,--build-id -o %t
-// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
-// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.so %t.proflite
-// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
-
-// One binary is built without build id.
-// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %t-libfoo.so -o %t
-// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
-// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.so %t.proflite
-// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
-
-// Warning about multiple correlate files have the same build id.
-// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t,%t-libfoo.o %t.proflite 2>&1 >/dev/null | FileCheck %s --check-prefix=WARN
-// WARN: Duplicate build id ({{.*}}) found for {{.*}} and {{.*}}
+// RUN: llvm-profdata show --all-functions --counts %t.cov.normal.profdata > %t.cov.normal.profdata.show
+// RUN: llvm-profdata show --all-functions --counts %t.cov.profdata > %t.cov.profdata.show
+// RUN: diff %t.cov.normal.profdata.show %t.cov.profdata.show
// Test debug info correlate with online merging.
// RUN: env LLVM_PROFILE_FILE=%t-1.profraw %run %t.normal
// RUN: env LLVM_PROFILE_FILE=%t-2.profraw %run %t.normal
-// RUN: llvm-profdata merge -o %t.normal.profdata %t-1.profraw %t-2.profraw
+// RUN: llvm-profdata merge -o %t.merged.normal.profdata %t-1.profraw %t-2.profraw
// RUN: rm -rf %t.profdir && mkdir %t.profdir
// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.proflite %run %t
// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.proflite %run %t
-// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t %t.profdir/
+// RUN: llvm-profdata merge -o %t.merged.profdata --debug-info=%t %t.profdir/
-// RUN: diff <(llvm-profdata show --all-functions --counts %t.normal.profdata) <(llvm-profdata show --all-functions --counts %t.profdata)
+// RUN: llvm-profdata show --all-functions --counts %t.merged.normal.profdata > %t.merged.normal.profdata.show
+// RUN: llvm-profdata show --all-functions --counts %t.merged.profdata > %t.merged.profdata.show
+// RUN: diff %t.merged.normal.profdata.show %t.merged.profdata.show
// RUN: rm -rf %t.profdir && mkdir %t.profdir
// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.cov.proflite %run %t.cov
// RUN: env LLVM_PROFILE_FILE=%t.profdir/%m.cov.proflite %run %t.cov
// RUN: llvm-profdata merge -o %t.cov.profdata --debug-info=%t.cov %t.profdir/
-// RUN: diff <(llvm-profdata show --all-functions --counts %t.cov.normal.profdata) <(llvm-profdata show --all-functions --counts %t.cov.profdata)
+// RUN: llvm-profdata show --all-functions --counts %t.cov.profdata > %t.cov.profdata.show
+// RUN: diff %t.cov.normal.profdata.show %t.cov.profdata.show
+
+// Test debug info correlate with build id.
+
+// Both binaries are built with build id.
+// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-foo.cpp -fpic -shared -Wl,--build-id -o %t-libfoo.so
+// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %t-libfoo.so -Wl,--build-id -o %t
+// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.so %t.proflite
+// RUN: llvm-profdata show --all-functions --counts %t.profdata > %t.profdata.show
+// RUN: diff %t.normal.profdata.show %t.profdata.show
+
+// One binary is built without build id.
+// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %S/../Inputs/instrprof-debug-info-correlate-main.cpp %t-libfoo.so -o %t
+// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t-libfoo.so %t.proflite
+// RUN: llvm-profdata show --all-functions --counts %t.profdata > %t.profdata.show
+// RUN: diff %t.normal.profdata.show %t.profdata.show
+
+// Warning about multiple correlate files have the same build id.
+// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t,%t,%t-libfoo.so %t.proflite 2>&1 >/dev/null | FileCheck %s --check-prefix=WARN
+// WARN: Duplicate build id ("") found for {{.*}} and {{.*}}
diff --git a/compiler-rt/test/profile/Windows/instrprof-binary-correlate.c b/compiler-rt/test/profile/Windows/instrprof-binary-correlate.c
new file mode 100644
index 00000000000000..f01fa2b85ee1f3
--- /dev/null
+++ b/compiler-rt/test/profile/Windows/instrprof-binary-correlate.c
@@ -0,0 +1,41 @@
+// REQUIRES: target={{.*windows-msvc.*}}
+// REQUIRES: lld-available
+
+// Test binary correlate with build id.
+
+// Three binaries are built with build id.
+// RUN: rm -rf %t.dir && split-file %s %t.dir
+// RUN: %clang_profgen %t.dir/main.c %t.dir/foo.c %t.dir/bar.c -o %t.dir/main.exe
+// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.dir/main.exe
+// RUN: llvm-profdata merge -o %t.normal.profdata %t.profraw
+// RUN: llvm-profdata show --all-functions --counts %t.normal.profdata > %t.normal.profdata.show
+
+// RUN: %clang_profgen -mllvm -profile-correlate=binary %t.dir/foo.c -fuse-ld=lld -Wl,-build-id -Wl,-dll -o %t.dir/foo.dll
+// RUN: %clang_profgen -mllvm -profile-correlate=binary %t.dir/bar.c -fuse-ld=lld -Wl,-build-id -Wl,-dll -o %t.dir/bar.dll
+// RUN: %clang_profgen -mllvm -profile-correlate=binary %t.dir/main.c -fuse-ld=lld -Wl,-build-id %t.dir/foo.lib %t.dir/bar.lib -o %t.dir/main.exe
+// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t.dir/main.exe
+// RUN: llvm-profdata merge -o %t.profdata %t.proflite --binary-file=%t.dir/foo.dll,%t.dir/bar.dll,%t.dir/main.exe
+// RUN: llvm-profdata show --all-functions --counts %t.profdata > %t.profdata.show
+// RUN: diff %t.normal.profdata.show %t.profdata.show
+
+// One binary is built without build id.
+// RUN: %clang_profgen -mllvm -profile-correlate=binary %t.dir/main.c -fuse-ld=lld %t.dir/foo.lib %t.dir/bar.lib -o %t.dir/main.exe
+// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t.dir/main.exe
+// RUN: llvm-profdata merge -o %t.profdata %t.proflite --binary-file=%t.dir/foo.dll,%t.dir/bar.dll,%t.dir/main.exe
+// RUN: llvm-profdata show --all-functions --counts %t.profdata > %t.profdata.show
+// RUN: diff %t.normal.profdata.show %t.profdata.show
+
+//--- foo.c
+__declspec(dllexport) void foo() {}
+
+//--- bar.c
+__declspec(dllexport) void bar() {}
+
+//--- main.c
+__declspec(dllimport) void foo();
+__declspec(dllimport) void bar();
+int main() {
+ foo();
+ bar();
+ return 0;
+}
diff --git a/compiler-rt/test/profile/instrprof-binary-correlate.c b/compiler-rt/test/profile/instrprof-binary-correlate.c
index 0e96745a9b58f4..2e9b636cb712a2 100644
--- a/compiler-rt/test/profile/instrprof-binary-correlate.c
+++ b/compiler-rt/test/profile/instrprof-binary-correlate.c
@@ -47,5 +47,3 @@
// RUN: diff %t.normal.merged.profdata.show %t-4.profdata.show
// RUN: diff %t.normal.merged.report %t-4.report
// RUN: diff %t.normal.merged.show %t-4.show
-
-// TODO: After adding support for binary ID, test binaries with different binary IDs.
diff --git a/llvm/lib/ProfileData/InstrProfCorrelator.cpp b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
index edd38fdcf9c446..ff2488654b70a0 100644
--- a/llvm/lib/ProfileData/InstrProfCorrelator.cpp
+++ b/llvm/lib/ProfileData/InstrProfCorrelator.cpp
@@ -534,7 +534,7 @@ llvm::Expected<std::unique_ptr<InstrProfCorrelators>> InstrProfCorrelators::get(
if (!Inserted && WarnCounter->shouldEmitWarning()) {
std::lock_guard<std::mutex> Guard(*WarnLock);
WithColor::warning() << format(
- "Duplicate build id (%s) found for %s and %s\n", BuildID.c_str(),
+ "Duplicate build id (\"%s\") found for %s and %s\n", BuildID.c_str(),
FileMap[BuildID].str().c_str(), Input.first.str().c_str());
}
}
diff --git a/llvm/lib/ProfileData/InstrProfReader.cpp b/llvm/lib/ProfileData/InstrProfReader.cpp
index ba3f8696a3fd45..8f7e694eba9691 100644
--- a/llvm/lib/ProfileData/InstrProfReader.cpp
+++ b/llvm/lib/ProfileData/InstrProfReader.cpp
@@ -177,9 +177,11 @@ InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
if (IndexedInstrProfReader::hasFormat(*Buffer))
Result.reset(new IndexedInstrProfReader(std::move(Buffer)));
else if (RawInstrProfReader64::hasFormat(*Buffer))
- Result.reset(new RawInstrProfReader64(std::move(Buffer), Correlators, Warn));
+ Result.reset(
+ new RawInstrProfReader64(std::move(Buffer), Correlators, Warn));
else if (RawInstrProfReader32::hasFormat(*Buffer))
- Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlators, Warn));
+ Result.reset(
+ new RawInstrProfReader32(std::move(Buffer), Correlators, Warn));
else if (TextInstrProfReader::hasFormat(*Buffer))
Result.reset(new TextInstrProfReader(std::move(Buffer)));
else
More information about the cfe-commits
mailing list