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