Path: blob/main/contrib/llvm-project/llvm/lib/MCA/HardwareUnits/LSUnit.cpp
35292 views
//===----------------------- LSUnit.cpp --------------------------*- C++-*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7/// \file8///9/// A Load-Store Unit for the llvm-mca tool.10///11//===----------------------------------------------------------------------===//1213#include "llvm/MCA/HardwareUnits/LSUnit.h"14#include "llvm/MCA/Instruction.h"15#include "llvm/Support/Debug.h"16#include "llvm/Support/raw_ostream.h"1718#define DEBUG_TYPE "llvm-mca"1920namespace llvm {21namespace mca {2223LSUnitBase::LSUnitBase(const MCSchedModel &SM, unsigned LQ, unsigned SQ,24bool AssumeNoAlias)25: LQSize(LQ), SQSize(SQ), UsedLQEntries(0), UsedSQEntries(0),26NoAlias(AssumeNoAlias), NextGroupID(1) {27if (SM.hasExtraProcessorInfo()) {28const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo();29if (!LQSize && EPI.LoadQueueID) {30const MCProcResourceDesc &LdQDesc = *SM.getProcResource(EPI.LoadQueueID);31LQSize = std::max(0, LdQDesc.BufferSize);32}3334if (!SQSize && EPI.StoreQueueID) {35const MCProcResourceDesc &StQDesc = *SM.getProcResource(EPI.StoreQueueID);36SQSize = std::max(0, StQDesc.BufferSize);37}38}39}4041LSUnitBase::~LSUnitBase() = default;4243void LSUnitBase::cycleEvent() {44for (const std::pair<unsigned, std::unique_ptr<MemoryGroup>> &G : Groups)45G.second->cycleEvent();46}4748#ifndef NDEBUG49void LSUnitBase::dump() const {50dbgs() << "[LSUnit] LQ_Size = " << getLoadQueueSize() << '\n';51dbgs() << "[LSUnit] SQ_Size = " << getStoreQueueSize() << '\n';52dbgs() << "[LSUnit] NextLQSlotIdx = " << getUsedLQEntries() << '\n';53dbgs() << "[LSUnit] NextSQSlotIdx = " << getUsedSQEntries() << '\n';54dbgs() << "\n";55for (const auto &GroupIt : Groups) {56const MemoryGroup &Group = *GroupIt.second;57dbgs() << "[LSUnit] Group (" << GroupIt.first << "): "58<< "[ #Preds = " << Group.getNumPredecessors()59<< ", #GIssued = " << Group.getNumExecutingPredecessors()60<< ", #GExecuted = " << Group.getNumExecutedPredecessors()61<< ", #Inst = " << Group.getNumInstructions()62<< ", #IIssued = " << Group.getNumExecuting()63<< ", #IExecuted = " << Group.getNumExecuted() << '\n';64}65}66#endif6768unsigned LSUnit::dispatch(const InstRef &IR) {69const Instruction &IS = *IR.getInstruction();70bool IsStoreBarrier = IS.isAStoreBarrier();71bool IsLoadBarrier = IS.isALoadBarrier();72assert((IS.getMayLoad() || IS.getMayStore()) && "Not a memory operation!");7374if (IS.getMayLoad())75acquireLQSlot();76if (IS.getMayStore())77acquireSQSlot();7879if (IS.getMayStore()) {80unsigned NewGID = createMemoryGroup();81MemoryGroup &NewGroup = getGroup(NewGID);82NewGroup.addInstruction();8384// A store may not pass a previous load or load barrier.85unsigned ImmediateLoadDominator =86std::max(CurrentLoadGroupID, CurrentLoadBarrierGroupID);87if (ImmediateLoadDominator) {88MemoryGroup &IDom = getGroup(ImmediateLoadDominator);89LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << ImmediateLoadDominator90<< ") --> (" << NewGID << ")\n");91IDom.addSuccessor(&NewGroup, !assumeNoAlias());92}9394// A store may not pass a previous store barrier.95if (CurrentStoreBarrierGroupID) {96MemoryGroup &StoreGroup = getGroup(CurrentStoreBarrierGroupID);97LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: ("98<< CurrentStoreBarrierGroupID99<< ") --> (" << NewGID << ")\n");100StoreGroup.addSuccessor(&NewGroup, true);101}102103// A store may not pass a previous store.104if (CurrentStoreGroupID &&105(CurrentStoreGroupID != CurrentStoreBarrierGroupID)) {106MemoryGroup &StoreGroup = getGroup(CurrentStoreGroupID);107LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID108<< ") --> (" << NewGID << ")\n");109StoreGroup.addSuccessor(&NewGroup, !assumeNoAlias());110}111112113CurrentStoreGroupID = NewGID;114if (IsStoreBarrier)115CurrentStoreBarrierGroupID = NewGID;116117if (IS.getMayLoad()) {118CurrentLoadGroupID = NewGID;119if (IsLoadBarrier)120CurrentLoadBarrierGroupID = NewGID;121}122123return NewGID;124}125126assert(IS.getMayLoad() && "Expected a load!");127128unsigned ImmediateLoadDominator =129std::max(CurrentLoadGroupID, CurrentLoadBarrierGroupID);130131// A new load group is created if we are in one of the following situations:132// 1) This is a load barrier (by construction, a load barrier is always133// assigned to a different memory group).134// 2) There is no load in flight (by construction we always keep loads and135// stores into separate memory groups).136// 3) There is a load barrier in flight. This load depends on it.137// 4) There is an intervening store between the last load dispatched to the138// LSU and this load. We always create a new group even if this load139// does not alias the last dispatched store.140// 5) There is no intervening store and there is an active load group.141// However that group has already started execution, so we cannot add142// this load to it.143bool ShouldCreateANewGroup =144IsLoadBarrier || !ImmediateLoadDominator ||145CurrentLoadBarrierGroupID == ImmediateLoadDominator ||146ImmediateLoadDominator <= CurrentStoreGroupID ||147getGroup(ImmediateLoadDominator).isExecuting();148149if (ShouldCreateANewGroup) {150unsigned NewGID = createMemoryGroup();151MemoryGroup &NewGroup = getGroup(NewGID);152NewGroup.addInstruction();153154// A load may not pass a previous store or store barrier155// unless flag 'NoAlias' is set.156if (!assumeNoAlias() && CurrentStoreGroupID) {157MemoryGroup &StoreGroup = getGroup(CurrentStoreGroupID);158LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID159<< ") --> (" << NewGID << ")\n");160StoreGroup.addSuccessor(&NewGroup, true);161}162163// A load barrier may not pass a previous load or load barrier.164if (IsLoadBarrier) {165if (ImmediateLoadDominator) {166MemoryGroup &LoadGroup = getGroup(ImmediateLoadDominator);167LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: ("168<< ImmediateLoadDominator169<< ") --> (" << NewGID << ")\n");170LoadGroup.addSuccessor(&NewGroup, true);171}172} else {173// A younger load cannot pass a older load barrier.174if (CurrentLoadBarrierGroupID) {175MemoryGroup &LoadGroup = getGroup(CurrentLoadBarrierGroupID);176LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: ("177<< CurrentLoadBarrierGroupID178<< ") --> (" << NewGID << ")\n");179LoadGroup.addSuccessor(&NewGroup, true);180}181}182183CurrentLoadGroupID = NewGID;184if (IsLoadBarrier)185CurrentLoadBarrierGroupID = NewGID;186return NewGID;187}188189// A load may pass a previous load.190MemoryGroup &Group = getGroup(CurrentLoadGroupID);191Group.addInstruction();192return CurrentLoadGroupID;193}194195LSUnit::Status LSUnit::isAvailable(const InstRef &IR) const {196const Instruction &IS = *IR.getInstruction();197if (IS.getMayLoad() && isLQFull())198return LSUnit::LSU_LQUEUE_FULL;199if (IS.getMayStore() && isSQFull())200return LSUnit::LSU_SQUEUE_FULL;201return LSUnit::LSU_AVAILABLE;202}203204void LSUnitBase::onInstructionExecuted(const InstRef &IR) {205unsigned GroupID = IR.getInstruction()->getLSUTokenID();206auto It = Groups.find(GroupID);207assert(It != Groups.end() && "Instruction not dispatched to the LS unit");208It->second->onInstructionExecuted(IR);209if (It->second->isExecuted())210Groups.erase(It);211}212213void LSUnitBase::onInstructionRetired(const InstRef &IR) {214const Instruction &IS = *IR.getInstruction();215bool IsALoad = IS.getMayLoad();216bool IsAStore = IS.getMayStore();217assert((IsALoad || IsAStore) && "Expected a memory operation!");218219if (IsALoad) {220releaseLQSlot();221LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR.getSourceIndex()222<< " has been removed from the load queue.\n");223}224225if (IsAStore) {226releaseSQSlot();227LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR.getSourceIndex()228<< " has been removed from the store queue.\n");229}230}231232void LSUnit::onInstructionExecuted(const InstRef &IR) {233const Instruction &IS = *IR.getInstruction();234if (!IS.isMemOp())235return;236237LSUnitBase::onInstructionExecuted(IR);238unsigned GroupID = IS.getLSUTokenID();239if (!isValidGroupID(GroupID)) {240if (GroupID == CurrentLoadGroupID)241CurrentLoadGroupID = 0;242if (GroupID == CurrentStoreGroupID)243CurrentStoreGroupID = 0;244if (GroupID == CurrentLoadBarrierGroupID)245CurrentLoadBarrierGroupID = 0;246if (GroupID == CurrentStoreBarrierGroupID)247CurrentStoreBarrierGroupID = 0;248}249}250251} // namespace mca252} // namespace llvm253254255