diff --git a/llvm/docs/CommandGuide/llvm-remarkutil.rst b/llvm/docs/CommandGuide/llvm-remarkutil.rst index 481774a6bd358..f3ecb56cd666e 100644 --- a/llvm/docs/CommandGuide/llvm-remarkutil.rst +++ b/llvm/docs/CommandGuide/llvm-remarkutil.rst @@ -20,7 +20,7 @@ Subcommands * :ref:`bitstream2yaml_subcommand` - Reserialize bitstream remarks to YAML. * :ref:`yaml2bitstream_subcommand` - Reserialize YAML remarks to bitstream. * :ref:`instruction-count_subcommand` - Output function instruction counts. - + * :ref:`annotation-count_subcommand` - Output remark type count from annotation remarks. .. _bitstream2yaml_subcommand: bitstream2yaml @@ -72,3 +72,24 @@ CSV format is as follows: :: Function,InstructionCount foo,123 + +annotation-count +~~~~~~~~~~~~~~~~~ + +.. program:: llvm-remarkutil annotation-count + +USAGE: :program:`llvm-remarkutil` annotation-count --parser= --annotation-type= -o + +Summary +^^^^^^^ + +Outputs a count for annotation-type `` remark for every function. The count expresses +the number of remark checks inserted at the function. + +Annotation count remarks require AnnotationRemarksPass remarks. + +CSV format is as follows: + +:: + Function,Count + foo,123 diff --git a/llvm/test/tools/llvm-remarkutil/Inputs/annotation-count.bitstream b/llvm/test/tools/llvm-remarkutil/Inputs/annotation-count.bitstream new file mode 100644 index 0000000000000..feb19692cea63 Binary files /dev/null and b/llvm/test/tools/llvm-remarkutil/Inputs/annotation-count.bitstream differ diff --git a/llvm/test/tools/llvm-remarkutil/Inputs/annotation-count.yaml b/llvm/test/tools/llvm-remarkutil/Inputs/annotation-count.yaml new file mode 100644 index 0000000000000..f29808a7772cf --- /dev/null +++ b/llvm/test/tools/llvm-remarkutil/Inputs/annotation-count.yaml @@ -0,0 +1,27 @@ +--- !Analysis +Pass: annotation-remarks +Name: AnnotationSummary +Function: func1 +Args: + - String: 'Annotated ' + - count: '1' + - String: ' instructions with ' + - type: remark +--- !Analysis +Pass: annotation-remarks +Name: AnnotationSummary +Function: func2 +Args: + - String: 'Annotated ' + - count: '2' + - String: ' instructions with ' + - type: remark +--- !Analysis +Pass: annotation-remarks +Name: AnnotationSummary +Function: func3 +Args: + - String: 'Annotated ' + - count: '3' + - String: ' instructions with ' + - type: remark diff --git a/llvm/test/tools/llvm-remarkutil/annotation-count.test b/llvm/test/tools/llvm-remarkutil/annotation-count.test new file mode 100644 index 0000000000000..73582402201dc --- /dev/null +++ b/llvm/test/tools/llvm-remarkutil/annotation-count.test @@ -0,0 +1,7 @@ +RUN: llvm-remarkutil annotation-count --parser=yaml --annotation-type=remark %p/Inputs/annotation-count.yaml | FileCheck %s +RUN: llvm-remarkutil yaml2bitstream %p/Inputs/annotation-count.yaml | llvm-remarkutil annotation-count --parser=bitstream --annotation-type=remark | FileCheck %s + +; CHECK-LABEL: Function,Count +; CHECK: func1,1 +; CHECK: func2,2 +; CHECK: func3,3 diff --git a/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark.test b/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark.test index 9f37c57f4f034..515c096f540eb 100644 --- a/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark.test +++ b/llvm/test/tools/llvm-remarkutil/broken-bitstream-remark.test @@ -1,3 +1,4 @@ RUN: not llvm-remarkutil bitstream2yaml %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s RUN: not llvm-remarkutil instruction-count --parser=bitstream %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s +RUN: not llvm-remarkutil annotation-count --parser=bitstream --annotation-type=remark %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s CHECK: error: Unknown magic number: expecting RMRK, got --- . diff --git a/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test b/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test index 764a839fc0fb8..df87e3db80442 100644 --- a/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test +++ b/llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test @@ -1,3 +1,4 @@ RUN: not llvm-remarkutil yaml2bitstream %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s RUN: not llvm-remarkutil instruction-count --parser=yaml %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s +RUN: not llvm-remarkutil annotation-count --parser=yaml --annotation-type=remark %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s CHECK: error: Type, Pass, Name or Function missing diff --git a/llvm/test/tools/llvm-remarkutil/empty-file.test b/llvm/test/tools/llvm-remarkutil/empty-file.test index 67dfea4bc7803..aa2ee41dd70bd 100644 --- a/llvm/test/tools/llvm-remarkutil/empty-file.test +++ b/llvm/test/tools/llvm-remarkutil/empty-file.test @@ -1,7 +1,9 @@ RUN: not llvm-remarkutil yaml2bitstream %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --check-prefix=YAMLPARSER RUN: not llvm-remarkutil instruction-count --parser=yaml %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --check-prefix=YAMLPARSER +RUN: not llvm-remarkutil annotation-count --parser=yaml --annotation-type=remark %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --check-prefix=YAMLPARSER RUN: llvm-remarkutil bitstream2yaml %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=BITSTREAM2YAML RUN: llvm-remarkutil instruction-count --parser=bitstream %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=SIZEBITSTREAM +RUN: llvm-remarkutil annotation-count --parser=bitstream --annotation-type=remark %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=ANNOTATIONBITSTREAM ; YAMLPARSER: error: document root is not of mapping type. @@ -9,4 +11,7 @@ RUN: llvm-remarkutil instruction-count --parser=bitstream %p/Inputs/empty-file - ; BITSTREAM2YAML-NOT: error ; SIZEBITSTREAM-LABEL: Function,InstructionCount -; SIZEBITSTREAM-EMPTY +; SIZEBITSTREAM-EMPTY: + +; ANNOTATIONBITSTREAM-LABEL: Function,Count +; ANNOTATIONBITSTREAM-EMPTY: diff --git a/llvm/test/tools/llvm-remarkutil/no-annotation-count.test b/llvm/test/tools/llvm-remarkutil/no-annotation-count.test new file mode 100644 index 0000000000000..9571bf760824d --- /dev/null +++ b/llvm/test/tools/llvm-remarkutil/no-annotation-count.test @@ -0,0 +1,5 @@ +RUN: llvm-remarkutil annotation-count --parser=yaml --annotation-type=remark %p/Inputs/made-up-fake-remarks.yaml | FileCheck %s +RUN: llvm-remarkutil yaml2bitstream %p/Inputs/made-up-fake-remarks.yaml | llvm-remarkutil annotation-count --parser=bitstream --annotation-type=remark | FileCheck %s + +; CHECK-LABEL: Function,Count +; CHECK-EMPTY: diff --git a/llvm/tools/llvm-remarkutil/RemarkUtil.cpp b/llvm/tools/llvm-remarkutil/RemarkUtil.cpp index 0412eae954ac9..004229c567dd2 100644 --- a/llvm/tools/llvm-remarkutil/RemarkUtil.cpp +++ b/llvm/tools/llvm-remarkutil/RemarkUtil.cpp @@ -38,6 +38,10 @@ static cl::SubCommand static cl::SubCommand InstructionCount( "instruction-count", "Function instruction count information (requires asm-printer remarks)"); +static cl::SubCommand + AnnotationCount("annotation-count", + "Collect count information from annotation remarks (uses " + "AnnotationRemarksPass)"); } // namespace subopts // Keep input + output help + names consistent across the various modes via a @@ -49,6 +53,14 @@ static cl::SubCommand InstructionCount( static cl::opt OutputFileName( \ "o", cl::init("-"), cl::cat(RemarkUtilCategory), cl::desc("Output"), \ cl::value_desc("filename"), cl::sub(SUBOPT)); + +// Keep Input format and names consistent accross the modes via a macro. +#define INPUT_FORMAT_COMMAND_LINE_OPTIONS(SUBOPT) \ + static cl::opt InputFormat( \ + "parser", cl::desc("Input remark format to parse"), \ + cl::values(clEnumValN(Format::YAML, "yaml", "YAML"), \ + clEnumValN(Format::Bitstream, "bitstream", "Bitstream")), \ + cl::sub(SUBOPT)); namespace yaml2bitstream { /// Remark format to parse. static constexpr Format InputFormat = Format::YAML; @@ -66,14 +78,18 @@ INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::Bitstream2YAML) } // namespace bitstream2yaml namespace instructioncount { -static cl::opt InputFormat( - "parser", cl::desc("Input remark format to parse"), - cl::values(clEnumValN(Format::YAML, "yaml", "YAML"), - clEnumValN(Format::Bitstream, "bitstream", "Bitstream")), - cl::sub(subopts::InstructionCount)); +INPUT_FORMAT_COMMAND_LINE_OPTIONS(subopts::InstructionCount) INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::InstructionCount) } // namespace instructioncount +namespace annotationcount { +INPUT_FORMAT_COMMAND_LINE_OPTIONS(subopts::AnnotationCount) +static cl::opt AnnotationTypeToCollect( + "annotation-type", cl::desc("annotation-type remark to collect count for"), + cl::sub(subopts::AnnotationCount)); +INPUT_OUTPUT_COMMAND_LINE_OPTIONS(subopts::AnnotationCount) +} // namespace annotationcount + /// \returns A MemoryBuffer for the input file on success, and an Error /// otherwise. static Expected> @@ -254,6 +270,51 @@ static Error tryInstructionCount() { } } // namespace instructioncount +namespace annotationcount { +static Error tryAnnotationCount() { + // Create the output buffer. + auto MaybeOF = getOutputFileWithFlags(OutputFileName, + /*Flags = */ sys::fs::OF_TextWithCRLF); + if (!MaybeOF) + return MaybeOF.takeError(); + auto OF = std::move(*MaybeOF); + // Create a parser for the user-specified input format. + auto MaybeBuf = getInputMemoryBuffer(InputFileName); + if (!MaybeBuf) + return MaybeBuf.takeError(); + auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer()); + if (!MaybeParser) + return MaybeParser.takeError(); + // Emit CSV header. + OF->os() << "Function,Count\n"; + // Parse all remarks. When we see the specified remark collect the count + // information. + auto &Parser = **MaybeParser; + auto MaybeRemark = Parser.next(); + for (; MaybeRemark; MaybeRemark = Parser.next()) { + auto &Remark = **MaybeRemark; + if (Remark.RemarkName != "AnnotationSummary") + continue; + auto *RemarkNameArg = find_if(Remark.Args, [](const Argument &Arg) { + return Arg.Key == "type" && Arg.Val == AnnotationTypeToCollect; + }); + if (RemarkNameArg == Remark.Args.end()) + continue; + auto *CountArg = find_if( + Remark.Args, [](const Argument &Arg) { return Arg.Key == "count"; }); + assert(CountArg != Remark.Args.end() && + "Expected annotation-type remark to have a count key?"); + OF->os() << Remark.FunctionName << "," << CountArg->Val << "\n"; + } + auto E = MaybeRemark.takeError(); + if (!E.isA()) + return E; + consumeError(std::move(E)); + OF->keep(); + return Error::success(); +} + +} // namespace annotationcount /// Handle user-specified suboptions (e.g. yaml2bitstream, bitstream2yaml). /// \returns An Error if the specified suboption fails or if no suboption was /// specified. Otherwise, Error::success(). @@ -264,6 +325,9 @@ static Error handleSuboptions() { return yaml2bitstream::tryYAML2Bitstream(); if (subopts::InstructionCount) return instructioncount::tryInstructionCount(); + if (subopts::AnnotationCount) + return annotationcount::tryAnnotationCount(); + return make_error( "Please specify a subcommand. (See -help for options)", inconvertibleErrorCode());