brintos

brintos / llvm-project-archived public Read only

0
0
Text · 4.8 KiB · 7c8ac47 Raw
144 lines · cpp
1//===- RemarkInstructionMix.cpp -------------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// Generic tool to extract instruction mix from asm-printer remarks.10//11//===----------------------------------------------------------------------===//12 13#include "RemarkUtilHelpers.h"14#include "RemarkUtilRegistry.h"15 16#include "llvm/Support/Format.h"17#include "llvm/Support/FormattedStream.h"18#include "llvm/Support/Regex.h"19 20#include <cmath>21#include <numeric>22 23using namespace llvm;24using namespace remarks;25using namespace llvm::remarkutil;26 27namespace instructionmix {28 29static cl::SubCommand30    InstructionMix("instruction-mix",31                   "Instruction Mix (requires asm-printer remarks)");32 33static cl::opt<std::string>34    FunctionFilter("filter", cl::sub(InstructionMix), cl::ValueOptional,35                   cl::desc("Optional function name to filter collection by"));36 37static cl::opt<std::string>38    FunctionFilterRE("rfilter", cl::sub(InstructionMix), cl::ValueOptional,39                     cl::desc("Optional function name to filter collection by "40                              "(accepts regular expressions)"));41 42enum ReportStyleOptions { human_output, csv_output };43static cl::opt<ReportStyleOptions> ReportStyle(44    "report_style", cl::sub(InstructionMix),45    cl::init(ReportStyleOptions::human_output),46    cl::desc("Choose the report output format:"),47    cl::values(clEnumValN(human_output, "human", "Human-readable format"),48               clEnumValN(csv_output, "csv", "CSV format")));49 50INPUT_FORMAT_COMMAND_LINE_OPTIONS(InstructionMix)51INPUT_OUTPUT_COMMAND_LINE_OPTIONS(InstructionMix)52 53static Error tryInstructionMix() {54  auto MaybeOF =55      getOutputFileWithFlags(OutputFileName, sys::fs::OF_TextWithCRLF);56  if (!MaybeOF)57    return MaybeOF.takeError();58 59  auto OF = std::move(*MaybeOF);60  auto MaybeBuf = getInputMemoryBuffer(InputFileName);61  if (!MaybeBuf)62    return MaybeBuf.takeError();63  auto MaybeParser = createRemarkParser(InputFormat, (*MaybeBuf)->getBuffer());64  if (!MaybeParser)65    return MaybeParser.takeError();66 67  Expected<std::optional<FilterMatcher>> Filter =68      FilterMatcher::createExactOrRE(FunctionFilter, FunctionFilterRE);69  if (!Filter)70    return Filter.takeError();71 72  // Collect the histogram of instruction counts.73  llvm::DenseMap<StringRef, unsigned> Histogram;74  auto &Parser = **MaybeParser;75  auto MaybeRemark = Parser.next();76  for (; MaybeRemark; MaybeRemark = Parser.next()) {77    Remark &Remark = **MaybeRemark;78    if (Remark.RemarkName != "InstructionMix")79      continue;80    if (*Filter && !(*Filter)->match(Remark.FunctionName))81      continue;82    for (auto &Arg : Remark.Args) {83      StringRef Key = Arg.Key;84      if (!Key.consume_front("INST_"))85        continue;86      unsigned Val = 0;87      bool ParseError = Arg.Val.getAsInteger(10, Val);88      assert(!ParseError);89      (void)ParseError;90      Histogram[Key] += Val;91    }92  }93 94  // Sort it.95  using MixEntry = std::pair<StringRef, unsigned>;96  llvm::SmallVector<MixEntry> Mix(Histogram.begin(), Histogram.end());97  std::sort(Mix.begin(), Mix.end(), [](const auto &LHS, const auto &RHS) {98    return LHS.second > RHS.second;99  });100 101  // Print the results.102  switch (ReportStyle) {103  case human_output: {104    formatted_raw_ostream FOS(OF->os());105    size_t MaxMnemonic =106        std::accumulate(Mix.begin(), Mix.end(), StringRef("Instruction").size(),107                        [](size_t MaxMnemonic, const MixEntry &Elt) {108                          return std::max(MaxMnemonic, Elt.first.size());109                        });110    unsigned MaxValue = std::accumulate(111        Mix.begin(), Mix.end(), 1, [](unsigned MaxValue, const MixEntry &Elt) {112          return std::max(MaxValue, Elt.second);113        });114    unsigned ValueWidth = std::log10(MaxValue) + 1;115    FOS << "Instruction";116    FOS.PadToColumn(MaxMnemonic + 1) << "Count\n";117    FOS << "-----------";118    FOS.PadToColumn(MaxMnemonic + 1) << "-----\n";119    for (const auto &[Inst, Count] : Mix) {120      FOS << Inst;121      FOS.PadToColumn(MaxMnemonic + 1)122          << " " << format_decimal(Count, ValueWidth) << "\n";123    }124  } break;125  case csv_output: {126    OF->os() << "Instruction,Count\n";127    for (const auto &[Inst, Count] : Mix)128      OF->os() << Inst << "," << Count << "\n";129  } break;130  }131 132  auto E = MaybeRemark.takeError();133  if (!E.isA<EndOfFileError>())134    return E;135  consumeError(std::move(E));136  OF->keep();137  return Error::success();138}139 140static CommandRegistration InstructionMixReg(&InstructionMix,141                                             tryInstructionMix);142 143} // namespace instructionmix144