160 lines · cpp
1//===- RemarkCount.cpp ----------------------------------------------------===//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-exception6//7//===----------------------------------------------------------------------===//8//9// Count remarks using `instruction-count` for asm-printer remarks and10// `annotation-count` for annotation-remarks11//12//===----------------------------------------------------------------------===//13#include "RemarkUtilHelpers.h"14#include "RemarkUtilRegistry.h"15 16using namespace llvm;17using namespace remarks;18using namespace llvm::remarkutil;19 20static cl::SubCommand InstructionCount(21 "instruction-count",22 "Function instruction count information (requires asm-printer remarks)");23static cl::SubCommand24 AnnotationCount("annotation-count",25 "Collect count information from annotation remarks (uses "26 "AnnotationRemarksPass)");27 28namespace instructioncount {29INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionCount)30INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionCount)31DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(InstructionCount)32} // namespace instructioncount33 34namespace annotationcount {35INPUT_FORMAT_COMMAND_LINE_OPTIONS(AnnotationCount)36static cl::opt<std::string> AnnotationTypeToCollect(37 "annotation-type", cl::desc("annotation-type remark to collect count for"),38 cl::sub(AnnotationCount));39INPUT_OUTPUT_COMMAND_LINE_OPTIONS(AnnotationCount)40DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(AnnotationCount)41} // namespace annotationcount42 43static bool shouldSkipRemark(bool UseDebugLoc, Remark &Remark) {44 return UseDebugLoc && !Remark.Loc.has_value();45}46 47namespace instructioncount {48/// Outputs all instruction count remarks in the file as a CSV.49/// \returns Error::success() on success, and an Error otherwise.50static Error tryInstructionCount() {51 // Create the output buffer.52 auto MaybeOF = getOutputFileWithFlags(OutputFileName,53 /*Flags = */ sys::fs::OF_TextWithCRLF);54 if (!MaybeOF)55 return MaybeOF.takeError();56 auto OF = std::move(*MaybeOF);57 // Create a parser for the user-specified input format.58 auto MaybeBuf = getInputMemoryBuffer(InputFileName);59 if (!MaybeBuf)60 return MaybeBuf.takeError();61 auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());62 if (!MaybeParser)63 return MaybeParser.takeError();64 // Emit CSV header.65 if (UseDebugLoc)66 OF->os() << "Source,";67 OF->os() << "Function,InstructionCount\n";68 // Parse all remarks. Whenever we see an instruction count remark, output69 // the file name and the number of instructions.70 auto &Parser = **MaybeParser;71 auto MaybeRemark = Parser.next();72 for (; MaybeRemark; MaybeRemark = Parser.next()) {73 auto &Remark = **MaybeRemark;74 if (Remark.RemarkName != "InstructionCount")75 continue;76 if (shouldSkipRemark(UseDebugLoc, Remark))77 continue;78 auto *InstrCountArg = find_if(Remark.Args, [](const Argument &Arg) {79 return Arg.Key == "NumInstructions";80 });81 assert(InstrCountArg != Remark.Args.end() &&82 "Expected instruction count remarks to have a NumInstructions key?");83 if (UseDebugLoc) {84 std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +85 std::to_string(Remark.Loc->SourceLine) + +":" +86 std::to_string(Remark.Loc->SourceColumn);87 OF->os() << Loc << ",";88 }89 OF->os() << Remark.FunctionName << "," << InstrCountArg->Val << "\n";90 }91 auto E = MaybeRemark.takeError();92 if (!E.isA<EndOfFileError>())93 return E;94 consumeError(std::move(E));95 OF->keep();96 return Error::success();97}98} // namespace instructioncount99 100namespace annotationcount {101static Error tryAnnotationCount() {102 // Create the output buffer.103 auto MaybeOF = getOutputFileWithFlags(OutputFileName,104 /*Flags = */ sys::fs::OF_TextWithCRLF);105 if (!MaybeOF)106 return MaybeOF.takeError();107 auto OF = std::move(*MaybeOF);108 // Create a parser for the user-specified input format.109 auto MaybeBuf = getInputMemoryBuffer(InputFileName);110 if (!MaybeBuf)111 return MaybeBuf.takeError();112 auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());113 if (!MaybeParser)114 return MaybeParser.takeError();115 // Emit CSV header.116 if (UseDebugLoc)117 OF->os() << "Source,";118 OF->os() << "Function,Count\n";119 // Parse all remarks. When we see the specified remark collect the count120 // information.121 auto &Parser = **MaybeParser;122 auto MaybeRemark = Parser.next();123 for (; MaybeRemark; MaybeRemark = Parser.next()) {124 auto &Remark = **MaybeRemark;125 if (Remark.RemarkName != "AnnotationSummary")126 continue;127 if (shouldSkipRemark(UseDebugLoc, Remark))128 continue;129 auto *RemarkNameArg = find_if(Remark.Args, [](const Argument &Arg) {130 return Arg.Key == "type" && Arg.Val == AnnotationTypeToCollect;131 });132 if (RemarkNameArg == Remark.Args.end())133 continue;134 auto *CountArg = find_if(135 Remark.Args, [](const Argument &Arg) { return Arg.Key == "count"; });136 assert(CountArg != Remark.Args.end() &&137 "Expected annotation-type remark to have a count key?");138 if (UseDebugLoc) {139 std::string Loc = Remark.Loc->SourceFilePath.str() + ":" +140 std::to_string(Remark.Loc->SourceLine) + +":" +141 std::to_string(Remark.Loc->SourceColumn);142 OF->os() << Loc << ",";143 }144 OF->os() << Remark.FunctionName << "," << CountArg->Val << "\n";145 }146 auto E = MaybeRemark.takeError();147 if (!E.isA<EndOfFileError>())148 return E;149 consumeError(std::move(E));150 OF->keep();151 return Error::success();152}153} // namespace annotationcount154 155static CommandRegistration156 InstructionCountReg(&InstructionCount,157 instructioncount::tryInstructionCount);158static CommandRegistration Yaml2Bitstream(&AnnotationCount,159 annotationcount::tryAnnotationCount);160