]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/include/llvm/MCA/Stages/MicroOpQueueStage.h
Merge llvm, clang, compiler-rt, libc++, libunwind, lld, lldb and openmp
[FreeBSD/FreeBSD.git] / contrib / llvm / include / llvm / MCA / Stages / MicroOpQueueStage.h
1 //===---------------------- MicroOpQueueStage.h -----------------*- C++ -*-===//
2 //
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
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 ///
10 /// This file defines a stage that implements a queue of micro opcodes.
11 /// It can be used to simulate a hardware micro-op queue that serves opcodes to
12 /// the out of order backend.
13 ///
14 //===----------------------------------------------------------------------===//
15
16 #ifndef LLVM_MCA_MICRO_OP_QUEUE_STAGE_H
17 #define LLVM_MCA_MICRO_OP_QUEUE_STAGE_H
18
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/MCA/Stages/Stage.h"
21
22 namespace llvm {
23 namespace mca {
24
25 /// A stage that simulates a queue of instruction opcodes.
26 class MicroOpQueueStage : public Stage {
27   SmallVector<InstRef, 8> Buffer;
28   unsigned NextAvailableSlotIdx;
29   unsigned CurrentInstructionSlotIdx;
30
31   // Limits the number of instructions that can be written to this buffer every
32   // cycle. A value of zero means that there is no limit to the instruction
33   // throughput in input.
34   const unsigned MaxIPC;
35   unsigned CurrentIPC;
36
37   // Number of entries that are available during this cycle.
38   unsigned AvailableEntries;
39
40   // True if instructions dispatched to this stage don't need to wait for the
41   // next cycle before moving to the next stage.
42   // False if this buffer acts as a one cycle delay in the execution pipeline.
43   bool IsZeroLatencyStage;
44
45   MicroOpQueueStage(const MicroOpQueueStage &Other) = delete;
46   MicroOpQueueStage &operator=(const MicroOpQueueStage &Other) = delete;
47
48   // By default, an instruction consumes a number of buffer entries equal to its
49   // number of micro opcodes (see field `InstrDesc::NumMicroOpcodes`).  The
50   // number of entries consumed by an instruction is normalized to the
51   // minimum value between NumMicroOpcodes and the buffer size. This is to avoid
52   // problems with (microcoded) instructions that generate a number of micro
53   // opcodes than doesn't fit in the buffer.
54   unsigned getNormalizedOpcodes(const InstRef &IR) const {
55     unsigned NormalizedOpcodes =
56         std::min(static_cast<unsigned>(Buffer.size()),
57                  IR.getInstruction()->getDesc().NumMicroOps);
58     return NormalizedOpcodes ? NormalizedOpcodes : 1U;
59   }
60
61   Error moveInstructions();
62
63 public:
64   MicroOpQueueStage(unsigned Size, unsigned IPC = 0,
65                     bool ZeroLatencyStage = true);
66
67   bool isAvailable(const InstRef &IR) const override {
68     if (MaxIPC && CurrentIPC == MaxIPC)
69       return false;
70     unsigned NormalizedOpcodes = getNormalizedOpcodes(IR);
71     if (NormalizedOpcodes > AvailableEntries)
72       return false;
73     return true;
74   }
75
76   bool hasWorkToComplete() const override {
77     return AvailableEntries != Buffer.size();
78   }
79
80   Error execute(InstRef &IR) override;
81   Error cycleStart() override;
82   Error cycleEnd() override;
83 };
84
85 } // namespace mca
86 } // namespace llvm
87
88 #endif // LLVM_MCA_MICRO_OP_QUEUE_STAGE_H