1 //===---------------------- EntryStage.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 Fetch stage of an instruction pipeline. Its sole 11 /// purpose in life is to produce instructions for the rest of the pipeline. 12 /// 13 //===----------------------------------------------------------------------===// 14 15 #include "llvm/MCA/Stages/EntryStage.h" 16 #include "llvm/MCA/Instruction.h" 17 18 namespace llvm { 19 namespace mca { 20 21 bool EntryStage::hasWorkToComplete() const { 22 return static_cast<bool>(CurrentInstruction); 23 } 24 25 bool EntryStage::isAvailable(const InstRef & /* unused */) const { 26 if (CurrentInstruction) 27 return checkNextStage(CurrentInstruction); 28 return false; 29 } 30 31 void EntryStage::getNextInstruction() { 32 assert(!CurrentInstruction && "There is already an instruction to process!"); 33 if (!SM.hasNext()) 34 return; 35 SourceRef SR = SM.peekNext(); 36 std::unique_ptr<Instruction> Inst = std::make_unique<Instruction>(SR.second); 37 CurrentInstruction = InstRef(SR.first, Inst.get()); 38 Instructions.emplace_back(std::move(Inst)); 39 SM.updateNext(); 40 } 41 42 llvm::Error EntryStage::execute(InstRef & /*unused */) { 43 assert(CurrentInstruction && "There is no instruction to process!"); 44 if (llvm::Error Val = moveToTheNextStage(CurrentInstruction)) 45 return Val; 46 47 // Move the program counter. 48 CurrentInstruction.invalidate(); 49 getNextInstruction(); 50 return llvm::ErrorSuccess(); 51 } 52 53 llvm::Error EntryStage::cycleStart() { 54 if (!CurrentInstruction) 55 getNextInstruction(); 56 return llvm::ErrorSuccess(); 57 } 58 59 llvm::Error EntryStage::cycleEnd() { 60 // Find the first instruction which hasn't been retired. 61 auto Range = make_range(&Instructions[NumRetired], Instructions.end()); 62 auto It = find_if(Range, [](const std::unique_ptr<Instruction> &I) { 63 return !I->isRetired(); 64 }); 65 66 NumRetired = std::distance(Instructions.begin(), It); 67 // Erase instructions up to the first that hasn't been retired. 68 if ((NumRetired * 2) >= Instructions.size()) { 69 Instructions.erase(Instructions.begin(), It); 70 NumRetired = 0; 71 } 72 73 return llvm::ErrorSuccess(); 74 } 75 76 } // namespace mca 77 } // namespace llvm 78