brintos

brintos / llvm-project-archived public Read only

0
0
Text · 9.0 KiB · bd69919 Raw
256 lines · cpp
1//===- ExegesisEmitter.cpp - Generate exegesis target data ----------------===//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// This tablegen backend emits llvm-exegesis information.10//11//===----------------------------------------------------------------------===//12 13#include "llvm/ADT/STLExtras.h"14#include "llvm/ADT/SmallSet.h"15#include "llvm/ADT/StringRef.h"16#include "llvm/Support/raw_ostream.h"17#include "llvm/TableGen/Error.h"18#include "llvm/TableGen/Record.h"19#include "llvm/TableGen/TableGenBackend.h"20#include <cassert>21#include <map>22#include <string>23#include <vector>24 25using namespace llvm;26 27#define DEBUG_TYPE "exegesis-emitter"28 29namespace {30 31class ExegesisEmitter {32public:33  ExegesisEmitter(const RecordKeeper &RK);34 35  void run(raw_ostream &OS) const;36 37private:38  unsigned getPfmCounterId(llvm::StringRef Name) const {39    const auto It = PfmCounterNameTable.find(Name);40    if (It == PfmCounterNameTable.end())41      PrintFatalError("no pfm counter id for " + Name);42    return It->second;43  }44 45  // Collects all the ProcPfmCounters definitions available in this target.46  void emitPfmCounters(raw_ostream &OS) const;47 48  void emitPfmCountersInfo(const Record &Def,49                           unsigned &IssueCountersTableOffset,50                           raw_ostream &OS) const;51 52  void emitPfmCountersLookupTable(raw_ostream &OS) const;53 54  const RecordKeeper &Records;55  std::string Target;56 57  // Table of counter name -> counter index.58  const std::map<llvm::StringRef, unsigned> PfmCounterNameTable;59};60 61struct ValidationCounterInfo {62  int64_t EventNumber;63  StringRef EventName;64  unsigned PfmCounterID;65};66 67} // namespace68 69static std::map<llvm::StringRef, unsigned>70collectPfmCounters(const RecordKeeper &Records) {71  std::map<llvm::StringRef, unsigned> PfmCounterNameTable;72  const auto AddPfmCounterName = [&PfmCounterNameTable](73                                     const Record *PfmCounterDef) {74    const llvm::StringRef Counter = PfmCounterDef->getValueAsString("Counter");75    if (!Counter.empty())76      PfmCounterNameTable.emplace(Counter, 0);77  };78  for (const Record *Def :79       Records.getAllDerivedDefinitions("ProcPfmCounters")) {80    // Check that ResourceNames are unique.81    llvm::SmallSet<llvm::StringRef, 16> Seen;82    for (const Record *IssueCounter :83         Def->getValueAsListOfDefs("IssueCounters")) {84      const llvm::StringRef ResourceName =85          IssueCounter->getValueAsString("ResourceName");86      if (ResourceName.empty())87        PrintFatalError(IssueCounter->getLoc(), "invalid empty ResourceName");88      if (!Seen.insert(ResourceName).second)89        PrintFatalError(IssueCounter->getLoc(),90                        "duplicate ResourceName " + ResourceName);91      AddPfmCounterName(IssueCounter);92    }93 94    for (const Record *ValidationCounter :95         Def->getValueAsListOfDefs("ValidationCounters"))96      AddPfmCounterName(ValidationCounter);97 98    AddPfmCounterName(Def->getValueAsDef("CycleCounter"));99    AddPfmCounterName(Def->getValueAsDef("UopsCounter"));100  }101  unsigned Index = 0;102  for (auto &NameAndIndex : PfmCounterNameTable)103    NameAndIndex.second = Index++;104  return PfmCounterNameTable;105}106 107ExegesisEmitter::ExegesisEmitter(const RecordKeeper &RK)108    : Records(RK), PfmCounterNameTable(collectPfmCounters(RK)) {109  ArrayRef<const Record *> Targets = Records.getAllDerivedDefinitions("Target");110  if (Targets.size() == 0)111    PrintFatalError("No 'Target' subclasses defined!");112  if (Targets.size() != 1)113    PrintFatalError("Multiple subclasses of Target defined!");114  Target = Targets[0]->getName().str();115}116 117static bool EventNumberLess(const ValidationCounterInfo &LHS,118                            const ValidationCounterInfo &RHS) {119  return LHS.EventNumber < RHS.EventNumber;120}121 122void ExegesisEmitter::emitPfmCountersInfo(const Record &Def,123                                          unsigned &IssueCountersTableOffset,124                                          raw_ostream &OS) const {125  const auto CycleCounter =126      Def.getValueAsDef("CycleCounter")->getValueAsString("Counter");127  const auto UopsCounter =128      Def.getValueAsDef("UopsCounter")->getValueAsString("Counter");129  const size_t NumIssueCounters =130      Def.getValueAsListOfDefs("IssueCounters").size();131  const size_t NumValidationCounters =132      Def.getValueAsListOfDefs("ValidationCounters").size();133 134  // Emit Validation Counters Array135  if (NumValidationCounters != 0) {136    std::vector<ValidationCounterInfo> ValidationCounters;137    ValidationCounters.reserve(NumValidationCounters);138    for (const Record *ValidationCounter :139         Def.getValueAsListOfDefs("ValidationCounters")) {140      ValidationCounters.push_back(141          {ValidationCounter->getValueAsDef("EventType")142               ->getValueAsInt("EventNumber"),143           ValidationCounter->getValueAsDef("EventType")->getName(),144           getPfmCounterId(ValidationCounter->getValueAsString("Counter"))});145    }146    std::sort(ValidationCounters.begin(), ValidationCounters.end(),147              EventNumberLess);148    OS << "\nstatic const std::pair<ValidationEvent, const char*> " << Target149       << Def.getName() << "ValidationCounters[] = {\n";150    for (const ValidationCounterInfo &VCI : ValidationCounters) {151      OS << "  { " << VCI.EventName << ", " << Target << "PfmCounterNames["152         << VCI.PfmCounterID << "]},\n";153    }154    OS << "};\n";155  }156 157  OS << "\nstatic const PfmCountersInfo " << Target << Def.getName()158     << " = {\n";159 160  // Cycle Counter.161  if (CycleCounter.empty())162    OS << "  nullptr,  // No cycle counter.\n";163  else164    OS << "  " << Target << "PfmCounterNames[" << getPfmCounterId(CycleCounter)165       << "],  // Cycle counter\n";166 167  // Uops Counter.168  if (UopsCounter.empty())169    OS << "  nullptr,  // No uops counter.\n";170  else171    OS << "  " << Target << "PfmCounterNames[" << getPfmCounterId(UopsCounter)172       << "],  // Uops counter\n";173 174  // Issue Counters175  if (NumIssueCounters == 0)176    OS << "  nullptr, 0, // No issue counters\n";177  else178    OS << "  " << Target << "PfmIssueCounters + " << IssueCountersTableOffset179       << ", " << NumIssueCounters << ", // Issue counters.\n";180 181  // Validation Counters182  if (NumValidationCounters == 0)183    OS << "  nullptr, 0 // No validation counters.\n";184  else185    OS << "  " << Target << Def.getName() << "ValidationCounters, "186       << NumValidationCounters << " // Validation counters.\n";187 188  OS << "};\n";189  IssueCountersTableOffset += NumIssueCounters;190}191 192void ExegesisEmitter::emitPfmCounters(raw_ostream &OS) const {193  // Emit the counter name table.194  OS << "\nstatic const char *" << Target << "PfmCounterNames[] = {\n";195  for (const auto &NameAndIndex : PfmCounterNameTable)196    OS << "  \"" << NameAndIndex.first << "\", // " << NameAndIndex.second197       << "\n";198  OS << "};\n\n";199 200  // Emit the IssueCounters table.201  const auto PfmCounterDefs =202      Records.getAllDerivedDefinitions("ProcPfmCounters");203  // Only emit if non-empty.204  const bool HasAtLeastOnePfmIssueCounter =205      llvm::any_of(PfmCounterDefs, [](const Record *Def) {206        return !Def->getValueAsListOfDefs("IssueCounters").empty();207      });208  if (HasAtLeastOnePfmIssueCounter) {209    OS << "static const PfmCountersInfo::IssueCounter " << Target210       << "PfmIssueCounters[] = {\n";211    for (const Record *Def : PfmCounterDefs) {212      for (const Record *ICDef : Def->getValueAsListOfDefs("IssueCounters"))213        OS << "  { " << Target << "PfmCounterNames["214           << getPfmCounterId(ICDef->getValueAsString("Counter")) << "], \""215           << ICDef->getValueAsString("ResourceName") << "\"},\n";216    }217    OS << "};\n";218  }219 220  // Now generate the PfmCountersInfo.221  unsigned IssueCountersTableOffset = 0;222  for (const Record *Def : PfmCounterDefs)223    emitPfmCountersInfo(*Def, IssueCountersTableOffset, OS);224 225  OS << "\n";226}227 228void ExegesisEmitter::emitPfmCountersLookupTable(raw_ostream &OS) const {229  std::vector<const Record *> Bindings =230      Records.getAllDerivedDefinitions("PfmCountersBinding");231  assert(!Bindings.empty() && "there must be at least one binding");232  llvm::sort(Bindings, [](const Record *L, const Record *R) {233    return L->getValueAsString("CpuName") < R->getValueAsString("CpuName");234  });235 236  OS << "// Sorted (by CpuName) array of pfm counters.\n"237     << "static const CpuAndPfmCounters " << Target << "CpuPfmCounters[] = {\n";238  for (const Record *Binding : Bindings) {239    // Emit as { "cpu", procinit },240    OS << "  { \""                                                        //241       << Binding->getValueAsString("CpuName") << "\","                   //242       << " &" << Target << Binding->getValueAsDef("Counters")->getName() //243       << " },\n";244  }245  OS << "};\n\n";246}247 248void ExegesisEmitter::run(raw_ostream &OS) const {249  emitSourceFileHeader("Exegesis Tables", OS);250  emitPfmCounters(OS);251  emitPfmCountersLookupTable(OS);252}253 254static TableGen::Emitter::OptClass<ExegesisEmitter>255    X("gen-exegesis", "Generate llvm-exegesis tables");256