1b3dd3171SStephen Neuendorffer //===- OpStats.cpp - Prints stats of operations in module -----------------===// 2b3dd3171SStephen Neuendorffer // 3b3dd3171SStephen Neuendorffer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4b3dd3171SStephen Neuendorffer // See https://llvm.org/LICENSE.txt for license information. 5b3dd3171SStephen Neuendorffer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6b3dd3171SStephen Neuendorffer // 7b3dd3171SStephen Neuendorffer //===----------------------------------------------------------------------===// 8b3dd3171SStephen Neuendorffer 967d0d7acSMichele Scuttari #include "mlir/Transforms/Passes.h" 1067d0d7acSMichele Scuttari 1165fcddffSRiver Riddle #include "mlir/IR/BuiltinOps.h" 12b3dd3171SStephen Neuendorffer #include "mlir/IR/Operation.h" 13b3dd3171SStephen Neuendorffer #include "mlir/IR/OperationSupport.h" 14b3dd3171SStephen Neuendorffer #include "llvm/ADT/DenseMap.h" 15b3dd3171SStephen Neuendorffer #include "llvm/Support/Format.h" 16b3dd3171SStephen Neuendorffer #include "llvm/Support/raw_ostream.h" 17b3dd3171SStephen Neuendorffer 1867d0d7acSMichele Scuttari namespace mlir { 1967d0d7acSMichele Scuttari #define GEN_PASS_DEF_PRINTOPSTATS 2067d0d7acSMichele Scuttari #include "mlir/Transforms/Passes.h.inc" 2167d0d7acSMichele Scuttari } // namespace mlir 2267d0d7acSMichele Scuttari 23b3dd3171SStephen Neuendorffer using namespace mlir; 24b3dd3171SStephen Neuendorffer 25b3dd3171SStephen Neuendorffer namespace { 2667d0d7acSMichele Scuttari struct PrintOpStatsPass : public impl::PrintOpStatsBase<PrintOpStatsPass> { 275ccb9df3SOkwan Kwon explicit PrintOpStatsPass(raw_ostream &os) : os(os) {} 28b3dd3171SStephen Neuendorffer 2985f19f99SOkwan Kwon explicit PrintOpStatsPass(raw_ostream &os, bool printAsJSON) : os(os) { 3085f19f99SOkwan Kwon this->printAsJSON = printAsJSON; 3185f19f99SOkwan Kwon } 3285f19f99SOkwan Kwon 33b3dd3171SStephen Neuendorffer // Prints the resultant operation statistics post iterating over the module. 34722f909fSRiver Riddle void runOnOperation() override; 35b3dd3171SStephen Neuendorffer 36b3dd3171SStephen Neuendorffer // Print summary of op stats. 37b3dd3171SStephen Neuendorffer void printSummary(); 38b3dd3171SStephen Neuendorffer 398010d7e0SOkwan Kwon // Print symmary of op stats in JSON. 408010d7e0SOkwan Kwon void printSummaryInJSON(); 418010d7e0SOkwan Kwon 42b3dd3171SStephen Neuendorffer private: 43b3dd3171SStephen Neuendorffer llvm::StringMap<int64_t> opCount; 44b3dd3171SStephen Neuendorffer raw_ostream &os; 45b3dd3171SStephen Neuendorffer }; 46b3dd3171SStephen Neuendorffer } // namespace 47b3dd3171SStephen Neuendorffer 48722f909fSRiver Riddle void PrintOpStatsPass::runOnOperation() { 49b3dd3171SStephen Neuendorffer opCount.clear(); 50b3dd3171SStephen Neuendorffer 51bf523186SMehdi Amini // Compute the operation statistics for the currently visited operation. 528010d7e0SOkwan Kwon getOperation()->walk( 538010d7e0SOkwan Kwon [&](Operation *op) { ++opCount[op->getName().getStringRef()]; }); 548010d7e0SOkwan Kwon if (printAsJSON) { 558010d7e0SOkwan Kwon printSummaryInJSON(); 568010d7e0SOkwan Kwon } else 57b3dd3171SStephen Neuendorffer printSummary(); 58*42c413b4SHideto Ueno markAllAnalysesPreserved(); 59b3dd3171SStephen Neuendorffer } 60b3dd3171SStephen Neuendorffer 61b3dd3171SStephen Neuendorffer void PrintOpStatsPass::printSummary() { 62b3dd3171SStephen Neuendorffer os << "Operations encountered:\n"; 63b3dd3171SStephen Neuendorffer os << "-----------------------\n"; 64b3dd3171SStephen Neuendorffer SmallVector<StringRef, 64> sorted(opCount.keys()); 65b3dd3171SStephen Neuendorffer llvm::sort(sorted); 66b3dd3171SStephen Neuendorffer 67b3dd3171SStephen Neuendorffer // Split an operation name from its dialect prefix. 68b3dd3171SStephen Neuendorffer auto splitOperationName = [](StringRef opName) { 69b3dd3171SStephen Neuendorffer auto splitName = opName.split('.'); 70b3dd3171SStephen Neuendorffer return splitName.second.empty() ? std::make_pair("", splitName.first) 71b3dd3171SStephen Neuendorffer : splitName; 72b3dd3171SStephen Neuendorffer }; 73b3dd3171SStephen Neuendorffer 74b3dd3171SStephen Neuendorffer // Compute the largest dialect and operation name. 75b3dd3171SStephen Neuendorffer size_t maxLenOpName = 0, maxLenDialect = 0; 76b3dd3171SStephen Neuendorffer for (const auto &key : sorted) { 779fa59e76SBenjamin Kramer auto [dialectName, opName] = splitOperationName(key); 78b3dd3171SStephen Neuendorffer maxLenDialect = std::max(maxLenDialect, dialectName.size()); 79b3dd3171SStephen Neuendorffer maxLenOpName = std::max(maxLenOpName, opName.size()); 80b3dd3171SStephen Neuendorffer } 81b3dd3171SStephen Neuendorffer 82b3dd3171SStephen Neuendorffer for (const auto &key : sorted) { 839fa59e76SBenjamin Kramer auto [dialectName, opName] = splitOperationName(key); 84b3dd3171SStephen Neuendorffer 85b3dd3171SStephen Neuendorffer // Left-align the names (aligning on the dialect) and right-align the count 86b3dd3171SStephen Neuendorffer // below. The alignment is for readability and does not affect CSV/FileCheck 87b3dd3171SStephen Neuendorffer // parsing. 88b3dd3171SStephen Neuendorffer if (dialectName.empty()) 89b3dd3171SStephen Neuendorffer os.indent(maxLenDialect + 3); 90b3dd3171SStephen Neuendorffer else 91b3dd3171SStephen Neuendorffer os << llvm::right_justify(dialectName, maxLenDialect + 2) << '.'; 92b3dd3171SStephen Neuendorffer 93b3dd3171SStephen Neuendorffer // Left justify the operation name. 94b3dd3171SStephen Neuendorffer os << llvm::left_justify(opName, maxLenOpName) << " , " << opCount[key] 95b3dd3171SStephen Neuendorffer << '\n'; 96b3dd3171SStephen Neuendorffer } 97b3dd3171SStephen Neuendorffer } 98b3dd3171SStephen Neuendorffer 998010d7e0SOkwan Kwon void PrintOpStatsPass::printSummaryInJSON() { 1008010d7e0SOkwan Kwon SmallVector<StringRef, 64> sorted(opCount.keys()); 1018010d7e0SOkwan Kwon llvm::sort(sorted); 1028010d7e0SOkwan Kwon 1038010d7e0SOkwan Kwon os << "{\n"; 1048010d7e0SOkwan Kwon 1058010d7e0SOkwan Kwon for (unsigned i = 0, e = sorted.size(); i != e; ++i) { 1068010d7e0SOkwan Kwon const auto &key = sorted[i]; 1078010d7e0SOkwan Kwon os << " \"" << key << "\" : " << opCount[key]; 1088010d7e0SOkwan Kwon if (i != e - 1) 1098010d7e0SOkwan Kwon os << ",\n"; 1108010d7e0SOkwan Kwon else 1118010d7e0SOkwan Kwon os << "\n"; 1128010d7e0SOkwan Kwon } 1138010d7e0SOkwan Kwon os << "}\n"; 1148010d7e0SOkwan Kwon } 1158010d7e0SOkwan Kwon 1165ccb9df3SOkwan Kwon std::unique_ptr<Pass> mlir::createPrintOpStatsPass(raw_ostream &os) { 1175ccb9df3SOkwan Kwon return std::make_unique<PrintOpStatsPass>(os); 118c6477050SMehdi Amini } 11985f19f99SOkwan Kwon 12085f19f99SOkwan Kwon std::unique_ptr<Pass> mlir::createPrintOpStatsPass(raw_ostream &os, 12185f19f99SOkwan Kwon bool printAsJSON) { 122f4ad2039SOkwan Kwon return std::make_unique<PrintOpStatsPass>(os, printAsJSON); 12385f19f99SOkwan Kwon } 124