Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:44:16

0001 //===---------------------- MicroOpQueueStage.h -----------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 /// \file
0009 ///
0010 /// This file defines a stage that implements a queue of micro opcodes.
0011 /// It can be used to simulate a hardware micro-op queue that serves opcodes to
0012 /// the out of order backend.
0013 ///
0014 //===----------------------------------------------------------------------===//
0015 
0016 #ifndef LLVM_MCA_STAGES_MICROOPQUEUESTAGE_H
0017 #define LLVM_MCA_STAGES_MICROOPQUEUESTAGE_H
0018 
0019 #include "llvm/ADT/SmallVector.h"
0020 #include "llvm/MCA/Stages/Stage.h"
0021 
0022 namespace llvm {
0023 namespace mca {
0024 
0025 /// A stage that simulates a queue of instruction opcodes.
0026 class MicroOpQueueStage : public Stage {
0027   SmallVector<InstRef, 8> Buffer;
0028   unsigned NextAvailableSlotIdx;
0029   unsigned CurrentInstructionSlotIdx;
0030 
0031   // Limits the number of instructions that can be written to this buffer every
0032   // cycle. A value of zero means that there is no limit to the instruction
0033   // throughput in input.
0034   const unsigned MaxIPC;
0035   unsigned CurrentIPC;
0036 
0037   // Number of entries that are available during this cycle.
0038   unsigned AvailableEntries;
0039 
0040   // True if instructions dispatched to this stage don't need to wait for the
0041   // next cycle before moving to the next stage.
0042   // False if this buffer acts as a one cycle delay in the execution pipeline.
0043   bool IsZeroLatencyStage;
0044 
0045   MicroOpQueueStage(const MicroOpQueueStage &Other) = delete;
0046   MicroOpQueueStage &operator=(const MicroOpQueueStage &Other) = delete;
0047 
0048   // By default, an instruction consumes a number of buffer entries equal to its
0049   // number of micro opcodes (see field `InstrDesc::NumMicroOpcodes`).  The
0050   // number of entries consumed by an instruction is normalized to the
0051   // minimum value between NumMicroOpcodes and the buffer size. This is to avoid
0052   // problems with (microcoded) instructions that generate a number of micro
0053   // opcodes than doesn't fit in the buffer.
0054   unsigned getNormalizedOpcodes(const InstRef &IR) const {
0055     unsigned NormalizedOpcodes =
0056         std::min(static_cast<unsigned>(Buffer.size()),
0057                  IR.getInstruction()->getDesc().NumMicroOps);
0058     return NormalizedOpcodes ? NormalizedOpcodes : 1U;
0059   }
0060 
0061   Error moveInstructions();
0062 
0063 public:
0064   MicroOpQueueStage(unsigned Size, unsigned IPC = 0,
0065                     bool ZeroLatencyStage = true);
0066 
0067   bool isAvailable(const InstRef &IR) const override {
0068     if (MaxIPC && CurrentIPC == MaxIPC)
0069       return false;
0070     unsigned NormalizedOpcodes = getNormalizedOpcodes(IR);
0071     if (NormalizedOpcodes > AvailableEntries)
0072       return false;
0073     return true;
0074   }
0075 
0076   bool hasWorkToComplete() const override {
0077     return AvailableEntries != Buffer.size();
0078   }
0079 
0080   Error execute(InstRef &IR) override;
0081   Error cycleStart() override;
0082   Error cycleEnd() override;
0083 };
0084 
0085 } // namespace mca
0086 } // namespace llvm
0087 
0088 #endif // LLVM_MCA_STAGES_MICROOPQUEUESTAGE_H