SnippetRepetitor.cpp 4.1 KB

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