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  const MCSchedModel *SchedModel;
58
59  /// Compare routine for std::lower_bound
60  bool operator<(StringRef S) const {
61    return StringRef(Key) < S;
62  }
63
64  /// Compare routine for std::is_sorted.
65  bool operator<(const SubtargetSubTypeKV &Other) const {
66    return StringRef(Key) < StringRef(Other.Key);
67  }
68};
69
70//===----------------------------------------------------------------------===//
71///
72/// Generic base class for all target subtargets.
73///
74class MCSubtargetInfo {
75  Triple TargetTriple;
76  std::string CPU; // CPU being targeted.
77  ArrayRef<SubtargetFeatureKV> ProcFeatures;  // Processor feature list
78  ArrayRef<SubtargetSubTypeKV> ProcDesc;  // Processor descriptions
79
80  // Scheduler machine model
81  const MCWriteProcResEntry *WriteProcResTable;
82  const MCWriteLatencyEntry *WriteLatencyTable;
83  const MCReadAdvanceEntry *ReadAdvanceTable;
84  const MCSchedModel *CPUSchedModel;
85
86  const InstrStage *Stages;            // Instruction itinerary stages
87  const unsigned *OperandCycles;       // Itinerary operand cycles
88  const unsigned *ForwardingPaths;
89  FeatureBitset FeatureBits;           // Feature bits for current CPU + FS
90
91public:
92  MCSubtargetInfo(const MCSubtargetInfo &) = default;
93  MCSubtargetInfo(const Triple &TT, StringRef CPU, StringRef FS,
94                  ArrayRef<SubtargetFeatureKV> PF,
95                  ArrayRef<SubtargetSubTypeKV> PD,
96                  const MCWriteProcResEntry *WPR, const MCWriteLatencyEntry *WL,
97                  const MCReadAdvanceEntry *RA, const InstrStage *IS,
98                  const unsigned *OC, const unsigned *FP);
99  MCSubtargetInfo() = delete;
100  MCSubtargetInfo &operator=(const MCSubtargetInfo &) = delete;
101  MCSubtargetInfo &operator=(MCSubtargetInfo &&) = delete;
102  virtual ~MCSubtargetInfo() = default;
103
104  const Triple &getTargetTriple() const { return TargetTriple; }
105  StringRef getCPU() const { return CPU; }
106
107  const FeatureBitset& getFeatureBits() const { return FeatureBits; }
108  void setFeatureBits(const FeatureBitset &FeatureBits_) {
109    FeatureBits = FeatureBits_;
110  }
111
112  bool hasFeature(unsigned Feature) const {
113    return FeatureBits[Feature];
114  }
115
116protected:
117  /// Initialize the scheduling model and feature bits.
118  ///
119  /// FIXME: Find a way to stick this in the constructor, since it should only
120  /// be called during initialization.
121  void InitMCProcessorInfo(StringRef CPU, StringRef FS);
122
123public:
124  /// Set the features to the default for the given CPU with an appended feature
125  /// string.
126  void setDefaultFeatures(StringRef CPU, StringRef FS);
127
128  /// Toggle a feature and return the re-computed feature bits.
129  /// This version does not change the implied bits.
130  FeatureBitset ToggleFeature(uint64_t FB);
131
132  /// Toggle a feature and return the re-computed feature bits.
133  /// This version does not change the implied bits.
134  FeatureBitset ToggleFeature(const FeatureBitset& FB);
135
136  /// Toggle a set of features and return the re-computed feature bits.
137  /// This version will also change all implied bits.
138  FeatureBitset ToggleFeature(StringRef FS);
139
140  /// Apply a feature flag and return the re-computed feature bits, including
141  /// all feature bits implied by the flag.
142  FeatureBitset ApplyFeatureFlag(StringRef FS);
143
144  /// Set/clear additional feature bits, including all other bits they imply.
145  FeatureBitset SetFeatureBitsTransitively(const FeatureBitset& FB);
146  FeatureBitset ClearFeatureBitsTransitively(const FeatureBitset &FB);
147
148  /// Check whether the subtarget features are enabled/disabled as per
149  /// the provided string, ignoring all other features.
150  bool checkFeatures(StringRef FS) const;
151
152  /// Get the machine model of a CPU.
153  const MCSchedModel &getSchedModelForCPU(StringRef CPU) const;
154
155  /// Get the machine model for this subtarget's CPU.
156  const MCSchedModel &getSchedModel() const { return *CPUSchedModel; }
157
158  /// Return an iterator at the first process resource consumed by the given
159  /// scheduling class.
160  const MCWriteProcResEntry *getWriteProcResBegin(
161    const MCSchedClassDesc *SC) const {
162    return &WriteProcResTable[SC->WriteProcResIdx];
163  }
164  const MCWriteProcResEntry *getWriteProcResEnd(
165    const MCSchedClassDesc *SC) const {
166    return getWriteProcResBegin(SC) + SC->NumWriteProcResEntries;
167  }
168
169  const MCWriteLatencyEntry *getWriteLatencyEntry(const MCSchedClassDesc *SC,
170                                                  unsigned DefIdx) const {
171    assert(DefIdx < SC->NumWriteLatencyEntries &&
172           "MachineModel does not specify a WriteResource for DefIdx");
173
174    return &WriteLatencyTable[SC->WriteLatencyIdx + DefIdx];
175  }
176
177  int getReadAdvanceCycles(const MCSchedClassDesc *SC, unsigned UseIdx,
178                           unsigned WriteResID) const {
179    // TODO: The number of read advance entries in a class can be significant
180    // (~50). Consider compressing the WriteID into a dense ID of those that are
181    // used by ReadAdvance and representing them as a bitset.
182    for (const MCReadAdvanceEntry *I = &ReadAdvanceTable[SC->ReadAdvanceIdx],
183           *E = I + SC->NumReadAdvanceEntries; I != E; ++I) {
184      if (I->UseIdx < UseIdx)
185        continue;
186      if (I->UseIdx > UseIdx)
187        break;
188      // Find the first WriteResIdx match, which has the highest cycle count.
189      if (!I->WriteResourceID || I->WriteResourceID == WriteResID) {
190        return I->Cycles;
191      }
192    }
193    return 0;
194  }
195
196  /// Return the set of ReadAdvance entries declared by the scheduling class
197  /// descriptor in input.
198  ArrayRef<MCReadAdvanceEntry>
199  getReadAdvanceEntries(const MCSchedClassDesc &SC) const {
200    if (!SC.NumReadAdvanceEntries)
201      return ArrayRef<MCReadAdvanceEntry>();
202    return ArrayRef<MCReadAdvanceEntry>(&ReadAdvanceTable[SC.ReadAdvanceIdx],
203                                        SC.NumReadAdvanceEntries);
204  }
205
206  /// Get scheduling itinerary of a CPU.
207  InstrItineraryData getInstrItineraryForCPU(StringRef CPU) const;
208
209  /// Initialize an InstrItineraryData instance.
210  void initInstrItins(InstrItineraryData &InstrItins) const;
211
212  /// Resolve a variant scheduling class for the given MCInst and CPU.
213  virtual unsigned
214  resolveVariantSchedClass(unsigned SchedClass, const MCInst *MI,
215                           unsigned CPUID) const {
216    return 0;
217  }
218
219  /// Check whether the CPU string is valid.
220  bool isCPUStringValid(StringRef CPU) const {
221    auto Found = std::lower_bound(ProcDesc.begin(), ProcDesc.end(), CPU);
222    return Found != ProcDesc.end() && StringRef(Found->Key) == CPU;
223  }
224
225  virtual unsigned getHwMode() const { return 0; }
226
227  /// Return the cache size in bytes for the given level of cache.
228  /// Level is zero-based, so a value of zero means the first level of
229  /// cache.
230  ///
231  virtual Optional<unsigned> getCacheSize(unsigned Level) const;
232
233  /// Return the cache associatvity for the given level of cache.
234  /// Level is zero-based, so a value of zero means the first level of
235  /// cache.
236  ///
237  virtual Optional<unsigned> getCacheAssociativity(unsigned Level) const;
238
239  /// Return the target cache line size in bytes at a given level.
240  ///
241  virtual Optional<unsigned> getCacheLineSize(unsigned Level) const;
242
243  /// Return the target cache line size in bytes.  By default, return
244  /// the line size for the bottom-most level of cache.  This provides
245  /// a more convenient interface for the common case where all cache
246  /// levels have the same line size.  Return zero if there is no
247  /// cache model.
248  ///
249  virtual unsigned getCacheLineSize() const {
250    Optional<unsigned> Size = getCacheLineSize(0);
251    if (Size)
252      return *Size;
253
254    return 0;
255  }
256
257  /// Return the preferred prefetch distance in terms of instructions.
258  ///
259  virtual unsigned getPrefetchDistance() const;
260
261  /// Return the maximum prefetch distance in terms of loop
262  /// iterations.
263  ///
264  virtual unsigned getMaxPrefetchIterationsAhead() const;
265
266  /// Return the minimum stride necessary to trigger software
267  /// prefetching.
268  ///
269  virtual unsigned getMinPrefetchStride() const;
270};
271
272} // end namespace llvm
273
274#endif // LLVM_MC_MCSUBTARGETINFO_H
275