| //===--- 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; |
| } |