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