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 //===----------------------------------------------------------------------===//
9 #include "SnippetRepetitor.h"
11 #include "llvm/ADT/Sequence.h"
12 #include "llvm/CodeGen/TargetInstrInfo.h"
13 #include "llvm/CodeGen/TargetSubtargetInfo.h"
19 class DuplicateSnippetRepetitor
: public SnippetRepetitor
{
21 using SnippetRepetitor::SnippetRepetitor
;
23 // Repeats the snippet until there are at least MinInstructions in the
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
{
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())
70 Entry
.addReturn(State
.getExegesisTarget(), CleanupMemory
);
74 auto Loop
= Filler
.addBasicBlock();
75 auto Exit
= Filler
.addBasicBlock();
77 const unsigned LoopUnrollFactor
=
78 LoopBodySize
<= Instructions
.size()
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(
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
)) {
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
122 return State
.getRATC().getRegister(LoopCounter
).aliasedBits();
126 const unsigned LoopCounter
;
131 SnippetRepetitor::~SnippetRepetitor() {}
133 std::unique_ptr
<const SnippetRepetitor
>
134 SnippetRepetitor::Create(Benchmark::RepetitionModeE Mode
,
135 const LLVMState
&State
) {
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
:
144 llvm_unreachable("Unknown RepetitionModeE enum");
147 } // namespace exegesis