1 //===-- SnippetRepetitor.cpp ------------------------------------*- C++ -*-===//
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
7 //===----------------------------------------------------------------------===//
12 #include "SnippetRepetitor.h"
14 #include "llvm/ADT/Sequence.h"
15 #include "llvm/CodeGen/TargetInstrInfo.h"
16 #include "llvm/CodeGen/TargetSubtargetInfo.h"
22 class DuplicateSnippetRepetitor
: public SnippetRepetitor
{
24 using SnippetRepetitor::SnippetRepetitor
;
26 // Repeats the snippet until there are at least MinInstructions in the
28 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()]);
43 BitVector
getReservedRegs() const override
{
44 // We're using no additional registers.
45 return State
.getRATC().emptyRegisters();
49 class LoopSnippetRepetitor
: public SnippetRepetitor
{
51 explicit LoopSnippetRepetitor(const LLVMState
&State
)
52 : SnippetRepetitor(State
),
53 LoopCounter(State
.getExegesisTarget().getLoopCounterRegister(
54 State
.getTargetMachine().getTargetTriple())) {}
56 // Loop over the snippet ceil(MinInstructions / Instructions.Size()) times.
57 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();
66 const unsigned LoopUnrollFactor
=
67 LoopBodySize
<= Instructions
.size()
69 : divideCeil(LoopBodySize
, Instructions
.size());
70 assert(LoopUnrollFactor
>= 1 && "Should end up with at least 1 snippet.");
72 // Set loop counter to the right value:
73 const APInt
LoopCount(
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
);
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
)) {
93 Loop
.addInstructions(Instructions
);
95 ET
.decrementLoopCounterAndJump(*Loop
.MBB
, *Loop
.MBB
,
96 State
.getInstrInfo());
98 // Set up the exit basic block.
99 Loop
.MBB
->addSuccessor(Exit
.MBB
, BranchProbability::getZero());
104 BitVector
getReservedRegs() const override
{
105 // We're using a single loop counter, but we have to reserve all aliasing
107 return State
.getRATC().getRegister(LoopCounter
).aliasedBits();
111 const unsigned LoopCounter
;
116 SnippetRepetitor::~SnippetRepetitor() {}
118 std::unique_ptr
<const SnippetRepetitor
>
119 SnippetRepetitor::Create(InstructionBenchmark::RepetitionModeE Mode
,
120 const LLVMState
&State
) {
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
:
129 llvm_unreachable("Unknown RepetitionModeE enum");
132 } // namespace exegesis