| 1 | //===--- llvm-ctxprof-util - utilities for ctxprof --------------*- C++ -*-===// |
| 2 | // |
| 3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
| 4 | // See https://llvm.org/LICENSE.txt for license information. |
| 5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| 6 | // |
| 7 | //===----------------------------------------------------------------------===// |
| 8 | /// |
| 9 | /// \file |
| 10 | /// |
| 11 | /// Utilities for manipulating contextual profiles |
| 12 | /// |
| 13 | //===----------------------------------------------------------------------===// |
| 14 | |
| 15 | #include "llvm/IR/GlobalValue.h" |
| 16 | #include "llvm/ProfileData/PGOCtxProfReader.h" |
| 17 | #include "llvm/ProfileData/PGOCtxProfWriter.h" |
| 18 | #include "llvm/Support/CommandLine.h" |
| 19 | #include "llvm/Support/Error.h" |
| 20 | #include "llvm/Support/ErrorHandling.h" |
| 21 | #include "llvm/Support/MemoryBuffer.h" |
| 22 | #include "llvm/Support/raw_ostream.h" |
| 23 | |
| 24 | using namespace llvm; |
| 25 | |
| 26 | static cl::SubCommand FromYAML("fromYAML" , "Convert from yaml" ); |
| 27 | static cl::SubCommand ToYAML("toYAML" , "Convert to yaml" ); |
| 28 | |
| 29 | static cl::opt<std::string> InputFilename( |
| 30 | "input" , cl::value_desc("input" ), cl::init(Val: "-" ), |
| 31 | cl::desc( |
| 32 | "Input file. The format is an array of contexts.\n" |
| 33 | "Each context is a dictionary with the following keys:\n" |
| 34 | "'Guid', mandatory. The value is a 64-bit integer.\n" |
| 35 | "'Counters', mandatory. An array of 32-bit ints. These are the " |
| 36 | "counter values.\n" |
| 37 | "'Contexts', optional. An array containing arrays of contexts. The " |
| 38 | "context array at a position 'i' is the set of callees at that " |
| 39 | "callsite index. Use an empty array to indicate no callees." ), |
| 40 | cl::sub(FromYAML), cl::sub(ToYAML)); |
| 41 | |
| 42 | static cl::opt<std::string> OutputFilename("output" , cl::value_desc("output" ), |
| 43 | cl::init(Val: "-" ), |
| 44 | cl::desc("Output file" ), |
| 45 | cl::sub(FromYAML), cl::sub(ToYAML)); |
| 46 | |
| 47 | namespace { |
| 48 | // Save the bitstream profile from the JSON representation. |
| 49 | Error convertFromYaml() { |
| 50 | auto BufOrError = |
| 51 | MemoryBuffer::getFileOrSTDIN(Filename: InputFilename, /*IsText=*/true); |
| 52 | if (!BufOrError) |
| 53 | return createFileError(F: InputFilename, EC: BufOrError.getError()); |
| 54 | |
| 55 | std::error_code EC; |
| 56 | // Using a fd_ostream instead of a fd_stream. The latter would be more |
| 57 | // efficient as the bitstream writer supports incremental flush to it, but the |
| 58 | // json scenario is for test, and file size scalability doesn't really concern |
| 59 | // us. |
| 60 | raw_fd_ostream Out(OutputFilename, EC); |
| 61 | if (EC) |
| 62 | return createStringError(EC, S: "failed to open output" ); |
| 63 | |
| 64 | return llvm::createCtxProfFromYAML(Profile: BufOrError.get()->getBuffer(), Out); |
| 65 | } |
| 66 | |
| 67 | Error convertToYaml() { |
| 68 | auto BufOrError = MemoryBuffer::getFileOrSTDIN(Filename: InputFilename); |
| 69 | if (!BufOrError) |
| 70 | return createFileError(F: InputFilename, EC: BufOrError.getError()); |
| 71 | |
| 72 | std::error_code EC; |
| 73 | raw_fd_ostream Out(OutputFilename, EC); |
| 74 | if (EC) |
| 75 | return createStringError(EC, S: "failed to open output" ); |
| 76 | PGOCtxProfileReader Reader(BufOrError.get()->getBuffer()); |
| 77 | auto Prof = Reader.loadProfiles(); |
| 78 | if (!Prof) |
| 79 | return Prof.takeError(); |
| 80 | llvm::convertCtxProfToYaml(OS&: Out, Profile: *Prof); |
| 81 | Out << "\n" ; |
| 82 | return Error::success(); |
| 83 | } |
| 84 | } // namespace |
| 85 | |
| 86 | int main(int argc, const char **argv) { |
| 87 | cl::ParseCommandLineOptions(argc, argv, Overview: "LLVM Contextual Profile Utils\n" ); |
| 88 | ExitOnError ExitOnErr("llvm-ctxprof-util: " ); |
| 89 | auto HandleErr = [&](Error E) -> int { |
| 90 | if (E) { |
| 91 | handleAllErrors(E: std::move(E), Handlers: [&](const ErrorInfoBase &E) { |
| 92 | E.log(OS&: errs()); |
| 93 | errs() << "\n" ; |
| 94 | }); |
| 95 | return 1; |
| 96 | } |
| 97 | return 0; |
| 98 | }; |
| 99 | |
| 100 | if (FromYAML) |
| 101 | return HandleErr(convertFromYaml()); |
| 102 | |
| 103 | if (ToYAML) |
| 104 | return HandleErr(convertToYaml()); |
| 105 | |
| 106 | cl::PrintHelpMessage(); |
| 107 | return 1; |
| 108 | } |
| 109 | |