blob: 5fd48d9e10102adbfeefc85785b076a162c10173 [file] [log] [blame]
Eugene Zelenko3d8b0eb2017-02-08 22:23:19 +00001//===- MCSubtargetInfo.cpp - Subtarget Information ------------------------===//
Evan Cheng54b68e32011-07-01 20:45:01 +00002//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// 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
Evan Cheng54b68e32011-07-01 20:45:01 +00006//
7//===----------------------------------------------------------------------===//
8
Chandler Carruth6bda14b2017-06-06 11:49:48 +00009#include "llvm/MC/MCSubtargetInfo.h"
Eugene Zelenko3d8b0eb2017-02-08 22:23:19 +000010#include "llvm/ADT/ArrayRef.h"
Evan Cheng54b68e32011-07-01 20:45:01 +000011#include "llvm/ADT/StringRef.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000012#include "llvm/MC/MCInstrItineraries.h"
Eugene Zelenko3d8b0eb2017-02-08 22:23:19 +000013#include "llvm/MC/MCSchedule.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000014#include "llvm/MC/SubtargetFeature.h"
Craig Topper16fc15a2019-03-05 18:54:30 +000015#include "llvm/Support/Format.h"
Evan Cheng54b68e32011-07-01 20:45:01 +000016#include "llvm/Support/raw_ostream.h"
17#include <algorithm>
Eugene Zelenko3d8b0eb2017-02-08 22:23:19 +000018#include <cassert>
19#include <cstring>
Evan Cheng54b68e32011-07-01 20:45:01 +000020
21using namespace llvm;
22
Craig Topper16fc15a2019-03-05 18:54:30 +000023/// Find KV in array using binary search.
Craig Topperca268082019-03-05 18:54:34 +000024template <typename T>
25static const T *Find(StringRef S, ArrayRef<T> A) {
Craig Topper16fc15a2019-03-05 18:54:30 +000026 // Binary search the array
Fangrui Songdc8de602019-06-21 05:40:31 +000027 auto F = llvm::lower_bound(A, S);
Craig Topper16fc15a2019-03-05 18:54:30 +000028 // If not found then return NULL
29 if (F == A.end() || StringRef(F->Key) != S) return nullptr;
30 // Return the found array item
31 return F;
32}
33
34/// For each feature that is (transitively) implied by this feature, set it.
35static
36void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
37 ArrayRef<SubtargetFeatureKV> FeatureTable) {
38 // OR the Implies bits in outside the loop. This allows the Implies for CPUs
39 // which might imply features not in FeatureTable to use this.
40 Bits |= Implies;
41 for (const SubtargetFeatureKV &FE : FeatureTable)
42 if (Implies.test(FE.Value))
43 SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
44}
45
46/// For each feature that (transitively) implies this feature, clear it.
47static
48void ClearImpliedBits(FeatureBitset &Bits, unsigned Value,
49 ArrayRef<SubtargetFeatureKV> FeatureTable) {
50 for (const SubtargetFeatureKV &FE : FeatureTable) {
51 if (FE.Implies.getAsBitset().test(Value)) {
52 Bits.reset(FE.Value);
53 ClearImpliedBits(Bits, FE.Value, FeatureTable);
54 }
55 }
56}
57
58static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
59 ArrayRef<SubtargetFeatureKV> FeatureTable) {
60 assert(SubtargetFeatures::hasFlag(Feature) &&
61 "Feature flags should start with '+' or '-'");
62
63 // Find feature in table.
64 const SubtargetFeatureKV *FeatureEntry =
65 Find(SubtargetFeatures::StripFlag(Feature), FeatureTable);
66 // If there is a match
67 if (FeatureEntry) {
68 // Enable/disable feature in bits
69 if (SubtargetFeatures::isEnabled(Feature)) {
70 Bits.set(FeatureEntry->Value);
71
72 // For each feature that this implies, set it.
73 SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
74 } else {
75 Bits.reset(FeatureEntry->Value);
76
77 // For each feature that implies this, clear it.
78 ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
79 }
80 } else {
81 errs() << "'" << Feature << "' is not a recognized feature for this target"
82 << " (ignoring feature)\n";
83 }
84}
85
86/// Return the length of the longest entry in the table.
Craig Topperca268082019-03-05 18:54:34 +000087template <typename T>
88static size_t getLongestEntryLength(ArrayRef<T> Table) {
Craig Topper16fc15a2019-03-05 18:54:30 +000089 size_t MaxLen = 0;
90 for (auto &I : Table)
91 MaxLen = std::max(MaxLen, std::strlen(I.Key));
92 return MaxLen;
93}
94
Ziang Wanaf857b92019-06-14 21:42:21 +000095/// Display help for feature and mcpu choices.
Craig Topperca268082019-03-05 18:54:34 +000096static void Help(ArrayRef<SubtargetSubTypeKV> CPUTable,
Craig Topper16fc15a2019-03-05 18:54:30 +000097 ArrayRef<SubtargetFeatureKV> FeatTable) {
Ziang Wanaf857b92019-06-14 21:42:21 +000098 // the static variable ensures that the help information only gets
99 // printed once even though a target machine creates multiple subtargets
100 static bool PrintOnce = false;
101 if (PrintOnce) {
102 return;
103 }
104
Craig Topper16fc15a2019-03-05 18:54:30 +0000105 // Determine the length of the longest CPU and Feature entries.
106 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
107 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
108
109 // Print the CPU table.
110 errs() << "Available CPUs for this target:\n\n";
111 for (auto &CPU : CPUTable)
Craig Topperca268082019-03-05 18:54:34 +0000112 errs() << format(" %-*s - Select the %s processor.\n", MaxCPULen, CPU.Key,
113 CPU.Key);
Craig Topper16fc15a2019-03-05 18:54:30 +0000114 errs() << '\n';
115
116 // Print the Feature table.
117 errs() << "Available features for this target:\n\n";
118 for (auto &Feature : FeatTable)
119 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
120 errs() << '\n';
121
122 errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
123 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
Ziang Wanaf857b92019-06-14 21:42:21 +0000124
125 PrintOnce = true;
126}
127
128/// Display help for mcpu choices only
129static void cpuHelp(ArrayRef<SubtargetSubTypeKV> CPUTable) {
130 // the static variable ensures that the help information only gets
131 // printed once even though a target machine creates multiple subtargets
132 static bool PrintOnce = false;
133 if (PrintOnce) {
134 return;
135 }
136
137 // Print the CPU table.
138 errs() << "Available CPUs for this target:\n\n";
139 for (auto &CPU : CPUTable)
140 errs() << "\t" << CPU.Key << "\n";
141 errs() << '\n';
142
143 errs() << "Use -mcpu or -mtune to specify the target's processor.\n"
144 "For example, clang --target=aarch64-unknown-linux-gui "
145 "-mcpu=cortex-a35\n";
146
147 PrintOnce = true;
Craig Topper16fc15a2019-03-05 18:54:30 +0000148}
149
Duncan P. N. Exon Smithe463e472015-07-10 22:52:15 +0000150static FeatureBitset getFeatures(StringRef CPU, StringRef FS,
Craig Topperca268082019-03-05 18:54:34 +0000151 ArrayRef<SubtargetSubTypeKV> ProcDesc,
Duncan P. N. Exon Smithe463e472015-07-10 22:52:15 +0000152 ArrayRef<SubtargetFeatureKV> ProcFeatures) {
Andrew Trickba7b9212012-09-18 05:33:15 +0000153 SubtargetFeatures Features(FS);
Craig Topper16fc15a2019-03-05 18:54:30 +0000154
155 if (ProcDesc.empty() || ProcFeatures.empty())
156 return FeatureBitset();
157
158 assert(std::is_sorted(std::begin(ProcDesc), std::end(ProcDesc)) &&
159 "CPU table is not sorted");
160 assert(std::is_sorted(std::begin(ProcFeatures), std::end(ProcFeatures)) &&
161 "CPU features table is not sorted");
162 // Resulting bits
163 FeatureBitset Bits;
164
165 // Check if help is needed
166 if (CPU == "help")
167 Help(ProcDesc, ProcFeatures);
168
169 // Find CPU entry if CPU name is specified.
170 else if (!CPU.empty()) {
Craig Topperca268082019-03-05 18:54:34 +0000171 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
Craig Topper16fc15a2019-03-05 18:54:30 +0000172
173 // If there is a match
174 if (CPUEntry) {
175 // Set the features implied by this CPU feature, if any.
176 SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
177 } else {
178 errs() << "'" << CPU << "' is not a recognized processor for this target"
179 << " (ignoring processor)\n";
180 }
181 }
182
183 // Iterate through each feature
184 for (const std::string &Feature : Features.getFeatures()) {
185 // Check for help
186 if (Feature == "+help")
187 Help(ProcDesc, ProcFeatures);
Ziang Wanaf857b92019-06-14 21:42:21 +0000188 else if (Feature == "+cpuHelp")
189 cpuHelp(ProcDesc);
Craig Topper16fc15a2019-03-05 18:54:30 +0000190 else
191 ApplyFeatureFlag(Bits, Feature, ProcFeatures);
192 }
193
194 return Bits;
Duncan P. N. Exon Smithe463e472015-07-10 22:52:15 +0000195}
196
197void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) {
198 FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures);
Andrew Trickba7b9212012-09-18 05:33:15 +0000199 if (!CPU.empty())
Duncan P. N. Exon Smithf862f872015-07-10 22:13:43 +0000200 CPUSchedModel = &getSchedModelForCPU(CPU);
Andrew Trickba7b9212012-09-18 05:33:15 +0000201 else
Duncan P. N. Exon Smithf862f872015-07-10 22:13:43 +0000202 CPUSchedModel = &MCSchedModel::GetDefaultSchedModel();
Andrew Trickba7b9212012-09-18 05:33:15 +0000203}
204
Bradley Smith323fee12015-11-16 11:10:19 +0000205void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef FS) {
206 FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures);
Duncan P. N. Exon Smithe463e472015-07-10 22:52:15 +0000207}
208
Duncan P. N. Exon Smith754e21f2015-07-10 22:43:42 +0000209MCSubtargetInfo::MCSubtargetInfo(
Daniel Sanders50f17232015-09-15 16:17:27 +0000210 const Triple &TT, StringRef C, StringRef FS,
Craig Topperca268082019-03-05 18:54:34 +0000211 ArrayRef<SubtargetFeatureKV> PF, ArrayRef<SubtargetSubTypeKV> PD,
Craig Topper2982b842019-03-05 18:54:38 +0000212 const MCWriteProcResEntry *WPR,
Daniel Sandersa73f1fd2015-06-10 12:11:26 +0000213 const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,
Duncan P. N. Exon Smith754e21f2015-07-10 22:43:42 +0000214 const InstrStage *IS, const unsigned *OC, const unsigned *FP)
Daniel Sanders50f17232015-09-15 16:17:27 +0000215 : TargetTriple(TT), CPU(C), ProcFeatures(PF), ProcDesc(PD),
Craig Topper2982b842019-03-05 18:54:38 +0000216 WriteProcResTable(WPR), WriteLatencyTable(WL),
Duncan P. N. Exon Smith754e21f2015-07-10 22:43:42 +0000217 ReadAdvanceTable(RA), Stages(IS), OperandCycles(OC), ForwardingPaths(FP) {
Andrew Trickba7b9212012-09-18 05:33:15 +0000218 InitMCProcessorInfo(CPU, FS);
Evan Cheng1a72add62011-07-07 07:07:08 +0000219}
220
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000221FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) {
222 FeatureBits.flip(FB);
223 return FeatureBits;
224}
225
226FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) {
Evan Cheng91111d22011-07-09 05:47:46 +0000227 FeatureBits ^= FB;
228 return FeatureBits;
229}
230
Simon Tatham760df472019-05-28 16:13:20 +0000231FeatureBitset MCSubtargetInfo::SetFeatureBitsTransitively(
232 const FeatureBitset &FB) {
233 SetImpliedBits(FeatureBits, FB, ProcFeatures);
234 return FeatureBits;
235}
236
237FeatureBitset MCSubtargetInfo::ClearFeatureBitsTransitively(
238 const FeatureBitset &FB) {
239 for (unsigned I = 0, E = FB.size(); I < E; I++) {
240 if (FB[I]) {
241 FeatureBits.reset(I);
242 ClearImpliedBits(FeatureBits, I, ProcFeatures);
243 }
244 }
245 return FeatureBits;
246}
247
Craig Topper16fc15a2019-03-05 18:54:30 +0000248FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef Feature) {
249 // Find feature in table.
250 const SubtargetFeatureKV *FeatureEntry =
251 Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);
252 // If there is a match
253 if (FeatureEntry) {
254 if (FeatureBits.test(FeatureEntry->Value)) {
255 FeatureBits.reset(FeatureEntry->Value);
256 // For each feature that implies this, clear it.
257 ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);
258 } else {
259 FeatureBits.set(FeatureEntry->Value);
260
261 // For each feature that this implies, set it.
262 SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),
263 ProcFeatures);
264 }
265 } else {
266 errs() << "'" << Feature << "' is not a recognized feature for this target"
267 << " (ignoring feature)\n";
268 }
269
Evan Cheng91111d22011-07-09 05:47:46 +0000270 return FeatureBits;
271}
272
John Brawnd03d2292015-06-05 13:29:24 +0000273FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) {
Craig Topper16fc15a2019-03-05 18:54:30 +0000274 ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
John Brawnd03d2292015-06-05 13:29:24 +0000275 return FeatureBits;
276}
Evan Cheng91111d22011-07-09 05:47:46 +0000277
Krzysztof Parzyszek788e7682017-09-14 20:44:20 +0000278bool MCSubtargetInfo::checkFeatures(StringRef FS) const {
279 SubtargetFeatures T(FS);
280 FeatureBitset Set, All;
281 for (std::string F : T.getFeatures()) {
Craig Topper16fc15a2019-03-05 18:54:30 +0000282 ::ApplyFeatureFlag(Set, F, ProcFeatures);
Krzysztof Parzyszek788e7682017-09-14 20:44:20 +0000283 if (F[0] == '-')
284 F[0] = '+';
Craig Topper16fc15a2019-03-05 18:54:30 +0000285 ::ApplyFeatureFlag(All, F, ProcFeatures);
Krzysztof Parzyszek788e7682017-09-14 20:44:20 +0000286 }
287 return (FeatureBits & All) == Set;
288}
289
Duncan P. N. Exon Smithf862f872015-07-10 22:13:43 +0000290const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
Craig Topper2982b842019-03-05 18:54:38 +0000291 assert(std::is_sorted(ProcDesc.begin(), ProcDesc.end()) &&
Craig Topperc177d9e2015-10-17 16:37:11 +0000292 "Processor machine model table is not sorted");
Evan Cheng54b68e32011-07-01 20:45:01 +0000293
294 // Find entry
Craig Topper2982b842019-03-05 18:54:38 +0000295 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
296
297 if (!CPUEntry) {
Craig Topper768ccc42015-04-02 04:27:50 +0000298 if (CPU != "help") // Don't error if the user asked for help.
299 errs() << "'" << CPU
300 << "' is not a recognized processor for this target"
301 << " (ignoring processor)\n";
Pete Cooper11759452014-09-02 17:43:54 +0000302 return MCSchedModel::GetDefaultSchedModel();
Artyom Skroboveab75152014-01-25 16:56:18 +0000303 }
Craig Topper2982b842019-03-05 18:54:38 +0000304 assert(CPUEntry->SchedModel && "Missing processor SchedModel value");
305 return *CPUEntry->SchedModel;
Andrew Trick87255e32012-07-07 04:00:00 +0000306}
Evan Cheng54b68e32011-07-01 20:45:01 +0000307
Andrew Trick87255e32012-07-07 04:00:00 +0000308InstrItineraryData
309MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const {
Krzysztof Parzyszekd0b6ceb2017-09-27 12:48:48 +0000310 const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);
Andrew Trick87255e32012-07-07 04:00:00 +0000311 return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
Evan Cheng54b68e32011-07-01 20:45:01 +0000312}
Andrew Trickd2a19da2012-09-14 20:26:46 +0000313
Andrew Trickd2a19da2012-09-14 20:26:46 +0000314void MCSubtargetInfo::initInstrItins(InstrItineraryData &InstrItins) const {
Duncan P. N. Exon Smithf862f872015-07-10 22:13:43 +0000315 InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
316 ForwardingPaths);
Andrew Trickd2a19da2012-09-14 20:26:46 +0000317}