blob: 2af8a5559b56efbfbf7d74a1a040fb044644b4ec [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
27 auto F = std::lower_bound(A.begin(), A.end(), S);
28 // 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
95/// Display help for feature 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) {
98 // Determine the length of the longest CPU and Feature entries.
99 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
100 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
101
102 // Print the CPU table.
103 errs() << "Available CPUs for this target:\n\n";
104 for (auto &CPU : CPUTable)
Craig Topperca268082019-03-05 18:54:34 +0000105 errs() << format(" %-*s - Select the %s processor.\n", MaxCPULen, CPU.Key,
106 CPU.Key);
Craig Topper16fc15a2019-03-05 18:54:30 +0000107 errs() << '\n';
108
109 // Print the Feature table.
110 errs() << "Available features for this target:\n\n";
111 for (auto &Feature : FeatTable)
112 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
113 errs() << '\n';
114
115 errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
116 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
117}
118
Duncan P. N. Exon Smithe463e472015-07-10 22:52:15 +0000119static FeatureBitset getFeatures(StringRef CPU, StringRef FS,
Craig Topperca268082019-03-05 18:54:34 +0000120 ArrayRef<SubtargetSubTypeKV> ProcDesc,
Duncan P. N. Exon Smithe463e472015-07-10 22:52:15 +0000121 ArrayRef<SubtargetFeatureKV> ProcFeatures) {
Andrew Trickba7b9212012-09-18 05:33:15 +0000122 SubtargetFeatures Features(FS);
Craig Topper16fc15a2019-03-05 18:54:30 +0000123
124 if (ProcDesc.empty() || ProcFeatures.empty())
125 return FeatureBitset();
126
127 assert(std::is_sorted(std::begin(ProcDesc), std::end(ProcDesc)) &&
128 "CPU table is not sorted");
129 assert(std::is_sorted(std::begin(ProcFeatures), std::end(ProcFeatures)) &&
130 "CPU features table is not sorted");
131 // Resulting bits
132 FeatureBitset Bits;
133
134 // Check if help is needed
135 if (CPU == "help")
136 Help(ProcDesc, ProcFeatures);
137
138 // Find CPU entry if CPU name is specified.
139 else if (!CPU.empty()) {
Craig Topperca268082019-03-05 18:54:34 +0000140 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
Craig Topper16fc15a2019-03-05 18:54:30 +0000141
142 // If there is a match
143 if (CPUEntry) {
144 // Set the features implied by this CPU feature, if any.
145 SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
146 } else {
147 errs() << "'" << CPU << "' is not a recognized processor for this target"
148 << " (ignoring processor)\n";
149 }
150 }
151
152 // Iterate through each feature
153 for (const std::string &Feature : Features.getFeatures()) {
154 // Check for help
155 if (Feature == "+help")
156 Help(ProcDesc, ProcFeatures);
157 else
158 ApplyFeatureFlag(Bits, Feature, ProcFeatures);
159 }
160
161 return Bits;
Duncan P. N. Exon Smithe463e472015-07-10 22:52:15 +0000162}
163
164void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) {
165 FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures);
Andrew Trickba7b9212012-09-18 05:33:15 +0000166 if (!CPU.empty())
Duncan P. N. Exon Smithf862f872015-07-10 22:13:43 +0000167 CPUSchedModel = &getSchedModelForCPU(CPU);
Andrew Trickba7b9212012-09-18 05:33:15 +0000168 else
Duncan P. N. Exon Smithf862f872015-07-10 22:13:43 +0000169 CPUSchedModel = &MCSchedModel::GetDefaultSchedModel();
Andrew Trickba7b9212012-09-18 05:33:15 +0000170}
171
Bradley Smith323fee12015-11-16 11:10:19 +0000172void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef FS) {
173 FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures);
Duncan P. N. Exon Smithe463e472015-07-10 22:52:15 +0000174}
175
Duncan P. N. Exon Smith754e21f2015-07-10 22:43:42 +0000176MCSubtargetInfo::MCSubtargetInfo(
Daniel Sanders50f17232015-09-15 16:17:27 +0000177 const Triple &TT, StringRef C, StringRef FS,
Craig Topperca268082019-03-05 18:54:34 +0000178 ArrayRef<SubtargetFeatureKV> PF, ArrayRef<SubtargetSubTypeKV> PD,
Craig Topper2982b842019-03-05 18:54:38 +0000179 const MCWriteProcResEntry *WPR,
Daniel Sandersa73f1fd2015-06-10 12:11:26 +0000180 const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,
Duncan P. N. Exon Smith754e21f2015-07-10 22:43:42 +0000181 const InstrStage *IS, const unsigned *OC, const unsigned *FP)
Daniel Sanders50f17232015-09-15 16:17:27 +0000182 : TargetTriple(TT), CPU(C), ProcFeatures(PF), ProcDesc(PD),
Craig Topper2982b842019-03-05 18:54:38 +0000183 WriteProcResTable(WPR), WriteLatencyTable(WL),
Duncan P. N. Exon Smith754e21f2015-07-10 22:43:42 +0000184 ReadAdvanceTable(RA), Stages(IS), OperandCycles(OC), ForwardingPaths(FP) {
Andrew Trickba7b9212012-09-18 05:33:15 +0000185 InitMCProcessorInfo(CPU, FS);
Evan Cheng1a72add62011-07-07 07:07:08 +0000186}
187
Michael Kupersteindb0712f2015-05-26 10:47:10 +0000188FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) {
189 FeatureBits.flip(FB);
190 return FeatureBits;
191}
192
193FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) {
Evan Cheng91111d22011-07-09 05:47:46 +0000194 FeatureBits ^= FB;
195 return FeatureBits;
196}
197
Craig Topper16fc15a2019-03-05 18:54:30 +0000198FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef Feature) {
199 // Find feature in table.
200 const SubtargetFeatureKV *FeatureEntry =
201 Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);
202 // If there is a match
203 if (FeatureEntry) {
204 if (FeatureBits.test(FeatureEntry->Value)) {
205 FeatureBits.reset(FeatureEntry->Value);
206 // For each feature that implies this, clear it.
207 ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);
208 } else {
209 FeatureBits.set(FeatureEntry->Value);
210
211 // For each feature that this implies, set it.
212 SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),
213 ProcFeatures);
214 }
215 } else {
216 errs() << "'" << Feature << "' is not a recognized feature for this target"
217 << " (ignoring feature)\n";
218 }
219
Evan Cheng91111d22011-07-09 05:47:46 +0000220 return FeatureBits;
221}
222
John Brawnd03d2292015-06-05 13:29:24 +0000223FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) {
Craig Topper16fc15a2019-03-05 18:54:30 +0000224 ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
John Brawnd03d2292015-06-05 13:29:24 +0000225 return FeatureBits;
226}
Evan Cheng91111d22011-07-09 05:47:46 +0000227
Krzysztof Parzyszek788e7682017-09-14 20:44:20 +0000228bool MCSubtargetInfo::checkFeatures(StringRef FS) const {
229 SubtargetFeatures T(FS);
230 FeatureBitset Set, All;
231 for (std::string F : T.getFeatures()) {
Craig Topper16fc15a2019-03-05 18:54:30 +0000232 ::ApplyFeatureFlag(Set, F, ProcFeatures);
Krzysztof Parzyszek788e7682017-09-14 20:44:20 +0000233 if (F[0] == '-')
234 F[0] = '+';
Craig Topper16fc15a2019-03-05 18:54:30 +0000235 ::ApplyFeatureFlag(All, F, ProcFeatures);
Krzysztof Parzyszek788e7682017-09-14 20:44:20 +0000236 }
237 return (FeatureBits & All) == Set;
238}
239
Duncan P. N. Exon Smithf862f872015-07-10 22:13:43 +0000240const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
Craig Topper2982b842019-03-05 18:54:38 +0000241 assert(std::is_sorted(ProcDesc.begin(), ProcDesc.end()) &&
Craig Topperc177d9e2015-10-17 16:37:11 +0000242 "Processor machine model table is not sorted");
Evan Cheng54b68e32011-07-01 20:45:01 +0000243
244 // Find entry
Craig Topper2982b842019-03-05 18:54:38 +0000245 const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
246
247 if (!CPUEntry) {
Craig Topper768ccc42015-04-02 04:27:50 +0000248 if (CPU != "help") // Don't error if the user asked for help.
249 errs() << "'" << CPU
250 << "' is not a recognized processor for this target"
251 << " (ignoring processor)\n";
Pete Cooper11759452014-09-02 17:43:54 +0000252 return MCSchedModel::GetDefaultSchedModel();
Artyom Skroboveab75152014-01-25 16:56:18 +0000253 }
Craig Topper2982b842019-03-05 18:54:38 +0000254 assert(CPUEntry->SchedModel && "Missing processor SchedModel value");
255 return *CPUEntry->SchedModel;
Andrew Trick87255e32012-07-07 04:00:00 +0000256}
Evan Cheng54b68e32011-07-01 20:45:01 +0000257
Andrew Trick87255e32012-07-07 04:00:00 +0000258InstrItineraryData
259MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const {
Krzysztof Parzyszekd0b6ceb2017-09-27 12:48:48 +0000260 const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);
Andrew Trick87255e32012-07-07 04:00:00 +0000261 return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
Evan Cheng54b68e32011-07-01 20:45:01 +0000262}
Andrew Trickd2a19da2012-09-14 20:26:46 +0000263
Andrew Trickd2a19da2012-09-14 20:26:46 +0000264void MCSubtargetInfo::initInstrItins(InstrItineraryData &InstrItins) const {
Duncan P. N. Exon Smithf862f872015-07-10 22:13:43 +0000265 InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
266 ForwardingPaths);
Andrew Trickd2a19da2012-09-14 20:26:46 +0000267}