SnippetRepetitor.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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. // We can not use loop snippet repetitor for terminator instructions.
  56. for (const MCInst &Inst : Instructions) {
  57. const unsigned Opcode = Inst.getOpcode();
  58. const MCInstrDesc &MCID = Filler.MCII->get(Opcode);
  59. if (!MCID.isTerminator())
  60. continue;
  61. Entry.addReturn();
  62. return;
  63. }
  64. auto Loop = Filler.addBasicBlock();
  65. auto Exit = Filler.addBasicBlock();
  66. const unsigned LoopUnrollFactor =
  67. LoopBodySize <= Instructions.size()
  68. ? 1
  69. : divideCeil(LoopBodySize, Instructions.size());
  70. assert(LoopUnrollFactor >= 1 && "Should end up with at least 1 snippet.");
  71. // Set loop counter to the right value:
  72. const APInt LoopCount(
  73. 32,
  74. divideCeil(MinInstructions, LoopUnrollFactor * Instructions.size()));
  75. assert(LoopCount.uge(1) && "Trip count should be at least 1.");
  76. for (const MCInst &Inst :
  77. ET.setRegTo(State.getSubtargetInfo(), LoopCounter, LoopCount))
  78. Entry.addInstruction(Inst);
  79. // Set up the loop basic block.
  80. Entry.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
  81. Loop.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
  82. // If the snippet setup completed, then we can track liveness.
  83. if (Loop.MF.getProperties().hasProperty(
  84. MachineFunctionProperties::Property::TracksLiveness)) {
  85. // The live ins are: the loop counter, the registers that were setup by
  86. // the entry block, and entry block live ins.
  87. Loop.MBB->addLiveIn(LoopCounter);
  88. for (unsigned Reg : Filler.getRegistersSetUp())
  89. Loop.MBB->addLiveIn(Reg);
  90. for (const auto &LiveIn : Entry.MBB->liveins())
  91. Loop.MBB->addLiveIn(LiveIn);
  92. }
  93. for (auto _ : seq(0U, LoopUnrollFactor)) {
  94. (void)_;
  95. Loop.addInstructions(Instructions);
  96. }
  97. ET.decrementLoopCounterAndJump(*Loop.MBB, *Loop.MBB,
  98. State.getInstrInfo());
  99. // Set up the exit basic block.
  100. Loop.MBB->addSuccessor(Exit.MBB, BranchProbability::getZero());
  101. Exit.addReturn();
  102. };
  103. }
  104. BitVector getReservedRegs() const override {
  105. // We're using a single loop counter, but we have to reserve all aliasing
  106. // registers.
  107. return State.getRATC().getRegister(LoopCounter).aliasedBits();
  108. }
  109. private:
  110. const unsigned LoopCounter;
  111. };
  112. } // namespace
  113. SnippetRepetitor::~SnippetRepetitor() {}
  114. std::unique_ptr<const SnippetRepetitor>
  115. SnippetRepetitor::Create(InstructionBenchmark::RepetitionModeE Mode,
  116. const LLVMState &State) {
  117. switch (Mode) {
  118. case InstructionBenchmark::Duplicate:
  119. return std::make_unique<DuplicateSnippetRepetitor>(State);
  120. case InstructionBenchmark::Loop:
  121. return std::make_unique<LoopSnippetRepetitor>(State);
  122. case InstructionBenchmark::AggregateMin:
  123. break;
  124. }
  125. llvm_unreachable("Unknown RepetitionModeE enum");
  126. }
  127. } // namespace exegesis
  128. } // namespace llvm