[RISCV] Eliminate dead li after emitting VSETVLIs (#65934)
[llvm-project.git] / llvm / tools / llvm-exegesis / lib / SnippetRepetitor.cpp
blobcc5a045a8be5dd4516a1a53ae5c4726105ccb30d
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 "SnippetRepetitor.h"
10 #include "Target.h"
11 #include "llvm/ADT/Sequence.h"
12 #include "llvm/CodeGen/TargetInstrInfo.h"
13 #include "llvm/CodeGen/TargetSubtargetInfo.h"
15 namespace llvm {
16 namespace exegesis {
17 namespace {
19 class DuplicateSnippetRepetitor : public SnippetRepetitor {
20 public:
21 using SnippetRepetitor::SnippetRepetitor;
23 // Repeats the snippet until there are at least MinInstructions in the
24 // resulting code.
25 FillFunction Repeat(ArrayRef<MCInst> Instructions, unsigned MinInstructions,
26 unsigned LoopBodySize,
27 bool CleanupMemory) const override {
28 return [this, Instructions, MinInstructions,
29 CleanupMemory](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()]);
38 Entry.addReturn(State.getExegesisTarget(), CleanupMemory);
42 BitVector getReservedRegs() const override {
43 // We're using no additional registers.
44 return State.getRATC().emptyRegisters();
48 class LoopSnippetRepetitor : public SnippetRepetitor {
49 public:
50 explicit LoopSnippetRepetitor(const LLVMState &State)
51 : SnippetRepetitor(State),
52 LoopCounter(State.getExegesisTarget().getLoopCounterRegister(
53 State.getTargetMachine().getTargetTriple())) {}
55 // Loop over the snippet ceil(MinInstructions / Instructions.Size()) times.
56 FillFunction Repeat(ArrayRef<MCInst> Instructions, unsigned MinInstructions,
57 unsigned LoopBodySize,
58 bool CleanupMemory) const override {
59 return [this, Instructions, MinInstructions, LoopBodySize,
60 CleanupMemory](FunctionFiller &Filler) {
61 const auto &ET = State.getExegesisTarget();
62 auto Entry = Filler.getEntry();
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(State.getExegesisTarget(), CleanupMemory);
71 return;
74 auto Loop = Filler.addBasicBlock();
75 auto Exit = Filler.addBasicBlock();
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.");
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);
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);
106 for (auto _ : seq(LoopUnrollFactor)) {
107 (void)_;
108 Loop.addInstructions(Instructions);
110 ET.decrementLoopCounterAndJump(*Loop.MBB, *Loop.MBB,
111 State.getInstrInfo());
113 // Set up the exit basic block.
114 Loop.MBB->addSuccessor(Exit.MBB, BranchProbability::getZero());
115 Exit.addReturn(State.getExegesisTarget(), CleanupMemory);
119 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();
125 private:
126 const unsigned LoopCounter;
129 } // namespace
131 SnippetRepetitor::~SnippetRepetitor() {}
133 std::unique_ptr<const SnippetRepetitor>
134 SnippetRepetitor::Create(Benchmark::RepetitionModeE Mode,
135 const LLVMState &State) {
136 switch (Mode) {
137 case Benchmark::Duplicate:
138 return std::make_unique<DuplicateSnippetRepetitor>(State);
139 case Benchmark::Loop:
140 return std::make_unique<LoopSnippetRepetitor>(State);
141 case Benchmark::AggregateMin:
142 break;
144 llvm_unreachable("Unknown RepetitionModeE enum");
147 } // namespace exegesis
148 } // namespace llvm