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 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 /// HwMode IDs are stored and accessed in a bit set format, enabling 244 /// users to efficiently retrieve specific IDs, such as the RegInfo 245 /// HwMode ID, from the set as required. Using this approach, various 246 /// types of HwMode IDs can be added to a subtarget to manage different 247 /// attributes within that subtarget, significantly enhancing the 248 /// scalability and usability of HwMode. Moreover, to ensure compatibility, 249 /// this method also supports controlling multiple attributes with a single 250 /// HwMode ID, just as was done previously. 251 enum HwModeType { 252 HwMode_Default, // Return the smallest HwMode ID of current subtarget. 253 HwMode_ValueType, // Return the HwMode ID that controls the ValueType. 254 HwMode_RegInfo, // Return the HwMode ID that controls the RegSizeInfo and 255 // SubRegRange. 256 HwMode_EncodingInfo // Return the HwMode ID that controls the EncodingInfo. 257 }; 258 259 /// Return a bit set containing all HwMode IDs of the current subtarget. getHwModeSet()260 virtual unsigned getHwModeSet() const { return 0; } 261 262 /// HwMode ID corresponding to the 'type' parameter is retrieved from the 263 /// HwMode bit set of the current subtarget. It’s important to note that if 264 /// the current subtarget possesses two HwMode IDs and both control a single 265 /// attribute (such as RegInfo), this interface will result in an error. 266 virtual unsigned getHwMode(enum HwModeType type = HwMode_Default) const { 267 return 0; 268 } 269 270 /// Return the cache size in bytes for the given level of cache. 271 /// Level is zero-based, so a value of zero means the first level of 272 /// cache. 273 /// 274 virtual std::optional<unsigned> getCacheSize(unsigned Level) const; 275 276 /// Return the cache associatvity for the given level of cache. 277 /// Level is zero-based, so a value of zero means the first level of 278 /// cache. 279 /// 280 virtual std::optional<unsigned> getCacheAssociativity(unsigned Level) const; 281 282 /// Return the target cache line size in bytes at a given level. 283 /// 284 virtual std::optional<unsigned> getCacheLineSize(unsigned Level) const; 285 286 /// Return the target cache line size in bytes. By default, return 287 /// the line size for the bottom-most level of cache. This provides 288 /// a more convenient interface for the common case where all cache 289 /// levels have the same line size. Return zero if there is no 290 /// cache model. 291 /// getCacheLineSize()292 virtual unsigned getCacheLineSize() const { 293 std::optional<unsigned> Size = getCacheLineSize(0); 294 if (Size) 295 return *Size; 296 297 return 0; 298 } 299 300 /// Return the preferred prefetch distance in terms of instructions. 301 /// 302 virtual unsigned getPrefetchDistance() const; 303 304 /// Return the maximum prefetch distance in terms of loop 305 /// iterations. 306 /// 307 virtual unsigned getMaxPrefetchIterationsAhead() const; 308 309 /// \return True if prefetching should also be done for writes. 310 /// 311 virtual bool enableWritePrefetching() const; 312 313 /// Return the minimum stride necessary to trigger software 314 /// prefetching. 315 /// 316 virtual unsigned getMinPrefetchStride(unsigned NumMemAccesses, 317 unsigned NumStridedMemAccesses, 318 unsigned NumPrefetches, 319 bool HasCall) const; 320 321 /// \return if target want to issue a prefetch in address space \p AS. 322 virtual bool shouldPrefetchAddressSpace(unsigned AS) const; 323 }; 324 325 } // end namespace llvm 326 327 #endif // LLVM_MC_MCSUBTARGETINFO_H 328