SnippetRepetitor.cpp 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. //===-- SnippetRepetitor.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 <array>
  9. #include <string>
  10. #include "SnippetRepetitor.h"
  11. #include "Target.h"
  12. #include "llvm/ADT/Sequence.h"
  13. #include "llvm/CodeGen/TargetInstrInfo.h"
  14. #include "llvm/CodeGen/TargetSubtargetInfo.h"
  15. namespace llvm {
  16. namespace exegesis {
  17. namespace {
  18. class DuplicateSnippetRepetitor : public SnippetRepetitor {
  19. public:
  20. using SnippetRepetitor::SnippetRepetitor;
  21. // Repeats the snippet until there are at least MinInstructions in the
  22. // resulting code.
  23. FillFunction Repeat(ArrayRef<MCInst> Instructions, unsigned MinInstructions,
  24. unsigned LoopBodySize) const override {
  25. return [Instructions, MinInstructions](FunctionFiller &Filler) {
  26. auto Entry = Filler.getEntry();
  27. if (!Instructions.empty()) {
  28. // Add the whole snippet at least once.
  29. Entry.addInstructions(Instructions);
  30. for (unsigned I = Instructions.size(); I < MinInstructions; ++I) {
  31. Entry.addInstruction(Instructions[I % Instructions.size()]);
  32. }
  33. }
  34. Entry.addReturn();
  35. };
  36. }
  37. BitVector getReservedRegs() const override {
  38. // We're using no additional registers.
  39. return State.getRATC().emptyRegisters();
  40. }
  41. };
  42. class LoopSnippetRepetitor : public SnippetRepetitor {
  43. public:
  44. explicit LoopSnippetRepetitor(const LLVMState &State)
  45. : SnippetRepetitor(State),
  46. LoopCounter(State.getExegesisTarget().getLoopCounterRegister(
  47. State.getTargetMachine().getTargetTriple())) {}
  48. // Loop over the snippet ceil(MinInstructions / Instructions.Size()) times.
  49. FillFunction Repeat(ArrayRef<MCInst> Instructions, unsigned MinInstructions,
  50. unsigned LoopBodySize) const override {
  51. return [this, Instructions, MinInstructions,
  52. LoopBodySize](FunctionFiller &Filler) {
  53. const auto &ET = State.getExegesisTarget();
  54. auto Entry = Filler.getEntry();
  55. auto Loop = Filler.addBasicBlock();
  56. auto Exit = Filler.addBasicBlock();
  57. const unsigned LoopUnrollFactor =
  58. LoopBodySize <= Instructions.size()
  59. ? 1
  60. : divideCeil(LoopBodySize, Instructions.size());
  61. assert(LoopUnrollFactor >= 1 && "Should end up with at least 1 snippet.");
  62. // Set loop counter to the right value:
  63. const APInt LoopCount(
  64. 32,
  65. divideCeil(MinInstructions, LoopUnrollFactor * Instructions.size()));
  66. assert(LoopCount.uge(1) && "Trip count should be at least 1.");
  67. for (const MCInst &Inst :
  68. ET.setRegTo(State.getSubtargetInfo(), LoopCounter, LoopCount))
  69. Entry.addInstruction(Inst);
  70. // Set up the loop basic block.
  71. Entry.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
  72. Loop.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
  73. // The live ins are: the loop counter, the registers that were setup by
  74. // the entry block, and entry block live ins.
  75. Loop.MBB->addLiveIn(LoopCounter);
  76. for (unsigned Reg : Filler.getRegistersSetUp())
  77. Loop.MBB->addLiveIn(Reg);
  78. for (const auto &LiveIn : Entry.MBB->liveins())
  79. Loop.MBB->addLiveIn(LiveIn);
  80. for (auto _ : seq(0U, LoopUnrollFactor)) {
  81. (void)_;
  82. Loop.addInstructions(Instructions);
  83. }
  84. ET.decrementLoopCounterAndJump(*Loop.MBB, *Loop.MBB,
  85. State.getInstrInfo());
  86. // Set up the exit basic block.
  87. Loop.MBB->addSuccessor(Exit.MBB, BranchProbability::getZero());
  88. Exit.addReturn();
  89. };
  90. }
  91. BitVector getReservedRegs() const override {
  92. // We're using a single loop counter, but we have to reserve all aliasing
  93. // registers.
  94. return State.getRATC().getRegister(LoopCounter).aliasedBits();
  95. }
  96. private:
  97. const unsigned LoopCounter;
  98. };
  99. } // namespace
  100. SnippetRepetitor::~SnippetRepetitor() {}
  101. std::unique_ptr<const SnippetRepetitor>
  102. SnippetRepetitor::Create(InstructionBenchmark::RepetitionModeE Mode,
  103. const LLVMState &State) {
  104. switch (Mode) {
  105. case InstructionBenchmark::Duplicate:
  106. return std::make_unique<DuplicateSnippetRepetitor>(State);
  107. case InstructionBenchmark::Loop:
  108. return std::make_unique<LoopSnippetRepetitor>(State);
  109. case InstructionBenchmark::AggregateMin:
  110. break;
  111. }
  112. llvm_unreachable("Unknown RepetitionModeE enum");
  113. }
  114. } // namespace exegesis
  115. } // namespace llvm