X-Git-Url: http://plrg.eecs.uci.edu/git/?a=blobdiff_plain;f=tools%2Fllvm-profdata%2Fllvm-profdata.cpp;h=e97779968d448862fcd5505d96ed3e195d5ef273;hb=127090dd75530a4e4684cbf775f915010c422bd6;hp=397b52396923b134de80e64b5f0a7469e3730ab8;hpb=f5afb78a9dbb62e69b3c59aeeeb57e1d560d1e23;p=oota-llvm.git diff --git a/tools/llvm-profdata/llvm-profdata.cpp b/tools/llvm-profdata/llvm-profdata.cpp index 397b5239692..e97779968d4 100644 --- a/tools/llvm-profdata/llvm-profdata.cpp +++ b/tools/llvm-profdata/llvm-profdata.cpp @@ -14,7 +14,11 @@ #include "llvm/ADT/StringRef.h" #include "llvm/ProfileData/InstrProfReader.h" #include "llvm/ProfileData/InstrProfWriter.h" +#include "llvm/ProfileData/SampleProfReader.h" +#include "llvm/ProfileData/SampleProfWriter.h" +#include "llvm/IR/LLVMContext.h" #include "llvm/Support/CommandLine.h" +#include "llvm/Support/FileSystem.h" #include "llvm/Support/Format.h" #include "llvm/Support/ManagedStatic.h" #include "llvm/Support/MemoryBuffer.h" @@ -32,86 +36,115 @@ static void exitWithError(const Twine &Message, StringRef Whence = "") { ::exit(1); } -int merge_main(int argc, const char *argv[]) { - cl::list Inputs(cl::Positional, cl::Required, cl::OneOrMore, - cl::desc("")); - - cl::opt OutputFilename("output", cl::value_desc("output"), - cl::init("-"), - cl::desc("Output file")); - cl::alias OutputFilenameA("o", cl::desc("Alias for --output"), - cl::aliasopt(OutputFilename)); +enum ProfileKinds { instr, sample }; - cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n"); +void mergeInstrProfile(cl::list Inputs, StringRef OutputFilename) { + if (OutputFilename.compare("-") == 0) + exitWithError("Cannot write indexed profdata format to stdout."); - if (OutputFilename.empty()) - OutputFilename = "-"; - - std::string ErrorInfo; - // FIXME: F_Text would be available if line_iterator could accept CRLF. - raw_fd_ostream Output(OutputFilename.data(), ErrorInfo, sys::fs::F_None); - if (!ErrorInfo.empty()) - exitWithError(ErrorInfo, OutputFilename); + std::error_code EC; + raw_fd_ostream Output(OutputFilename.data(), EC, sys::fs::F_None); + if (EC) + exitWithError(EC.message(), OutputFilename); InstrProfWriter Writer; for (const auto &Filename : Inputs) { - std::unique_ptr Reader; - if (error_code ec = InstrProfReader::create(Filename, Reader)) + auto ReaderOrErr = InstrProfReader::create(Filename); + if (std::error_code ec = ReaderOrErr.getError()) exitWithError(ec.message(), Filename); + auto Reader = std::move(ReaderOrErr.get()); for (const auto &I : *Reader) - if (error_code EC = Writer.addFunctionCounts(I.Name, I.Hash, I.Counts)) + if (std::error_code EC = + Writer.addFunctionCounts(I.Name, I.Hash, I.Counts)) errs() << Filename << ": " << I.Name << ": " << EC.message() << "\n"; if (Reader->hasError()) exitWithError(Reader->getError().message(), Filename); } Writer.write(Output); - - return 0; } -int show_main(int argc, const char *argv[]) { - cl::opt Filename(cl::Positional, cl::Required, - cl::desc("")); +void mergeSampleProfile(cl::list Inputs, StringRef OutputFilename, + sampleprof::SampleProfileFormat OutputFormat) { + using namespace sampleprof; + auto WriterOrErr = SampleProfileWriter::create(OutputFilename, OutputFormat); + if (std::error_code EC = WriterOrErr.getError()) + exitWithError(EC.message(), OutputFilename); - cl::opt ShowCounts("counts", cl::init(false), - cl::desc("Show counter values for shown functions")); - cl::opt ShowAllFunctions("all-functions", cl::init(false), - cl::desc("Details for every function")); - cl::opt ShowFunction("function", - cl::desc("Details for matching functions")); + auto Writer = std::move(WriterOrErr.get()); + StringMap ProfileMap; + for (const auto &Filename : Inputs) { + auto ReaderOrErr = + SampleProfileReader::create(Filename, getGlobalContext()); + if (std::error_code EC = ReaderOrErr.getError()) + exitWithError(EC.message(), Filename); + + auto Reader = std::move(ReaderOrErr.get()); + if (std::error_code EC = Reader->read()) + exitWithError(EC.message(), Filename); + + StringMap &Profiles = Reader->getProfiles(); + for (StringMap::iterator I = Profiles.begin(), + E = Profiles.end(); + I != E; ++I) { + StringRef FName = I->first(); + FunctionSamples &Samples = I->second; + ProfileMap[FName].merge(Samples); + } + } + Writer->write(ProfileMap); +} + +int merge_main(int argc, const char *argv[]) { + cl::list Inputs(cl::Positional, cl::Required, cl::OneOrMore, + cl::desc("")); cl::opt OutputFilename("output", cl::value_desc("output"), - cl::init("-"), + cl::init("-"), cl::Required, cl::desc("Output file")); cl::alias OutputFilenameA("o", cl::desc("Alias for --output"), cl::aliasopt(OutputFilename)); + cl::opt ProfileKind( + cl::desc("Profile kind:"), cl::init(instr), + cl::values(clEnumVal(instr, "Instrumentation profile (default)"), + clEnumVal(sample, "Sample profile"), clEnumValEnd)); + + cl::opt OutputFormat( + cl::desc("Format of output profile (only meaningful with --sample)"), + cl::init(sampleprof::SPF_Binary), + cl::values(clEnumValN(sampleprof::SPF_Binary, "binary", + "Binary encoding (default)"), + clEnumValN(sampleprof::SPF_Text, "text", "Text encoding"), + clEnumValN(sampleprof::SPF_GCC, "gcc", "GCC encoding"), + clEnumValEnd)); - cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); - - std::unique_ptr Reader; - if (error_code EC = InstrProfReader::create(Filename, Reader)) - exitWithError(EC.message(), Filename); + cl::ParseCommandLineOptions(argc, argv, "LLVM profile data merger\n"); - if (OutputFilename.empty()) - OutputFilename = "-"; + if (ProfileKind == instr) + mergeInstrProfile(Inputs, OutputFilename); + else + mergeSampleProfile(Inputs, OutputFilename, OutputFormat); - std::string ErrorInfo; - raw_fd_ostream OS(OutputFilename.data(), ErrorInfo, sys::fs::F_Text); - if (!ErrorInfo.empty()) - exitWithError(ErrorInfo, OutputFilename); + return 0; +} - if (ShowAllFunctions && !ShowFunction.empty()) - errs() << "warning: -function argument ignored: showing all functions\n"; +int showInstrProfile(std::string Filename, bool ShowCounts, + bool ShowAllFunctions, std::string ShowFunction, + raw_fd_ostream &OS) { + auto ReaderOrErr = InstrProfReader::create(Filename); + if (std::error_code EC = ReaderOrErr.getError()) + exitWithError(EC.message(), Filename); + auto Reader = std::move(ReaderOrErr.get()); uint64_t MaxFunctionCount = 0, MaxBlockCount = 0; size_t ShownFunctions = 0, TotalFunctions = 0; for (const auto &Func : *Reader) { - bool Show = ShowAllFunctions || - (!ShowFunction.empty() && - Func.Name.find(ShowFunction) != Func.Name.npos); + bool Show = + ShowAllFunctions || (!ShowFunction.empty() && + Func.Name.find(ShowFunction) != Func.Name.npos); ++TotalFunctions; + assert(Func.Counts.size() > 0 && "function missing entry counter"); if (Func.Counts[0] > MaxFunctionCount) MaxFunctionCount = Func.Counts[0]; @@ -148,6 +181,65 @@ int show_main(int argc, const char *argv[]) { return 0; } +int showSampleProfile(std::string Filename, bool ShowCounts, + bool ShowAllFunctions, std::string ShowFunction, + raw_fd_ostream &OS) { + using namespace sampleprof; + auto ReaderOrErr = SampleProfileReader::create(Filename, getGlobalContext()); + if (std::error_code EC = ReaderOrErr.getError()) + exitWithError(EC.message(), Filename); + + auto Reader = std::move(ReaderOrErr.get()); + Reader->read(); + if (ShowAllFunctions || ShowFunction.empty()) + Reader->dump(OS); + else + Reader->dumpFunctionProfile(ShowFunction, OS); + + return 0; +} + +int show_main(int argc, const char *argv[]) { + cl::opt Filename(cl::Positional, cl::Required, + cl::desc("")); + + cl::opt ShowCounts("counts", cl::init(false), + cl::desc("Show counter values for shown functions")); + cl::opt ShowAllFunctions("all-functions", cl::init(false), + cl::desc("Details for every function")); + cl::opt ShowFunction("function", + cl::desc("Details for matching functions")); + + cl::opt OutputFilename("output", cl::value_desc("output"), + cl::init("-"), cl::desc("Output file")); + cl::alias OutputFilenameA("o", cl::desc("Alias for --output"), + cl::aliasopt(OutputFilename)); + cl::opt ProfileKind( + cl::desc("Profile kind:"), cl::init(instr), + cl::values(clEnumVal(instr, "Instrumentation profile (default)"), + clEnumVal(sample, "Sample profile"), clEnumValEnd)); + + cl::ParseCommandLineOptions(argc, argv, "LLVM profile data summary\n"); + + if (OutputFilename.empty()) + OutputFilename = "-"; + + std::error_code EC; + raw_fd_ostream OS(OutputFilename.data(), EC, sys::fs::F_Text); + if (EC) + exitWithError(EC.message(), OutputFilename); + + if (ShowAllFunctions && !ShowFunction.empty()) + errs() << "warning: -function argument ignored: showing all functions\n"; + + if (ProfileKind == instr) + return showInstrProfile(Filename, ShowCounts, ShowAllFunctions, + ShowFunction, OS); + else + return showSampleProfile(Filename, ShowCounts, ShowAllFunctions, + ShowFunction, OS); +} + int main(int argc, const char *argv[]) { // Print a stack trace if we signal out. sys::PrintStackTraceOnErrorSignal(); @@ -156,7 +248,7 @@ int main(int argc, const char *argv[]) { StringRef ProgName(sys::path::filename(argv[0])); if (argc > 1) { - int (*func)(int, const char *[]) = 0; + int (*func)(int, const char *[]) = nullptr; if (strcmp(argv[1], "merge") == 0) func = merge_main;