forked from OSchip/llvm-project
Revert "[InstrProf] Add Correlator class to read debug info"
Also reverts an attempt to fix the build errors https://reviews.llvm.org/D115911
The original diff https://reviews.llvm.org/D114566 causes some build
errors that I need to investigate.
https://lab.llvm.org/buildbot/#/builders/118/builds/7037
This reverts commit 95946d2f85
.
Reviewed By: kyulee
Differential Revision: https://reviews.llvm.org/D115913
This commit is contained in:
parent
59f1d0eed5
commit
bdc68ee70f
|
@ -1,31 +0,0 @@
|
|||
// Value profiling is currently not supported in lightweight mode.
|
||||
// RUN: %clang_pgogen -o %t.normal -mllvm --disable-vp=true %s
|
||||
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.normal
|
||||
// RUN: llvm-profdata merge -o %t.normal.profdata %t.profraw
|
||||
|
||||
// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %s
|
||||
// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
|
||||
// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t.dSYM %t.proflite
|
||||
|
||||
// RUN: diff %t.normal.profdata %t.profdata
|
||||
|
||||
int foo(int a) {
|
||||
if (a % 2)
|
||||
return 4 * a + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bar(int a) {
|
||||
while (a > 100)
|
||||
a /= 2;
|
||||
return a;
|
||||
}
|
||||
|
||||
typedef int (*FP)(int);
|
||||
FP Fps[3] = {foo, bar};
|
||||
|
||||
int main() {
|
||||
for (int i = 0; i < 5; i++)
|
||||
Fps[i % 2](i);
|
||||
return 0;
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
// Value profiling is currently not supported in lightweight mode.
|
||||
// RUN: %clang_pgogen -o %t.normal -mllvm --disable-vp=true %s
|
||||
// RUN: env LLVM_PROFILE_FILE=%t.profraw %run %t.normal
|
||||
// RUN: llvm-profdata merge -o %t.normal.profdata %t.profraw
|
||||
|
||||
// RUN: %clang_pgogen -o %t -g -mllvm --debug-info-correlate -mllvm --disable-vp=true %s
|
||||
// RUN: env LLVM_PROFILE_FILE=%t.proflite %run %t
|
||||
// RUN: llvm-profdata merge -o %t.profdata --debug-info=%t %t.proflite
|
||||
|
||||
// RUN: diff %t.normal.profdata %t.profdata
|
||||
|
||||
int foo(int a) {
|
||||
if (a % 2)
|
||||
return 4 * a + 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int bar(int a) {
|
||||
while (a > 100)
|
||||
a /= 2;
|
||||
return a;
|
||||
}
|
||||
|
||||
typedef int (*FP)(int);
|
||||
FP Fps[3] = {foo, bar};
|
||||
|
||||
int main() {
|
||||
for (int i = 0; i < 5; i++)
|
||||
Fps[i % 2](i);
|
||||
return 0;
|
||||
}
|
|
@ -290,10 +290,6 @@ enum class instrprof_error {
|
|||
too_large,
|
||||
truncated,
|
||||
malformed,
|
||||
missing_debug_info_for_correlation,
|
||||
unexpected_debug_info_for_correlation,
|
||||
unable_to_correlate_profile,
|
||||
unsupported_debug_format,
|
||||
unknown_function,
|
||||
invalid_prof,
|
||||
hash_mismatch,
|
||||
|
|
|
@ -1,170 +0,0 @@
|
|||
//===- InstrProfCorrelator.h ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
// This file defines InstrProfCorrelator used to generate PGO profiles from
|
||||
// raw profile data and debug info.
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
|
||||
#define LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
|
||||
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/Object/ObjectFile.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/MemoryBuffer.h"
|
||||
#include <vector>
|
||||
|
||||
namespace llvm {
|
||||
|
||||
/// InstrProfCorrelator - A base class used to create raw instrumentation data
|
||||
/// to their functions.
|
||||
class InstrProfCorrelator {
|
||||
public:
|
||||
static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
|
||||
get(StringRef DebugInfoFilename);
|
||||
|
||||
/// Construct a ProfileData vector used to correlate raw instrumentation data
|
||||
/// to their functions.
|
||||
virtual Error correlateProfileData() = 0;
|
||||
|
||||
static const char *FunctionNameAttributeName;
|
||||
static const char *CFGHashAttributeName;
|
||||
static const char *NumCountersAttributeName;
|
||||
|
||||
enum InstrProfCorrelatorKind { CK_32Bit, CK_64Bit };
|
||||
InstrProfCorrelatorKind getKind() const { return Kind; }
|
||||
virtual ~InstrProfCorrelator() {}
|
||||
|
||||
protected:
|
||||
struct Context {
|
||||
static llvm::Expected<std::unique_ptr<Context>>
|
||||
get(std::unique_ptr<MemoryBuffer> Buffer, const object::ObjectFile &Obj);
|
||||
std::unique_ptr<MemoryBuffer> Buffer;
|
||||
/// The address range of the __llvm_prf_cnts section.
|
||||
uint64_t CountersSectionStart;
|
||||
uint64_t CountersSectionEnd;
|
||||
/// True if target and host have different endian orders.
|
||||
bool ShouldSwapBytes;
|
||||
};
|
||||
const std::unique_ptr<InstrProfCorrelator::Context> Ctx;
|
||||
|
||||
InstrProfCorrelator(InstrProfCorrelatorKind K, std::unique_ptr<Context> Ctx)
|
||||
: Ctx(std::move(Ctx)), Kind(K) {}
|
||||
|
||||
private:
|
||||
static llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
|
||||
get(std::unique_ptr<MemoryBuffer> Buffer);
|
||||
|
||||
const InstrProfCorrelatorKind Kind;
|
||||
};
|
||||
|
||||
/// InstrProfCorrelatorImpl - A child of InstrProfCorrelator with a template
|
||||
/// pointer type so that the ProfileData vector can be materialized.
|
||||
template <class IntPtrT>
|
||||
class InstrProfCorrelatorImpl : public InstrProfCorrelator {
|
||||
public:
|
||||
InstrProfCorrelatorImpl(std::unique_ptr<InstrProfCorrelator::Context> Ctx);
|
||||
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();
|
||||
}
|
||||
|
||||
/// Return the number of ProfileData elements.
|
||||
size_t getDataSize() const { return Data.size(); }
|
||||
|
||||
/// Return a pointer to the compressed names string that this class
|
||||
/// constructs.
|
||||
const char *getCompressedNamesPointer() const {
|
||||
return CompressedNames.c_str();
|
||||
}
|
||||
|
||||
/// Return the number of bytes in the compressed names string.
|
||||
size_t getCompressedNamesSize() const { return CompressedNames.size(); }
|
||||
|
||||
static llvm::Expected<std::unique_ptr<InstrProfCorrelatorImpl<IntPtrT>>>
|
||||
get(std::unique_ptr<InstrProfCorrelator::Context> Ctx,
|
||||
const object::ObjectFile &Obj);
|
||||
|
||||
protected:
|
||||
std::vector<RawInstrProf::ProfileData<IntPtrT>> Data;
|
||||
std::string CompressedNames;
|
||||
|
||||
Error correlateProfileData() override;
|
||||
virtual void correlateProfileDataImpl() = 0;
|
||||
|
||||
void addProbe(StringRef FunctionName, uint64_t CFGHash, IntPtrT CounterOffset,
|
||||
IntPtrT FunctionPtr, uint32_t NumCounters);
|
||||
|
||||
private:
|
||||
InstrProfCorrelatorImpl(InstrProfCorrelatorKind Kind,
|
||||
std::unique_ptr<InstrProfCorrelator::Context> Ctx)
|
||||
: InstrProfCorrelator(Kind, std::move(Ctx)){};
|
||||
std::vector<std::string> Names;
|
||||
|
||||
// Byte-swap the value if necessary.
|
||||
template <class T> T maybeSwap(T Value) const {
|
||||
return Ctx->ShouldSwapBytes ? sys::getSwappedBytes(Value) : Value;
|
||||
}
|
||||
};
|
||||
|
||||
/// DwarfInstrProfCorrelator - A child of InstrProfCorrelatorImpl that takes
|
||||
/// DWARF debug info as input to correlate profiles.
|
||||
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)),
|
||||
DICtx(std::move(DICtx)) {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<DWARFContext> DICtx;
|
||||
|
||||
/// Return the address of the object that the provided DIE symbolizes.
|
||||
llvm::Optional<uint64_t> getLocation(const DWARFDie &Die) const;
|
||||
|
||||
/// Returns true if the provided DIE symbolizes an instrumentation probe
|
||||
/// symbol.
|
||||
static bool isDIEOfProbe(const DWARFDie &Die);
|
||||
|
||||
/// Iterate over DWARF DIEs to find those that symbolize instrumentation
|
||||
/// probes and construct the ProfileData vector and CompressedNames string.
|
||||
///
|
||||
/// Here is some example DWARF for an instrumentation probe we are looking
|
||||
/// for:
|
||||
/// \code
|
||||
/// DW_TAG_subprogram
|
||||
/// DW_AT_low_pc (0x0000000000000000)
|
||||
/// DW_AT_high_pc (0x0000000000000014)
|
||||
/// DW_AT_name ("foo")
|
||||
/// DW_TAG_variable
|
||||
/// DW_AT_name ("__profc_foo")
|
||||
/// DW_AT_location (DW_OP_addr 0x0)
|
||||
/// DW_TAG_LLVM_annotation
|
||||
/// DW_AT_name ("Function Name")
|
||||
/// DW_AT_const_value ("foo")
|
||||
/// DW_TAG_LLVM_annotation
|
||||
/// DW_AT_name ("CFG Hash")
|
||||
/// DW_AT_const_value (12345678)
|
||||
/// DW_TAG_LLVM_annotation
|
||||
/// DW_AT_name ("Num Counters")
|
||||
/// DW_AT_const_value (2)
|
||||
/// NULL
|
||||
/// NULL
|
||||
/// \endcode
|
||||
void correlateProfileDataImpl() override;
|
||||
};
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_PROFILEDATA_INSTRPROFCORRELATOR_H
|
|
@ -18,7 +18,6 @@
|
|||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/IR/ProfileSummary.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/ProfileData/InstrProfCorrelator.h"
|
||||
#include "llvm/Support/Endian.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/LineIterator.h"
|
||||
|
@ -97,9 +96,6 @@ public:
|
|||
|
||||
virtual bool instrEntryBBEnabled() const = 0;
|
||||
|
||||
/// Return true if we must provide debug info to create PGO profiles.
|
||||
virtual bool useDebugInfoCorrelate() const { return false; }
|
||||
|
||||
/// Return the PGO symtab. There are three different readers:
|
||||
/// Raw, Text, and Indexed profile readers. The first two types
|
||||
/// of readers are used only by llvm-profdata tool, while the indexed
|
||||
|
@ -154,12 +150,10 @@ public:
|
|||
|
||||
/// Factory method to create an appropriately typed reader for the given
|
||||
/// instrprof file.
|
||||
static Expected<std::unique_ptr<InstrProfReader>>
|
||||
create(const Twine &Path, const InstrProfCorrelator *Correlator = nullptr);
|
||||
static Expected<std::unique_ptr<InstrProfReader>> create(const Twine &Path);
|
||||
|
||||
static Expected<std::unique_ptr<InstrProfReader>>
|
||||
create(std::unique_ptr<MemoryBuffer> Buffer,
|
||||
const InstrProfCorrelator *Correlator = nullptr);
|
||||
create(std::unique_ptr<MemoryBuffer> Buffer);
|
||||
};
|
||||
|
||||
/// Reader for the simple text based instrprof format.
|
||||
|
@ -221,9 +215,6 @@ class RawInstrProfReader : public InstrProfReader {
|
|||
private:
|
||||
/// The profile data file contents.
|
||||
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;
|
||||
bool ShouldSwapBytes;
|
||||
// The value of the version field of the raw profile data header. The lower 56
|
||||
// bits specifies the format version and the most significant 8 bits specify
|
||||
|
@ -235,7 +226,7 @@ private:
|
|||
const RawInstrProf::ProfileData<IntPtrT> *DataEnd;
|
||||
const uint64_t *CountersStart;
|
||||
const char *NamesStart;
|
||||
const char *NamesEnd;
|
||||
uint64_t NamesSize;
|
||||
// After value profile is all read, this pointer points to
|
||||
// the header of next profile data (if exists)
|
||||
const uint8_t *ValueDataStart;
|
||||
|
@ -246,11 +237,8 @@ private:
|
|||
const uint8_t *BinaryIdsStart;
|
||||
|
||||
public:
|
||||
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer,
|
||||
const InstrProfCorrelator *Correlator)
|
||||
: DataBuffer(std::move(DataBuffer)),
|
||||
Correlator(dyn_cast_or_null<const InstrProfCorrelatorImpl<IntPtrT>>(
|
||||
Correlator)) {}
|
||||
RawInstrProfReader(std::unique_ptr<MemoryBuffer> DataBuffer)
|
||||
: DataBuffer(std::move(DataBuffer)) {}
|
||||
RawInstrProfReader(const RawInstrProfReader &) = delete;
|
||||
RawInstrProfReader &operator=(const RawInstrProfReader &) = delete;
|
||||
|
||||
|
@ -271,10 +259,6 @@ public:
|
|||
return (Version & VARIANT_MASK_INSTR_ENTRY) != 0;
|
||||
}
|
||||
|
||||
bool useDebugInfoCorrelate() const override {
|
||||
return (Version & VARIANT_MASK_DBG_CORRELATE) != 0;
|
||||
}
|
||||
|
||||
InstrProfSymtab &getSymtab() override {
|
||||
assert(Symtab.get());
|
||||
return *Symtab.get();
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
add_llvm_component_library(LLVMProfileData
|
||||
GCOV.cpp
|
||||
InstrProf.cpp
|
||||
InstrProfCorrelator.cpp
|
||||
InstrProfReader.cpp
|
||||
InstrProfWriter.cpp
|
||||
ProfileSummaryBuilder.cpp
|
||||
|
@ -20,8 +19,6 @@ add_llvm_component_library(LLVMProfileData
|
|||
Core
|
||||
Support
|
||||
Demangle
|
||||
Object
|
||||
DebugInfoDWARF
|
||||
)
|
||||
|
||||
add_subdirectory(Coverage)
|
||||
|
|
|
@ -110,18 +110,6 @@ static std::string getInstrProfErrString(instrprof_error Err,
|
|||
case instrprof_error::malformed:
|
||||
OS << "malformed instrumentation profile data";
|
||||
break;
|
||||
case instrprof_error::missing_debug_info_for_correlation:
|
||||
OS << "debug info for correlation is required";
|
||||
break;
|
||||
case instrprof_error::unexpected_debug_info_for_correlation:
|
||||
OS << "debug info for correlation is not necessary";
|
||||
break;
|
||||
case instrprof_error::unable_to_correlate_profile:
|
||||
OS << "unable to correlate profile";
|
||||
break;
|
||||
case instrprof_error::unsupported_debug_format:
|
||||
OS << "unsupported debug info format (only DWARF is supported)";
|
||||
break;
|
||||
case instrprof_error::invalid_prof:
|
||||
OS << "invalid profile created. Please file a bug "
|
||||
"at: " BUG_REPORT_URL
|
||||
|
|
|
@ -1,260 +0,0 @@
|
|||
//===-- InstrProfCorrelator.cpp -------------------------------------------===//
|
||||
//
|
||||
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
||||
// See https://llvm.org/LICENSE.txt for license information.
|
||||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/ProfileData/InstrProfCorrelator.h"
|
||||
#include "llvm/Object/MachO.h"
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
|
||||
#define DEBUG_TYPE "correlator"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
/// Get the __llvm_prf_cnts section.
|
||||
Expected<object::SectionRef> getCountersSection(const object::ObjectFile &Obj) {
|
||||
for (auto &Section : Obj.sections())
|
||||
if (auto SectionName = Section.getName())
|
||||
if (SectionName.get() == INSTR_PROF_CNTS_SECT_NAME)
|
||||
return Section;
|
||||
return make_error<InstrProfError>(
|
||||
instrprof_error::unable_to_correlate_profile);
|
||||
}
|
||||
|
||||
const char *InstrProfCorrelator::FunctionNameAttributeName = "Function Name";
|
||||
const char *InstrProfCorrelator::CFGHashAttributeName = "CFG Hash";
|
||||
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);
|
||||
if (auto Err = CountersSection.takeError())
|
||||
return std::move(Err);
|
||||
auto C = std::make_unique<Context>();
|
||||
C->Buffer = std::move(Buffer);
|
||||
C->CountersSectionStart = CountersSection->getAddress();
|
||||
C->CountersSectionEnd = C->CountersSectionStart + CountersSection->getSize();
|
||||
C->ShouldSwapBytes = Obj.isLittleEndian() != sys::IsLittleEndianHost;
|
||||
return Expected<std::unique_ptr<Context>>(std::move(C));
|
||||
}
|
||||
|
||||
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 createStringError(
|
||||
std::error_code(),
|
||||
"Profile correlation using multiple objects is not yet supported");
|
||||
DebugInfoFilename = *DsymObjectsOrErr->begin();
|
||||
}
|
||||
auto BufferOrErr =
|
||||
errorOrToExpected(MemoryBuffer::getFile(DebugInfoFilename));
|
||||
if (auto Err = BufferOrErr.takeError())
|
||||
return std::move(Err);
|
||||
|
||||
return get(std::move(*BufferOrErr));
|
||||
}
|
||||
|
||||
llvm::Expected<std::unique_ptr<InstrProfCorrelator>>
|
||||
InstrProfCorrelator::get(std::unique_ptr<MemoryBuffer> Buffer) {
|
||||
auto BinOrErr = object::createBinary(*Buffer);
|
||||
if (auto Err = BinOrErr.takeError())
|
||||
return std::move(Err);
|
||||
|
||||
if (auto *Obj = dyn_cast<object::ObjectFile>(BinOrErr->get())) {
|
||||
auto CtxOrErr = Context::get(std::move(Buffer), *Obj);
|
||||
if (auto Err = CtxOrErr.takeError())
|
||||
return std::move(Err);
|
||||
auto T = Obj->makeTriple();
|
||||
if (T.isArch64Bit())
|
||||
return InstrProfCorrelatorImpl<uint64_t>::get(std::move(*CtxOrErr), *Obj);
|
||||
if (T.isArch32Bit())
|
||||
return InstrProfCorrelatorImpl<uint32_t>::get(std::move(*CtxOrErr), *Obj);
|
||||
}
|
||||
return make_error<InstrProfError>(
|
||||
instrprof_error::unable_to_correlate_profile);
|
||||
}
|
||||
|
||||
template <>
|
||||
InstrProfCorrelatorImpl<uint32_t>::InstrProfCorrelatorImpl(
|
||||
std::unique_ptr<InstrProfCorrelator::Context> Ctx)
|
||||
: InstrProfCorrelatorImpl(InstrProfCorrelatorKind::CK_32Bit,
|
||||
std::move(Ctx)) {}
|
||||
template <>
|
||||
InstrProfCorrelatorImpl<uint64_t>::InstrProfCorrelatorImpl(
|
||||
std::unique_ptr<InstrProfCorrelator::Context> Ctx)
|
||||
: InstrProfCorrelatorImpl(InstrProfCorrelatorKind::CK_64Bit,
|
||||
std::move(Ctx)) {}
|
||||
template <>
|
||||
bool InstrProfCorrelatorImpl<uint32_t>::classof(const InstrProfCorrelator *C) {
|
||||
return C->getKind() == InstrProfCorrelatorKind::CK_32Bit;
|
||||
}
|
||||
template <>
|
||||
bool InstrProfCorrelatorImpl<uint64_t>::classof(const InstrProfCorrelator *C) {
|
||||
return C->getKind() == InstrProfCorrelatorKind::CK_64Bit;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
return make_error<InstrProfError>(instrprof_error::unsupported_debug_format);
|
||||
}
|
||||
|
||||
template <class IntPtrT>
|
||||
Error InstrProfCorrelatorImpl<IntPtrT>::correlateProfileData() {
|
||||
assert(Data.empty() && CompressedNames.empty() && Names.empty());
|
||||
correlateProfileDataImpl();
|
||||
auto Result =
|
||||
collectPGOFuncNameStrings(Names, /*doCompression=*/true, CompressedNames);
|
||||
Names.clear();
|
||||
return Result;
|
||||
}
|
||||
|
||||
template <class IntPtrT>
|
||||
void InstrProfCorrelatorImpl<IntPtrT>::addProbe(StringRef FunctionName,
|
||||
uint64_t CFGHash,
|
||||
IntPtrT CounterOffset,
|
||||
IntPtrT FunctionPtr,
|
||||
uint32_t NumCounters) {
|
||||
Data.push_back({
|
||||
maybeSwap<uint64_t>(IndexedInstrProf::ComputeHash(FunctionName)),
|
||||
maybeSwap<uint64_t>(CFGHash),
|
||||
// In this mode, CounterPtr actually stores the section relative address
|
||||
// of the counter.
|
||||
maybeSwap<IntPtrT>(CounterOffset),
|
||||
maybeSwap<IntPtrT>(FunctionPtr),
|
||||
// TODO: Value profiling is not yet supported.
|
||||
/*ValuesPtr=*/maybeSwap<IntPtrT>(0),
|
||||
maybeSwap<uint32_t>(NumCounters),
|
||||
/*NumValueSites=*/{maybeSwap<uint16_t>(0), maybeSwap<uint16_t>(0)},
|
||||
});
|
||||
Names.push_back(FunctionName.str());
|
||||
}
|
||||
|
||||
template <class IntPtrT>
|
||||
llvm::Optional<uint64_t>
|
||||
DwarfInstrProfCorrelator<IntPtrT>::getLocation(const DWARFDie &Die) const {
|
||||
auto Locations = Die.getLocations(dwarf::DW_AT_location);
|
||||
if (!Locations) {
|
||||
consumeError(Locations.takeError());
|
||||
return {};
|
||||
}
|
||||
auto &DU = *Die.getDwarfUnit();
|
||||
for (auto &Location : *Locations) {
|
||||
auto AddressSize = DU.getAddressByteSize();
|
||||
DataExtractor Data(Location.Expr, DICtx->isLittleEndian(), AddressSize);
|
||||
DWARFExpression Expr(Data, AddressSize);
|
||||
for (auto &Op : Expr)
|
||||
if (Op.getCode() == dwarf::DW_OP_addr)
|
||||
return Op.getRawOperand(0);
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
template <class IntPtrT>
|
||||
bool DwarfInstrProfCorrelator<IntPtrT>::isDIEOfProbe(const DWARFDie &Die) {
|
||||
const auto &ParentDie = Die.getParent();
|
||||
if (!Die.isValid() || !ParentDie.isValid() || Die.isNULL())
|
||||
return false;
|
||||
if (Die.getTag() != dwarf::DW_TAG_variable)
|
||||
return false;
|
||||
if (!ParentDie.isSubprogramDIE())
|
||||
return false;
|
||||
if (!Die.hasChildren())
|
||||
return false;
|
||||
if (const char *Name = Die.getName(DINameKind::ShortName))
|
||||
return StringRef(Name).startswith(getInstrProfCountersVarPrefix());
|
||||
return false;
|
||||
}
|
||||
|
||||
template <class IntPtrT>
|
||||
void DwarfInstrProfCorrelator<IntPtrT>::correlateProfileDataImpl() {
|
||||
auto maybeAddProbe = [&](DWARFDie Die) {
|
||||
if (!isDIEOfProbe(Die))
|
||||
return;
|
||||
Optional<const char *> FunctionName;
|
||||
Optional<uint64_t> CFGHash;
|
||||
Optional<uint64_t> CounterPtr = getLocation(Die);
|
||||
auto FunctionPtr =
|
||||
dwarf::toAddress(Die.getParent().find(dwarf::DW_AT_low_pc));
|
||||
Optional<uint64_t> NumCounters;
|
||||
for (const DWARFDie &Child : Die.children()) {
|
||||
if (Child.getTag() != dwarf::DW_TAG_LLVM_annotation)
|
||||
continue;
|
||||
auto AnnotationFormName = Child.find(dwarf::DW_AT_name);
|
||||
auto AnnotationFormValue = Child.find(dwarf::DW_AT_const_value);
|
||||
if (!AnnotationFormName || !AnnotationFormValue)
|
||||
continue;
|
||||
auto AnnotationNameOrErr = AnnotationFormName->getAsCString();
|
||||
if (auto Err = AnnotationNameOrErr.takeError()) {
|
||||
consumeError(std::move(Err));
|
||||
continue;
|
||||
}
|
||||
StringRef AnnotationName = *AnnotationNameOrErr;
|
||||
if (AnnotationName.compare(
|
||||
InstrProfCorrelator::FunctionNameAttributeName) == 0) {
|
||||
if (auto EC =
|
||||
AnnotationFormValue->getAsCString().moveInto(FunctionName))
|
||||
consumeError(std::move(EC));
|
||||
} else if (AnnotationName.compare(
|
||||
InstrProfCorrelator::CFGHashAttributeName) == 0) {
|
||||
CFGHash = AnnotationFormValue->getAsUnsignedConstant();
|
||||
} else if (AnnotationName.compare(
|
||||
InstrProfCorrelator::NumCountersAttributeName) == 0) {
|
||||
NumCounters = AnnotationFormValue->getAsUnsignedConstant();
|
||||
}
|
||||
}
|
||||
if (!FunctionName || !CFGHash || !CounterPtr || !NumCounters) {
|
||||
LLVM_DEBUG(dbgs() << "Incomplete DIE for probe\n\tFunctionName: "
|
||||
<< FunctionName << "\n\tCFGHash: " << CFGHash
|
||||
<< "\n\tCounterPtr: " << CounterPtr
|
||||
<< "\n\tNumCounters: " << NumCounters);
|
||||
LLVM_DEBUG(Die.dump(dbgs()));
|
||||
return;
|
||||
}
|
||||
uint64_t CountersStart = this->Ctx->CountersSectionStart;
|
||||
uint64_t CountersEnd = this->Ctx->CountersSectionEnd;
|
||||
if (*CounterPtr < CountersStart || *CounterPtr >= CountersEnd) {
|
||||
LLVM_DEBUG(
|
||||
dbgs() << "CounterPtr out of range for probe\n\tFunction Name: "
|
||||
<< FunctionName << "\n\tExpected: [0x"
|
||||
<< Twine::utohexstr(CountersStart) << ", 0x"
|
||||
<< Twine::utohexstr(CountersEnd) << ")\n\tActual: 0x"
|
||||
<< Twine::utohexstr(*CounterPtr));
|
||||
LLVM_DEBUG(Die.dump(dbgs()));
|
||||
return;
|
||||
}
|
||||
if (!FunctionPtr) {
|
||||
LLVM_DEBUG(dbgs() << "Could not find address of " << *FunctionName
|
||||
<< "\n");
|
||||
LLVM_DEBUG(Die.dump(dbgs()));
|
||||
}
|
||||
this->addProbe(*FunctionName, *CFGHash, *CounterPtr - CountersStart,
|
||||
FunctionPtr.getValueOr(0), *NumCounters);
|
||||
};
|
||||
for (auto &CU : DICtx->normal_units())
|
||||
for (const auto &Entry : CU->dies())
|
||||
maybeAddProbe(DWARFDie(CU.get(), &Entry));
|
||||
for (auto &CU : DICtx->dwo_units())
|
||||
for (const auto &Entry : CU->dies())
|
||||
maybeAddProbe(DWARFDie(CU.get(), &Entry));
|
||||
}
|
|
@ -52,19 +52,16 @@ static Error initializeReader(InstrProfReader &Reader) {
|
|||
}
|
||||
|
||||
Expected<std::unique_ptr<InstrProfReader>>
|
||||
InstrProfReader::create(const Twine &Path,
|
||||
const InstrProfCorrelator *Correlator) {
|
||||
InstrProfReader::create(const Twine &Path) {
|
||||
// Set up the buffer to read.
|
||||
auto BufferOrError = setupMemoryBuffer(Path);
|
||||
if (Error E = BufferOrError.takeError())
|
||||
return std::move(E);
|
||||
return InstrProfReader::create(std::move(BufferOrError.get()), Correlator);
|
||||
return InstrProfReader::create(std::move(BufferOrError.get()));
|
||||
}
|
||||
|
||||
Expected<std::unique_ptr<InstrProfReader>>
|
||||
InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer,
|
||||
const InstrProfCorrelator *Correlator) {
|
||||
// Sanity check the buffer.
|
||||
InstrProfReader::create(std::unique_ptr<MemoryBuffer> Buffer) {
|
||||
if (uint64_t(Buffer->getBufferSize()) > std::numeric_limits<uint64_t>::max())
|
||||
return make_error<InstrProfError>(instrprof_error::too_large);
|
||||
|
||||
|
@ -76,9 +73,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));
|
||||
Result.reset(new RawInstrProfReader64(std::move(Buffer)));
|
||||
else if (RawInstrProfReader32::hasFormat(*Buffer))
|
||||
Result.reset(new RawInstrProfReader32(std::move(Buffer), Correlator));
|
||||
Result.reset(new RawInstrProfReader32(std::move(Buffer)));
|
||||
else if (TextInstrProfReader::hasFormat(*Buffer))
|
||||
Result.reset(new TextInstrProfReader(std::move(Buffer)));
|
||||
else
|
||||
|
@ -355,7 +352,7 @@ Error RawInstrProfReader<IntPtrT>::readNextHeader(const char *CurrentPos) {
|
|||
|
||||
template <class IntPtrT>
|
||||
Error RawInstrProfReader<IntPtrT>::createSymtab(InstrProfSymtab &Symtab) {
|
||||
if (Error E = Symtab.create(StringRef(NamesStart, NamesEnd - NamesStart)))
|
||||
if (Error E = Symtab.create(StringRef(NamesStart, NamesSize)))
|
||||
return error(std::move(E));
|
||||
for (const RawInstrProf::ProfileData<IntPtrT> *I = Data; I != DataEnd; ++I) {
|
||||
const IntPtrT FPtr = swap(I->FunctionPointer);
|
||||
|
@ -372,10 +369,6 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
|
|||
Version = swap(Header.Version);
|
||||
if (GET_VERSION(Version) != RawInstrProf::Version)
|
||||
return error(instrprof_error::unsupported_version);
|
||||
if (useDebugInfoCorrelate() && !Correlator)
|
||||
return error(instrprof_error::missing_debug_info_for_correlation);
|
||||
if (!useDebugInfoCorrelate() && Correlator)
|
||||
return error(instrprof_error::unexpected_debug_info_for_correlation);
|
||||
|
||||
BinaryIdsSize = swap(Header.BinaryIdsSize);
|
||||
if (BinaryIdsSize % sizeof(uint64_t))
|
||||
|
@ -387,7 +380,7 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
|
|||
auto PaddingBytesBeforeCounters = swap(Header.PaddingBytesBeforeCounters);
|
||||
auto CountersSize = swap(Header.CountersSize);
|
||||
auto PaddingBytesAfterCounters = swap(Header.PaddingBytesAfterCounters);
|
||||
auto NamesSize = swap(Header.NamesSize);
|
||||
NamesSize = swap(Header.NamesSize);
|
||||
ValueKindLast = swap(Header.ValueKindLast);
|
||||
|
||||
auto DataSizeInBytes = DataSize * sizeof(RawInstrProf::ProfileData<IntPtrT>);
|
||||
|
@ -405,27 +398,15 @@ Error RawInstrProfReader<IntPtrT>::readHeader(
|
|||
if (Start + ValueDataOffset > DataBuffer->getBufferEnd())
|
||||
return error(instrprof_error::bad_header);
|
||||
|
||||
if (Correlator) {
|
||||
// These sizes in the raw file are zero because we constructed them in the
|
||||
// Correlator.
|
||||
assert(DataSize == 0 && NamesSize == 0);
|
||||
assert(CountersDelta == 0 && NamesDelta == 0);
|
||||
Data = Correlator->getDataPointer();
|
||||
DataEnd = Data + Correlator->getDataSize();
|
||||
NamesStart = Correlator->getCompressedNamesPointer();
|
||||
NamesEnd = NamesStart + Correlator->getCompressedNamesSize();
|
||||
} else {
|
||||
Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
|
||||
Start + DataOffset);
|
||||
DataEnd = Data + DataSize;
|
||||
NamesStart = Start + NamesOffset;
|
||||
NamesEnd = NamesStart + NamesSize;
|
||||
}
|
||||
Data = reinterpret_cast<const RawInstrProf::ProfileData<IntPtrT> *>(
|
||||
Start + DataOffset);
|
||||
DataEnd = Data + DataSize;
|
||||
|
||||
// Binary ids start just after the header.
|
||||
BinaryIdsStart =
|
||||
reinterpret_cast<const uint8_t *>(&Header) + sizeof(RawInstrProf::Header);
|
||||
CountersStart = reinterpret_cast<const uint64_t *>(Start + CountersOffset);
|
||||
NamesStart = Start + NamesOffset;
|
||||
ValueDataStart = reinterpret_cast<const uint8_t *>(Start + ValueDataOffset);
|
||||
|
||||
const uint8_t *BufferEnd = (const uint8_t *)DataBuffer->getBufferEnd();
|
||||
|
@ -459,50 +440,45 @@ Error RawInstrProfReader<IntPtrT>::readRawCounts(
|
|||
if (NumCounters == 0)
|
||||
return error(instrprof_error::malformed, "number of counters is zero");
|
||||
|
||||
ArrayRef<uint64_t> RawCounts;
|
||||
if (Correlator) {
|
||||
uint64_t CounterOffset = swap<IntPtrT>(Data->CounterPtr) / sizeof(uint64_t);
|
||||
RawCounts =
|
||||
makeArrayRef<uint64_t>(CountersStart + CounterOffset, NumCounters);
|
||||
} else {
|
||||
IntPtrT CounterPtr = Data->CounterPtr;
|
||||
ptrdiff_t CounterOffset = getCounterOffset(CounterPtr);
|
||||
if (CounterOffset < 0)
|
||||
return error(
|
||||
instrprof_error::malformed,
|
||||
("counter offset " + Twine(CounterOffset) + " is negative").str());
|
||||
IntPtrT CounterPtr = Data->CounterPtr;
|
||||
auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
|
||||
ptrdiff_t MaxNumCounters = NamesStartAsCounter - CountersStart;
|
||||
|
||||
// Check bounds. Note that the counter pointer embedded in the data record
|
||||
// may itself be corrupt.
|
||||
auto *NamesStartAsCounter = reinterpret_cast<const uint64_t *>(NamesStart);
|
||||
ptrdiff_t MaxNumCounters = NamesStartAsCounter - CountersStart;
|
||||
if (MaxNumCounters < 0 || NumCounters > (uint32_t)MaxNumCounters)
|
||||
return error(instrprof_error::malformed,
|
||||
"counter pointer is out of bounds");
|
||||
// We need to compute the in-buffer counter offset from the in-memory
|
||||
// address distance. The initial CountersDelta is the in-memory address
|
||||
// difference start(__llvm_prf_cnts)-start(__llvm_prf_data), so
|
||||
// SrcData->CounterPtr - CountersDelta computes the offset into the
|
||||
// in-buffer counter section.
|
||||
if (CounterOffset > MaxNumCounters)
|
||||
return error(instrprof_error::malformed,
|
||||
("counter offset " + Twine(CounterOffset) +
|
||||
" is greater than the maximum number of counters " +
|
||||
Twine((uint32_t)MaxNumCounters))
|
||||
.str());
|
||||
// Check bounds. Note that the counter pointer embedded in the data record
|
||||
// may itself be corrupt.
|
||||
if (MaxNumCounters < 0 || NumCounters > (uint32_t)MaxNumCounters)
|
||||
return error(instrprof_error::malformed,
|
||||
"counter pointer is out of bounds");
|
||||
|
||||
if (((uint32_t)CounterOffset + NumCounters) > (uint32_t)MaxNumCounters)
|
||||
return error(instrprof_error::malformed,
|
||||
("number of counters " +
|
||||
Twine(((uint32_t)CounterOffset + NumCounters)) +
|
||||
" is greater than the maximum number of counters " +
|
||||
Twine((uint32_t)MaxNumCounters))
|
||||
.str());
|
||||
// CountersDelta decreases as we advance to the next data record.
|
||||
CountersDelta -= sizeof(*Data);
|
||||
// We need to compute the in-buffer counter offset from the in-memory address
|
||||
// distance. The initial CountersDelta is the in-memory address difference
|
||||
// start(__llvm_prf_cnts)-start(__llvm_prf_data), so SrcData->CounterPtr -
|
||||
// CountersDelta computes the offset into the in-buffer counter section.
|
||||
//
|
||||
// CountersDelta decreases as we advance to the next data record.
|
||||
ptrdiff_t CounterOffset = getCounterOffset(CounterPtr);
|
||||
CountersDelta -= sizeof(*Data);
|
||||
if (CounterOffset < 0)
|
||||
return error(
|
||||
instrprof_error::malformed,
|
||||
("counter offset " + Twine(CounterOffset) + " is negative").str());
|
||||
|
||||
RawCounts = makeArrayRef(getCounter(CounterOffset), NumCounters);
|
||||
}
|
||||
if (CounterOffset > MaxNumCounters)
|
||||
return error(instrprof_error::malformed,
|
||||
("counter offset " + Twine(CounterOffset) +
|
||||
" is greater than the maximum number of counters " +
|
||||
Twine((uint32_t)MaxNumCounters))
|
||||
.str());
|
||||
|
||||
if (((uint32_t)CounterOffset + NumCounters) > (uint32_t)MaxNumCounters)
|
||||
return error(instrprof_error::malformed,
|
||||
("number of counters " +
|
||||
Twine(((uint32_t)CounterOffset + NumCounters)) +
|
||||
" is greater than the maximum number of counters " +
|
||||
Twine((uint32_t)MaxNumCounters))
|
||||
.str());
|
||||
|
||||
auto RawCounts = makeArrayRef(getCounter(CounterOffset), NumCounters);
|
||||
|
||||
if (ShouldSwapBytes) {
|
||||
Record.Counts.clear();
|
||||
|
|
|
@ -42,7 +42,6 @@
|
|||
#include "llvm/InitializePasses.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/ProfileData/InstrProf.h"
|
||||
#include "llvm/ProfileData/InstrProfCorrelator.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
|
@ -942,15 +941,15 @@ InstrProfiling::getOrCreateRegionCounters(InstrProfIncrementInst *Inc) {
|
|||
if (auto *SP = Fn->getSubprogram()) {
|
||||
DIBuilder DB(*M, true, SP->getUnit());
|
||||
Metadata *FunctionNameAnnotation[] = {
|
||||
MDString::get(Ctx, InstrProfCorrelator::FunctionNameAttributeName),
|
||||
MDString::get(Ctx, "Function Name"),
|
||||
MDString::get(Ctx, getPGOFuncNameVarInitializer(NamePtr)),
|
||||
};
|
||||
Metadata *CFGHashAnnotation[] = {
|
||||
MDString::get(Ctx, InstrProfCorrelator::CFGHashAttributeName),
|
||||
MDString::get(Ctx, "CFG Hash"),
|
||||
ConstantAsMetadata::get(Inc->getHash()),
|
||||
};
|
||||
Metadata *NumCountersAnnotation[] = {
|
||||
MDString::get(Ctx, InstrProfCorrelator::NumCountersAttributeName),
|
||||
MDString::get(Ctx, "Num Counters"),
|
||||
ConstantAsMetadata::get(Inc->getNumCounters()),
|
||||
};
|
||||
auto Annotations = DB.getOrCreateArray({
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
set(LLVM_LINK_COMPONENTS
|
||||
Core
|
||||
ProfileData
|
||||
Object
|
||||
DebugInfoDWARF
|
||||
Support
|
||||
)
|
||||
|
||||
|
|
|
@ -13,10 +13,7 @@
|
|||
#include "llvm/ADT/SmallSet.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/DebugInfo/DWARF/DWARFContext.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/Object/Binary.h"
|
||||
#include "llvm/ProfileData/InstrProfCorrelator.h"
|
||||
#include "llvm/ProfileData/InstrProfReader.h"
|
||||
#include "llvm/ProfileData/InstrProfWriter.h"
|
||||
#include "llvm/ProfileData/ProfileCommon.h"
|
||||
|
@ -236,7 +233,6 @@ 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,
|
||||
WriterContext *WC) {
|
||||
std::unique_lock<std::mutex> CtxGuard{WC->Lock};
|
||||
|
||||
|
@ -245,7 +241,7 @@ static void loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
|
|||
// invalid outside of this packaged task.
|
||||
std::string Filename = Input.Filename;
|
||||
|
||||
auto ReaderOrErr = InstrProfReader::create(Input.Filename, Correlator);
|
||||
auto ReaderOrErr = InstrProfReader::create(Input.Filename);
|
||||
if (Error E = ReaderOrErr.takeError()) {
|
||||
// Skip the empty profiles by returning sliently.
|
||||
instrprof_error IPE = InstrProfError::take(std::move(E));
|
||||
|
@ -329,7 +325,6 @@ static void writeInstrProfile(StringRef OutputFilename,
|
|||
}
|
||||
|
||||
static void mergeInstrProfile(const WeightedFileVector &Inputs,
|
||||
StringRef DebugInfoFilename,
|
||||
SymbolRemapper *Remapper,
|
||||
StringRef OutputFilename,
|
||||
ProfileFormat OutputFormat, bool OutputSparse,
|
||||
|
@ -338,15 +333,6 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
|
|||
OutputFormat != PF_Ext_Binary && OutputFormat != PF_Text)
|
||||
exitWithError("unknown format is specified");
|
||||
|
||||
std::unique_ptr<InstrProfCorrelator> Correlator;
|
||||
if (!DebugInfoFilename.empty()) {
|
||||
if (auto Err =
|
||||
InstrProfCorrelator::get(DebugInfoFilename).moveInto(Correlator))
|
||||
exitWithError(std::move(Err), DebugInfoFilename);
|
||||
if (auto Err = Correlator->correlateProfileData())
|
||||
exitWithError(std::move(Err), DebugInfoFilename);
|
||||
}
|
||||
|
||||
std::mutex ErrorLock;
|
||||
SmallSet<instrprof_error, 4> WriterErrorCodes;
|
||||
|
||||
|
@ -366,15 +352,14 @@ static void mergeInstrProfile(const WeightedFileVector &Inputs,
|
|||
|
||||
if (NumThreads == 1) {
|
||||
for (const auto &Input : Inputs)
|
||||
loadInput(Input, Remapper, Correlator.get(), Contexts[0].get());
|
||||
loadInput(Input, Remapper, Contexts[0].get());
|
||||
} else {
|
||||
ThreadPool Pool(hardware_concurrency(NumThreads));
|
||||
|
||||
// Load the inputs in parallel (N/NumThreads serial steps).
|
||||
unsigned Ctx = 0;
|
||||
for (const auto &Input : Inputs) {
|
||||
Pool.async(loadInput, Input, Remapper, Correlator.get(),
|
||||
Contexts[Ctx].get());
|
||||
Pool.async(loadInput, Input, Remapper, Contexts[Ctx].get());
|
||||
Ctx = (Ctx + 1) % NumThreads;
|
||||
}
|
||||
Pool.wait();
|
||||
|
@ -590,7 +575,7 @@ static void supplementInstrProfile(
|
|||
SmallSet<instrprof_error, 4> WriterErrorCodes;
|
||||
auto WC = std::make_unique<WriterContext>(OutputSparse, ErrorLock,
|
||||
WriterErrorCodes);
|
||||
loadInput(Inputs[0], nullptr, nullptr, WC.get());
|
||||
loadInput(Inputs[0], nullptr, WC.get());
|
||||
if (WC->Errors.size() > 0)
|
||||
exitWithError(std::move(WC->Errors[0].first), InstrFilename);
|
||||
|
||||
|
@ -967,9 +952,6 @@ static int merge_main(int argc, const char *argv[]) {
|
|||
cl::opt<bool> GenCSNestedProfile(
|
||||
"gen-cs-nested-profile", cl::Hidden, cl::init(false),
|
||||
cl::desc("Generate nested function profiles for CSSPGO"));
|
||||
cl::opt<std::string> DebugInfoFilename(
|
||||
"debug-info", cl::init(""), cl::Hidden,
|
||||
cl::desc("Use the provided debug info to correlate the raw profile."));
|
||||
|
||||
cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n");
|
||||
|
||||
|
@ -1010,9 +992,8 @@ static int merge_main(int argc, const char *argv[]) {
|
|||
}
|
||||
|
||||
if (ProfileKind == instr)
|
||||
mergeInstrProfile(WeightedInputs, DebugInfoFilename, Remapper.get(),
|
||||
OutputFilename, OutputFormat, OutputSparse, NumThreads,
|
||||
FailureMode);
|
||||
mergeInstrProfile(WeightedInputs, Remapper.get(), OutputFilename,
|
||||
OutputFormat, OutputSparse, NumThreads, FailureMode);
|
||||
else
|
||||
mergeSampleProfile(WeightedInputs, Remapper.get(), OutputFilename,
|
||||
OutputFormat, ProfileSymbolListFile, CompressAllSections,
|
||||
|
@ -1043,7 +1024,7 @@ static void overlapInstrProfile(const std::string &BaseFilename,
|
|||
OS << "Sum of edge counts for profile " << TestFilename << " is 0.\n";
|
||||
exit(0);
|
||||
}
|
||||
loadInput(WeightedInput, nullptr, nullptr, &Context);
|
||||
loadInput(WeightedInput, nullptr, &Context);
|
||||
overlapInput(BaseFilename, TestFilename, &Context, Overlap, FuncFilter, OS,
|
||||
IsCS);
|
||||
Overlap.dump(OS);
|
||||
|
|
Loading…
Reference in New Issue