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.
Repeat(ArrayRef<MCInst> Instructions,unsigned MinInstructions) const27   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 
getReservedRegs() const42   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:
LoopSnippetRepetitor(const LLVMState & State)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.
Repeat(ArrayRef<MCInst> Instructions,unsigned MinInstructions) const56   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, BranchProbability::getOne());
73       Loop.MBB->addSuccessor(Loop.MBB, 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.decrementLoopCounterAndJump(*Loop.MBB, *Loop.MBB,
83                                      State.getInstrInfo());
84 
85       // Set up the exit basic block.
86       Loop.MBB->addSuccessor(Exit.MBB, BranchProbability::getZero());
87       Exit.addReturn();
88     };
89   }
90 
getReservedRegs() const91   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 
97 private:
98   const unsigned LoopCounter;
99 };
100 
101 } // namespace
102 
~SnippetRepetitor()103 SnippetRepetitor::~SnippetRepetitor() {}
104 
105 std::unique_ptr<const SnippetRepetitor>
Create(InstructionBenchmark::RepetitionModeE Mode,const LLVMState & State)106 SnippetRepetitor::Create(InstructionBenchmark::RepetitionModeE Mode,
107                          const LLVMState &State) {
108   switch (Mode) {
109   case InstructionBenchmark::Duplicate:
110     return std::make_unique<DuplicateSnippetRepetitor>(State);
111   case InstructionBenchmark::Loop:
112     return std::make_unique<LoopSnippetRepetitor>(State);
113   case InstructionBenchmark::AggregateMin:
114     break;
115   }
116   llvm_unreachable("Unknown RepetitionModeE enum");
117 }
118 
119 } // namespace exegesis
120 } // namespace llvm
121