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
,
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
{
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())
73 Entry
.addReturn(State
.getExegesisTarget(), CleanupMemory
);
77 auto Loop
= Filler
.addBasicBlock();
78 auto Exit
= Filler
.addBasicBlock();
80 const unsigned LoopUnrollFactor
=
81 LoopBodySize
<= Instructions
.size()
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(
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
)) {
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
125 return State
.getRATC().getRegister(LoopCounter
).aliasedBits();
129 const unsigned LoopCounter
;
134 SnippetRepetitor::~SnippetRepetitor() {}
136 std::unique_ptr
<const SnippetRepetitor
>
137 SnippetRepetitor::Create(Benchmark::RepetitionModeE Mode
,
138 const LLVMState
&State
) {
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
:
147 llvm_unreachable("Unknown RepetitionModeE enum");
150 } // namespace exegesis