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_STAGES_MICROOPQUEUESTAGE_H
17#define LLVM_MCA_STAGES_MICROOPQUEUESTAGE_H
18
19#include "llvm/ADT/SmallVector.h"
20#include "llvm/MCA/Stages/Stage.h"
21
22namespace llvm {
23namespace mca {
24
25/// A stage that simulates a queue of instruction opcodes.
26class 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(a: static_cast<unsigned>(Buffer.size()),
57 b: IR.getInstruction()->getDesc().NumMicroOps);
58 return NormalizedOpcodes ? NormalizedOpcodes : 1U;
59 }
60
61 Error moveInstructions();
62
63public:
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_STAGES_MICROOPQUEUESTAGE_H
89

source code of llvm/include/llvm/MCA/Stages/MicroOpQueueStage.h