[llvm] Remark Util introduce remark count (PR #66214)
Florian Hahn via llvm-commits
llvm-commits at lists.llvm.org
Mon Sep 25 05:50:02 PDT 2023
================
@@ -0,0 +1,198 @@
+//===- RemarkCounter.h ----------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic tool to count remarks based on properties
+//
+//===----------------------------------------------------------------------===//
+#ifndef TOOLS_LLVM_REMARKCOUNTER_H
+#define TOOLS_LLVM_REMARKCOUNTER_H
+#include "RemarkUtilHelpers.h"
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/SmallSet.h"
+#include "llvm/Support/Regex.h"
+#include <list>
+
+namespace llvm {
+namespace remarks {
+
+/// Collect remarks by counting the existance of a remark or by looking through
+/// the keys and summing through the total count.
+enum class CountBy { REMARK, ARGUMENT };
+
+/// Summarize the count by either emitting one count for the remark file, or
+/// grouping the count by source file or by function name.
+enum class GroupBy {
+ TOTAL,
+ PER_SOURCE,
+ PER_FUNCTION,
+ PER_FUNCTION_WITH_DEBUG_LOC
+};
+
+/// Convert \p GroupBy to a std::string.
+inline std::string groupByToStr(GroupBy GroupBy) {
+ switch (GroupBy) {
+ default:
+ return "Total";
+ case GroupBy::PER_FUNCTION:
+ return "Function";
+ case GroupBy::PER_FUNCTION_WITH_DEBUG_LOC:
+ return "FuctionWithDebugLoc";
+ case GroupBy::PER_SOURCE:
+ return "Source";
+ }
+}
+
+/// Filter object which can be either a string or a regex to match with the
+/// remark properties.
+struct FilterMatcher {
+ std::variant<Regex, std::string> FilterRE, FilterStr;
+ bool IsRegex;
+ FilterMatcher(std::string Filter, bool IsRegex) : IsRegex(IsRegex) {
+ if (IsRegex)
+ FilterRE = Regex(Filter);
+ else
+ FilterStr = Filter;
+ }
+
+ bool match(StringRef StringToMatch) {
+ if (IsRegex)
+ return std::get<Regex>(FilterRE).match(StringToMatch);
+ std::string FString = std::get<std::string>(FilterStr);
+ return FString == StringToMatch.trim().str();
+ }
+};
+
+/// Filter out remarks based on remark properties based on name, pass name,
+/// argument and type.
+struct Filters {
+ std::optional<FilterMatcher> RemarkNameFilter;
+ std::optional<FilterMatcher> PassNameFilter;
+ std::optional<FilterMatcher> ArgFilter;
+ std::optional<Type> RemarkTypeFilter;
+ /// Returns a filter object if all the arguments provided are valid regex
+ /// types otherwise return an error.
+ static Expected<Filters>
+ createRemarkFilter(std::optional<FilterMatcher> RemarkNameFilter,
+ std::optional<FilterMatcher> PassNameFilter,
+ std::optional<FilterMatcher> ArgFilter,
+ std::optional<Type> RemarkTypeFilter) {
+ Filters Filter;
+ Filter.RemarkNameFilter = std::move(RemarkNameFilter);
+ Filter.PassNameFilter = std::move(PassNameFilter);
+ Filter.ArgFilter = std::move(ArgFilter);
+ Filter.RemarkTypeFilter = std::move(RemarkTypeFilter);
+ if (auto E = Filter.regexArgumentsValid())
+ return E;
+ return Filter;
+ }
+ /// Returns true if \p Remark satisfies all the provided filters.
+ bool filterRemark(const Remark &Remark);
+
+private:
+ /// Check if arguments can be parsed as valid regex types.
+ Error regexArgumentsValid();
+};
+
+/// Convert Regex string error to an error object.
+inline Error checkRegex(const Regex &Regex) {
+ std::string Error;
+ if (!Regex.isValid(Error))
+ return createStringError(make_error_code(std::errc::invalid_argument),
+ Twine("Regex: ", Error));
+ return Error::success();
+}
+
+/// Abstract counter class used to define the general required methods for
+/// counting a remark.
+struct Counter {
+ GroupBy GroupBy;
+ Counter(){};
+ Counter(enum GroupBy GroupBy) : GroupBy(GroupBy) {}
+ std::optional<std::string> getGroupByKey(const Remark &Remark);
+
+ /// Collect count information from \p Remark organized based on \p GroupBy
+ /// property.
+ virtual void collect(const Remark &) = 0;
+ /// Output the final count to the file \p OutputFileName
+ virtual Error print(StringRef OutputFileName) = 0;
+ virtual ~Counter() = default;
+};
+
+/// Count remarks based on the provided \p Keys argument and summing up the
+/// value for each matching key organized by source, function or reporting a
+/// total for the specified remark file.
+/// Reporting count grouped by source:
+///
+/// | source | key1 | key2 | key3 |
+/// |---------------|------|------|------|
+/// | path/to/file1 | 0 | 1 | 3 |
+/// | path/to/file2 | 1 | 0 | 2 |
+/// | path/to/file3 | 2 | 3 | 1 |
+///
+/// Reporting count grouped by function:
+///
+/// | Function | key1 | key2 | key3 |
+/// |---------------|------|------|------|
+/// | function1 | 0 | 1 | 3 |
+/// | function2 | 1 | 0 | 2 |
+/// | function3 | 2 | 3 | 1 |
+struct KeyCounter : Counter {
+ /// The internal object to keep the count for the remarks. The first argument
+ /// corresponds to the property we are collecting for this can be either a
+ /// source or function. The second argument is a row of integers where each
+ /// item in the row is the count for a specified key.
+ std::map<std::string, SmallVector<int, 4>> CountByKeysMap;
----------------
fhahn wrote:
`DenseMap`?
Would it make sense to use `unsigned` for the counts, assuming they all need to be positive?
https://github.com/llvm/llvm-project/pull/66214
More information about the llvm-commits
mailing list