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