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.
Repeat(ArrayRef<MCInst> Instructions,unsigned MinInstructions,unsigned LoopBodySize) const28 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
getReservedRegs() const43 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:
LoopSnippetRepetitor(const LLVMState & State)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.
Repeat(ArrayRef<MCInst> Instructions,unsigned MinInstructions,unsigned LoopBodySize) const57 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
getReservedRegs() const104 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
~SnippetRepetitor()116 SnippetRepetitor::~SnippetRepetitor() {}
117
118 std::unique_ptr<const SnippetRepetitor>
Create(InstructionBenchmark::RepetitionModeE Mode,const LLVMState & State)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