Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / tools / llvm-remarkutil / RemarkCounter.h
blob3dd06622bc03f36b0edd809e1a72a544eb5be9e9
1 //===- RemarkCounter.h ----------------------------------------------------===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // Generic tool to count remarks based on properties
11 //===----------------------------------------------------------------------===//
12 #ifndef TOOLS_LLVM_REMARKCOUNTER_H
13 #define TOOLS_LLVM_REMARKCOUNTER_H
14 #include "RemarkUtilHelpers.h"
15 #include "llvm/ADT/MapVector.h"
16 #include "llvm/ADT/SmallSet.h"
17 #include "llvm/Support/Regex.h"
18 #include <list>
20 namespace llvm {
21 namespace remarks {
23 /// Collect remarks by counting the existance of a remark or by looking through
24 /// the keys and summing through the total count.
25 enum class CountBy { REMARK, ARGUMENT };
27 /// Summarize the count by either emitting one count for the remark file, or
28 /// grouping the count by source file or by function name.
29 enum class GroupBy {
30 TOTAL,
31 PER_SOURCE,
32 PER_FUNCTION,
33 PER_FUNCTION_WITH_DEBUG_LOC
36 /// Convert \p GroupBy to a std::string.
37 inline std::string groupByToStr(GroupBy GroupBy) {
38 switch (GroupBy) {
39 default:
40 return "Total";
41 case GroupBy::PER_FUNCTION:
42 return "Function";
43 case GroupBy::PER_FUNCTION_WITH_DEBUG_LOC:
44 return "FuctionWithDebugLoc";
45 case GroupBy::PER_SOURCE:
46 return "Source";
50 /// Filter object which can be either a string or a regex to match with the
51 /// remark properties.
52 struct FilterMatcher {
53 Regex FilterRE;
54 std::string FilterStr;
55 bool IsRegex;
56 FilterMatcher(std::string Filter, bool IsRegex) : IsRegex(IsRegex) {
57 if (IsRegex)
58 FilterRE = Regex(Filter);
59 else
60 FilterStr = Filter;
63 bool match(StringRef StringToMatch) const {
64 if (IsRegex)
65 return FilterRE.match(StringToMatch);
66 return FilterStr == StringToMatch.trim().str();
70 /// Filter out remarks based on remark properties based on name, pass name,
71 /// argument and type.
72 struct Filters {
73 std::optional<FilterMatcher> RemarkNameFilter;
74 std::optional<FilterMatcher> PassNameFilter;
75 std::optional<FilterMatcher> ArgFilter;
76 std::optional<Type> RemarkTypeFilter;
77 /// Returns a filter object if all the arguments provided are valid regex
78 /// types otherwise return an error.
79 static Expected<Filters>
80 createRemarkFilter(std::optional<FilterMatcher> RemarkNameFilter,
81 std::optional<FilterMatcher> PassNameFilter,
82 std::optional<FilterMatcher> ArgFilter,
83 std::optional<Type> RemarkTypeFilter) {
84 Filters Filter;
85 Filter.RemarkNameFilter = std::move(RemarkNameFilter);
86 Filter.PassNameFilter = std::move(PassNameFilter);
87 Filter.ArgFilter = std::move(ArgFilter);
88 Filter.RemarkTypeFilter = std::move(RemarkTypeFilter);
89 if (auto E = Filter.regexArgumentsValid())
90 return std::move(E);
91 return std::move(Filter);
93 /// Returns true if \p Remark satisfies all the provided filters.
94 bool filterRemark(const Remark &Remark);
96 private:
97 /// Check if arguments can be parsed as valid regex types.
98 Error regexArgumentsValid();
101 /// Convert Regex string error to an error object.
102 inline Error checkRegex(const Regex &Regex) {
103 std::string Error;
104 if (!Regex.isValid(Error))
105 return createStringError(make_error_code(std::errc::invalid_argument),
106 Twine("Regex: ", Error));
107 return Error::success();
110 /// Abstract counter class used to define the general required methods for
111 /// counting a remark.
112 struct Counter {
113 GroupBy Group = GroupBy::TOTAL;
114 Counter() = default;
115 Counter(enum GroupBy GroupBy) : Group(GroupBy) {}
116 /// Obtain the field for collecting remark info based on how we are
117 /// collecting. Remarks are grouped by FunctionName, Source, Source and
118 /// Function or collect by file.
119 std::optional<std::string> getGroupByKey(const Remark &Remark);
121 /// Collect count information from \p Remark organized based on \p Group
122 /// property.
123 virtual void collect(const Remark &) = 0;
124 /// Output the final count to the file \p OutputFileName
125 virtual Error print(StringRef OutputFileName) = 0;
126 virtual ~Counter() = default;
129 /// Count remarks based on the provided \p Keys argument and summing up the
130 /// value for each matching key organized by source, function or reporting a
131 /// total for the specified remark file.
132 /// Reporting count grouped by source:
134 /// | source | key1 | key2 | key3 |
135 /// |---------------|------|------|------|
136 /// | path/to/file1 | 0 | 1 | 3 |
137 /// | path/to/file2 | 1 | 0 | 2 |
138 /// | path/to/file3 | 2 | 3 | 1 |
140 /// Reporting count grouped by function:
142 /// | Function | key1 | key2 | key3 |
143 /// |---------------|------|------|------|
144 /// | function1 | 0 | 1 | 3 |
145 /// | function2 | 1 | 0 | 2 |
146 /// | function3 | 2 | 3 | 1 |
147 struct ArgumentCounter : Counter {
148 /// The internal object to keep the count for the remarks. The first argument
149 /// corresponds to the property we are collecting for this can be either a
150 /// source or function. The second argument is a row of integers where each
151 /// item in the row is the count for a specified key.
152 std::map<std::string, SmallVector<unsigned, 4>> CountByKeysMap;
153 /// A set of all the remark argument found in the remark file. The second
154 /// argument is the index of each of those arguments which can be used in
155 /// `CountByKeysMap` to fill count information for that argument.
156 MapVector<StringRef, unsigned> ArgumentSetIdxMap;
157 /// Create an argument counter. If the provided \p Arguments represent a regex
158 /// vector then we need to check that the provided regular expressions are
159 /// valid if not we return an Error.
160 static Expected<ArgumentCounter>
161 createArgumentCounter(GroupBy Group, ArrayRef<FilterMatcher> Arguments,
162 StringRef Buffer, Filters &Filter) {
163 ArgumentCounter AC;
164 AC.Group = Group;
165 for (auto &Arg : Arguments) {
166 if (Arg.IsRegex) {
167 if (auto E = checkRegex(Arg.FilterRE))
168 return std::move(E);
171 if (auto E = AC.getAllMatchingArgumentsInRemark(Buffer, Arguments, Filter))
172 return std::move(E);
173 return AC;
176 /// Update the internal count map based on the remark integer arguments that
177 /// correspond the the user specified argument keys to collect for.
178 void collect(const Remark &) override;
180 /// Print a CSV table consisting of an index which is specified by \p
181 /// `Group` and can be a function name, source file name or function name
182 /// with the full source path and columns of user specified remark arguments
183 /// to collect the count for.
184 Error print(StringRef OutputFileName) override;
186 private:
187 /// collect all the arguments that match the list of \p Arguments provided by
188 /// parsing through \p Buffer of remarks and filling \p ArgumentSetIdxMap
189 /// acting as a row for for all the keys that we are interested in collecting
190 /// information for.
191 Error getAllMatchingArgumentsInRemark(StringRef Buffer,
192 ArrayRef<FilterMatcher> Arguments,
193 Filters &Filter);
196 /// Collect remarks based by counting the existance of individual remarks. The
197 /// reported table will be structured based on the provided \p Group argument
198 /// by reporting count for functions, source or total count for the provided
199 /// remark file.
200 struct RemarkCounter : Counter {
201 std::map<std::string, unsigned> CountedByRemarksMap;
202 RemarkCounter(GroupBy Group) : Counter(Group) {}
204 /// Advance the internal map count broken by \p Group when
205 /// seeing \p Remark.
206 void collect(const Remark &) override;
208 /// Print a CSV table consisting of an index which is specified by \p
209 /// `Group` and can be a function name, source file name or function name
210 /// with the full source path and a counts column corresponding to the count
211 /// of each individual remark at th index.
212 Error print(StringRef OutputFileName) override;
214 } // namespace remarks
216 } // namespace llvm
217 #endif // TOOLS_LLVM_REMARKCOUNTER_H