xref: /openbsd-src/gnu/llvm/llvm/tools/llvm-exegesis/lib/SnippetRepetitor.cpp (revision d415bd752c734aee168c4ee86ff32e8cc249eb16)
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 
64       // We can not use loop snippet repetitor for terminator instructions.
65       for (const MCInst &Inst : Instructions) {
66         const unsigned Opcode = Inst.getOpcode();
67         const MCInstrDesc &MCID = Filler.MCII->get(Opcode);
68         if (!MCID.isTerminator())
69           continue;
70         Entry.addReturn();
71         return;
72       }
73 
74       auto Loop = Filler.addBasicBlock();
75       auto Exit = Filler.addBasicBlock();
76 
77       const unsigned LoopUnrollFactor =
78           LoopBodySize <= Instructions.size()
79               ? 1
80               : divideCeil(LoopBodySize, Instructions.size());
81       assert(LoopUnrollFactor >= 1 && "Should end up with at least 1 snippet.");
82 
83       // Set loop counter to the right value:
84       const APInt LoopCount(
85           32,
86           divideCeil(MinInstructions, LoopUnrollFactor * Instructions.size()));
87       assert(LoopCount.uge(1) && "Trip count should be at least 1.");
88       for (const MCInst &Inst :
89            ET.setRegTo(State.getSubtargetInfo(), LoopCounter, LoopCount))
90         Entry.addInstruction(Inst);
91 
92       // Set up the loop basic block.
93       Entry.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
94       Loop.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
95       // If the snippet setup completed, then we can track liveness.
96       if (Loop.MF.getProperties().hasProperty(
97               MachineFunctionProperties::Property::TracksLiveness)) {
98         // The live ins are: the loop counter, the registers that were setup by
99         // the entry block, and entry block live ins.
100         Loop.MBB->addLiveIn(LoopCounter);
101         for (unsigned Reg : Filler.getRegistersSetUp())
102           Loop.MBB->addLiveIn(Reg);
103         for (const auto &LiveIn : Entry.MBB->liveins())
104           Loop.MBB->addLiveIn(LiveIn);
105       }
106       for (auto _ : seq(0U, LoopUnrollFactor)) {
107         (void)_;
108         Loop.addInstructions(Instructions);
109       }
110       ET.decrementLoopCounterAndJump(*Loop.MBB, *Loop.MBB,
111                                      State.getInstrInfo());
112 
113       // Set up the exit basic block.
114       Loop.MBB->addSuccessor(Exit.MBB, BranchProbability::getZero());
115       Exit.addReturn();
116     };
117   }
118 
getReservedRegs() const119   BitVector getReservedRegs() const override {
120     // We're using a single loop counter, but we have to reserve all aliasing
121     // registers.
122     return State.getRATC().getRegister(LoopCounter).aliasedBits();
123   }
124 
125 private:
126   const unsigned LoopCounter;
127 };
128 
129 } // namespace
130 
~SnippetRepetitor()131 SnippetRepetitor::~SnippetRepetitor() {}
132 
133 std::unique_ptr<const SnippetRepetitor>
Create(InstructionBenchmark::RepetitionModeE Mode,const LLVMState & State)134 SnippetRepetitor::Create(InstructionBenchmark::RepetitionModeE Mode,
135                          const LLVMState &State) {
136   switch (Mode) {
137   case InstructionBenchmark::Duplicate:
138     return std::make_unique<DuplicateSnippetRepetitor>(State);
139   case InstructionBenchmark::Loop:
140     return std::make_unique<LoopSnippetRepetitor>(State);
141   case InstructionBenchmark::AggregateMin:
142     break;
143   }
144   llvm_unreachable("Unknown RepetitionModeE enum");
145 }
146 
147 } // namespace exegesis
148 } // namespace llvm
149