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
27namespace llvm {
28
29class MCInst;
30
31//===----------------------------------------------------------------------===//
32
33/// Used to provide key value pairs for feature and CPU bit flags.
34struct 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.
54struct 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///
75class 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
94public:
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
107 const Triple &getTargetTriple() const { return TargetTriple; }
108 StringRef getCPU() const { return CPU; }
109 StringRef getTuneCPU() const { return TuneCPU; }
110
111 const FeatureBitset& getFeatureBits() const { return FeatureBits; }
112 void setFeatureBits(const FeatureBitset &FeatureBits_) {
113 FeatureBits = FeatureBits_;
114 }
115
116 StringRef getFeatureString() const { return FeatureString; }
117
118 bool hasFeature(unsigned Feature) const {
119 return FeatureBits[Feature];
120 }
121
122protected:
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
129public:
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.
162 const MCSchedModel &getSchedModel() const { return *CPUSchedModel; }
163
164 /// Return an iterator at the first process resource consumed by the given
165 /// scheduling class.
166 const MCWriteProcResEntry *getWriteProcResBegin(
167 const MCSchedClassDesc *SC) const {
168 return &WriteProcResTable[SC->WriteProcResIdx];
169 }
170 const MCWriteProcResEntry *getWriteProcResEnd(
171 const MCSchedClassDesc *SC) const {
172 return getWriteProcResBegin(SC) + SC->NumWriteProcResEntries;
173 }
174
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
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>
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.
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.
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
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 ///
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