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