diff options
author | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
---|---|---|
committer | monster <monster@ydb.tech> | 2022-07-07 14:41:37 +0300 |
commit | 06e5c21a835c0e923506c4ff27929f34e00761c2 (patch) | |
tree | 75efcbc6854ef9bd476eb8bf00cc5c900da436a2 /contrib/libs/llvm12/lib/MCA/HardwareUnits/LSUnit.cpp | |
parent | 03f024c4412e3aa613bb543cf1660176320ba8f4 (diff) | |
download | ydb-06e5c21a835c0e923506c4ff27929f34e00761c2.tar.gz |
fix ya.make
Diffstat (limited to 'contrib/libs/llvm12/lib/MCA/HardwareUnits/LSUnit.cpp')
-rw-r--r-- | contrib/libs/llvm12/lib/MCA/HardwareUnits/LSUnit.cpp | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/contrib/libs/llvm12/lib/MCA/HardwareUnits/LSUnit.cpp b/contrib/libs/llvm12/lib/MCA/HardwareUnits/LSUnit.cpp new file mode 100644 index 0000000000..4594368fc0 --- /dev/null +++ b/contrib/libs/llvm12/lib/MCA/HardwareUnits/LSUnit.cpp @@ -0,0 +1,252 @@ +//===----------------------- LSUnit.cpp --------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +/// \file +/// +/// A Load-Store Unit for the llvm-mca tool. +/// +//===----------------------------------------------------------------------===// + +#include "llvm/MCA/HardwareUnits/LSUnit.h" +#include "llvm/MCA/Instruction.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "llvm-mca" + +namespace llvm { +namespace mca { + +LSUnitBase::LSUnitBase(const MCSchedModel &SM, unsigned LQ, unsigned SQ, + bool AssumeNoAlias) + : LQSize(LQ), SQSize(SQ), UsedLQEntries(0), UsedSQEntries(0), + NoAlias(AssumeNoAlias), NextGroupID(1) { + if (SM.hasExtraProcessorInfo()) { + const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo(); + if (!LQSize && EPI.LoadQueueID) { + const MCProcResourceDesc &LdQDesc = *SM.getProcResource(EPI.LoadQueueID); + LQSize = std::max(0, LdQDesc.BufferSize); + } + + if (!SQSize && EPI.StoreQueueID) { + const MCProcResourceDesc &StQDesc = *SM.getProcResource(EPI.StoreQueueID); + SQSize = std::max(0, StQDesc.BufferSize); + } + } +} + +LSUnitBase::~LSUnitBase() {} + +void LSUnitBase::cycleEvent() { + for (const std::pair<unsigned, std::unique_ptr<MemoryGroup>> &G : Groups) + G.second->cycleEvent(); +} + +#ifndef NDEBUG +void LSUnitBase::dump() const { + dbgs() << "[LSUnit] LQ_Size = " << getLoadQueueSize() << '\n'; + dbgs() << "[LSUnit] SQ_Size = " << getStoreQueueSize() << '\n'; + dbgs() << "[LSUnit] NextLQSlotIdx = " << getUsedLQEntries() << '\n'; + dbgs() << "[LSUnit] NextSQSlotIdx = " << getUsedSQEntries() << '\n'; + dbgs() << "\n"; + for (const auto &GroupIt : Groups) { + const MemoryGroup &Group = *GroupIt.second; + dbgs() << "[LSUnit] Group (" << GroupIt.first << "): " + << "[ #Preds = " << Group.getNumPredecessors() + << ", #GIssued = " << Group.getNumExecutingPredecessors() + << ", #GExecuted = " << Group.getNumExecutedPredecessors() + << ", #Inst = " << Group.getNumInstructions() + << ", #IIssued = " << Group.getNumExecuting() + << ", #IExecuted = " << Group.getNumExecuted() << '\n'; + } +} +#endif + +unsigned LSUnit::dispatch(const InstRef &IR) { + const InstrDesc &Desc = IR.getInstruction()->getDesc(); + unsigned IsMemBarrier = Desc.HasSideEffects; + assert((Desc.MayLoad || Desc.MayStore) && "Not a memory operation!"); + + if (Desc.MayLoad) + acquireLQSlot(); + if (Desc.MayStore) + acquireSQSlot(); + + if (Desc.MayStore) { + unsigned NewGID = createMemoryGroup(); + MemoryGroup &NewGroup = getGroup(NewGID); + NewGroup.addInstruction(); + + // A store may not pass a previous load or load barrier. + unsigned ImmediateLoadDominator = + std::max(CurrentLoadGroupID, CurrentLoadBarrierGroupID); + if (ImmediateLoadDominator) { + MemoryGroup &IDom = getGroup(ImmediateLoadDominator); + LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << ImmediateLoadDominator + << ") --> (" << NewGID << ")\n"); + IDom.addSuccessor(&NewGroup, !assumeNoAlias()); + } + + // A store may not pass a previous store barrier. + if (CurrentStoreBarrierGroupID) { + MemoryGroup &StoreGroup = getGroup(CurrentStoreBarrierGroupID); + LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" + << CurrentStoreBarrierGroupID + << ") --> (" << NewGID << ")\n"); + StoreGroup.addSuccessor(&NewGroup, true); + } + + // A store may not pass a previous store. + if (CurrentStoreGroupID && + (CurrentStoreGroupID != CurrentStoreBarrierGroupID)) { + MemoryGroup &StoreGroup = getGroup(CurrentStoreGroupID); + LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID + << ") --> (" << NewGID << ")\n"); + StoreGroup.addSuccessor(&NewGroup, !assumeNoAlias()); + } + + + CurrentStoreGroupID = NewGID; + if (IsMemBarrier) + CurrentStoreBarrierGroupID = NewGID; + + if (Desc.MayLoad) { + CurrentLoadGroupID = NewGID; + if (IsMemBarrier) + CurrentLoadBarrierGroupID = NewGID; + } + + return NewGID; + } + + assert(Desc.MayLoad && "Expected a load!"); + + unsigned ImmediateLoadDominator = + std::max(CurrentLoadGroupID, CurrentLoadBarrierGroupID); + + // A new load group is created if we are in one of the following situations: + // 1) This is a load barrier (by construction, a load barrier is always + // assigned to a different memory group). + // 2) There is no load in flight (by construction we always keep loads and + // stores into separate memory groups). + // 3) There is a load barrier in flight. This load depends on it. + // 4) There is an intervening store between the last load dispatched to the + // LSU and this load. We always create a new group even if this load + // does not alias the last dispatched store. + // 5) There is no intervening store and there is an active load group. + // However that group has already started execution, so we cannot add + // this load to it. + bool ShouldCreateANewGroup = + IsMemBarrier || !ImmediateLoadDominator || + CurrentLoadBarrierGroupID == ImmediateLoadDominator || + ImmediateLoadDominator <= CurrentStoreGroupID || + getGroup(ImmediateLoadDominator).isExecuting(); + + if (ShouldCreateANewGroup) { + unsigned NewGID = createMemoryGroup(); + MemoryGroup &NewGroup = getGroup(NewGID); + NewGroup.addInstruction(); + + // A load may not pass a previous store or store barrier + // unless flag 'NoAlias' is set. + if (!assumeNoAlias() && CurrentStoreGroupID) { + MemoryGroup &StoreGroup = getGroup(CurrentStoreGroupID); + LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID + << ") --> (" << NewGID << ")\n"); + StoreGroup.addSuccessor(&NewGroup, true); + } + + // A load barrier may not pass a previous load or load barrier. + if (IsMemBarrier) { + if (ImmediateLoadDominator) { + MemoryGroup &LoadGroup = getGroup(ImmediateLoadDominator); + LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" + << ImmediateLoadDominator + << ") --> (" << NewGID << ")\n"); + LoadGroup.addSuccessor(&NewGroup, true); + } + } else { + // A younger load cannot pass a older load barrier. + if (CurrentLoadBarrierGroupID) { + MemoryGroup &LoadGroup = getGroup(CurrentLoadBarrierGroupID); + LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" + << CurrentLoadBarrierGroupID + << ") --> (" << NewGID << ")\n"); + LoadGroup.addSuccessor(&NewGroup, true); + } + } + + CurrentLoadGroupID = NewGID; + if (IsMemBarrier) + CurrentLoadBarrierGroupID = NewGID; + return NewGID; + } + + // A load may pass a previous load. + MemoryGroup &Group = getGroup(CurrentLoadGroupID); + Group.addInstruction(); + return CurrentLoadGroupID; +} + +LSUnit::Status LSUnit::isAvailable(const InstRef &IR) const { + const InstrDesc &Desc = IR.getInstruction()->getDesc(); + if (Desc.MayLoad && isLQFull()) + return LSUnit::LSU_LQUEUE_FULL; + if (Desc.MayStore && isSQFull()) + return LSUnit::LSU_SQUEUE_FULL; + return LSUnit::LSU_AVAILABLE; +} + +void LSUnitBase::onInstructionExecuted(const InstRef &IR) { + unsigned GroupID = IR.getInstruction()->getLSUTokenID(); + auto It = Groups.find(GroupID); + assert(It != Groups.end() && "Instruction not dispatched to the LS unit"); + It->second->onInstructionExecuted(); + if (It->second->isExecuted()) + Groups.erase(It); +} + +void LSUnitBase::onInstructionRetired(const InstRef &IR) { + const InstrDesc &Desc = IR.getInstruction()->getDesc(); + bool IsALoad = Desc.MayLoad; + bool IsAStore = Desc.MayStore; + assert((IsALoad || IsAStore) && "Expected a memory operation!"); + + if (IsALoad) { + releaseLQSlot(); + LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR.getSourceIndex() + << " has been removed from the load queue.\n"); + } + + if (IsAStore) { + releaseSQSlot(); + LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR.getSourceIndex() + << " has been removed from the store queue.\n"); + } +} + +void LSUnit::onInstructionExecuted(const InstRef &IR) { + const Instruction &IS = *IR.getInstruction(); + if (!IS.isMemOp()) + return; + + LSUnitBase::onInstructionExecuted(IR); + unsigned GroupID = IS.getLSUTokenID(); + if (!isValidGroupID(GroupID)) { + if (GroupID == CurrentLoadGroupID) + CurrentLoadGroupID = 0; + if (GroupID == CurrentStoreGroupID) + CurrentStoreGroupID = 0; + if (GroupID == CurrentLoadBarrierGroupID) + CurrentLoadBarrierGroupID = 0; + if (GroupID == CurrentStoreBarrierGroupID) + CurrentStoreBarrierGroupID = 0; + } +} + +} // namespace mca +} // namespace llvm |