1 //===----------------------- LSUnit.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 /// A Load-Store Unit for the llvm-mca tool. 11 /// 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/MCA/HardwareUnits/LSUnit.h" 15 #include "llvm/MCA/Instruction.h" 16 #include "llvm/Support/Debug.h" 17 #include "llvm/Support/raw_ostream.h" 18 19 #define DEBUG_TYPE "llvm-mca" 20 21 namespace llvm { 22 namespace mca { 23 24 LSUnit::LSUnit(const MCSchedModel &SM, unsigned LQ, unsigned SQ, 25 bool AssumeNoAlias) 26 : LQ_Size(LQ), SQ_Size(SQ), NoAlias(AssumeNoAlias) { 27 if (SM.hasExtraProcessorInfo()) { 28 const MCExtraProcessorInfo &EPI = SM.getExtraProcessorInfo(); 29 if (!LQ_Size && EPI.LoadQueueID) { 30 const MCProcResourceDesc &LdQDesc = *SM.getProcResource(EPI.LoadQueueID); 31 LQ_Size = LdQDesc.BufferSize; 32 } 33 34 if (!SQ_Size && EPI.StoreQueueID) { 35 const MCProcResourceDesc &StQDesc = *SM.getProcResource(EPI.StoreQueueID); 36 SQ_Size = StQDesc.BufferSize; 37 } 38 } 39 } 40 41 #ifndef NDEBUG 42 void LSUnit::dump() const { 43 dbgs() << "[LSUnit] LQ_Size = " << LQ_Size << '\n'; 44 dbgs() << "[LSUnit] SQ_Size = " << SQ_Size << '\n'; 45 dbgs() << "[LSUnit] NextLQSlotIdx = " << LoadQueue.size() << '\n'; 46 dbgs() << "[LSUnit] NextSQSlotIdx = " << StoreQueue.size() << '\n'; 47 } 48 #endif 49 50 void LSUnit::assignLQSlot(unsigned Index) { 51 assert(!isLQFull()); 52 assert(LoadQueue.count(Index) == 0); 53 54 LLVM_DEBUG(dbgs() << "[LSUnit] - AssignLQSlot <Idx=" << Index 55 << ",slot=" << LoadQueue.size() << ">\n"); 56 LoadQueue.insert(Index); 57 } 58 59 void LSUnit::assignSQSlot(unsigned Index) { 60 assert(!isSQFull()); 61 assert(StoreQueue.count(Index) == 0); 62 63 LLVM_DEBUG(dbgs() << "[LSUnit] - AssignSQSlot <Idx=" << Index 64 << ",slot=" << StoreQueue.size() << ">\n"); 65 StoreQueue.insert(Index); 66 } 67 68 void LSUnit::dispatch(const InstRef &IR) { 69 const InstrDesc &Desc = IR.getInstruction()->getDesc(); 70 unsigned IsMemBarrier = Desc.HasSideEffects; 71 assert((Desc.MayLoad || Desc.MayStore) && "Not a memory operation!"); 72 73 const unsigned Index = IR.getSourceIndex(); 74 if (Desc.MayLoad) { 75 if (IsMemBarrier) 76 LoadBarriers.insert(Index); 77 assignLQSlot(Index); 78 } 79 80 if (Desc.MayStore) { 81 if (IsMemBarrier) 82 StoreBarriers.insert(Index); 83 assignSQSlot(Index); 84 } 85 } 86 87 LSUnit::Status LSUnit::isAvailable(const InstRef &IR) const { 88 const InstrDesc &Desc = IR.getInstruction()->getDesc(); 89 if (Desc.MayLoad && isLQFull()) 90 return LSUnit::LSU_LQUEUE_FULL; 91 if (Desc.MayStore && isSQFull()) 92 return LSUnit::LSU_SQUEUE_FULL; 93 return LSUnit::LSU_AVAILABLE; 94 } 95 96 unsigned LSUnit::isReady(const InstRef &IR) const { 97 const InstrDesc &Desc = IR.getInstruction()->getDesc(); 98 const unsigned Index = IR.getSourceIndex(); 99 bool IsALoad = Desc.MayLoad; 100 bool IsAStore = Desc.MayStore; 101 assert((IsALoad || IsAStore) && "Not a memory operation!"); 102 assert((!IsALoad || LoadQueue.count(Index) == 1) && "Load not in queue!"); 103 assert((!IsAStore || StoreQueue.count(Index) == 1) && "Store not in queue!"); 104 105 if (IsALoad && !LoadBarriers.empty()) { 106 unsigned LoadBarrierIndex = *LoadBarriers.begin(); 107 // A younger load cannot pass a older load barrier. 108 if (Index > LoadBarrierIndex) 109 return LoadBarrierIndex; 110 // A load barrier cannot pass a older load. 111 if (Index == LoadBarrierIndex && Index != *LoadQueue.begin()) 112 return *LoadQueue.begin(); 113 } 114 115 if (IsAStore && !StoreBarriers.empty()) { 116 unsigned StoreBarrierIndex = *StoreBarriers.begin(); 117 // A younger store cannot pass a older store barrier. 118 if (Index > StoreBarrierIndex) 119 return StoreBarrierIndex; 120 // A store barrier cannot pass a older store. 121 if (Index == StoreBarrierIndex && Index != *StoreQueue.begin()) 122 return *StoreQueue.begin(); 123 } 124 125 // A load may not pass a previous store unless flag 'NoAlias' is set. 126 // A load may pass a previous load. 127 if (NoAlias && IsALoad) 128 return Index; 129 130 if (StoreQueue.size()) { 131 // A load may not pass a previous store. 132 // A store may not pass a previous store. 133 if (Index > *StoreQueue.begin()) 134 return *StoreQueue.begin(); 135 } 136 137 // Okay, we are older than the oldest store in the queue. 138 // If there are no pending loads, then we can say for sure that this 139 // instruction is ready. 140 if (isLQEmpty()) 141 return Index; 142 143 // Check if there are no older loads. 144 if (Index <= *LoadQueue.begin()) 145 return Index; 146 147 // There is at least one younger load. 148 // 149 // A load may pass a previous load. 150 if (IsALoad) 151 return Index; 152 153 // A store may not pass a previous load. 154 return *LoadQueue.begin(); 155 } 156 157 void LSUnit::onInstructionExecuted(const InstRef &IR) { 158 const InstrDesc &Desc = IR.getInstruction()->getDesc(); 159 const unsigned Index = IR.getSourceIndex(); 160 bool IsALoad = Desc.MayLoad; 161 bool IsAStore = Desc.MayStore; 162 163 if (IsALoad) { 164 if (LoadQueue.erase(Index)) { 165 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index 166 << " has been removed from the load queue.\n"); 167 } 168 if (!LoadBarriers.empty() && Index == *LoadBarriers.begin()) { 169 LLVM_DEBUG( 170 dbgs() << "[LSUnit]: Instruction idx=" << Index 171 << " has been removed from the set of load barriers.\n"); 172 LoadBarriers.erase(Index); 173 } 174 } 175 176 if (IsAStore) { 177 if (StoreQueue.erase(Index)) { 178 LLVM_DEBUG(dbgs() << "[LSUnit]: Instruction idx=" << Index 179 << " has been removed from the store queue.\n"); 180 } 181 182 if (!StoreBarriers.empty() && Index == *StoreBarriers.begin()) { 183 LLVM_DEBUG( 184 dbgs() << "[LSUnit]: Instruction idx=" << Index 185 << " has been removed from the set of store barriers.\n"); 186 StoreBarriers.erase(Index); 187 } 188 } 189 } 190 191 } // namespace mca 192 } // namespace llvm 193