| 1 | //===---------------------- RetireStage.cpp ---------------------*- 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 the retire stage of an instruction pipeline. |
| 11 | /// The RetireStage represents the process logic that interacts with the |
| 12 | /// simulated RetireControlUnit hardware. |
| 13 | /// |
| 14 | //===----------------------------------------------------------------------===// |
| 15 | |
| 16 | #include "llvm/MCA/Stages/RetireStage.h" |
| 17 | #include "llvm/MCA/HWEventListener.h" |
| 18 | #include "llvm/Support/Debug.h" |
| 19 | |
| 20 | #define DEBUG_TYPE "llvm-mca" |
| 21 | |
| 22 | namespace llvm { |
| 23 | namespace mca { |
| 24 | |
| 25 | llvm::Error RetireStage::cycleStart() { |
| 26 | PRF.cycleStart(); |
| 27 | |
| 28 | const unsigned MaxRetirePerCycle = RCU.getMaxRetirePerCycle(); |
| 29 | unsigned NumRetired = 0; |
| 30 | while (!RCU.isEmpty()) { |
| 31 | if (MaxRetirePerCycle != 0 && NumRetired == MaxRetirePerCycle) |
| 32 | break; |
| 33 | const RetireControlUnit::RUToken &Current = RCU.getCurrentToken(); |
| 34 | if (!Current.Executed) |
| 35 | break; |
| 36 | notifyInstructionRetired(IR: Current.IR); |
| 37 | RCU.consumeCurrentToken(); |
| 38 | NumRetired++; |
| 39 | } |
| 40 | |
| 41 | return llvm::ErrorSuccess(); |
| 42 | } |
| 43 | |
| 44 | llvm::Error RetireStage::cycleEnd() { |
| 45 | PRF.cycleEnd(); |
| 46 | return llvm::ErrorSuccess(); |
| 47 | } |
| 48 | |
| 49 | llvm::Error RetireStage::execute(InstRef &IR) { |
| 50 | Instruction &IS = *IR.getInstruction(); |
| 51 | |
| 52 | PRF.onInstructionExecuted(IS: &IS); |
| 53 | unsigned TokenID = IS.getRCUTokenID(); |
| 54 | assert(TokenID != RetireControlUnit::UnhandledTokenID); |
| 55 | RCU.onInstructionExecuted(TokenID); |
| 56 | |
| 57 | return llvm::ErrorSuccess(); |
| 58 | } |
| 59 | |
| 60 | void RetireStage::notifyInstructionRetired(const InstRef &IR) const { |
| 61 | LLVM_DEBUG(llvm::dbgs() << "[E] Instruction Retired: #"<< IR << '\n'); |
| 62 | llvm::SmallVector<unsigned, 4> FreedRegs(PRF.getNumRegisterFiles()); |
| 63 | const Instruction &Inst = *IR.getInstruction(); |
| 64 | |
| 65 | // Release the load/store queue entries. |
| 66 | if (Inst.isMemOp()) |
| 67 | LSU.onInstructionRetired(IR); |
| 68 | |
| 69 | for (const WriteState &WS : Inst.getDefs()) |
| 70 | PRF.removeRegisterWrite(WS, FreedPhysRegs: FreedRegs); |
| 71 | notifyEvent<HWInstructionEvent>(Event: HWInstructionRetiredEvent(IR, FreedRegs)); |
| 72 | } |
| 73 | |
| 74 | } // namespace mca |
| 75 | } // namespace llvm |
| 76 |