Target.cpp 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. //===-- Target.cpp ----------------------------------------------*- C++ -*-===//
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. #include "Target.h"
  9. #include "LatencyBenchmarkRunner.h"
  10. #include "ParallelSnippetGenerator.h"
  11. #include "SerialSnippetGenerator.h"
  12. #include "UopsBenchmarkRunner.h"
  13. #include "llvm/ADT/Twine.h"
  14. #include "llvm/Support/Error.h"
  15. namespace llvm {
  16. namespace exegesis {
  17. ExegesisTarget::~ExegesisTarget() {} // anchor.
  18. static ExegesisTarget *FirstTarget = nullptr;
  19. const ExegesisTarget *ExegesisTarget::lookup(Triple TT) {
  20. for (const ExegesisTarget *T = FirstTarget; T != nullptr; T = T->Next) {
  21. if (T->matchesArch(TT.getArch()))
  22. return T;
  23. }
  24. return nullptr;
  25. }
  26. Expected<std::unique_ptr<pfm::Counter>>
  27. ExegesisTarget::createCounter(StringRef CounterName, const LLVMState &) const {
  28. pfm::PerfEvent Event(CounterName);
  29. if (!Event.valid())
  30. return llvm::make_error<Failure>(
  31. llvm::Twine("Unable to create counter with name '")
  32. .concat(CounterName)
  33. .concat("'"));
  34. return std::make_unique<pfm::Counter>(std::move(Event));
  35. }
  36. void ExegesisTarget::registerTarget(ExegesisTarget *Target) {
  37. if (FirstTarget == nullptr) {
  38. FirstTarget = Target;
  39. return;
  40. }
  41. if (Target->Next != nullptr)
  42. return; // Already registered.
  43. Target->Next = FirstTarget;
  44. FirstTarget = Target;
  45. }
  46. std::unique_ptr<SnippetGenerator> ExegesisTarget::createSnippetGenerator(
  47. InstructionBenchmark::ModeE Mode, const LLVMState &State,
  48. const SnippetGenerator::Options &Opts) const {
  49. switch (Mode) {
  50. case InstructionBenchmark::Unknown:
  51. return nullptr;
  52. case InstructionBenchmark::Latency:
  53. return createSerialSnippetGenerator(State, Opts);
  54. case InstructionBenchmark::Uops:
  55. case InstructionBenchmark::InverseThroughput:
  56. return createParallelSnippetGenerator(State, Opts);
  57. }
  58. return nullptr;
  59. }
  60. Expected<std::unique_ptr<BenchmarkRunner>>
  61. ExegesisTarget::createBenchmarkRunner(
  62. InstructionBenchmark::ModeE Mode, const LLVMState &State,
  63. InstructionBenchmark::ResultAggregationModeE ResultAggMode) const {
  64. PfmCountersInfo PfmCounters = State.getPfmCounters();
  65. switch (Mode) {
  66. case InstructionBenchmark::Unknown:
  67. return nullptr;
  68. case InstructionBenchmark::Latency:
  69. case InstructionBenchmark::InverseThroughput:
  70. if (!PfmCounters.CycleCounter) {
  71. const char *ModeName = Mode == InstructionBenchmark::Latency
  72. ? "latency"
  73. : "inverse_throughput";
  74. return make_error<Failure>(
  75. Twine("can't run '")
  76. .concat(ModeName)
  77. .concat("' mode, sched model does not define a cycle counter."));
  78. }
  79. return createLatencyBenchmarkRunner(State, Mode, ResultAggMode);
  80. case InstructionBenchmark::Uops:
  81. if (!PfmCounters.UopsCounter && !PfmCounters.IssueCounters)
  82. return make_error<Failure>("can't run 'uops' mode, sched model does not "
  83. "define uops or issue counters.");
  84. return createUopsBenchmarkRunner(State, ResultAggMode);
  85. }
  86. return nullptr;
  87. }
  88. std::unique_ptr<SnippetGenerator> ExegesisTarget::createSerialSnippetGenerator(
  89. const LLVMState &State, const SnippetGenerator::Options &Opts) const {
  90. return std::make_unique<SerialSnippetGenerator>(State, Opts);
  91. }
  92. std::unique_ptr<SnippetGenerator> ExegesisTarget::createParallelSnippetGenerator(
  93. const LLVMState &State, const SnippetGenerator::Options &Opts) const {
  94. return std::make_unique<ParallelSnippetGenerator>(State, Opts);
  95. }
  96. std::unique_ptr<BenchmarkRunner> ExegesisTarget::createLatencyBenchmarkRunner(
  97. const LLVMState &State, InstructionBenchmark::ModeE Mode,
  98. InstructionBenchmark::ResultAggregationModeE ResultAggMode) const {
  99. return std::make_unique<LatencyBenchmarkRunner>(State, Mode, ResultAggMode);
  100. }
  101. std::unique_ptr<BenchmarkRunner> ExegesisTarget::createUopsBenchmarkRunner(
  102. const LLVMState &State,
  103. InstructionBenchmark::ResultAggregationModeE /*unused*/) const {
  104. return std::make_unique<UopsBenchmarkRunner>(State);
  105. }
  106. static_assert(std::is_pod<PfmCountersInfo>::value,
  107. "We shouldn't have dynamic initialization here");
  108. const PfmCountersInfo PfmCountersInfo::Default = {nullptr, nullptr, nullptr,
  109. 0u};
  110. const PfmCountersInfo &ExegesisTarget::getPfmCounters(StringRef CpuName) const {
  111. assert(llvm::is_sorted(
  112. CpuPfmCounters,
  113. [](const CpuAndPfmCounters &LHS, const CpuAndPfmCounters &RHS) {
  114. return strcmp(LHS.CpuName, RHS.CpuName) < 0;
  115. }) &&
  116. "CpuPfmCounters table is not sorted");
  117. // Find entry
  118. auto Found = llvm::lower_bound(CpuPfmCounters, CpuName);
  119. if (Found == CpuPfmCounters.end() || StringRef(Found->CpuName) != CpuName) {
  120. // Use the default.
  121. if (!CpuPfmCounters.empty() && CpuPfmCounters.begin()->CpuName[0] == '\0') {
  122. Found = CpuPfmCounters.begin(); // The target specifies a default.
  123. } else {
  124. return PfmCountersInfo::Default; // No default for the target.
  125. }
  126. }
  127. assert(Found->PCI && "Missing counters");
  128. return *Found->PCI;
  129. }
  130. ExegesisTarget::SavedState::~SavedState() {} // anchor.
  131. namespace {
  132. // Default implementation.
  133. class ExegesisDefaultTarget : public ExegesisTarget {
  134. public:
  135. ExegesisDefaultTarget() : ExegesisTarget({}) {}
  136. private:
  137. std::vector<MCInst> setRegTo(const MCSubtargetInfo &STI, unsigned Reg,
  138. const APInt &Value) const override {
  139. llvm_unreachable("Not yet implemented");
  140. }
  141. bool matchesArch(Triple::ArchType Arch) const override {
  142. llvm_unreachable("never called");
  143. return false;
  144. }
  145. };
  146. } // namespace
  147. const ExegesisTarget &ExegesisTarget::getDefault() {
  148. static ExegesisDefaultTarget Target;
  149. return Target;
  150. }
  151. } // namespace exegesis
  152. } // namespace llvm