Index: docs/CommandGuide/llvm-exegesis.rst =================================================================== --- docs/CommandGuide/llvm-exegesis.rst +++ docs/CommandGuide/llvm-exegesis.rst @@ -24,6 +24,13 @@ The main goal of this tool is to automatically (in)validate the LLVM's TableDef scheduling models. +EXAMPLES +-------- + + - Runnin + + + OPTIONS ------- @@ -41,9 +48,9 @@ Specify the opcode to measure, by name. Either `opcode-index` or `opcode-name` must be set. -.. option:: -benchmark-mode=[Latency|Uops] +.. option:: -mode=[latency|uops|analysis] - Specify which characteristic of the opcode to measure. + Specify the operation mode. See the tool description for more information. .. option:: -num-repetitions= Index: tools/llvm-exegesis/lib/Analysis.h =================================================================== --- tools/llvm-exegesis/lib/Analysis.h +++ tools/llvm-exegesis/lib/Analysis.h @@ -33,10 +33,12 @@ const InstructionBenchmarkClustering &Clustering); // Prints a csv of instructions for each cluster. - llvm::Error printClusters(llvm::raw_ostream &OS) const; - + struct PrintClusters {}; // Find potential errors in the scheduling information given measurements. - llvm::Error printSchedClassInconsistencies(llvm::raw_ostream &OS) const; + struct PrintSchedClassInconsistencies {}; + + template + llvm::Error run(llvm::raw_ostream &OS) const; private: void printInstructionRow(bool PrintSchedClass, size_t PointId, Index: tools/llvm-exegesis/lib/Analysis.cpp =================================================================== --- tools/llvm-exegesis/lib/Analysis.cpp +++ tools/llvm-exegesis/lib/Analysis.cpp @@ -91,7 +91,8 @@ MnemonicToOpcode_.emplace(InstrInfo_->getName(I), I); } -llvm::Error Analysis::printClusters(llvm::raw_ostream &OS) const { +template <> +llvm::Error Analysis::run(llvm::raw_ostream &OS) const { if (Clustering_.getPoints().empty()) return llvm::Error::success(); @@ -133,8 +134,8 @@ return PointsPerSchedClass; } -llvm::Error -Analysis::printSchedClassInconsistencies(llvm::raw_ostream &OS) const { +template <> +llvm::Error Analysis::run(llvm::raw_ostream &OS) const { // All the points in a scheduling class should be in the same cluster. // Print any scheduling class for which this is not the case. for (const auto &SchedClassAndPoints : makePointsPerSchedClass()) { @@ -167,4 +168,9 @@ return llvm::Error::success(); } +template llvm::Error +Analysis::run(llvm::raw_ostream &OS) const; +template llvm::Error Analysis::run( + llvm::raw_ostream &OS) const; + } // namespace exegesis Index: tools/llvm-exegesis/llvm-exegesis.cpp =================================================================== --- tools/llvm-exegesis/llvm-exegesis.cpp +++ tools/llvm-exegesis/llvm-exegesis.cpp @@ -70,9 +70,12 @@ llvm::cl::desc("dbscan epsilon for analysis clustering"), llvm::cl::init(0.1)); -static llvm::cl::opt AnalysisClustersFile("analysis-clusters-file", - llvm::cl::desc(""), - llvm::cl::init("-")); +static llvm::cl::opt + AnalysisClustersOutputFile("analysis-clusters-output-file", llvm::cl::desc(""), + llvm::cl::init("-")); +static llvm::cl::opt + AnalysisInconsistenciesOutputFile("analysis-inconsistencies-output-file", + llvm::cl::desc(""), llvm::cl::init("-")); namespace exegesis { @@ -125,6 +128,25 @@ exegesis::pfm::pfmTerminate(); } +// Prints the results of running analysis printer `Print` to file `Filename` if +// Filename is non-empty. +template +void maybeRunAnalysis(const Analysis &Analyzer, const std::string &Name, + const std::string &OutputFilename) { + if (OutputFilename.empty()) + return; + if (OutputFilename != "-") { + llvm::errs() << "Printing " << Name << " results to file '" << OutputFilename + << "'\n"; + } + std::error_code ErrorCode; + llvm::raw_fd_ostream ClustersOS(OutputFilename, ErrorCode, llvm::sys::fs::F_RW); + if (ErrorCode) + llvm::report_fatal_error("cannot open out file: " + OutputFilename); + if (auto Err = Analyzer.run(ClustersOS)) + llvm::report_fatal_error(std::move(Err)); +} + void analysisMain() { // Read benchmarks. const std::vector Points = @@ -152,17 +174,11 @@ const Analysis Analyzer(*TheTarget, Clustering); - std::error_code ErrorCode; - llvm::raw_fd_ostream ClustersOS(AnalysisClustersFile, ErrorCode, - llvm::sys::fs::F_RW); - if (ErrorCode) - llvm::report_fatal_error("cannot open out file: " + AnalysisClustersFile); - - if (auto Err = Analyzer.printClusters(ClustersOS)) - llvm::report_fatal_error(std::move(Err)); - - if (auto Err = Analyzer.printSchedClassInconsistencies(llvm::outs())) - llvm::report_fatal_error(std::move(Err)); + maybeRunAnalysis(Analyzer, "analysis clusters", + AnalysisClustersOutputFile); + maybeRunAnalysis( + Analyzer, "sched class consistency analysis", + AnalysisInconsistenciesOutputFile); } } // namespace exegesis