EntryStage.cpp revision 360784
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 18namespace llvm { 19namespace mca { 20 21bool EntryStage::hasWorkToComplete() const { 22 return static_cast<bool>(CurrentInstruction); 23} 24 25bool EntryStage::isAvailable(const InstRef & /* unused */) const { 26 if (CurrentInstruction) 27 return checkNextStage(CurrentInstruction); 28 return false; 29} 30 31void 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 42llvm::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 53llvm::Error EntryStage::cycleStart() { 54 if (!CurrentInstruction) 55 getNextInstruction(); 56 return llvm::ErrorSuccess(); 57} 58 59llvm::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