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