1 //===- llvm/MC/MCSubtargetInfo.h - Subtarget Information --------*- 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 // 9 // This file describes the subtarget options of a Target machine. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_MC_MCSUBTARGETINFO_H 14 #define LLVM_MC_MCSUBTARGETINFO_H 15 16 #include "llvm/ADT/ArrayRef.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/MC/MCInstrItineraries.h" 20 #include "llvm/MC/MCSchedule.h" 21 #include "llvm/TargetParser/SubtargetFeature.h" 22 #include "llvm/TargetParser/Triple.h" 23 #include <cassert> 24 #include <cstdint> 25 #include <optional> 26 #include <string> 27 28 namespace llvm { 29 30 class MCInst; 31 32 //===----------------------------------------------------------------------===// 33 34 /// Used to provide key value pairs for feature and CPU bit flags. 35 struct SubtargetFeatureKV { 36 const char *Key; ///< K-V key string 37 const char *Desc; ///< Help descriptor 38 unsigned Value; ///< K-V integer value 39 FeatureBitArray Implies; ///< K-V bit mask 40 41 /// Compare routine for std::lower_bound 42 bool operator<(StringRef S) const { 43 return StringRef(Key) < S; 44 } 45 46 /// Compare routine for std::is_sorted. 47 bool operator<(const SubtargetFeatureKV &Other) const { 48 return StringRef(Key) < StringRef(Other.Key); 49 } 50 }; 51 52 //===----------------------------------------------------------------------===// 53 54 /// Used to provide key value pairs for feature and CPU bit flags. 55 struct SubtargetSubTypeKV { 56 const char *Key; ///< K-V key string 57 FeatureBitArray Implies; ///< K-V bit mask 58 FeatureBitArray TuneImplies; ///< K-V bit mask 59 const MCSchedModel *SchedModel; 60 61 /// Compare routine for std::lower_bound 62 bool operator<(StringRef S) const { 63 return StringRef(Key) < S; 64 } 65 66 /// Compare routine for std::is_sorted. 67 bool operator<(const SubtargetSubTypeKV &Other) const { 68 return StringRef(Key) < StringRef(Other.Key); 69 } 70 }; 71 72 //===----------------------------------------------------------------------===// 73 /// 74 /// Generic base class for all target subtargets. 75 /// 76 class MCSubtargetInfo { 77 Triple TargetTriple; 78 std::string CPU; // CPU being targeted. 79 std::string TuneCPU; // CPU being tuned for. 80 ArrayRef<SubtargetFeatureKV> ProcFeatures; // Processor feature list 81 ArrayRef<SubtargetSubTypeKV> ProcDesc; // Processor descriptions 82 83 // Scheduler machine model 84 const MCWriteProcResEntry *WriteProcResTable; 85 const MCWriteLatencyEntry *WriteLatencyTable; 86 const MCReadAdvanceEntry *ReadAdvanceTable; 87 const MCSchedModel *CPUSchedModel; 88 89 const InstrStage *Stages; // Instruction itinerary stages 90 const unsigned *OperandCycles; // Itinerary operand cycles 91 const unsigned *ForwardingPaths; 92 FeatureBitset FeatureBits; // Feature bits for current CPU + FS 93 std::string FeatureString; // Feature string 94 95 public: 96 MCSubtargetInfo(const MCSubtargetInfo &) = default; 97 MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef TuneCPU, 98 StringRef FS, ArrayRef<SubtargetFeatureKV> PF, 99 ArrayRef<SubtargetSubTypeKV> PD, 100 const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, 101 const MCReadAdvanceEntry *RA, const InstrStage *IS, 102 const unsigned *OC, const unsigned *FP); 103 MCSubtargetInfo() = delete; 104 MCSubtargetInfo &operator=(const MCSubtargetInfo &) = delete; 105 MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete; 106 virtual ~MCSubtargetInfo() = default; 107 getTargetTriple()108 const Triple &getTargetTriple() const { return TargetTriple; } getCPU()109 StringRef getCPU() const { return CPU; } getTuneCPU()110 StringRef getTuneCPU() const { return TuneCPU; } 111 getFeatureBits()112 const FeatureBitset& getFeatureBits() const { return FeatureBits; } setFeatureBits(const FeatureBitset & FeatureBits_)113 void setFeatureBits(const FeatureBitset &FeatureBits_) { 114 FeatureBits = FeatureBits_; 115 } 116 getFeatureString()117 StringRef getFeatureString() const { return FeatureString; } 118 hasFeature(unsigned Feature)119 bool hasFeature(unsigned Feature) const { 120 return FeatureBits[Feature]; 121 } 122 123 protected: 124 /// Initialize the scheduling model and feature bits. 125 /// 126 /// FIXME: Find a way to stick this in the constructor, since it should only 127 /// be called during initialization. 128 void InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU, StringRef FS); 129 130 public: 131 /// Set the features to the default for the given CPU and TuneCPU, with ano 132 /// appended feature string. 133 void setDefaultFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 134 135 /// Toggle a feature and return the re-computed feature bits. 136 /// This version does not change the implied bits. 137 FeatureBitset ToggleFeature(uint64_t FB); 138 139 /// Toggle a feature and return the re-computed feature bits. 140 /// This version does not change the implied bits. 141 FeatureBitset ToggleFeature(const FeatureBitset& FB); 142 143 /// Toggle a set of features and return the re-computed feature bits. 144 /// This version will also change all implied bits. 145 FeatureBitset ToggleFeature(StringRef FS); 146 147 /// Apply a feature flag and return the re-computed feature bits, including 148 /// all feature bits implied by the flag. 149 FeatureBitset ApplyFeatureFlag(StringRef FS); 150 151 /// Set/clear additional feature bits, including all other bits they imply. 152 FeatureBitset SetFeatureBitsTransitively(const FeatureBitset& FB); 153 FeatureBitset ClearFeatureBitsTransitively(const FeatureBitset &FB); 154 155 /// Check whether the subtarget features are enabled/disabled as per 156 /// the provided string, ignoring all other features. 157 bool checkFeatures(StringRef FS) const; 158 159 /// Get the machine model of a CPU. 160 const MCSchedModel &getSchedModelForCPU(StringRef CPU) const; 161 162 /// Get the machine model for this subtarget's CPU. getSchedModel()163 const MCSchedModel &getSchedModel() const { return *CPUSchedModel; } 164 165 /// Return an iterator at the first process resource consumed by the given 166 /// scheduling class. getWriteProcResBegin(const MCSchedClassDesc * SC)167 const MCWriteProcResEntry *getWriteProcResBegin( 168 const MCSchedClassDesc *SC) const { 169 return &WriteProcResTable[SC->WriteProcResIdx]; 170 } getWriteProcResEnd(const MCSchedClassDesc * SC)171 const MCWriteProcResEntry *getWriteProcResEnd( 172 const MCSchedClassDesc *SC) const { 173 return getWriteProcResBegin(SC) + SC->NumWriteProcResEntries; 174 } 175 getWriteLatencyEntry(const MCSchedClassDesc * SC,unsigned DefIdx)176 const MCWriteLatencyEntry *getWriteLatencyEntry(const MCSchedClassDesc *SC, 177 unsigned DefIdx) const { 178 assert(DefIdx < SC->NumWriteLatencyEntries && 179 "MachineModel does not specify a WriteResource for DefIdx"); 180 181 return &WriteLatencyTable[SC->WriteLatencyIdx + DefIdx]; 182 } 183 getReadAdvanceCycles(const MCSchedClassDesc * SC,unsigned UseIdx,unsigned WriteResID)184 int getReadAdvanceCycles(const MCSchedClassDesc *SC, unsigned UseIdx, 185 unsigned WriteResID) const { 186 // TODO: The number of read advance entries in a class can be significant 187 // (~50). Consider compressing the WriteID into a dense ID of those that are 188 // used by ReadAdvance and representing them as a bitset. 189 for (const MCReadAdvanceEntry *I = &ReadAdvanceTable[SC->ReadAdvanceIdx], 190 *E = I + SC->NumReadAdvanceEntries; I != E; ++I) { 191 if (I->UseIdx < UseIdx) 192 continue; 193 if (I->UseIdx > UseIdx) 194 break; 195 // Find the first WriteResIdx match, which has the highest cycle count. 196 if (!I->WriteResourceID || I->WriteResourceID == WriteResID) { 197 return I->Cycles; 198 } 199 } 200 return 0; 201 } 202 203 /// Return the set of ReadAdvance entries declared by the scheduling class 204 /// descriptor in input. 205 ArrayRef<MCReadAdvanceEntry> getReadAdvanceEntries(const MCSchedClassDesc & SC)206 getReadAdvanceEntries(const MCSchedClassDesc &SC) const { 207 if (!SC.NumReadAdvanceEntries) 208 return ArrayRef<MCReadAdvanceEntry>(); 209 return ArrayRef<MCReadAdvanceEntry>(&ReadAdvanceTable[SC.ReadAdvanceIdx], 210 SC.NumReadAdvanceEntries); 211 } 212 213 /// Get scheduling itinerary of a CPU. 214 InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const; 215 216 /// Initialize an InstrItineraryData instance. 217 void initInstrItins(InstrItineraryData &InstrItins) const; 218 219 /// Resolve a variant scheduling class for the given MCInst and CPU. resolveVariantSchedClass(unsigned SchedClass,const MCInst * MI,const MCInstrInfo * MCII,unsigned CPUID)220 virtual unsigned resolveVariantSchedClass(unsigned SchedClass, 221 const MCInst *MI, 222 const MCInstrInfo *MCII, 223 unsigned CPUID) const { 224 return 0; 225 } 226 227 /// Check whether the CPU string is valid. isCPUStringValid(StringRef CPU)228 virtual bool isCPUStringValid(StringRef CPU) const { 229 auto Found = llvm::lower_bound(ProcDesc, CPU); 230 return Found != ProcDesc.end() && StringRef(Found->Key) == CPU; 231 } 232 233 /// Return processor descriptions. getAllProcessorDescriptions()234 ArrayRef<SubtargetSubTypeKV> getAllProcessorDescriptions() const { 235 return ProcDesc; 236 } 237 238 /// Return processor features. getAllProcessorFeatures()239 ArrayRef<SubtargetFeatureKV> getAllProcessorFeatures() const { 240 return ProcFeatures; 241 } 242 243 /// Return the list of processor features currently enabled. 244 std::vector<SubtargetFeatureKV> getEnabledProcessorFeatures() const; 245 246 /// HwMode IDs are stored and accessed in a bit set format, enabling 247 /// users to efficiently retrieve specific IDs, such as the RegInfo 248 /// HwMode ID, from the set as required. Using this approach, various 249 /// types of HwMode IDs can be added to a subtarget to manage different 250 /// attributes within that subtarget, significantly enhancing the 251 /// scalability and usability of HwMode. Moreover, to ensure compatibility, 252 /// this method also supports controlling multiple attributes with a single 253 /// HwMode ID, just as was done previously. 254 enum HwModeType { 255 HwMode_Default, // Return the smallest HwMode ID of current subtarget. 256 HwMode_ValueType, // Return the HwMode ID that controls the ValueType. 257 HwMode_RegInfo, // Return the HwMode ID that controls the RegSizeInfo and 258 // SubRegRange. 259 HwMode_EncodingInfo // Return the HwMode ID that controls the EncodingInfo. 260 }; 261 262 /// Return a bit set containing all HwMode IDs of the current subtarget. getHwModeSet()263 virtual unsigned getHwModeSet() const { return 0; } 264 265 /// HwMode ID corresponding to the 'type' parameter is retrieved from the 266 /// HwMode bit set of the current subtarget. It’s important to note that if 267 /// the current subtarget possesses two HwMode IDs and both control a single 268 /// attribute (such as RegInfo), this interface will result in an error. 269 virtual unsigned getHwMode(enum HwModeType type = HwMode_Default) const { 270 return 0; 271 } 272 273 /// Return the cache size in bytes for the given level of cache. 274 /// Level is zero-based, so a value of zero means the first level of 275 /// cache. 276 /// 277 virtual std::optional<unsigned> getCacheSize(unsigned Level) const; 278 279 /// Return the cache associatvity for the given level of cache. 280 /// Level is zero-based, so a value of zero means the first level of 281 /// cache. 282 /// 283 virtual std::optional<unsigned> getCacheAssociativity(unsigned Level) const; 284 285 /// Return the target cache line size in bytes at a given level. 286 /// 287 virtual std::optional<unsigned> getCacheLineSize(unsigned Level) const; 288 289 /// Return the target cache line size in bytes. By default, return 290 /// the line size for the bottom-most level of cache. This provides 291 /// a more convenient interface for the common case where all cache 292 /// levels have the same line size. Return zero if there is no 293 /// cache model. 294 /// getCacheLineSize()295 virtual unsigned getCacheLineSize() const { 296 std::optional<unsigned> Size = getCacheLineSize(0); 297 if (Size) 298 return *Size; 299 300 return 0; 301 } 302 303 /// Return the preferred prefetch distance in terms of instructions. 304 /// 305 virtual unsigned getPrefetchDistance() const; 306 307 /// Return the maximum prefetch distance in terms of loop 308 /// iterations. 309 /// 310 virtual unsigned getMaxPrefetchIterationsAhead() const; 311 312 /// \return True if prefetching should also be done for writes. 313 /// 314 virtual bool enableWritePrefetching() const; 315 316 /// Return the minimum stride necessary to trigger software 317 /// prefetching. 318 /// 319 virtual unsigned getMinPrefetchStride(unsigned NumMemAccesses, 320 unsigned NumStridedMemAccesses, 321 unsigned NumPrefetches, 322 bool HasCall) const; 323 324 /// \return if target want to issue a prefetch in address space \p AS. 325 virtual bool shouldPrefetchAddressSpace(unsigned AS) const; 326 }; 327 328 } // end namespace llvm 329 330 #endif // LLVM_MC_MCSUBTARGETINFO_H 331