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 std::string FeatureString; // Feature string 93 94 public: 95 MCSubtargetInfo(const MCSubtargetInfo &) = default; 96 MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef TuneCPU, 97 StringRef FS, ArrayRef<SubtargetFeatureKV> PF, 98 ArrayRef<SubtargetSubTypeKV> PD, 99 const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL, 100 const MCReadAdvanceEntry *RA, const InstrStage *IS, 101 const unsigned *OC, const unsigned *FP); 102 MCSubtargetInfo() = delete; 103 MCSubtargetInfo &operator=(const MCSubtargetInfo &) = delete; 104 MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete; 105 virtual ~MCSubtargetInfo() = default; 106 getTargetTriple()107 const Triple &getTargetTriple() const { return TargetTriple; } getCPU()108 StringRef getCPU() const { return CPU; } getTuneCPU()109 StringRef getTuneCPU() const { return TuneCPU; } 110 getFeatureBits()111 const FeatureBitset& getFeatureBits() const { return FeatureBits; } setFeatureBits(const FeatureBitset & FeatureBits_)112 void setFeatureBits(const FeatureBitset &FeatureBits_) { 113 FeatureBits = FeatureBits_; 114 } 115 getFeatureString()116 StringRef getFeatureString() const { return FeatureString; } 117 hasFeature(unsigned Feature)118 bool hasFeature(unsigned Feature) const { 119 return FeatureBits[Feature]; 120 } 121 122 protected: 123 /// Initialize the scheduling model and feature bits. 124 /// 125 /// FIXME: Find a way to stick this in the constructor, since it should only 126 /// be called during initialization. 127 void InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU, StringRef FS); 128 129 public: 130 /// Set the features to the default for the given CPU and TuneCPU, with ano 131 /// appended feature string. 132 void setDefaultFeatures(StringRef CPU, StringRef TuneCPU, StringRef FS); 133 134 /// Toggle a feature and return the re-computed feature bits. 135 /// This version does not change the implied bits. 136 FeatureBitset ToggleFeature(uint64_t FB); 137 138 /// Toggle a feature and return the re-computed feature bits. 139 /// This version does not change the implied bits. 140 FeatureBitset ToggleFeature(const FeatureBitset& FB); 141 142 /// Toggle a set of features and return the re-computed feature bits. 143 /// This version will also change all implied bits. 144 FeatureBitset ToggleFeature(StringRef FS); 145 146 /// Apply a feature flag and return the re-computed feature bits, including 147 /// all feature bits implied by the flag. 148 FeatureBitset ApplyFeatureFlag(StringRef FS); 149 150 /// Set/clear additional feature bits, including all other bits they imply. 151 FeatureBitset SetFeatureBitsTransitively(const FeatureBitset& FB); 152 FeatureBitset ClearFeatureBitsTransitively(const FeatureBitset &FB); 153 154 /// Check whether the subtarget features are enabled/disabled as per 155 /// the provided string, ignoring all other features. 156 bool checkFeatures(StringRef FS) const; 157 158 /// Get the machine model of a CPU. 159 const MCSchedModel &getSchedModelForCPU(StringRef CPU) const; 160 161 /// Get the machine model for this subtarget's CPU. getSchedModel()162 const MCSchedModel &getSchedModel() const { return *CPUSchedModel; } 163 164 /// Return an iterator at the first process resource consumed by the given 165 /// scheduling class. getWriteProcResBegin(const MCSchedClassDesc * SC)166 const MCWriteProcResEntry *getWriteProcResBegin( 167 const MCSchedClassDesc *SC) const { 168 return &WriteProcResTable[SC->WriteProcResIdx]; 169 } getWriteProcResEnd(const MCSchedClassDesc * SC)170 const MCWriteProcResEntry *getWriteProcResEnd( 171 const MCSchedClassDesc *SC) const { 172 return getWriteProcResBegin(SC) + SC->NumWriteProcResEntries; 173 } 174 getWriteLatencyEntry(const MCSchedClassDesc * SC,unsigned DefIdx)175 const MCWriteLatencyEntry *getWriteLatencyEntry(const MCSchedClassDesc *SC, 176 unsigned DefIdx) const { 177 assert(DefIdx < SC->NumWriteLatencyEntries && 178 "MachineModel does not specify a WriteResource for DefIdx"); 179 180 return &WriteLatencyTable[SC->WriteLatencyIdx + DefIdx]; 181 } 182 getReadAdvanceCycles(const MCSchedClassDesc * SC,unsigned UseIdx,unsigned WriteResID)183 int getReadAdvanceCycles(const MCSchedClassDesc *SC, unsigned UseIdx, 184 unsigned WriteResID) const { 185 // TODO: The number of read advance entries in a class can be significant 186 // (~50). Consider compressing the WriteID into a dense ID of those that are 187 // used by ReadAdvance and representing them as a bitset. 188 for (const MCReadAdvanceEntry *I = &ReadAdvanceTable[SC->ReadAdvanceIdx], 189 *E = I + SC->NumReadAdvanceEntries; I != E; ++I) { 190 if (I->UseIdx < UseIdx) 191 continue; 192 if (I->UseIdx > UseIdx) 193 break; 194 // Find the first WriteResIdx match, which has the highest cycle count. 195 if (!I->WriteResourceID || I->WriteResourceID == WriteResID) { 196 return I->Cycles; 197 } 198 } 199 return 0; 200 } 201 202 /// Return the set of ReadAdvance entries declared by the scheduling class 203 /// descriptor in input. 204 ArrayRef<MCReadAdvanceEntry> getReadAdvanceEntries(const MCSchedClassDesc & SC)205 getReadAdvanceEntries(const MCSchedClassDesc &SC) const { 206 if (!SC.NumReadAdvanceEntries) 207 return ArrayRef<MCReadAdvanceEntry>(); 208 return ArrayRef<MCReadAdvanceEntry>(&ReadAdvanceTable[SC.ReadAdvanceIdx], 209 SC.NumReadAdvanceEntries); 210 } 211 212 /// Get scheduling itinerary of a CPU. 213 InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const; 214 215 /// Initialize an InstrItineraryData instance. 216 void initInstrItins(InstrItineraryData &InstrItins) const; 217 218 /// Resolve a variant scheduling class for the given MCInst and CPU. resolveVariantSchedClass(unsigned SchedClass,const MCInst * MI,const MCInstrInfo * MCII,unsigned CPUID)219 virtual unsigned resolveVariantSchedClass(unsigned SchedClass, 220 const MCInst *MI, 221 const MCInstrInfo *MCII, 222 unsigned CPUID) const { 223 return 0; 224 } 225 226 /// Check whether the CPU string is valid. isCPUStringValid(StringRef CPU)227 bool isCPUStringValid(StringRef CPU) const { 228 auto Found = llvm::lower_bound(ProcDesc, CPU); 229 return Found != ProcDesc.end() && StringRef(Found->Key) == CPU; 230 } 231 getHwMode()232 virtual unsigned getHwMode() const { return 0; } 233 234 /// Return the cache size in bytes for the given level of cache. 235 /// Level is zero-based, so a value of zero means the first level of 236 /// cache. 237 /// 238 virtual Optional<unsigned> getCacheSize(unsigned Level) const; 239 240 /// Return the cache associatvity for the given level of cache. 241 /// Level is zero-based, so a value of zero means the first level of 242 /// cache. 243 /// 244 virtual Optional<unsigned> getCacheAssociativity(unsigned Level) const; 245 246 /// Return the target cache line size in bytes at a given level. 247 /// 248 virtual Optional<unsigned> getCacheLineSize(unsigned Level) const; 249 250 /// Return the target cache line size in bytes. By default, return 251 /// the line size for the bottom-most level of cache. This provides 252 /// a more convenient interface for the common case where all cache 253 /// levels have the same line size. Return zero if there is no 254 /// cache model. 255 /// getCacheLineSize()256 virtual unsigned getCacheLineSize() const { 257 Optional<unsigned> Size = getCacheLineSize(0); 258 if (Size) 259 return *Size; 260 261 return 0; 262 } 263 264 /// Return the preferred prefetch distance in terms of instructions. 265 /// 266 virtual unsigned getPrefetchDistance() const; 267 268 /// Return the maximum prefetch distance in terms of loop 269 /// iterations. 270 /// 271 virtual unsigned getMaxPrefetchIterationsAhead() const; 272 273 /// \return True if prefetching should also be done for writes. 274 /// 275 virtual bool enableWritePrefetching() const; 276 277 /// Return the minimum stride necessary to trigger software 278 /// prefetching. 279 /// 280 virtual unsigned getMinPrefetchStride(unsigned NumMemAccesses, 281 unsigned NumStridedMemAccesses, 282 unsigned NumPrefetches, 283 bool HasCall) const; 284 }; 285 286 } // end namespace llvm 287 288 #endif // LLVM_MC_MCSUBTARGETINFO_H 289