Target.cpp 6.8 KB

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