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/TargetLowering.h"
14 #include "llvm/CodeGen/TargetSubtargetInfo.h"
20 class DuplicateSnippetRepetitor
: public SnippetRepetitor
{
22 using SnippetRepetitor::SnippetRepetitor
;
24 // Repeats the snippet until there are at least MinInstructions in the
26 FillFunction
Repeat(ArrayRef
<MCInst
> Instructions
, unsigned MinInstructions
,
27 unsigned LoopBodySize
,
28 bool CleanupMemory
) const override
{
29 return [this, Instructions
, MinInstructions
,
30 CleanupMemory
](FunctionFiller
&Filler
) {
31 auto Entry
= Filler
.getEntry();
32 if (!Instructions
.empty()) {
33 const unsigned NumRepetitions
=
34 divideCeil(MinInstructions
, Instructions
.size());
35 for (unsigned I
= 0; I
< NumRepetitions
; ++I
) {
36 Entry
.addInstructions(Instructions
);
39 Entry
.addReturn(State
.getExegesisTarget(), CleanupMemory
);
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
, unsigned LoopRegister
)
52 : SnippetRepetitor(State
), LoopCounter(LoopRegister
) {}
54 // Loop over the snippet ceil(MinInstructions / Instructions.Size()) times.
55 FillFunction
Repeat(ArrayRef
<MCInst
> Instructions
, unsigned MinInstructions
,
56 unsigned LoopBodySize
,
57 bool CleanupMemory
) const override
{
58 return [this, Instructions
, MinInstructions
, LoopBodySize
,
59 CleanupMemory
](FunctionFiller
&Filler
) {
60 const auto &ET
= State
.getExegesisTarget();
61 auto Entry
= Filler
.getEntry();
63 // We can not use loop snippet repetitor for terminator instructions.
64 for (const MCInst
&Inst
: Instructions
) {
65 const unsigned Opcode
= Inst
.getOpcode();
66 const MCInstrDesc
&MCID
= Filler
.MCII
->get(Opcode
);
67 if (!MCID
.isTerminator())
69 Entry
.addReturn(State
.getExegesisTarget(), CleanupMemory
);
73 auto Loop
= Filler
.addBasicBlock();
74 auto Exit
= Filler
.addBasicBlock();
76 // Align the loop machine basic block to a target-specific boundary
77 // to promote optimal instruction fetch/predecoding conditions.
78 Loop
.MBB
->setAlignment(
79 Filler
.MF
.getSubtarget().getTargetLowering()->getPrefLoopAlignment());
81 const unsigned LoopUnrollFactor
=
82 LoopBodySize
<= Instructions
.size()
84 : divideCeil(LoopBodySize
, Instructions
.size());
85 assert(LoopUnrollFactor
>= 1 && "Should end up with at least 1 snippet.");
87 // Set loop counter to the right value:
88 const APInt
LoopCount(
90 divideCeil(MinInstructions
, LoopUnrollFactor
* Instructions
.size()));
91 assert(LoopCount
.uge(1) && "Trip count should be at least 1.");
92 for (const MCInst
&Inst
:
93 ET
.setRegTo(State
.getSubtargetInfo(), LoopCounter
, LoopCount
))
94 Entry
.addInstruction(Inst
);
96 // Set up the loop basic block.
97 Entry
.MBB
->addSuccessor(Loop
.MBB
, BranchProbability::getOne());
98 Loop
.MBB
->addSuccessor(Loop
.MBB
, BranchProbability::getOne());
99 // If the snippet setup completed, then we can track liveness.
100 if (Loop
.MF
.getProperties().hasProperty(
101 MachineFunctionProperties::Property::TracksLiveness
)) {
102 // The live ins are: the loop counter, the registers that were setup by
103 // the entry block, and entry block live ins.
104 Loop
.MBB
->addLiveIn(LoopCounter
);
105 for (unsigned Reg
: Filler
.getRegistersSetUp())
106 Loop
.MBB
->addLiveIn(Reg
);
107 for (const auto &LiveIn
: Entry
.MBB
->liveins())
108 Loop
.MBB
->addLiveIn(LiveIn
);
110 for (auto _
: seq(LoopUnrollFactor
)) {
112 Loop
.addInstructions(Instructions
);
114 ET
.decrementLoopCounterAndJump(*Loop
.MBB
, *Loop
.MBB
, State
.getInstrInfo(),
117 // Set up the exit basic block.
118 Loop
.MBB
->addSuccessor(Exit
.MBB
, BranchProbability::getZero());
119 Exit
.addReturn(State
.getExegesisTarget(), CleanupMemory
);
123 BitVector
getReservedRegs() const override
{
124 // We're using a single loop counter, but we have to reserve all aliasing
126 return State
.getRATC().getRegister(LoopCounter
).aliasedBits();
130 const unsigned LoopCounter
;
135 SnippetRepetitor::~SnippetRepetitor() {}
137 std::unique_ptr
<const SnippetRepetitor
>
138 SnippetRepetitor::Create(Benchmark::RepetitionModeE Mode
,
139 const LLVMState
&State
, unsigned LoopRegister
) {
141 case Benchmark::Duplicate
:
142 case Benchmark::MiddleHalfDuplicate
:
143 return std::make_unique
<DuplicateSnippetRepetitor
>(State
);
144 case Benchmark::Loop
:
145 case Benchmark::MiddleHalfLoop
:
146 return std::make_unique
<LoopSnippetRepetitor
>(State
, LoopRegister
);
147 case Benchmark::AggregateMin
:
150 llvm_unreachable("Unknown RepetitionModeE enum");
153 } // namespace exegesis