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