1 //===- llvm-profgen.cpp - LLVM SPGO profile generation tool -----*- 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 // llvm-profgen generates SPGO profiles from perf script ouput. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "ErrorHandling.h" 14 #include "PerfReader.h" 15 #include "ProfileGenerator.h" 16 #include "ProfiledBinary.h" 17 #include "llvm/Support/CommandLine.h" 18 #include "llvm/Support/FileSystem.h" 19 #include "llvm/Support/InitLLVM.h" 20 #include "llvm/Support/TargetSelect.h" 21 22 static cl::OptionCategory ProfGenCategory("ProfGen Options"); 23 24 static cl::list<std::string> PerfTraceFilenames( 25 "perfscript", cl::value_desc("perfscript"), cl::OneOrMore, 26 llvm::cl::MiscFlags::CommaSeparated, 27 cl::desc("Path of perf-script trace created by Linux perf tool with " 28 "`script` command(the raw perf.data should be profiled with -b)"), 29 cl::cat(ProfGenCategory)); 30 31 static cl::opt<std::string> BinaryPath( 32 "binary", cl::value_desc("binary"), cl::Required, 33 cl::desc("Path of profiled binary, only one binary is supported."), 34 cl::cat(ProfGenCategory)); 35 36 extern cl::opt<bool> ShowDisassemblyOnly; 37 extern cl::opt<bool> ShowSourceLocations; 38 extern cl::opt<bool> SkipSymbolization; 39 40 using namespace llvm; 41 using namespace sampleprof; 42 43 // Validate the command line input. 44 static void validateCommandLine(StringRef BinaryPath, 45 cl::list<std::string> &PerfTraceFilenames) { 46 // Allow the invalid perfscript if we only use to show binary disassembly. 47 if (!ShowDisassemblyOnly) { 48 for (auto &File : PerfTraceFilenames) { 49 if (!llvm::sys::fs::exists(File)) { 50 std::string Msg = "Input perf script(" + File + ") doesn't exist!"; 51 exitWithError(Msg); 52 } 53 } 54 } 55 56 if (!llvm::sys::fs::exists(BinaryPath)) { 57 std::string Msg = "Input binary(" + BinaryPath.str() + ") doesn't exist!"; 58 exitWithError(Msg); 59 } 60 61 if (CSProfileGenerator::MaxCompressionSize < -1) { 62 exitWithError("Value of --compress-recursion should >= -1"); 63 } 64 if (ShowSourceLocations && !ShowDisassemblyOnly) { 65 exitWithError("--show-source-locations should work together with " 66 "--show-disassembly-only!"); 67 } 68 } 69 70 int main(int argc, const char *argv[]) { 71 InitLLVM X(argc, argv); 72 73 // Initialize targets and assembly printers/parsers. 74 InitializeAllTargetInfos(); 75 InitializeAllTargetMCs(); 76 InitializeAllDisassemblers(); 77 78 cl::HideUnrelatedOptions({&ProfGenCategory, &getColorCategory()}); 79 cl::ParseCommandLineOptions(argc, argv, "llvm SPGO profile generator\n"); 80 validateCommandLine(BinaryPath, PerfTraceFilenames); 81 82 // Load symbols and disassemble the code of a given binary. 83 std::unique_ptr<ProfiledBinary> Binary = 84 std::make_unique<ProfiledBinary>(BinaryPath); 85 if (ShowDisassemblyOnly) 86 return EXIT_SUCCESS; 87 88 // Parse perf events and samples 89 std::unique_ptr<PerfReaderBase> Reader = 90 PerfReaderBase::create(Binary.get(), PerfTraceFilenames); 91 Reader->parsePerfTraces(PerfTraceFilenames); 92 93 if (SkipSymbolization) 94 return EXIT_SUCCESS; 95 96 // TBD 97 if (Reader->getPerfScriptType() == PERF_LBR) { 98 WithColor::warning() << "Currently LBR only perf script is not supported!"; 99 return EXIT_SUCCESS; 100 } 101 102 std::unique_ptr<ProfileGenerator> Generator = ProfileGenerator::create( 103 Binary.get(), Reader->getSampleCounters(), Reader->getPerfScriptType()); 104 Generator->generateProfile(); 105 Generator->write(); 106 107 return EXIT_SUCCESS; 108 } 109