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