123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- //===-- SnippetRepetitor.cpp ------------------------------------*- C++ -*-===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- #include <array>
- #include <string>
- #include "SnippetRepetitor.h"
- #include "Target.h"
- #include "llvm/ADT/Sequence.h"
- #include "llvm/CodeGen/TargetInstrInfo.h"
- #include "llvm/CodeGen/TargetSubtargetInfo.h"
- namespace llvm {
- namespace exegesis {
- namespace {
- class DuplicateSnippetRepetitor : public SnippetRepetitor {
- public:
- using SnippetRepetitor::SnippetRepetitor;
- // Repeats the snippet until there are at least MinInstructions in the
- // resulting code.
- FillFunction Repeat(ArrayRef<MCInst> Instructions, unsigned MinInstructions,
- unsigned LoopBodySize) const override {
- return [Instructions, MinInstructions](FunctionFiller &Filler) {
- auto Entry = Filler.getEntry();
- if (!Instructions.empty()) {
- // Add the whole snippet at least once.
- Entry.addInstructions(Instructions);
- for (unsigned I = Instructions.size(); I < MinInstructions; ++I) {
- Entry.addInstruction(Instructions[I % Instructions.size()]);
- }
- }
- Entry.addReturn();
- };
- }
- BitVector getReservedRegs() const override {
- // We're using no additional registers.
- return State.getRATC().emptyRegisters();
- }
- };
- class LoopSnippetRepetitor : public SnippetRepetitor {
- public:
- explicit LoopSnippetRepetitor(const LLVMState &State)
- : SnippetRepetitor(State),
- LoopCounter(State.getExegesisTarget().getLoopCounterRegister(
- State.getTargetMachine().getTargetTriple())) {}
- // Loop over the snippet ceil(MinInstructions / Instructions.Size()) times.
- FillFunction Repeat(ArrayRef<MCInst> Instructions, unsigned MinInstructions,
- unsigned LoopBodySize) const override {
- return [this, Instructions, MinInstructions,
- LoopBodySize](FunctionFiller &Filler) {
- const auto &ET = State.getExegesisTarget();
- auto Entry = Filler.getEntry();
- // We can not use loop snippet repetitor for terminator instructions.
- for (const MCInst &Inst : Instructions) {
- const unsigned Opcode = Inst.getOpcode();
- const MCInstrDesc &MCID = Filler.MCII->get(Opcode);
- if (!MCID.isTerminator())
- continue;
- Entry.addReturn();
- return;
- }
- auto Loop = Filler.addBasicBlock();
- auto Exit = Filler.addBasicBlock();
- const unsigned LoopUnrollFactor =
- LoopBodySize <= Instructions.size()
- ? 1
- : divideCeil(LoopBodySize, Instructions.size());
- assert(LoopUnrollFactor >= 1 && "Should end up with at least 1 snippet.");
- // Set loop counter to the right value:
- const APInt LoopCount(
- 32,
- divideCeil(MinInstructions, LoopUnrollFactor * Instructions.size()));
- assert(LoopCount.uge(1) && "Trip count should be at least 1.");
- for (const MCInst &Inst :
- ET.setRegTo(State.getSubtargetInfo(), LoopCounter, LoopCount))
- Entry.addInstruction(Inst);
- // Set up the loop basic block.
- Entry.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
- Loop.MBB->addSuccessor(Loop.MBB, BranchProbability::getOne());
- // If the snippet setup completed, then we can track liveness.
- if (Loop.MF.getProperties().hasProperty(
- MachineFunctionProperties::Property::TracksLiveness)) {
- // The live ins are: the loop counter, the registers that were setup by
- // the entry block, and entry block live ins.
- Loop.MBB->addLiveIn(LoopCounter);
- for (unsigned Reg : Filler.getRegistersSetUp())
- Loop.MBB->addLiveIn(Reg);
- for (const auto &LiveIn : Entry.MBB->liveins())
- Loop.MBB->addLiveIn(LiveIn);
- }
- for (auto _ : seq(0U, LoopUnrollFactor)) {
- (void)_;
- Loop.addInstructions(Instructions);
- }
- ET.decrementLoopCounterAndJump(*Loop.MBB, *Loop.MBB,
- State.getInstrInfo());
- // Set up the exit basic block.
- Loop.MBB->addSuccessor(Exit.MBB, BranchProbability::getZero());
- Exit.addReturn();
- };
- }
- BitVector getReservedRegs() const override {
- // We're using a single loop counter, but we have to reserve all aliasing
- // registers.
- return State.getRATC().getRegister(LoopCounter).aliasedBits();
- }
- private:
- const unsigned LoopCounter;
- };
- } // namespace
- SnippetRepetitor::~SnippetRepetitor() {}
- std::unique_ptr<const SnippetRepetitor>
- SnippetRepetitor::Create(InstructionBenchmark::RepetitionModeE Mode,
- const LLVMState &State) {
- switch (Mode) {
- case InstructionBenchmark::Duplicate:
- return std::make_unique<DuplicateSnippetRepetitor>(State);
- case InstructionBenchmark::Loop:
- return std::make_unique<LoopSnippetRepetitor>(State);
- case InstructionBenchmark::AggregateMin:
- break;
- }
- llvm_unreachable("Unknown RepetitionModeE enum");
- }
- } // namespace exegesis
- } // namespace llvm
|