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