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