Path: blob/main/contrib/llvm-project/llvm/tools/llvm-remarkutil/RemarkInstructionMix.cpp
213766 views
//===- RemarkInstructionMix.cpp -------------------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7//8// Generic tool to extract instruction mix from asm-printer remarks.9//10//===----------------------------------------------------------------------===//1112#include "RemarkUtilHelpers.h"13#include "RemarkUtilRegistry.h"1415#include "llvm/Support/Format.h"16#include "llvm/Support/FormattedStream.h"17#include "llvm/Support/Regex.h"1819#include <cmath>20#include <numeric>2122using namespace llvm;23using namespace remarks;24using namespace llvm::remarkutil;2526namespace instructionmix {2728static cl::SubCommand29InstructionMix("instruction-mix",30"Instruction Mix (requires asm-printer remarks)");3132static cl::opt<std::string>33FunctionFilter("filter", cl::sub(InstructionMix), cl::ValueOptional,34cl::desc("Optional function name to filter collection by"));3536static cl::opt<std::string>37FunctionFilterRE("rfilter", cl::sub(InstructionMix), cl::ValueOptional,38cl::desc("Optional function name to filter collection by "39"(accepts regular expressions)"));4041enum ReportStyleOptions { human_output, csv_output };42static cl::opt<ReportStyleOptions> ReportStyle(43"report_style", cl::sub(InstructionMix),44cl::init(ReportStyleOptions::human_output),45cl::desc("Choose the report output format:"),46cl::values(clEnumValN(human_output, "human", "Human-readable format"),47clEnumValN(csv_output, "csv", "CSV format")));4849INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionMix)50INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionMix)5152static Error tryInstructionMix() {53auto MaybeOF =54getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);55if (!MaybeOF)56return MaybeOF.takeError();5758auto OF = std::move(*MaybeOF);59auto MaybeBuf = getInputMemoryBuffer(InputFileName);60if (!MaybeBuf)61return MaybeBuf.takeError();62auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());63if (!MaybeParser)64return MaybeParser.takeError();6566Expected<std::optional<FilterMatcher>> Filter =67FilterMatcher::createExactOrRE(FunctionFilter, FunctionFilterRE);68if (!Filter)69return Filter.takeError();7071// Collect the histogram of instruction counts.72llvm::DenseMap<StringRef, unsigned> Histogram;73auto &Parser = **MaybeParser;74auto MaybeRemark = Parser.next();75for (; MaybeRemark; MaybeRemark = Parser.next()) {76Remark &Remark = **MaybeRemark;77if (Remark.RemarkName != "InstructionMix")78continue;79if (*Filter && !(*Filter)->match(Remark.FunctionName))80continue;81for (auto &Arg : Remark.Args) {82StringRef Key = Arg.Key;83if (!Key.consume_front("INST_"))84continue;85unsigned Val = 0;86bool ParseError = Arg.Val.getAsInteger(10, Val);87assert(!ParseError);88(void)ParseError;89Histogram[Key] += Val;90}91}9293// Sort it.94using MixEntry = std::pair<StringRef, unsigned>;95llvm::SmallVector<MixEntry> Mix(Histogram.begin(), Histogram.end());96std::sort(Mix.begin(), Mix.end(), [](const auto &LHS, const auto &RHS) {97return LHS.second > RHS.second;98});99100// Print the results.101switch (ReportStyle) {102case human_output: {103formatted_raw_ostream FOS(OF->os());104size_t MaxMnemonic =105std::accumulate(Mix.begin(), Mix.end(), StringRef("Instruction").size(),106[](size_t MaxMnemonic, const MixEntry &Elt) {107return std::max(MaxMnemonic, Elt.first.size());108});109unsigned MaxValue = std::accumulate(110Mix.begin(), Mix.end(), 1, [](unsigned MaxValue, const MixEntry &Elt) {111return std::max(MaxValue, Elt.second);112});113unsigned ValueWidth = std::log10(MaxValue) + 1;114FOS << "Instruction";115FOS.PadToColumn(MaxMnemonic + 1) << "Count\n";116FOS << "-----------";117FOS.PadToColumn(MaxMnemonic + 1) << "-----\n";118for (const auto &[Inst, Count] : Mix) {119FOS << Inst;120FOS.PadToColumn(MaxMnemonic + 1)121<< " " << format_decimal(Count, ValueWidth) << "\n";122}123} break;124case csv_output: {125OF->os() << "Instruction,Count\n";126for (const auto &[Inst, Count] : Mix)127OF->os() << Inst << "," << Count << "\n";128} break;129}130131auto E = MaybeRemark.takeError();132if (!E.isA<EndOfFileError>())133return E;134consumeError(std::move(E));135OF->keep();136return Error::success();137}138139static CommandRegistration InstructionMixReg(&InstructionMix,140tryInstructionMix);141142} // namespace instructionmix143144145