Path: blob/main/contrib/llvm-project/llvm/tools/llvm-remarkutil/RemarkCount.cpp
35231 views
//===- RemarkCount.cpp ----------------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Count remarks using `instruction-count` for asm-printer remarks and9// `annotation-count` for annotation-remarks10//11//===----------------------------------------------------------------------===//12#include "RemarkUtilHelpers.h"13#include "RemarkUtilRegistry.h"1415using namespace llvm;16using namespace remarks;17using namespace llvm::remarkutil;1819static cl::SubCommand InstructionCount(20"instruction-count",21"Function instruction count information (requires asm-printer remarks)");22static cl::SubCommand23AnnotationCount("annotation-count",24"Collect count information from annotation remarks (uses "25"AnnotationRemarksPass)");2627namespace instructioncount {28INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionCount)29INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionCount)30DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(InstructionCount)31} // namespace instructioncount3233namespace annotationcount {34INPUT_FORMAT_COMMAND_LINE_OPTIONS(AnnotationCount)35static cl::opt<std::string> AnnotationTypeToCollect(36"annotation-type", cl::desc("annotation-type remark to collect count for"),37cl::sub(AnnotationCount));38INPUT_OUTPUT_COMMAND_LINE_OPTIONS(AnnotationCount)39DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(AnnotationCount)40} // namespace annotationcount4142static bool shouldSkipRemark(bool UseDebugLoc, Remark &Remark) {43return UseDebugLoc && !Remark.Loc.has_value();44}4546namespace instructioncount {47/// Outputs all instruction count remarks in the file as a CSV.48/// \returns Error::success() on success, and an Error otherwise.49static Error tryInstructionCount() {50// Create the output buffer.51auto MaybeOF = getOutputFileWithFlags(OutputFileName,52/*Flags = */ sys::fs::OF_TextWithCRLF);53if (!MaybeOF)54return MaybeOF.takeError();55auto OF = std::move(*MaybeOF);56// Create a parser for the user-specified input format.57auto MaybeBuf = getInputMemoryBuffer(InputFileName);58if (!MaybeBuf)59return MaybeBuf.takeError();60auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());61if (!MaybeParser)62return MaybeParser.takeError();63// Emit CSV header.64if (UseDebugLoc)65OF->os() << "Source,";66OF->os() << "Function,InstructionCount\n";67// Parse all remarks. Whenever we see an instruction count remark, output68// the file name and the number of instructions.69auto &Parser = **MaybeParser;70auto MaybeRemark = Parser.next();71for (; MaybeRemark; MaybeRemark = Parser.next()) {72auto &Remark = **MaybeRemark;73if (Remark.RemarkName != "InstructionCount")74continue;75if (shouldSkipRemark(UseDebugLoc, Remark))76continue;77auto *InstrCountArg = find_if(Remark.Args, [](const Argument &Arg) {78return Arg.Key == "NumInstructions";79});80assert(InstrCountArg != Remark.Args.end() &&81"Expected instruction count remarks to have a NumInstructions key?");82if (UseDebugLoc) {83std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +84std::to_string(Remark.Loc->SourceLine) + +":" +85std::to_string(Remark.Loc->SourceColumn);86OF->os() << Loc << ",";87}88OF->os() << Remark.FunctionName << "," << InstrCountArg->Val << "\n";89}90auto E = MaybeRemark.takeError();91if (!E.isA<EndOfFileError>())92return E;93consumeError(std::move(E));94OF->keep();95return Error::success();96}97} // namespace instructioncount9899namespace annotationcount {100static Error tryAnnotationCount() {101// Create the output buffer.102auto MaybeOF = getOutputFileWithFlags(OutputFileName,103/*Flags = */ sys::fs::OF_TextWithCRLF);104if (!MaybeOF)105return MaybeOF.takeError();106auto OF = std::move(*MaybeOF);107// Create a parser for the user-specified input format.108auto MaybeBuf = getInputMemoryBuffer(InputFileName);109if (!MaybeBuf)110return MaybeBuf.takeError();111auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());112if (!MaybeParser)113return MaybeParser.takeError();114// Emit CSV header.115if (UseDebugLoc)116OF->os() << "Source,";117OF->os() << "Function,Count\n";118// Parse all remarks. When we see the specified remark collect the count119// information.120auto &Parser = **MaybeParser;121auto MaybeRemark = Parser.next();122for (; MaybeRemark; MaybeRemark = Parser.next()) {123auto &Remark = **MaybeRemark;124if (Remark.RemarkName != "AnnotationSummary")125continue;126if (shouldSkipRemark(UseDebugLoc, Remark))127continue;128auto *RemarkNameArg = find_if(Remark.Args, [](const Argument &Arg) {129return Arg.Key == "type" && Arg.Val == AnnotationTypeToCollect;130});131if (RemarkNameArg == Remark.Args.end())132continue;133auto *CountArg = find_if(134Remark.Args, [](const Argument &Arg) { return Arg.Key == "count"; });135assert(CountArg != Remark.Args.end() &&136"Expected annotation-type remark to have a count key?");137if (UseDebugLoc) {138std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +139std::to_string(Remark.Loc->SourceLine) + +":" +140std::to_string(Remark.Loc->SourceColumn);141OF->os() << Loc << ",";142}143OF->os() << Remark.FunctionName << "," << CountArg->Val << "\n";144}145auto E = MaybeRemark.takeError();146if (!E.isA<EndOfFileError>())147return E;148consumeError(std::move(E));149OF->keep();150return Error::success();151}152} // namespace annotationcount153154static CommandRegistration155InstructionCountReg(&InstructionCount,156instructioncount::tryInstructionCount);157static CommandRegistration Yaml2Bitstream(&AnnotationCount,158annotationcount::tryAnnotationCount);159160161