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 1 commit
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:
22 changes: 22 additions & 0 deletions llvm/test/tools/llvm-remarkutil/instruction-mix.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
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 --filter=meow | FileCheck %s --check-prefix=MEOW

; 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: Instruction Count
; MEOW-NEXT: ----------- -----
; MEOW-NEXT: mul 15
; MEOW-NEXT: add 12
; MEOW-NEXT: nop 9
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
125 changes: 125 additions & 0 deletions llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@

#include "RemarkUtilHelpers.h"
#include "RemarkUtilRegistry.h"

#include "llvm/Support/Format.h"
#include "llvm/Support/FormattedStream.h"
#include "llvm/Support/Regex.h"

#include <numeric>

using namespace llvm;
using namespace remarks;
using namespace llvm::remarkutil;

namespace instructionmix {

static cl::SubCommand
InstructionMix("instruction-mix",
"Instruction Mix (requires asm-printer remarks)");

static cl::opt<std::string>
FunctionFilter("filter", cl::sub(InstructionMix), cl::init(".*"),
cl::value_desc("filter_regex"),
cl::desc("regex to filter functions with"));

enum ReportStyleOptions { human_output, csv_output };
static cl::opt<ReportStyleOptions> ReportStyle(
"report_style", cl::sub(InstructionMix),
cl::init(ReportStyleOptions::human_output),
cl::desc("Choose the report output format:"),
cl::values(clEnumValN(human_output, "human", "Human-readable format"),
clEnumValN(csv_output, "csv", "CSV format")));

INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionMix)
INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionMix)
DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS(InstructionMix)

static Error tryInstructionMix() {
auto MaybeOF =
getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);
if (!MaybeOF)
return MaybeOF.takeError();

auto OF = std::move(*MaybeOF);
auto MaybeBuf = getInputMemoryBuffer(InputFileName);
if (!MaybeBuf)
return MaybeBuf.takeError();
auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());
if (!MaybeParser)
return MaybeParser.takeError();

Regex Filter(FunctionFilter);

// Collect the histogram of instruction counts.
std::unordered_map<std::string, unsigned> Histogram;
auto &Parser = **MaybeParser;
auto MaybeRemark = Parser.next();
for (; MaybeRemark; MaybeRemark = Parser.next()) {
auto &Remark = **MaybeRemark;
if (Remark.RemarkName != "InstructionMix")
continue;
if (!Filter.match(Remark.FunctionName))
continue;
for (auto &Arg : Remark.Args) {
StringRef Key = Arg.Key;
if (!Key.consume_front("INST_"))
continue;
unsigned Val = 0;
bool ParseError = Arg.Val.getAsInteger(10, Val);
assert(!ParseError);
(void)ParseError;
Histogram[std::string(Key)] += Val;
}
}

// Sort it.
using MixEntry = std::pair<std::string, unsigned>;
llvm::SmallVector<MixEntry> Mix(Histogram.begin(), Histogram.end());
std::sort(Mix.begin(), Mix.end(), [](const auto &LHS, const auto &RHS) {
return LHS.second > RHS.second;
});

// Print the results.
switch (ReportStyle) {
case human_output: {
formatted_raw_ostream FOS(OF->os());
size_t MaxMnemonic =
std::accumulate(Mix.begin(), Mix.end(), StringRef("Instruction").size(),
[](size_t MaxMnemonic, const MixEntry &Elt) {
return std::max(MaxMnemonic, Elt.first.length());
});
unsigned MaxValue = std::accumulate(
Mix.begin(), Mix.end(), 0, [](unsigned MaxValue, const MixEntry &Elt) {
return std::max(MaxValue, Elt.second);
});
unsigned ValueWidth = log10(MaxValue) + 1;
FOS << "Instruction";
FOS.PadToColumn(MaxMnemonic + 1) << "Count\n";
FOS << "-----------";
FOS.PadToColumn(MaxMnemonic + 1) << "-----\n";
for (const auto &[Inst, Count] : Mix) {
FOS << Inst;
FOS.PadToColumn(MaxMnemonic + 1)
<< " " << format_decimal(Count, ValueWidth) << "\n";
}
} break;
case csv_output: {
OF->os() << "Instruction,Count\n";
for (const auto &[Inst, Count] : Mix)
OF->os() << Inst << "," << Count << "\n";
} break;
}

auto E = MaybeRemark.takeError();
if (!E.isA<EndOfFileError>())
return E;
consumeError(std::move(E));
OF->keep();
return Error::success();
}

static CommandRegistration InstructionMixReg(&InstructionMix,
tryInstructionMix);

} // namespace instructionmix
Loading