Skip to content

[llvm-remarkutil] Add an instruction-mix tool #140598

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 28 commits into from
May 29, 2025
Merged
Show file tree
Hide file tree
Changes from 25 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
e0dce31
[llvm-remarkutil] Add an instruction-mix tool
jroelofs May 19, 2025
27be6e1
drop debugloc cl opts
jroelofs May 20, 2025
dc263e1
Add regex error handling.
jroelofs May 20, 2025
72cb5d0
Use FilterMatcher, and move it to RemarkUtilHelpers.h
jroelofs May 20, 2025
23daed4
Make invalid states unrepresentable
jroelofs May 21, 2025
baf3841
Add missing file header
jroelofs May 21, 2025
237deb0
clang-format
jroelofs May 21, 2025
fb8bed1
EOL whitespace
jroelofs May 21, 2025
8e39094
remove now-useless static member ctor
jroelofs May 21, 2025
7e8ee10
rm dead function
jroelofs May 21, 2025
28a34df
[llvm-remarkutil] Make invalid states un-representable in the count t…
jroelofs May 19, 2025
294e4ca
Merge branch 'jroelofs/remarkutil-refactor' into jroelofs/remarkutil-…
jroelofs May 21, 2025
e5acd04
add tests for count error handling
jroelofs May 21, 2025
35e8352
simplify new test
jroelofs May 21, 2025
17bd09b
make it harder to mention the wrong arg name in an error
jroelofs May 21, 2025
c604173
rm stray whitespace
jroelofs May 21, 2025
3a94f26
Merge branch 'jroelofs/remarkutil-refactor' into jroelofs/remarkutil-…
jroelofs May 21, 2025
a063bed
fix build after merge
jroelofs May 21, 2025
abe8f96
clang-format
jroelofs May 21, 2025
3895801
Merge branch 'jroelofs/remarkutil-refactor' into jroelofs/remarkutil-…
jroelofs May 21, 2025
1df5289
use std::log10 from <cmath>
jroelofs May 21, 2025
3a8444d
createExactOrRE
jroelofs May 28, 2025
65812f1
clang-format
jroelofs May 28, 2025
add1455
avoid UB when all remarks are filtered out
jroelofs May 28, 2025
6267372
Merge branch 'jroelofs/remarkutil-refactor' into jroelofs/remarkutil-…
jroelofs May 28, 2025
b4e7910
review feedback
jroelofs May 28, 2025
0c03a05
tobias is right re: lifetimes
jroelofs May 28, 2025
c28463b
Merge remote-tracking branch 'origin/main' into jroelofs/remarkutil-i…
jroelofs May 28, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions llvm/test/tools/llvm-remarkutil/Inputs/instruction-mix.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
--- !Analysis
Pass: asm-printer
Name: InstructionMix
Function: home
Args:
- INST_nop: '1'
- INST_add: '3'
- INST_mul: '5'
...
--- !Analysis
Pass: asm-printer
Name: InstructionMix
Function: homeowner
Args:
- INST_nop: '2'
- INST_add: '4'
- INST_mul: '6'
...
--- !Analysis
Pass: asm-printer
Name: InstructionMix
Function: meow
Args:
- INST_nop: '7'
- INST_add: '8'
- INST_mul: '9'
...
1 change: 1 addition & 0 deletions llvm/test/tools/llvm-remarkutil/broken-yaml-remark.test
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
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 instruction-mix --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
RUN: not llvm-remarkutil count --parser=yaml %p/Inputs/broken-remark -o - 2>&1 | FileCheck %s

Expand Down
5 changes: 5 additions & 0 deletions llvm/test/tools/llvm-remarkutil/empty-file.test
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
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 instruction-mix --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: not llvm-remarkutil count --parser=yaml %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 instruction-mix --parser=bitstream %p/Inputs/empty-file --report_style=csv -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=MIXBITSTREAM
RUN: llvm-remarkutil annotation-count --parser=bitstream --annotation-type=remark %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=ANNOTATIONBITSTREAM
RUN: llvm-remarkutil count --parser=bitstream %p/Inputs/empty-file -o - 2>&1 | FileCheck %s --allow-empty --check-prefix=COUNTBITSTREAM

Expand All @@ -20,3 +22,6 @@ RUN: llvm-remarkutil count --parser=bitstream %p/Inputs/empty-file -o - 2>&1 | F

; COUNTBITSTREAM-LABEL: Source,Count
; COUNTBITSTREAM-EMPTY:

; MIXBITSTREAM-LABEL: Instruction,Count
; MIXBITSTREAM-EMPTY:
7 changes: 7 additions & 0 deletions llvm/test/tools/llvm-remarkutil/instruction-count.test
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ RUN: llvm-remarkutil instruction-count --parser=yaml %p/Inputs/instruction-count
RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-count.yaml | llvm-remarkutil instruction-count --parser=bitstream | FileCheck %s
RUN: llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --remark-name="InstructionCount" %p/Inputs/instruction-count.yaml | FileCheck %s --check-prefix=COUNT-CHECK
RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-count.yaml | llvm-remarkutil count --parser=bitstream --count-by=arg --group-by=function --remark-name="InstructionCount" | FileCheck %s --check-prefix=COUNT-CHECK
RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rremark-name=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-REPOPERATOR -DARG=rremark-name
RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rpass-name=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-REPOPERATOR -DARG=rpass-name
RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rfilter-arg-by=* %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-REPOPERATOR -DARG=rfilter-arg-by
RUN: not llvm-remarkutil count --parser=yaml --count-by=arg --group-by=function --rremark-name=InstCombine --remark-name=InstCombine %p/Inputs/instruction-count.yaml 2>&1 | FileCheck %s --check-prefix=ERROR-BOTHFILTERS -DARG=rremark-name

; CHECK-LABEL: Function,InstructionCount
; CHECK: func1,1
Expand All @@ -12,3 +16,6 @@ RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-count.yaml | llvm-rem
; COUNT-CHECK: func1,1
; COUNT-CHECK: func2,2
; COUNT-CHECK: func3,3

; ERROR-REPOPERATOR: error: invalid argument '--[[ARG]]=*': repetition-operator operand invalid
; ERROR-BOTHFILTERS: error: conflicting arguments: --remark-name and --rremark-name
37 changes: 37 additions & 0 deletions llvm/test/tools/llvm-remarkutil/instruction-mix.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml | FileCheck %s
RUN: llvm-remarkutil yaml2bitstream %p/Inputs/instruction-mix.yaml | llvm-remarkutil instruction-mix --parser=bitstream | FileCheck %s
RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --report_style=human | FileCheck %s
RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --report_style=csv | FileCheck %s --check-prefix=CSV
RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --rfilter=meow | FileCheck %s --check-prefix=MEOW-RE
RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --filter=meow | FileCheck %s --check-prefix=MEOW-EXACT
RUN: llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --filter=none | FileCheck %s --check-prefix=NONE-EXACT
RUN: not llvm-remarkutil instruction-mix --parser=yaml %p/Inputs/instruction-mix.yaml --rfilter=* 2>&1 | FileCheck %s --check-prefix=ERROR

; CHECK-LABEL: Instruction Count
; CHECK-NEXT: ----------- -----
; CHECK-NEXT: mul 20
; CHECK-NEXT: add 15
; CHECK-NEXT: nop 10

; CSV-LABEL: Instruction,Count
; CSV-NEXT: mul,20
; CSV-NEXT: add,15
; CSV-NEXT: nop,10

; MEOW-RE: Instruction Count
; MEOW-RE-NEXT: ----------- -----
; MEOW-RE-NEXT: mul 15
; MEOW-RE-NEXT: add 12
; MEOW-RE-NEXT: nop 9

; MEOW-EXACT: Instruction Count
; MEOW-EXACT-NEXT: ----------- -----
; MEOW-EXACT-NEXT: mul 9
; MEOW-EXACT-NEXT: add 8
; MEOW-EXACT-NEXT: nop 7

; NONE-EXACT: Instruction Count
; NONE-EXACT: ----------- -----
; NONE-NOT: {{.*}}

; ERROR: error: invalid argument '--rfilter=*': repetition-operator operand invalid
1 change: 1 addition & 0 deletions llvm/tools/llvm-remarkutil/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_llvm_tool(llvm-remarkutil
RemarkConvert.cpp
RemarkCount.cpp
RemarkCounter.cpp
RemarkInstructionMix.cpp
RemarkSizeDiff.cpp
RemarkUtil.cpp
RemarkUtilHelpers.cpp
Expand Down
62 changes: 27 additions & 35 deletions llvm/tools/llvm-remarkutil/RemarkCounter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,19 +111,6 @@ static unsigned getValForKey(StringRef Key, const Remark &Remark) {
return *RemarkArg->getValAsInt();
}

Error Filters::regexArgumentsValid() {
if (RemarkNameFilter && RemarkNameFilter->IsRegex)
if (auto E = checkRegex(RemarkNameFilter->FilterRE))
return E;
if (PassNameFilter && PassNameFilter->IsRegex)
if (auto E = checkRegex(PassNameFilter->FilterRE))
return E;
if (ArgFilter && ArgFilter->IsRegex)
if (auto E = checkRegex(ArgFilter->FilterRE))
return E;
return Error::success();
}

bool Filters::filterRemark(const Remark &Remark) {
if (RemarkNameFilter && !RemarkNameFilter->match(Remark.RemarkName))
return false;
Expand Down Expand Up @@ -249,28 +236,29 @@ Error RemarkCounter::print(StringRef OutputFileName) {

Expected<Filters> getRemarkFilter() {
// Create Filter properties.
std::optional<FilterMatcher> RemarkNameFilter;
std::optional<FilterMatcher> PassNameFilter;
std::optional<FilterMatcher> RemarkArgFilter;
auto MaybeRemarkNameFilter =
FilterMatcher::createExactOrRE(RemarkNameOpt, RemarkNameOptRE);
if (!MaybeRemarkNameFilter)
return MaybeRemarkNameFilter.takeError();

auto MaybePassNameFilter =
FilterMatcher::createExactOrRE(PassNameOpt, PassNameOptRE);
if (!MaybePassNameFilter)
return MaybePassNameFilter.takeError();

auto MaybeRemarkArgFilter = FilterMatcher::createExactOrRE(
RemarkFilterArgByOpt, RemarkArgFilterOptRE);
if (!MaybeRemarkArgFilter)
return MaybeRemarkArgFilter.takeError();

std::optional<Type> RemarkType;
if (!RemarkNameOpt.empty())
RemarkNameFilter = {RemarkNameOpt, false};
else if (!RemarkNameOptRE.empty())
RemarkNameFilter = {RemarkNameOptRE, true};
if (!PassNameOpt.empty())
PassNameFilter = {PassNameOpt, false};
else if (!PassNameOptRE.empty())
PassNameFilter = {PassNameOptRE, true};
if (RemarkTypeOpt != Type::Failure)
RemarkType = RemarkTypeOpt;
if (!RemarkFilterArgByOpt.empty())
RemarkArgFilter = {RemarkFilterArgByOpt, false};
else if (!RemarkArgFilterOptRE.empty())
RemarkArgFilter = {RemarkArgFilterOptRE, true};

// Create RemarkFilter.
return Filters::createRemarkFilter(std::move(RemarkNameFilter),
std::move(PassNameFilter),
std::move(RemarkArgFilter), RemarkType);
return Filters{std::move(*MaybeRemarkNameFilter),
std::move(*MaybePassNameFilter),
std::move(*MaybeRemarkArgFilter), RemarkType};
}

Error useCollectRemark(StringRef Buffer, Counter &Counter, Filters &Filter) {
Expand Down Expand Up @@ -313,12 +301,16 @@ static Error collectRemarks() {
SmallVector<FilterMatcher, 4> ArgumentsVector;
if (!Keys.empty()) {
for (auto &Key : Keys)
ArgumentsVector.push_back({Key, false});
ArgumentsVector.push_back(FilterMatcher::createExact(Key));
} else if (!RKeys.empty())
for (auto Key : RKeys)
ArgumentsVector.push_back({Key, true});
for (auto Key : RKeys) {
auto FM = FilterMatcher::createRE(Key, RKeys);
if (!FM)
return FM.takeError();
ArgumentsVector.push_back(std::move(*FM));
}
else
ArgumentsVector.push_back({".*", true});
ArgumentsVector.push_back(FilterMatcher::createAny());

Expected<ArgumentCounter> AC = ArgumentCounter::createArgumentCounter(
GroupByOpt, ArgumentsVector, Buffer, Filter);
Expand Down
56 changes: 1 addition & 55 deletions llvm/tools/llvm-remarkutil/RemarkCounter.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,66 +45,18 @@ inline std::string groupByToStr(GroupBy GroupBy) {
}
}

/// Filter object which can be either a string or a regex to match with the
/// remark properties.
struct FilterMatcher {
Regex FilterRE;
std::string FilterStr;
bool IsRegex;
FilterMatcher(std::string Filter, bool IsRegex) : IsRegex(IsRegex) {
if (IsRegex)
FilterRE = Regex(Filter);
else
FilterStr = Filter;
}

bool match(StringRef StringToMatch) const {
if (IsRegex)
return FilterRE.match(StringToMatch);
return FilterStr == 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 std::move(E);
return std::move(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 {
Expand Down Expand Up @@ -160,12 +112,6 @@ struct ArgumentCounter : Counter {
StringRef Buffer, Filters &Filter) {
ArgumentCounter AC;
AC.Group = Group;
for (auto &Arg : Arguments) {
if (Arg.IsRegex) {
if (auto E = checkRegex(Arg.FilterRE))
return std::move(E);
}
}
if (auto E = AC.getAllMatchingArgumentsInRemark(Buffer, Arguments, Filter))
return std::move(E);
return AC;
Expand Down
Loading
Loading