1+
2+ #include " RemarkUtilHelpers.h"
3+ #include " RemarkUtilRegistry.h"
4+
5+ #include " llvm/Support/Format.h"
6+ #include " llvm/Support/FormattedStream.h"
7+ #include " llvm/Support/Regex.h"
8+
9+ #include < numeric>
10+
11+ using namespace llvm ;
12+ using namespace remarks ;
13+ using namespace llvm ::remarkutil;
14+
15+ namespace instructionmix {
16+
17+ static cl::SubCommand
18+ InstructionMix (" instruction-mix" ,
19+ " Instruction Mix (requires asm-printer remarks)" );
20+
21+ static cl::opt<std::string>
22+ FunctionFilter (" filter" , cl::sub(InstructionMix), cl::init(" .*" ),
23+ cl::value_desc (" filter_regex" ),
24+ cl::desc(" regex to filter functions with" ));
25+
26+ enum ReportStyleOptions { human_output, csv_output };
27+ static cl::opt<ReportStyleOptions> ReportStyle (
28+ " report_style" , cl::sub(InstructionMix),
29+ cl::init(ReportStyleOptions::human_output),
30+ cl::desc(" Choose the report output format:" ),
31+ cl::values(clEnumValN(human_output, " human" , " Human-readable format" ),
32+ clEnumValN(csv_output, " csv" , " CSV format" )));
33+
34+ INPUT_FORMAT_COMMAND_LINE_OPTIONS (InstructionMix)
35+ INPUT_OUTPUT_COMMAND_LINE_OPTIONS (InstructionMix)
36+ DEBUG_LOC_INFO_COMMAND_LINE_OPTIONS (InstructionMix)
37+
38+ static Error tryInstructionMix () {
39+ auto MaybeOF =
40+ getOutputFileWithFlags (OutputFileName, sys::fs::OF_TextWithCRLF);
41+ if (!MaybeOF)
42+ return MaybeOF.takeError ();
43+
44+ auto OF = std::move (*MaybeOF);
45+ auto MaybeBuf = getInputMemoryBuffer (InputFileName);
46+ if (!MaybeBuf)
47+ return MaybeBuf.takeError ();
48+ auto MaybeParser = createRemarkParser (InputFormat, (*MaybeBuf)->getBuffer ());
49+ if (!MaybeParser)
50+ return MaybeParser.takeError ();
51+
52+ Regex Filter (FunctionFilter);
53+
54+ // Collect the histogram of instruction counts.
55+ std::unordered_map<std::string, unsigned > Histogram;
56+ auto &Parser = **MaybeParser;
57+ auto MaybeRemark = Parser.next ();
58+ for (; MaybeRemark; MaybeRemark = Parser.next ()) {
59+ auto &Remark = **MaybeRemark;
60+ if (Remark.RemarkName != " InstructionMix" )
61+ continue ;
62+ if (!Filter.match (Remark.FunctionName ))
63+ continue ;
64+ for (auto &Arg : Remark.Args ) {
65+ StringRef Key = Arg.Key ;
66+ if (!Key.consume_front (" INST_" ))
67+ continue ;
68+ unsigned Val = 0 ;
69+ bool ParseError = Arg.Val .getAsInteger (10 , Val);
70+ assert (!ParseError);
71+ (void )ParseError;
72+ Histogram[std::string (Key)] += Val;
73+ }
74+ }
75+
76+ // Sort it.
77+ using MixEntry = std::pair<std::string, unsigned >;
78+ llvm::SmallVector<MixEntry> Mix (Histogram.begin (), Histogram.end ());
79+ std::sort (Mix.begin (), Mix.end (), [](const auto &LHS, const auto &RHS) {
80+ return LHS.second > RHS.second ;
81+ });
82+
83+ // Print the results.
84+ switch (ReportStyle) {
85+ case human_output: {
86+ formatted_raw_ostream FOS (OF->os ());
87+ size_t MaxMnemonic =
88+ std::accumulate (Mix.begin (), Mix.end (), StringRef (" Instruction" ).size (),
89+ [](size_t MaxMnemonic, const MixEntry &Elt) {
90+ return std::max (MaxMnemonic, Elt.first .length ());
91+ });
92+ unsigned MaxValue = std::accumulate (
93+ Mix.begin (), Mix.end (), 0 , [](unsigned MaxValue, const MixEntry &Elt) {
94+ return std::max (MaxValue, Elt.second );
95+ });
96+ unsigned ValueWidth = log10 (MaxValue) + 1 ;
97+ FOS << " Instruction" ;
98+ FOS.PadToColumn (MaxMnemonic + 1 ) << " Count\n " ;
99+ FOS << " -----------" ;
100+ FOS.PadToColumn (MaxMnemonic + 1 ) << " -----\n " ;
101+ for (const auto &[Inst, Count] : Mix) {
102+ FOS << Inst;
103+ FOS.PadToColumn (MaxMnemonic + 1 )
104+ << " " << format_decimal (Count, ValueWidth) << " \n " ;
105+ }
106+ } break ;
107+ case csv_output: {
108+ OF->os () << " Instruction,Count\n " ;
109+ for (const auto &[Inst, Count] : Mix)
110+ OF->os () << Inst << " ," << Count << " \n " ;
111+ } break ;
112+ }
113+
114+ auto E = MaybeRemark.takeError ();
115+ if (!E.isA <EndOfFileError>())
116+ return E;
117+ consumeError (std::move (E));
118+ OF->keep ();
119+ return Error::success ();
120+ }
121+
122+ static CommandRegistration InstructionMixReg (&InstructionMix,
123+ tryInstructionMix);
124+
125+ } // namespace instructionmix
0 commit comments