llvm-project/llvm/tools/llvm-ctxprof-util/llvm-ctxprof-util.cpp
Mircea Trofin 5223ddd83f
[ctxprof] Prepare profile format for flat profiles (#129626)
The profile format has now a separate section called "Contexts" - there will be a corresponding one for flat profiles. The root has a separate tag because, in addition to not having a callsite ID as all the other context nodes have under it, it will have additional fields in subsequent patches.

The rest of this patch amounts to a bit of refactorings in the reader/writer (for better reuse later) and tests fixups.
2025-03-05 07:22:35 -08:00

109 lines
3.7 KiB
C++

//===--- llvm-ctxprof-util - utilities for ctxprof --------------*- 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
//
//===----------------------------------------------------------------------===//
///
/// \file
///
/// Utilities for manipulating contextual profiles
///
//===----------------------------------------------------------------------===//
#include "llvm/IR/GlobalValue.h"
#include "llvm/ProfileData/PGOCtxProfReader.h"
#include "llvm/ProfileData/PGOCtxProfWriter.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
using namespace llvm;
static cl::SubCommand FromYAML("fromYAML", "Convert from yaml");
static cl::SubCommand ToYAML("toYAML", "Convert to yaml");
static cl::opt<std::string> InputFilename(
"input", cl::value_desc("input"), cl::init("-"),
cl::desc(
"Input file. The format is an array of contexts.\n"
"Each context is a dictionary with the following keys:\n"
"'Guid', mandatory. The value is a 64-bit integer.\n"
"'Counters', mandatory. An array of 32-bit ints. These are the "
"counter values.\n"
"'Contexts', optional. An array containing arrays of contexts. The "
"context array at a position 'i' is the set of callees at that "
"callsite index. Use an empty array to indicate no callees."),
cl::sub(FromYAML), cl::sub(ToYAML));
static cl::opt<std::string> OutputFilename("output", cl::value_desc("output"),
cl::init("-"),
cl::desc("Output file"),
cl::sub(FromYAML), cl::sub(ToYAML));
namespace {
// Save the bitstream profile from the JSON representation.
Error convertFromYaml() {
auto BufOrError =
MemoryBuffer::getFileOrSTDIN(InputFilename, /*IsText=*/true);
if (!BufOrError)
return createFileError(InputFilename, BufOrError.getError());
std::error_code EC;
// Using a fd_ostream instead of a fd_stream. The latter would be more
// efficient as the bitstream writer supports incremental flush to it, but the
// json scenario is for test, and file size scalability doesn't really concern
// us.
raw_fd_ostream Out(OutputFilename, EC);
if (EC)
return createStringError(EC, "failed to open output");
return llvm::createCtxProfFromYAML(BufOrError.get()->getBuffer(), Out);
}
Error convertToYaml() {
auto BufOrError = MemoryBuffer::getFileOrSTDIN(InputFilename);
if (!BufOrError)
return createFileError(InputFilename, BufOrError.getError());
std::error_code EC;
raw_fd_ostream Out(OutputFilename, EC);
if (EC)
return createStringError(EC, "failed to open output");
PGOCtxProfileReader Reader(BufOrError.get()->getBuffer());
auto Prof = Reader.loadProfiles();
if (!Prof)
return Prof.takeError();
llvm::convertCtxProfToYaml(Out, *Prof);
Out << "\n";
return Error::success();
}
} // namespace
int main(int argc, const char **argv) {
cl::ParseCommandLineOptions(argc, argv, "LLVM Contextual Profile Utils\n");
ExitOnError ExitOnErr("llvm-ctxprof-util: ");
auto HandleErr = [&](Error E) -> int {
if (E) {
handleAllErrors(std::move(E), [&](const ErrorInfoBase &E) {
E.log(errs());
errs() << "\n";
});
return 1;
}
return 0;
};
if (FromYAML)
return HandleErr(convertFromYaml());
if (ToYAML)
return HandleErr(convertToYaml());
cl::PrintHelpMessage();
return 1;
}