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("-"), 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("-"), 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(InputFilename, /*IsText=*/true); 52 if (!BufOrError) 53 return createFileError(InputFilename, 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, "failed to open output"); 63 64 return llvm::createCtxProfFromYAML(BufOrError.get()->getBuffer(), Out); 65 } 66 67 Error convertToYaml() { 68 auto BufOrError = MemoryBuffer::getFileOrSTDIN(InputFilename); 69 if (!BufOrError) 70 return createFileError(InputFilename, BufOrError.getError()); 71 72 std::error_code EC; 73 raw_fd_ostream Out(OutputFilename, EC); 74 if (EC) 75 return createStringError(EC, "failed to open output"); 76 PGOCtxProfileReader Reader(BufOrError.get()->getBuffer()); 77 auto Prof = Reader.loadContexts(); 78 if (!Prof) 79 return Prof.takeError(); 80 llvm::convertCtxProfToYaml(Out, *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, "LLVM Contextual Profile Utils\n"); 88 ExitOnError ExitOnErr("llvm-ctxprof-util: "); 89 auto HandleErr = [&](Error E) -> int { 90 if (E) { 91 handleAllErrors(std::move(E), [&](const ErrorInfoBase &E) { 92 E.log(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