[clang][modules] Don't prevent translation of FW_Private includes when explicitly...
[llvm-project.git] / llvm / tools / llvm-exegesis / lib / SnippetRepetitor.cpp
blob636dd11ff32658b93e5e406fc53496b39ddcac98
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 //===----------------------------------------------------------------------===//
9 #include <array>
10 #include <string>
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"
18 namespace llvm {
19 namespace exegesis {
20 namespace {
22 class DuplicateSnippetRepetitor : public SnippetRepetitor {
23 public:
24 using SnippetRepetitor::SnippetRepetitor;
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,
30 bool CleanupMemory) const override {
31 return [this, Instructions, MinInstructions,
32 CleanupMemory](FunctionFiller &Filler) {
33 auto Entry = Filler.getEntry();
34 if (!Instructions.empty()) {
35 // Add the whole snippet at least once.
36 Entry.addInstructions(Instructions);
37 for (unsigned I = Instructions.size(); I < MinInstructions; ++I) {
38 Entry.addInstruction(Instructions[I % Instructions.size()]);
41 Entry.addReturn(State.getExegesisTarget(), CleanupMemory);
45 BitVector getReservedRegs() const override {
46 // We're using no additional registers.
47 return State.getRATC().emptyRegisters();
51 class LoopSnippetRepetitor : public SnippetRepetitor {
52 public:
53 explicit LoopSnippetRepetitor(const LLVMState &State)
54 : SnippetRepetitor(State),
55 LoopCounter(State.getExegesisTarget().getLoopCounterRegister(
56 State.getTargetMachine().getTargetTriple())) {}
58 // Loop over the snippet ceil(MinInstructions / Instructions.Size()) times.
59 FillFunction Repeat(ArrayRef<MCInst> Instructions, unsigned MinInstructions,
60 unsigned LoopBodySize,
61 bool CleanupMemory) const override {
62 return [this, Instructions, MinInstructions, LoopBodySize,
63 CleanupMemory](FunctionFiller &Filler) {
64 const auto &ET = State.getExegesisTarget();
65 auto Entry = Filler.getEntry();
67 // We can not use loop snippet repetitor for terminator instructions.
68 for (const MCInst &Inst : Instructions) {
69 const unsigned Opcode = Inst.getOpcode();
70 const MCInstrDesc &MCID = Filler.MCII->get(Opcode);
71 if (!MCID.isTerminator())
72 continue;
73 Entry.addReturn(State.getExegesisTarget(), CleanupMemory);
74 return;
77 auto Loop = Filler.addBasicBlock();
78 auto Exit = Filler.addBasicBlock();
80 const unsigned LoopUnrollFactor =
81 LoopBodySize <= Instructions.size()
82 ? 1
83 : divideCeil(LoopBodySize, Instructions.size());
84 assert(LoopUnrollFactor >= 1 && "Should end up with at least 1 snippet.");
86 // Set loop counter to the right value:
87 const APInt LoopCount(
88 32,
89 divideCeil(MinInstructions, LoopUnrollFactor * Instructions.size()));
90 assert(LoopCount.uge(1) && "Trip count should be at least 1.");
91 for (const MCInst &Inst :
92 ET.setRegTo(State.getSubtargetInfo(), LoopCounter, LoopCount))
93 Entry.addInstruction(Inst);
95 // Set up the loop basic block.
96 Entry.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
97 Loop.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
98 // If the snippet setup completed, then we can track liveness.
99 if (Loop.MF.getProperties().hasProperty(
100 MachineFunctionProperties::Property::TracksLiveness)) {
101 // The live ins are: the loop counter, the registers that were setup by
102 // the entry block, and entry block live ins.
103 Loop.MBB->addLiveIn(LoopCounter);
104 for (unsigned Reg : Filler.getRegistersSetUp())
105 Loop.MBB->addLiveIn(Reg);
106 for (const auto &LiveIn : Entry.MBB->liveins())
107 Loop.MBB->addLiveIn(LiveIn);
109 for (auto _ : seq(LoopUnrollFactor)) {
110 (void)_;
111 Loop.addInstructions(Instructions);
113 ET.decrementLoopCounterAndJump(*Loop.MBB, *Loop.MBB,
114 State.getInstrInfo());
116 // Set up the exit basic block.
117 Loop.MBB->addSuccessor(Exit.MBB, BranchProbability::getZero());
118 Exit.addReturn(State.getExegesisTarget(), CleanupMemory);
122 BitVector getReservedRegs() const override {
123 // We're using a single loop counter, but we have to reserve all aliasing
124 // registers.
125 return State.getRATC().getRegister(LoopCounter).aliasedBits();
128 private:
129 const unsigned LoopCounter;
132 } // namespace
134 SnippetRepetitor::~SnippetRepetitor() {}
136 std::unique_ptr<const SnippetRepetitor>
137 SnippetRepetitor::Create(Benchmark::RepetitionModeE Mode,
138 const LLVMState &State) {
139 switch (Mode) {
140 case Benchmark::Duplicate:
141 return std::make_unique<DuplicateSnippetRepetitor>(State);
142 case Benchmark::Loop:
143 return std::make_unique<LoopSnippetRepetitor>(State);
144 case Benchmark::AggregateMin:
145 break;
147 llvm_unreachable("Unknown RepetitionModeE enum");
150 } // namespace exegesis
151 } // namespace llvm