llvm/llvm/tools/llvm-profdata/llvm-profdata.cpp

//===- llvm-profdata.cpp - LLVM profile data tool -------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// llvm-profdata merges .profdata files.
//
//===----------------------------------------------------------------------===//

#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Debuginfod/HTTPClient.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/MemProf.h"
#include "llvm/ProfileData/MemProfReader.h"
#include "llvm/ProfileData/ProfileCommon.h"
#include "llvm/ProfileData/SampleProfReader.h"
#include "llvm/ProfileData/SampleProfWriter.h"
#include "llvm/Support/BalancedPartitioning.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Discriminator.h"
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/LLVMDriver.h"
#include "llvm/Support/MD5.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Regex.h"
#include "llvm/Support/ThreadPool.h"
#include "llvm/Support/Threading.h"
#include "llvm/Support/VirtualFileSystem.h"
#include "llvm/Support/WithColor.h"
#include "llvm/Support/raw_ostream.h"
#include <algorithm>
#include <cmath>
#include <optional>
#include <queue>

usingnamespacellvm;
ProfCorrelatorKind;

// https://llvm.org/docs/CommandGuide/llvm-profdata.html has documentations
// on each subcommand.
cl::SubCommand ShowSubcommand(
    "show",
    "Takes a profile data file and displays the profiles. See detailed "
    "documentation in "
    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-show");
cl::SubCommand OrderSubcommand(
    "order",
    "Reads temporal profiling traces from a profile and outputs a function "
    "order that reduces the number of page faults for those traces. See "
    "detailed documentation in "
    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-order");
cl::SubCommand OverlapSubcommand(
    "overlap",
    "Computes and displays the overlap between two profiles. See detailed "
    "documentation in "
    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-overlap");
cl::SubCommand MergeSubcommand(
    "merge",
    "Takes several profiles and merge them together. See detailed "
    "documentation in "
    "https://llvm.org/docs/CommandGuide/llvm-profdata.html#profdata-merge");

namespace {
enum ProfileKinds {};
enum FailureMode {};

enum ProfileFormat {};

enum class ShowFormat {};
} // namespace

// Common options.
cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
                                    cl::init("-"), cl::desc("Output file"),
                                    cl::sub(ShowSubcommand),
                                    cl::sub(OrderSubcommand),
                                    cl::sub(OverlapSubcommand),
                                    cl::sub(MergeSubcommand));
// NOTE: cl::alias must not have cl::sub(), since aliased option's cl::sub()
// will be used. llvm::cl::alias::done() method asserts this condition.
cl::alias OutputFilenameA("o", cl::desc("Alias for --output"),
                          cl::aliasopt(OutputFilename));

// Options common to at least two commands.
cl::opt<ProfileKinds> ProfileKind(
    cl::desc("Profile kind:"), cl::sub(MergeSubcommand),
    cl::sub(OverlapSubcommand), cl::init(instr),
    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
               clEnumVal(sample, "Sample profile")));
cl::opt<std::string> Filename(cl::Positional, cl::desc("<profdata-file>"),
                              cl::sub(ShowSubcommand),
                              cl::sub(OrderSubcommand));
cl::opt<unsigned> MaxDbgCorrelationWarnings(
    "max-debug-info-correlation-warnings",
    cl::desc("The maximum number of warnings to emit when correlating "
             "profile from debug info (0 = no limit)"),
    cl::sub(MergeSubcommand), cl::sub(ShowSubcommand), cl::init(5));
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::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> DebugFileDirectory(
    "debug-file-directory",
    cl::desc("Directories to search for object files by build ID"));
cl::opt<bool> DebugInfod("debuginfod", cl::init(false), cl::Hidden,
                         cl::sub(MergeSubcommand),
                         cl::desc("Enable debuginfod"));
cl::opt<ProfCorrelatorKind> BIDFetcherProfileCorrelate(
    "correlate",
    cl::desc("Use debug-info or binary correlation to correlate profiles with "
             "build id fetcher"),
    cl::init(InstrProfCorrelator::NONE),
    cl::values(clEnumValN(InstrProfCorrelator::NONE, "",
                          "No profile correlation"),
               clEnumValN(InstrProfCorrelator::DEBUG_INFO, "debug-info",
                          "Use debug info to correlate"),
               clEnumValN(InstrProfCorrelator::BINARY, "binary",
                          "Use binary to correlate")));
cl::opt<std::string> FuncNameFilter(
    "function",
    cl::desc("Only functions matching the filter are shown in the output. For "
             "overlapping CSSPGO, this takes a function name with calling "
             "context."),
    cl::sub(ShowSubcommand), cl::sub(OverlapSubcommand),
    cl::sub(MergeSubcommand));

// TODO: Consider creating a template class (e.g., MergeOption, ShowOption) to
// factor out the common cl::sub in cl::opt constructor for subcommand-specific
// options.

// Options specific to merge subcommand.
cl::list<std::string> InputFilenames(cl::Positional, cl::sub(MergeSubcommand),
                                     cl::desc("<filename...>"));
cl::list<std::string> WeightedInputFilenames("weighted-input",
                                             cl::sub(MergeSubcommand),
                                             cl::desc("<weight>,<filename>"));
cl::opt<ProfileFormat> OutputFormat(
    cl::desc("Format of output profile"), cl::sub(MergeSubcommand),
    cl::init(PF_Ext_Binary),
    cl::values(clEnumValN(PF_Binary, "binary", "Binary encoding"),
               clEnumValN(PF_Ext_Binary, "extbinary",
                          "Extensible binary encoding "
                          "(default)"),
               clEnumValN(PF_Text, "text", "Text encoding"),
               clEnumValN(PF_GCC, "gcc",
                          "GCC encoding (only meaningful for -sample)")));
cl::opt<std::string>
    InputFilenamesFile("input-files", cl::init(""), cl::sub(MergeSubcommand),
                       cl::desc("Path to file containing newline-separated "
                                "[<weight>,]<filename> entries"));
cl::alias InputFilenamesFileA("f", cl::desc("Alias for --input-files"),
                              cl::aliasopt(InputFilenamesFile));
cl::opt<bool> DumpInputFileList(
    "dump-input-file-list", cl::init(false), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("Dump the list of input files and their weights, then exit"));
cl::opt<std::string> RemappingFile("remapping-file", cl::value_desc("file"),
                                   cl::sub(MergeSubcommand),
                                   cl::desc("Symbol remapping file"));
cl::alias RemappingFileA("r", cl::desc("Alias for --remapping-file"),
                         cl::aliasopt(RemappingFile));
cl::opt<bool>
    UseMD5("use-md5", cl::init(false), cl::Hidden,
           cl::desc("Choose to use MD5 to represent string in name table (only "
                    "meaningful for -extbinary)"),
           cl::sub(MergeSubcommand));
cl::opt<bool> CompressAllSections(
    "compress-all-sections", cl::init(false), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("Compress all sections when writing the profile (only "
             "meaningful for -extbinary)"));
cl::opt<bool> SampleMergeColdContext(
    "sample-merge-cold-context", cl::init(false), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc(
        "Merge context sample profiles whose count is below cold threshold"));
cl::opt<bool> SampleTrimColdContext(
    "sample-trim-cold-context", cl::init(false), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc(
        "Trim context sample profiles whose count is below cold threshold"));
cl::opt<uint32_t> SampleColdContextFrameDepth(
    "sample-frame-depth-for-cold-context", cl::init(1),
    cl::sub(MergeSubcommand),
    cl::desc("Keep the last K frames while merging cold profile. 1 means the "
             "context-less base profile"));
cl::opt<size_t> OutputSizeLimit(
    "output-size-limit", cl::init(0), cl::Hidden, cl::sub(MergeSubcommand),
    cl::desc("Trim cold functions until profile size is below specified "
             "limit in bytes. This uses a heursitic and functions may be "
             "excessively trimmed"));
cl::opt<bool> GenPartialProfile(
    "gen-partial-profile", cl::init(false), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("Generate a partial profile (only meaningful for -extbinary)"));
cl::opt<bool> SplitLayout(
    "split-layout", cl::init(false), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("Split the profile to two sections with one containing sample "
             "profiles with inlined functions and the other without (only "
             "meaningful for -extbinary)"));
cl::opt<std::string> SupplInstrWithSample(
    "supplement-instr-with-sample", cl::init(""), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("Supplement an instr profile with sample profile, to correct "
             "the profile unrepresentativeness issue. The sample "
             "profile is the input of the flag. Output will be in instr "
             "format (The flag only works with -instr)"));
cl::opt<float> ZeroCounterThreshold(
    "zero-counter-threshold", cl::init(0.7), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("For the function which is cold in instr profile but hot in "
             "sample profile, if the ratio of the number of zero counters "
             "divided by the total number of counters is above the "
             "threshold, the profile of the function will be regarded as "
             "being harmful for performance and will be dropped."));
cl::opt<unsigned> SupplMinSizeThreshold(
    "suppl-min-size-threshold", cl::init(10), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("If the size of a function is smaller than the threshold, "
             "assume it can be inlined by PGO early inliner and it won't "
             "be adjusted based on sample profile."));
cl::opt<unsigned> InstrProfColdThreshold(
    "instr-prof-cold-threshold", cl::init(0), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("User specified cold threshold for instr profile which will "
             "override the cold threshold got from profile summary. "));
// WARNING: This reservoir size value is propagated to any input indexed
// profiles for simplicity. Changing this value between invocations could
// result in sample bias.
cl::opt<uint64_t> TemporalProfTraceReservoirSize(
    "temporal-profile-trace-reservoir-size", cl::init(100),
    cl::sub(MergeSubcommand),
    cl::desc("The maximum number of stored temporal profile traces (default: "
             "100)"));
cl::opt<uint64_t> TemporalProfMaxTraceLength(
    "temporal-profile-max-trace-length", cl::init(10000),
    cl::sub(MergeSubcommand),
    cl::desc("The maximum length of a single temporal profile trace "
             "(default: 10000)"));
cl::opt<std::string> FuncNameNegativeFilter(
    "no-function", cl::init(""),
    cl::sub(MergeSubcommand),
    cl::desc("Exclude functions matching the filter from the output."));

cl::opt<FailureMode>
    FailMode("failure-mode", cl::init(failIfAnyAreInvalid),
             cl::desc("Failure mode:"), cl::sub(MergeSubcommand),
             cl::values(clEnumValN(warnOnly, "warn",
                                   "Do not fail and just print warnings."),
                        clEnumValN(failIfAnyAreInvalid, "any",
                                   "Fail if any profile is invalid."),
                        clEnumValN(failIfAllAreInvalid, "all",
                                   "Fail only if all profiles are invalid.")));

cl::opt<bool> OutputSparse(
    "sparse", cl::init(false), cl::sub(MergeSubcommand),
    cl::desc("Generate a sparse profile (only meaningful for -instr)"));
cl::opt<unsigned> NumThreads(
    "num-threads", cl::init(0), cl::sub(MergeSubcommand),
    cl::desc("Number of merge threads to use (default: autodetect)"));
cl::alias NumThreadsA("j", cl::desc("Alias for --num-threads"),
                      cl::aliasopt(NumThreads));

cl::opt<std::string> ProfileSymbolListFile(
    "prof-sym-list", cl::init(""), cl::sub(MergeSubcommand),
    cl::desc("Path to file containing the list of function symbols "
             "used to populate profile symbol list"));

cl::opt<SampleProfileLayout> ProfileLayout(
    "convert-sample-profile-layout",
    cl::desc("Convert the generated profile to a profile with a new layout"),
    cl::sub(MergeSubcommand), cl::init(SPL_None),
    cl::values(
        clEnumValN(SPL_Nest, "nest",
                   "Nested profile, the input should be CS flat profile"),
        clEnumValN(SPL_Flat, "flat",
                   "Profile with nested inlinee flatten out")));

cl::opt<bool> DropProfileSymbolList(
    "drop-profile-symbol-list", cl::init(false), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("Drop the profile symbol list when merging AutoFDO profiles "
             "(only meaningful for -sample)"));

cl::opt<bool> KeepVTableSymbols(
    "keep-vtable-symbols", cl::init(false), cl::Hidden,
    cl::sub(MergeSubcommand),
    cl::desc("If true, keep the vtable symbols in indexed profiles"));

// Temporary support for writing the previous version of the format, to enable
// some forward compatibility.
// TODO: Consider enabling this with future version changes as well, to ease
// deployment of newer versions of llvm-profdata.
cl::opt<bool> DoWritePrevVersion(
    "write-prev-version", cl::init(false), cl::Hidden,
    cl::desc("Write the previous version of indexed format, to enable "
             "some forward compatibility."));

cl::opt<memprof::IndexedVersion> MemProfVersionRequested(
    "memprof-version", cl::Hidden, cl::sub(MergeSubcommand),
    cl::desc("Specify the version of the memprof format to use"),
    cl::init(memprof::Version0),
    cl::values(clEnumValN(memprof::Version0, "0", "version 0"),
               clEnumValN(memprof::Version1, "1", "version 1"),
               clEnumValN(memprof::Version2, "2", "version 2"),
               clEnumValN(memprof::Version3, "3", "version 3")));

cl::opt<bool> MemProfFullSchema(
    "memprof-full-schema", cl::Hidden, cl::sub(MergeSubcommand),
    cl::desc("Use the full schema for serialization"), cl::init(false));

// Options specific to overlap subcommand.
cl::opt<std::string> BaseFilename(cl::Positional, cl::Required,
                                  cl::desc("<base profile file>"),
                                  cl::sub(OverlapSubcommand));
cl::opt<std::string> TestFilename(cl::Positional, cl::Required,
                                  cl::desc("<test profile file>"),
                                  cl::sub(OverlapSubcommand));

cl::opt<unsigned long long> SimilarityCutoff(
    "similarity-cutoff", cl::init(0),
    cl::desc("For sample profiles, list function names (with calling context "
             "for csspgo) for overlapped functions "
             "with similarities below the cutoff (percentage times 10000)."),
    cl::sub(OverlapSubcommand));

cl::opt<bool> IsCS(
    "cs", cl::init(false),
    cl::desc("For context sensitive PGO counts. Does not work with CSSPGO."),
    cl::sub(OverlapSubcommand));

cl::opt<unsigned long long> OverlapValueCutoff(
    "value-cutoff", cl::init(-1),
    cl::desc(
        "Function level overlap information for every function (with calling "
        "context for csspgo) in test "
        "profile with max count value greater then the parameter value"),
    cl::sub(OverlapSubcommand));

// Options specific to show subcommand.
cl::opt<bool> ShowCounts("counts", cl::init(false),
                         cl::desc("Show counter values for shown functions"),
                         cl::sub(ShowSubcommand));
cl::opt<ShowFormat>
    SFormat("show-format", cl::init(ShowFormat::Text),
            cl::desc("Emit output in the selected format if supported"),
            cl::sub(ShowSubcommand),
            cl::values(clEnumValN(ShowFormat::Text, "text",
                                  "emit normal text output (default)"),
                       clEnumValN(ShowFormat::Json, "json", "emit JSON"),
                       clEnumValN(ShowFormat::Yaml, "yaml", "emit YAML")));
// TODO: Consider replacing this with `--show-format=text-encoding`.
cl::opt<bool>
    TextFormat("text", cl::init(false),
               cl::desc("Show instr profile data in text dump format"),
               cl::sub(ShowSubcommand));
cl::opt<bool>
    JsonFormat("json",
               cl::desc("Show sample profile data in the JSON format "
                        "(deprecated, please use --show-format=json)"),
               cl::sub(ShowSubcommand));
cl::opt<bool> ShowIndirectCallTargets(
    "ic-targets", cl::init(false),
    cl::desc("Show indirect call site target values for shown functions"),
    cl::sub(ShowSubcommand));
cl::opt<bool> ShowVTables("show-vtables", cl::init(false),
                          cl::desc("Show vtable names for shown functions"),
                          cl::sub(ShowSubcommand));
cl::opt<bool> ShowMemOPSizes(
    "memop-sizes", cl::init(false),
    cl::desc("Show the profiled sizes of the memory intrinsic calls "
             "for shown functions"),
    cl::sub(ShowSubcommand));
cl::opt<bool> ShowDetailedSummary("detailed-summary", cl::init(false),
                                  cl::desc("Show detailed profile summary"),
                                  cl::sub(ShowSubcommand));
cl::list<uint32_t> DetailedSummaryCutoffs(
    cl::CommaSeparated, "detailed-summary-cutoffs",
    cl::desc(
        "Cutoff percentages (times 10000) for generating detailed summary"),
    cl::value_desc("800000,901000,999999"), cl::sub(ShowSubcommand));
cl::opt<bool>
    ShowHotFuncList("hot-func-list", cl::init(false),
                    cl::desc("Show profile summary of a list of hot functions"),
                    cl::sub(ShowSubcommand));
cl::opt<bool> ShowAllFunctions("all-functions", cl::init(false),
                               cl::desc("Details for each and every function"),
                               cl::sub(ShowSubcommand));
cl::opt<bool> ShowCS("showcs", cl::init(false),
                     cl::desc("Show context sensitive counts"),
                     cl::sub(ShowSubcommand));
cl::opt<ProfileKinds> ShowProfileKind(
    cl::desc("Profile kind supported by show:"), cl::sub(ShowSubcommand),
    cl::init(instr),
    cl::values(clEnumVal(instr, "Instrumentation profile (default)"),
               clEnumVal(sample, "Sample profile"),
               clEnumVal(memory, "MemProf memory access profile")));
cl::opt<uint32_t> TopNFunctions(
    "topn", cl::init(0),
    cl::desc("Show the list of functions with the largest internal counts"),
    cl::sub(ShowSubcommand));
cl::opt<uint32_t> ShowValueCutoff(
    "value-cutoff", cl::init(0),
    cl::desc("Set the count value cutoff. Functions with the maximum count "
             "less than this value will not be printed out. (Default is 0)"),
    cl::sub(ShowSubcommand));
cl::opt<bool> OnlyListBelow(
    "list-below-cutoff", cl::init(false),
    cl::desc("Only output names of functions whose max count values are "
             "below the cutoff value"),
    cl::sub(ShowSubcommand));
cl::opt<bool> ShowProfileSymbolList(
    "show-prof-sym-list", cl::init(false),
    cl::desc("Show profile symbol list if it exists in the profile. "),
    cl::sub(ShowSubcommand));
cl::opt<bool> ShowSectionInfoOnly(
    "show-sec-info-only", cl::init(false),
    cl::desc("Show the information of each section in the sample profile. "
             "The flag is only usable when the sample profile is in "
             "extbinary format"),
    cl::sub(ShowSubcommand));
cl::opt<bool> ShowBinaryIds("binary-ids", cl::init(false),
                            cl::desc("Show binary ids in the profile. "),
                            cl::sub(ShowSubcommand));
cl::opt<bool> ShowTemporalProfTraces(
    "temporal-profile-traces",
    cl::desc("Show temporal profile traces in the profile."),
    cl::sub(ShowSubcommand));

cl::opt<bool>
    ShowCovered("covered", cl::init(false),
                cl::desc("Show only the functions that have been executed."),
                cl::sub(ShowSubcommand));

cl::opt<bool> ShowProfileVersion("profile-version", cl::init(false),
                                 cl::desc("Show profile version. "),
                                 cl::sub(ShowSubcommand));

// Options specific to order subcommand.
cl::opt<unsigned>
    NumTestTraces("num-test-traces", cl::init(0),
                  cl::desc("Keep aside the last <num-test-traces> traces in "
                           "the profile when computing the function order and "
                           "instead use them to evaluate that order"),
                  cl::sub(OrderSubcommand));

// We use this string to indicate that there are
// multiple static functions map to the same name.
const std::string DuplicateNameStr =;

static void warn(Twine Message, StringRef Whence = "", StringRef Hint = "") {}

static void warn(Error E, StringRef Whence = "") {}

static void exitWithError(Twine Message, StringRef Whence = "",
                          StringRef Hint = "") {}

static void exitWithError(Error E, StringRef Whence = "") {}

static void exitWithErrorCode(std::error_code EC, StringRef Whence = "") {}

static void warnOrExitGivenError(FailureMode FailMode, std::error_code EC,
                                 StringRef Whence = "") {}

static void handleMergeWriterError(Error E, StringRef WhenceFile = "",
                                   StringRef WhenceFunction = "",
                                   bool ShowHint = true) {}

namespace {
/// A remapper from original symbol names to new symbol names based on a file
/// containing a list of mappings from old name to new name.
class SymbolRemapper {};
}

struct WeightedFile {};
WeightedFileVector;

/// Keep track of merged data and reported errors.
struct WriterContext {};

/// Computer the overlap b/w profile BaseFilename and TestFileName,
/// and store the program level result to Overlap.
static void overlapInput(const std::string &BaseFilename,
                         const std::string &TestFilename, WriterContext *WC,
                         OverlapStats &Overlap,
                         const OverlapFuncFilters &FuncFilter,
                         raw_fd_ostream &OS, bool IsCS) {}

/// Load an input into a writer context.
static void
loadInput(const WeightedFile &Input, SymbolRemapper *Remapper,
          const InstrProfCorrelator *Correlator, const StringRef ProfiledBinary,
          WriterContext *WC, const object::BuildIDFetcher *BIDFetcher = nullptr,
          const ProfCorrelatorKind *BIDFetcherCorrelatorKind = nullptr) {}

/// Merge the \p Src writer context into \p Dst.
static void mergeWriterContexts(WriterContext *Dst, WriterContext *Src) {}

static StringRef
getFuncName(const StringMap<InstrProfWriter::ProfilingData>::value_type &Val) {}

static std::string
getFuncName(const SampleProfileMap::value_type &Val) {}

template <typename T>
static void filterFunctions(T &ProfileMap) {}

static void writeInstrProfile(StringRef OutputFilename,
                              ProfileFormat OutputFormat,
                              InstrProfWriter &Writer) {}

static void mergeInstrProfile(const WeightedFileVector &Inputs,
                              SymbolRemapper *Remapper,
                              int MaxDbgCorrelationWarnings,
                              const StringRef ProfiledBinary) {}

/// The profile entry for a function in instrumentation profile.
struct InstrProfileEntry {};

InstrProfileEntry::InstrProfileEntry(InstrProfRecord *Record) {}

/// Either set all the counters in the instr profile entry \p IFE to
/// -1 / -2 /in order to drop the profile or scale up the
/// counters in \p IFP to be above hot / cold threshold. We use
/// the ratio of zero counters in the profile of a function to
/// decide the profile is helpful or harmful for performance,
/// and to choose whether to scale up or drop it.
static void updateInstrProfileEntry(InstrProfileEntry &IFE, bool SetToHot,
                                    uint64_t HotInstrThreshold,
                                    uint64_t ColdInstrThreshold,
                                    float ZeroCounterThreshold) {}

const uint64_t ColdPercentileIdx =;
const uint64_t HotPercentileIdx =;

FSDiscriminatorPass;

// Internal options to set FSDiscriminatorPass. Used in merge and show
// commands.
static cl::opt<FSDiscriminatorPass> FSDiscriminatorPassOption(
    "fs-discriminator-pass", cl::init(PassLast), cl::Hidden,
    cl::desc("Zero out the discriminator bits for the FS discrimiantor "
             "pass beyond this value. The enum values are defined in "
             "Support/Discriminator.h"),
    cl::values(clEnumVal(Base, "Use base discriminators only"),
               clEnumVal(Pass1, "Use base and pass 1 discriminators"),
               clEnumVal(Pass2, "Use base and pass 1-2 discriminators"),
               clEnumVal(Pass3, "Use base and pass 1-3 discriminators"),
               clEnumVal(PassLast, "Use all discriminator bits (default)")));

static unsigned getDiscriminatorMask() {}

/// Adjust the instr profile in \p WC based on the sample profile in
/// \p Reader.
static void
adjustInstrProfile(std::unique_ptr<WriterContext> &WC,
                   std::unique_ptr<sampleprof::SampleProfileReader> &Reader,
                   unsigned SupplMinSizeThreshold, float ZeroCounterThreshold,
                   unsigned InstrProfColdThreshold) {}

/// The main function to supplement instr profile with sample profile.
/// \Inputs contains the instr profile. \p SampleFilename specifies the
/// sample profile. \p OutputFilename specifies the output profile name.
/// \p OutputFormat specifies the output profile format. \p OutputSparse
/// specifies whether to generate sparse profile. \p SupplMinSizeThreshold
/// specifies the minimal size for the functions whose profile will be
/// adjusted. \p ZeroCounterThreshold is the threshold to check whether
/// a function contains too many zero counters and whether its profile
/// should be dropped. \p InstrProfColdThreshold is the user specified
/// cold threshold which will override the cold threshold got from the
/// instr profile summary.
static void supplementInstrProfile(const WeightedFileVector &Inputs,
                                   StringRef SampleFilename, bool OutputSparse,
                                   unsigned SupplMinSizeThreshold,
                                   float ZeroCounterThreshold,
                                   unsigned InstrProfColdThreshold) {}

/// Make a copy of the given function samples with all symbol names remapped
/// by the provided symbol remapper.
static sampleprof::FunctionSamples
remapSamples(const sampleprof::FunctionSamples &Samples,
             SymbolRemapper &Remapper, sampleprof_error &Error) {}

static sampleprof::SampleProfileFormat FormatMap[] =;

static std::unique_ptr<MemoryBuffer>
getInputFileBuf(const StringRef &InputFile) {}

static void populateProfileSymbolList(MemoryBuffer *Buffer,
                                      sampleprof::ProfileSymbolList &PSL) {}

static void handleExtBinaryWriter(sampleprof::SampleProfileWriter &Writer,
                                  ProfileFormat OutputFormat,
                                  MemoryBuffer *Buffer,
                                  sampleprof::ProfileSymbolList &WriterList,
                                  bool CompressAllSections, bool UseMD5,
                                  bool GenPartialProfile) {}

static void mergeSampleProfile(const WeightedFileVector &Inputs,
                               SymbolRemapper *Remapper,
                               StringRef ProfileSymbolListFile,
                               size_t OutputSizeLimit) {}

static WeightedFile parseWeightedFile(const StringRef &WeightedFilename) {}

static void addWeightedInput(WeightedFileVector &WNI, const WeightedFile &WF) {}

static void parseInputFilenamesFile(MemoryBuffer *Buffer,
                                    WeightedFileVector &WFV) {}

static int merge_main(StringRef ProgName) {}

/// Computer the overlap b/w profile BaseFilename and profile TestFilename.
static void overlapInstrProfile(const std::string &BaseFilename,
                                const std::string &TestFilename,
                                const OverlapFuncFilters &FuncFilter,
                                raw_fd_ostream &OS, bool IsCS) {}

namespace {
struct SampleOverlapStats {};
} // end anonymous namespace

namespace {
struct FuncSampleStats {};
} // end anonymous namespace

namespace {
enum MatchStatus {};

// Class for updating merging steps for two sorted maps. The class should be
// instantiated with a map iterator type.
template <class T> class MatchStep {};
} // end anonymous namespace

template <class T> void MatchStep<T>::updateOneStep() {}

// Return the sum of line/block samples, the max line/block sample, and the
// number of line/block samples above the given threshold in a function
// including its inlinees.
static void getFuncSampleStats(const sampleprof::FunctionSamples &Func,
                               FuncSampleStats &FuncStats,
                               uint64_t HotThreshold) {}

/// Predicate that determines if a function is hot with a given threshold. We
/// keep it separate from its callsites for possible extension in the future.
static bool isFunctionHot(const FuncSampleStats &FuncStats,
                          uint64_t HotThreshold) {}

namespace {
class SampleOverlapAggregator {};
} // end anonymous namespace

bool SampleOverlapAggregator::detectZeroSampleProfile(
    raw_fd_ostream &OS) const {}

double SampleOverlapAggregator::computeBlockSimilarity(
    uint64_t BaseSample, uint64_t TestSample,
    const SampleOverlapStats &FuncOverlap) const {}

void SampleOverlapAggregator::updateHotBlockOverlap(uint64_t BaseSample,
                                                    uint64_t TestSample,
                                                    uint64_t HotBlockCount) {}

void SampleOverlapAggregator::getHotFunctions(
    const FuncSampleStatsMap &ProfStats, FuncSampleStatsMap &HotFunc,
    uint64_t HotThreshold) const {}

void SampleOverlapAggregator::computeHotFuncOverlap() {}

void SampleOverlapAggregator::updateOverlapStatsForFunction(
    uint64_t BaseSample, uint64_t TestSample, uint64_t HotBlockCount,
    SampleOverlapStats &FuncOverlap, double &Difference, MatchStatus Status) {}

void SampleOverlapAggregator::updateForUnmatchedCallee(
    const sampleprof::FunctionSamples &Func, SampleOverlapStats &FuncOverlap,
    double &Difference, MatchStatus Status) {}

double SampleOverlapAggregator::computeSampleFunctionInternalOverlap(
    const sampleprof::FunctionSamples &BaseFunc,
    const sampleprof::FunctionSamples &TestFunc,
    SampleOverlapStats &FuncOverlap) {}

double SampleOverlapAggregator::weightForFuncSimilarity(
    double FuncInternalSimilarity, uint64_t BaseFuncSample,
    uint64_t TestFuncSample) const {}

double
SampleOverlapAggregator::weightByImportance(double FuncSimilarity,
                                            uint64_t BaseFuncSample,
                                            uint64_t TestFuncSample) const {}

double SampleOverlapAggregator::computeSampleFunctionOverlap(
    const sampleprof::FunctionSamples *BaseFunc,
    const sampleprof::FunctionSamples *TestFunc,
    SampleOverlapStats *FuncOverlap, uint64_t BaseFuncSample,
    uint64_t TestFuncSample) {}

void SampleOverlapAggregator::computeSampleProfileOverlap(raw_fd_ostream &OS) {}

void SampleOverlapAggregator::initializeSampleProfileOverlap() {}

void SampleOverlapAggregator::dumpFuncSimilarity(raw_fd_ostream &OS) const {}

void SampleOverlapAggregator::dumpProgramSummary(raw_fd_ostream &OS) const {}

void SampleOverlapAggregator::dumpHotFuncAndBlockOverlap(
    raw_fd_ostream &OS) const {}

std::error_code SampleOverlapAggregator::loadProfiles() {}

void overlapSampleProfile(const std::string &BaseFilename,
                          const std::string &TestFilename,
                          const OverlapFuncFilters &FuncFilter,
                          uint64_t SimilarityCutoff, raw_fd_ostream &OS) {}

static int overlap_main() {}

namespace {
struct ValueSitesStats {};
} // namespace

static void traverseAllValueSites(const InstrProfRecord &Func, uint32_t VK,
                                  ValueSitesStats &Stats, raw_fd_ostream &OS,
                                  InstrProfSymtab *Symtab) {}

static void showValueSitesStats(raw_fd_ostream &OS, uint32_t VK,
                                ValueSitesStats &Stats) {}

static int showInstrProfile(ShowFormat SFormat, raw_fd_ostream &OS) {}

static void showSectionInfo(sampleprof::SampleProfileReader *Reader,
                            raw_fd_ostream &OS) {}

namespace {
struct HotFuncInfo {};
} // namespace

// Print out detailed information about hot functions in PrintValues vector.
// Users specify titles and offset of every columns through ColumnTitle and
// ColumnOffset. The size of ColumnTitle and ColumnOffset need to be the same
// and at least 4. Besides, users can optionally give a HotFuncMetric string to
// print out or let it be an empty string.
static void dumpHotFunctionList(const std::vector<std::string> &ColumnTitle,
                                const std::vector<int> &ColumnOffset,
                                const std::vector<HotFuncInfo> &PrintValues,
                                uint64_t HotFuncCount, uint64_t TotalFuncCount,
                                uint64_t HotProfCount, uint64_t TotalProfCount,
                                const std::string &HotFuncMetric,
                                uint32_t TopNFunctions, raw_fd_ostream &OS) {}

static int showHotFunctionList(const sampleprof::SampleProfileMap &Profiles,
                               ProfileSummary &PS, uint32_t TopN,
                               raw_fd_ostream &OS) {}

static int showSampleProfile(ShowFormat SFormat, raw_fd_ostream &OS) {}

static int showMemProfProfile(ShowFormat SFormat, raw_fd_ostream &OS) {}

static int showDebugInfoCorrelation(const std::string &Filename,
                                    ShowFormat SFormat, raw_fd_ostream &OS) {}

static int show_main(StringRef ProgName) {}

static int order_main() {}

int llvm_profdata_main(int argc, char **argvNonConst,
                       const llvm::ToolContext &) {}