diff options
Diffstat (limited to 'lib/MCA/HardwareUnits/LSUnit.cpp')
-rw-r--r-- | lib/MCA/HardwareUnits/LSUnit.cpp | 256 |
1 files changed, 136 insertions, 120 deletions
diff --git a/lib/MCA/HardwareUnits/LSUnit.cpp b/lib/MCA/HardwareUnits/LSUnit.cpp index 8895eb392b60..ac1a6a36547b 100644 --- a/lib/MCA/HardwareUnits/LSUnit.cpp +++ b/lib/MCA/HardwareUnits/LSUnit.cpp @@ -1,9 +1,8 @@ //===----------------------- LSUnit.cpp --------------------------*- C++-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// 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 @@ -22,67 +21,133 @@ namespace llvm { namespace mca { -LSUnit::LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ, - bool AssumeNoAlias) - : LQ_Size(LQ), SQ_Size(SQ), NoAlias(AssumeNoAlias) { +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 (!LQ_Size && EPI.LoadQueueID) { + if (!LQSize && EPI.LoadQueueID) { const MCProcResourceDesc &LdQDesc = *SM.getProcResource(EPI.LoadQueueID); - LQ_Size = LdQDesc.BufferSize; + LQSize = LdQDesc.BufferSize; } - if (!SQ_Size && EPI.StoreQueueID) { + if (!SQSize && EPI.StoreQueueID) { const MCProcResourceDesc &StQDesc = *SM.getProcResource(EPI.StoreQueueID); - SQ_Size = StQDesc.BufferSize; + SQSize = StQDesc.BufferSize; } } } -#ifndef NDEBUG -void LSUnit::dump() const { - dbgs() << "[LSUnit] LQ_Size = " << LQ_Size << '\n'; - dbgs() << "[LSUnit] SQ_Size = " << SQ_Size << '\n'; - dbgs() << "[LSUnit] NextLQSlotIdx = " << LoadQueue.size() << '\n'; - dbgs() << "[LSUnit] NextSQSlotIdx = " << StoreQueue.size() << '\n'; -} -#endif - -void LSUnit::assignLQSlot(unsigned Index) { - assert(!isLQFull()); - assert(LoadQueue.count(Index) == 0); +LSUnitBase::~LSUnitBase() {} - LLVM_DEBUG(dbgs() << "[LSUnit] - AssignLQSlot <Idx=" << Index - << ",slot=" << LoadQueue.size() << ">\n"); - LoadQueue.insert(Index); +void LSUnitBase::cycleEvent() { + for (const std::pair<unsigned, std::unique_ptr<MemoryGroup>> &G : Groups) + G.second->cycleEvent(); } -void LSUnit::assignSQSlot(unsigned Index) { - assert(!isSQFull()); - assert(StoreQueue.count(Index) == 0); - - LLVM_DEBUG(dbgs() << "[LSUnit] - AssignSQSlot <Idx=" << Index - << ",slot=" << StoreQueue.size() << ">\n"); - StoreQueue.insert(Index); +#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 -void LSUnit::dispatch(const InstRef &IR) { +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!"); - const unsigned Index = IR.getSourceIndex(); - if (Desc.MayLoad) { - if (IsMemBarrier) - LoadBarriers.insert(Index); - assignLQSlot(Index); - } + if (Desc.MayLoad) + assignLQSlot(); + if (Desc.MayStore) + assignSQSlot(); if (Desc.MayStore) { + // Always create a new group for store operations. + + // A store may not pass a previous store or store barrier. + 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); + } + if (CurrentStoreGroupID) { + MemoryGroup &StoreGroup = getGroup(CurrentStoreGroupID); + LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID + << ") --> (" << NewGID << ")\n"); + StoreGroup.addSuccessor(&NewGroup); + } + + CurrentStoreGroupID = NewGID; + if (Desc.MayLoad) { + CurrentLoadGroupID = NewGID; + if (IsMemBarrier) + CurrentLoadBarrierGroupID = NewGID; + } + + return NewGID; + } + + assert(Desc.MayLoad && "Expected a load!"); + + // Always create a new memory group if this is the first load of the sequence. + + // A load may not pass a previous store unless flag 'NoAlias' is set. + // A load may pass a previous load. + // A younger load cannot pass a older load barrier. + // A load barrier cannot pass a older load. + bool ShouldCreateANewGroup = !CurrentLoadGroupID || IsMemBarrier || + CurrentLoadGroupID <= CurrentStoreGroupID || + CurrentLoadGroupID <= CurrentLoadBarrierGroupID; + if (ShouldCreateANewGroup) { + unsigned NewGID = createMemoryGroup(); + MemoryGroup &NewGroup = getGroup(NewGID); + NewGroup.addInstruction(); + + if (!assumeNoAlias() && CurrentStoreGroupID) { + MemoryGroup &StGroup = getGroup(CurrentStoreGroupID); + LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentStoreGroupID + << ") --> (" << NewGID << ")\n"); + StGroup.addSuccessor(&NewGroup); + } + if (CurrentLoadBarrierGroupID) { + MemoryGroup &LdGroup = getGroup(CurrentLoadBarrierGroupID); + LLVM_DEBUG(dbgs() << "[LSUnit]: GROUP DEP: (" << CurrentLoadBarrierGroupID + << ") --> (" << NewGID << ")\n"); + LdGroup.addSuccessor(&NewGroup); + } + + CurrentLoadGroupID = NewGID; if (IsMemBarrier) - StoreBarriers.insert(Index); - assignSQSlot(Index); + CurrentLoadBarrierGroupID = NewGID; + return NewGID; } + + MemoryGroup &Group = getGroup(CurrentLoadGroupID); + Group.addInstruction(); + return CurrentLoadGroupID; } LSUnit::Status LSUnit::isAvailable(const InstRef &IR) const { @@ -94,95 +159,46 @@ LSUnit::Status LSUnit::isAvailable(const InstRef &IR) const { return LSUnit::LSU_AVAILABLE; } -bool LSUnit::isReady(const InstRef &IR) const { +void LSUnitBase::onInstructionExecuted(const InstRef &IR) { const InstrDesc &Desc = IR.getInstruction()->getDesc(); - const unsigned Index = IR.getSourceIndex(); bool IsALoad = Desc.MayLoad; bool IsAStore = Desc.MayStore; - assert((IsALoad || IsAStore) && "Not a memory operation!"); - assert((!IsALoad || LoadQueue.count(Index) == 1) && "Load not in queue!"); - assert((!IsAStore || StoreQueue.count(Index) == 1) && "Store not in queue!"); - - if (IsALoad && !LoadBarriers.empty()) { - unsigned LoadBarrierIndex = *LoadBarriers.begin(); - // A younger load cannot pass a older load barrier. - if (Index > LoadBarrierIndex) - return false; - // A load barrier cannot pass a older load. - if (Index == LoadBarrierIndex && Index != *LoadQueue.begin()) - return false; - } + assert((IsALoad || IsAStore) && "Expected a memory operation!"); - if (IsAStore && !StoreBarriers.empty()) { - unsigned StoreBarrierIndex = *StoreBarriers.begin(); - // A younger store cannot pass a older store barrier. - if (Index > StoreBarrierIndex) - return false; - // A store barrier cannot pass a older store. - if (Index == StoreBarrierIndex && Index != *StoreQueue.begin()) - return false; - } - - // A load may not pass a previous store unless flag 'NoAlias' is set. - // A load may pass a previous load. - if (NoAlias && IsALoad) - return true; - - if (StoreQueue.size()) { - // A load may not pass a previous store. - // A store may not pass a previous store. - if (Index > *StoreQueue.begin()) - return false; + unsigned GroupID = IR.getInstruction()->getLSUTokenID(); + auto It = Groups.find(GroupID); + It->second->onInstructionExecuted(); + if (It->second->isExecuted()) { + Groups.erase(It); } - // Okay, we are older than the oldest store in the queue. - // If there are no pending loads, then we can say for sure that this - // instruction is ready. - if (isLQEmpty()) - return true; - - // Check if there are no older loads. - if (Index <= *LoadQueue.begin()) - return true; - - // There is at least one younger load. - // - // A store may not pass a previous load. - // A load may pass a previous load. - return !IsAStore; -} - -void LSUnit::onInstructionExecuted(const InstRef &IR) { - const InstrDesc &Desc = IR.getInstruction()->getDesc(); - const unsigned Index = IR.getSourceIndex(); - bool IsALoad = Desc.MayLoad; - bool IsAStore = Desc.MayStore; - if (IsALoad) { - if (LoadQueue.erase(Index)) { - LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index - << " has been removed from the load queue.\n"); - } - if (!LoadBarriers.empty() && Index == *LoadBarriers.begin()) { - LLVM_DEBUG( - dbgs() << "[LSUnit]: Instruction idx=" << Index - << " has been removed from the set of load barriers.\n"); - LoadBarriers.erase(Index); - } + UsedLQEntries--; + LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR.getSourceIndex() + << " has been removed from the load queue.\n"); } if (IsAStore) { - if (StoreQueue.erase(Index)) { - LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index - << " has been removed from the store queue.\n"); - } + UsedSQEntries--; + LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << IR.getSourceIndex() + << " has been removed from the store queue.\n"); + } +} - if (!StoreBarriers.empty() && Index == *StoreBarriers.begin()) { - LLVM_DEBUG( - dbgs() << "[LSUnit]: Instruction idx=" << Index - << " has been removed from the set of store barriers.\n"); - StoreBarriers.erase(Index); - } +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; } } |