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
28namespace llvm {
29
30class MCInst;
31
32//===----------------------------------------------------------------------===//
33
34/// Used to provide key value pairs for feature and CPU bit flags.
35struct 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.
55struct 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///
76class 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
95public:
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
108  const Triple &getTargetTriple() const { return TargetTriple; }
109  StringRef getCPU() const { return CPU; }
110  StringRef getTuneCPU() const { return TuneCPU; }
111
112  const FeatureBitset& getFeatureBits() const { return FeatureBits; }
113  void setFeatureBits(const FeatureBitset &FeatureBits_) {
114    FeatureBits = FeatureBits_;
115  }
116
117  StringRef getFeatureString() const { return FeatureString; }
118
119  bool hasFeature(unsigned Feature) const {
120    return FeatureBits[Feature];
121  }
122
123protected:
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
130public:
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.
163  const MCSchedModel &getSchedModel() const { return *CPUSchedModel; }
164
165  /// Return an iterator at the first process resource consumed by the given
166  /// scheduling class.
167  const MCWriteProcResEntry *getWriteProcResBegin(
168    const MCSchedClassDesc *SC) const {
169    return &WriteProcResTable[SC->WriteProcResIdx];
170  }
171  const MCWriteProcResEntry *getWriteProcResEnd(
172    const MCSchedClassDesc *SC) const {
173    return getWriteProcResBegin(SC) + SC->NumWriteProcResEntries;
174  }
175
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
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>
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.
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.
228  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.
234  ArrayRef<SubtargetSubTypeKV> getAllProcessorDescriptions() const {
235    return ProcDesc;
236  }
237
238  /// Return processor features.
239  ArrayRef<SubtargetFeatureKV> getAllProcessorFeatures() const {
240    return ProcFeatures;
241  }
242
243  virtual unsigned getHwMode() const { return 0; }
244
245  /// Return the cache size in bytes for the given level of cache.
246  /// Level is zero-based, so a value of zero means the first level of
247  /// cache.
248  ///
249  virtual std::optional<unsigned> getCacheSize(unsigned Level) const;
250
251  /// Return the cache associatvity for the given level of cache.
252  /// Level is zero-based, so a value of zero means the first level of
253  /// cache.
254  ///
255  virtual std::optional<unsigned> getCacheAssociativity(unsigned Level) const;
256
257  /// Return the target cache line size in bytes at a given level.
258  ///
259  virtual std::optional<unsigned> getCacheLineSize(unsigned Level) const;
260
261  /// Return the target cache line size in bytes.  By default, return
262  /// the line size for the bottom-most level of cache.  This provides
263  /// a more convenient interface for the common case where all cache
264  /// levels have the same line size.  Return zero if there is no
265  /// cache model.
266  ///
267  virtual unsigned getCacheLineSize() const {
268    std::optional<unsigned> Size = getCacheLineSize(0);
269    if (Size)
270      return *Size;
271
272    return 0;
273  }
274
275  /// Return the preferred prefetch distance in terms of instructions.
276  ///
277  virtual unsigned getPrefetchDistance() const;
278
279  /// Return the maximum prefetch distance in terms of loop
280  /// iterations.
281  ///
282  virtual unsigned getMaxPrefetchIterationsAhead() const;
283
284  /// \return True if prefetching should also be done for writes.
285  ///
286  virtual bool enableWritePrefetching() const;
287
288  /// Return the minimum stride necessary to trigger software
289  /// prefetching.
290  ///
291  virtual unsigned getMinPrefetchStride(unsigned NumMemAccesses,
292                                        unsigned NumStridedMemAccesses,
293                                        unsigned NumPrefetches,
294                                        bool HasCall) const;
295
296  /// \return if target want to issue a prefetch in address space \p AS.
297  virtual bool shouldPrefetchAddressSpace(unsigned AS) const;
298};
299
300} // end namespace llvm
301
302#endif // LLVM_MC_MCSUBTARGETINFO_H
303