1 //===- RemarkCount.cpp ----------------------------------------------------===//
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-exception
7 //===----------------------------------------------------------------------===//
9 // Count remarks using `instruction-count` for asm-printer remarks and
10 // `annotation-count` for annotation-remarks
12 //===----------------------------------------------------------------------===//
13 #include "RemarkUtilHelpers.h"
14 #include "RemarkUtilRegistry.h"
17 using namespace remarks
;
18 using namespace llvm::remarkutil
;
20 static cl::SubCommand
InstructionCount(
22 "Function instruction count information (requires asm-printer remarks)");
24 AnnotationCount("annotation-count",
25 "Collect count information from annotation remarks (uses "
26 "AnnotationRemarksPass)");
28 namespace instructioncount
{
29 INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionCount
)
30 INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionCount
)
31 DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(InstructionCount
)
32 } // namespace instructioncount
34 namespace annotationcount
{
35 INPUT_FORMAT_COMMAND_LINE_OPTIONS(AnnotationCount
)
36 static cl::opt
<std::string
> AnnotationTypeToCollect(
37 "annotation-type", cl::desc("annotation-type remark to collect count for"),
38 cl::sub(AnnotationCount
));
39 INPUT_OUTPUT_COMMAND_LINE_OPTIONS(AnnotationCount
)
40 DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(AnnotationCount
)
41 } // namespace annotationcount
43 static bool shouldSkipRemark(bool UseDebugLoc
, Remark
&Remark
) {
44 return UseDebugLoc
&& !Remark
.Loc
.has_value();
47 namespace instructioncount
{
48 /// Outputs all instruction count remarks in the file as a CSV.
49 /// \returns Error::success() on success, and an Error otherwise.
50 static Error
tryInstructionCount() {
51 // Create the output buffer.
52 auto MaybeOF
= getOutputFileWithFlags(OutputFileName
,
53 /*Flags = */ sys::fs::OF_TextWithCRLF
);
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
);
60 return MaybeBuf
.takeError();
61 auto MaybeParser
= createRemarkParser(InputFormat
, (*MaybeBuf
)->getBuffer());
63 return MaybeParser
.takeError();
66 OF
->os() << "Source,";
67 OF
->os() << "Function,InstructionCount\n";
68 // Parse all remarks. Whenever we see an instruction count remark, output
69 // 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")
76 if (shouldSkipRemark(UseDebugLoc
, Remark
))
78 auto *InstrCountArg
= find_if(Remark
.Args
, [](const Argument
&Arg
) {
79 return Arg
.Key
== "NumInstructions";
81 assert(InstrCountArg
!= Remark
.Args
.end() &&
82 "Expected instruction count remarks to have a NumInstructions key?");
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
<< ",";
89 OF
->os() << Remark
.FunctionName
<< "," << InstrCountArg
->Val
<< "\n";
91 auto E
= MaybeRemark
.takeError();
92 if (!E
.isA
<EndOfFileError
>())
94 consumeError(std::move(E
));
96 return Error::success();
98 } // namespace instructioncount
100 namespace annotationcount
{
101 static Error
tryAnnotationCount() {
102 // Create the output buffer.
103 auto MaybeOF
= getOutputFileWithFlags(OutputFileName
,
104 /*Flags = */ sys::fs::OF_TextWithCRLF
);
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
);
111 return MaybeBuf
.takeError();
112 auto MaybeParser
= createRemarkParser(InputFormat
, (*MaybeBuf
)->getBuffer());
114 return MaybeParser
.takeError();
117 OF
->os() << "Source,";
118 OF
->os() << "Function,Count\n";
119 // Parse all remarks. When we see the specified remark collect the count
121 auto &Parser
= **MaybeParser
;
122 auto MaybeRemark
= Parser
.next();
123 for (; MaybeRemark
; MaybeRemark
= Parser
.next()) {
124 auto &Remark
= **MaybeRemark
;
125 if (Remark
.RemarkName
!= "AnnotationSummary")
127 if (shouldSkipRemark(UseDebugLoc
, Remark
))
129 auto *RemarkNameArg
= find_if(Remark
.Args
, [](const Argument
&Arg
) {
130 return Arg
.Key
== "type" && Arg
.Val
== AnnotationTypeToCollect
;
132 if (RemarkNameArg
== Remark
.Args
.end())
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?");
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
<< ",";
144 OF
->os() << Remark
.FunctionName
<< "," << CountArg
->Val
<< "\n";
146 auto E
= MaybeRemark
.takeError();
147 if (!E
.isA
<EndOfFileError
>())
149 consumeError(std::move(E
));
151 return Error::success();
153 } // namespace annotationcount
155 static CommandRegistration
156 InstructionCountReg(&InstructionCount
,
157 instructioncount::tryInstructionCount
);
158 static CommandRegistration
Yaml2Bitstream(&AnnotationCount
,
159 annotationcount::tryAnnotationCount
);