llvm.org GIT mirror llvm / cd52d11
[Subtarget] Move SubtargetFeatureKV/SubtargetInfoKV from SubtargetFeature.h to MCSubtargetInfo.h. Move all code that operates on ProcFeatures and ProcDesc arrays to MCSubtargetInfo. The SubtargetFeature class managed a list of features as strings. And it also had functions for setting bits in a FeatureBitset. The methods that operated on the Feature list as strings are used in other parts of the backend. But the parts that operate on FeatureBitset are very tightly coupled to MCSubtargetInfo and requires passing in the arrays that MCSubtargetInfo owns. And the same struct type is used for ProcFeatures and ProcDesc. This has led to MCSubtargetInfo having 2 arrays keyed by CPU name. One containing a mapping from a CPU name to its features. And one containing a mapping from CPU name to its scheduler model. I would like to make a single CPU array containing all CPU information and remove some unneeded fields the ProcDesc array currently has. But I don't want to make SubtargetFeatures.h have to know about the scheduler model type and have to forward declare or pull in the header file. Differential Revision: https://reviews.llvm.org/D58937 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@355428 91177308-0d34-0410-b5e6-96231b3b80d8 Craig Topper 7 months ago
4 changed file(s) with 224 addition(s) and 245 deletion(s). Raw diff Collapse all Expand all
2626 namespace llvm {
2727
2828 class MCInst;
29
30 //===----------------------------------------------------------------------===//
31
32 /// Used to provide key value pairs for feature and CPU bit flags.
33 struct SubtargetFeatureKV {
34 const char *Key; ///< K-V key string
35 const char *Desc; ///< Help descriptor
36 unsigned Value; ///< K-V integer value
37 FeatureBitArray Implies; ///< K-V bit mask
38
39 /// Compare routine for std::lower_bound
40 bool operator<(StringRef S) const {
41 return StringRef(Key) < S;
42 }
43
44 /// Compare routine for std::is_sorted.
45 bool operator<(const SubtargetFeatureKV &Other) const {
46 return StringRef(Key) < StringRef(Other.Key);
47 }
48 };
49
50 //===----------------------------------------------------------------------===//
51
52 /// Used to provide key value pairs for CPU and arbitrary pointers.
53 struct SubtargetInfoKV {
54 const char *Key; ///< K-V key string
55 const void *Value; ///< K-V pointer value
56
57 /// Compare routine for std::lower_bound
58 bool operator<(StringRef S) const {
59 return StringRef(Key) < S;
60 }
61
62 /// Compare routine for std::is_sorted.
63 bool operator<(const SubtargetInfoKV &Other) const {
64 return StringRef(Key) < StringRef(Other.Key);
65 }
66 };
2967
3068 //===----------------------------------------------------------------------===//
3169 ///
2525
2626 namespace llvm {
2727
28 template class ArrayRef;
2928 class raw_ostream;
3029 class Triple;
3130
7069
7170 //===----------------------------------------------------------------------===//
7271
73 /// Used to provide key value pairs for feature and CPU bit flags.
74 struct SubtargetFeatureKV {
75 const char *Key; ///< K-V key string
76 const char *Desc; ///< Help descriptor
77 unsigned Value; ///< K-V integer value
78 FeatureBitArray Implies; ///< K-V bit mask
79
80 /// Compare routine for std::lower_bound
81 bool operator<(StringRef S) const {
82 return StringRef(Key) < S;
83 }
84
85 /// Compare routine for std::is_sorted.
86 bool operator<(const SubtargetFeatureKV &Other) const {
87 return StringRef(Key) < StringRef(Other.Key);
88 }
89 };
90
91 //===----------------------------------------------------------------------===//
92
93 /// Used to provide key value pairs for CPU and arbitrary pointers.
94 struct SubtargetInfoKV {
95 const char *Key; ///< K-V key string
96 const void *Value; ///< K-V pointer value
97
98 /// Compare routine for std::lower_bound
99 bool operator<(StringRef S) const {
100 return StringRef(Key) < S;
101 }
102
103 /// Compare routine for std::is_sorted.
104 bool operator<(const SubtargetInfoKV &Other) const {
105 return StringRef(Key) < StringRef(Other.Key);
106 }
107 };
108
109 //===----------------------------------------------------------------------===//
110
11172 /// Manages the enabling and disabling of subtarget specific features.
11273 ///
11374 /// Features are encoded as a string of the form
12889 /// Adds Features.
12990 void AddFeature(StringRef String, bool Enable = true);
13091
131 /// Toggles a feature and update the feature bits.
132 static void ToggleFeature(FeatureBitset &Bits, StringRef String,
133 ArrayRef FeatureTable);
134
135 /// Applies the feature flag and update the feature bits.
136 static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
137 ArrayRef FeatureTable);
138
139 /// Returns feature bits of a CPU.
140 FeatureBitset getFeatureBits(StringRef CPU,
141 ArrayRef CPUTable,
142 ArrayRef FeatureTable);
143
14492 /// Returns the vector of individual subtarget features.
14593 const std::vector &getFeatures() const { return Features; }
14694
152100
153101 /// Adds the default features for the specified target triple.
154102 void getDefaultSubtargetFeatures(const Triple& Triple);
103
104 /// Determine if a feature has a flag; '+' or '-'
105 static bool hasFlag(StringRef Feature) {
106 assert(!Feature.empty() && "Empty string");
107 // Get first character
108 char Ch = Feature[0];
109 // Check if first character is '+' or '-' flag
110 return Ch == '+' || Ch =='-';
111 }
112
113 /// Return string stripped of flag.
114 static std::string StripFlag(StringRef Feature) {
115 return hasFlag(Feature) ? Feature.substr(1) : Feature;
116 }
117
118 /// Return true if enable flag; '+'.
119 static inline bool isEnabled(StringRef Feature) {
120 assert(!Feature.empty() && "Empty string");
121 // Get first character
122 char Ch = Feature[0];
123 // Check if first character is '+' for enabled
124 return Ch == '+';
125 }
126
127 /// Splits a string of comma separated items in to a vector of strings.
128 static void Split(std::vector &V, StringRef S);
155129 };
156130
157131 } // end namespace llvm
1111 #include "llvm/MC/MCInstrItineraries.h"
1212 #include "llvm/MC/MCSchedule.h"
1313 #include "llvm/MC/SubtargetFeature.h"
14 #include "llvm/Support/Format.h"
1415 #include "llvm/Support/raw_ostream.h"
1516 #include
1617 #include
1819
1920 using namespace llvm;
2021
22 /// Find KV in array using binary search.
23 static const SubtargetFeatureKV *Find(StringRef S,
24 ArrayRef A) {
25 // Binary search the array
26 auto F = std::lower_bound(A.begin(), A.end(), S);
27 // If not found then return NULL
28 if (F == A.end() || StringRef(F->Key) != S) return nullptr;
29 // Return the found array item
30 return F;
31 }
32
33 /// For each feature that is (transitively) implied by this feature, set it.
34 static
35 void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
36 ArrayRef FeatureTable) {
37 // OR the Implies bits in outside the loop. This allows the Implies for CPUs
38 // which might imply features not in FeatureTable to use this.
39 Bits |= Implies;
40 for (const SubtargetFeatureKV &FE : FeatureTable)
41 if (Implies.test(FE.Value))
42 SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
43 }
44
45 /// For each feature that (transitively) implies this feature, clear it.
46 static
47 void ClearImpliedBits(FeatureBitset &Bits, unsigned Value,
48 ArrayRef FeatureTable) {
49 for (const SubtargetFeatureKV &FE : FeatureTable) {
50 if (FE.Implies.getAsBitset().test(Value)) {
51 Bits.reset(FE.Value);
52 ClearImpliedBits(Bits, FE.Value, FeatureTable);
53 }
54 }
55 }
56
57 static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
58 ArrayRef FeatureTable) {
59 assert(SubtargetFeatures::hasFlag(Feature) &&
60 "Feature flags should start with '+' or '-'");
61
62 // Find feature in table.
63 const SubtargetFeatureKV *FeatureEntry =
64 Find(SubtargetFeatures::StripFlag(Feature), FeatureTable);
65 // If there is a match
66 if (FeatureEntry) {
67 // Enable/disable feature in bits
68 if (SubtargetFeatures::isEnabled(Feature)) {
69 Bits.set(FeatureEntry->Value);
70
71 // For each feature that this implies, set it.
72 SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
73 } else {
74 Bits.reset(FeatureEntry->Value);
75
76 // For each feature that implies this, clear it.
77 ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
78 }
79 } else {
80 errs() << "'" << Feature << "' is not a recognized feature for this target"
81 << " (ignoring feature)\n";
82 }
83 }
84
85 /// Return the length of the longest entry in the table.
86 static size_t getLongestEntryLength(ArrayRef Table) {
87 size_t MaxLen = 0;
88 for (auto &I : Table)
89 MaxLen = std::max(MaxLen, std::strlen(I.Key));
90 return MaxLen;
91 }
92
93 /// Display help for feature choices.
94 static void Help(ArrayRef CPUTable,
95 ArrayRef FeatTable) {
96 // Determine the length of the longest CPU and Feature entries.
97 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
98 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
99
100 // Print the CPU table.
101 errs() << "Available CPUs for this target:\n\n";
102 for (auto &CPU : CPUTable)
103 errs() << format(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
104 errs() << '\n';
105
106 // Print the Feature table.
107 errs() << "Available features for this target:\n\n";
108 for (auto &Feature : FeatTable)
109 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
110 errs() << '\n';
111
112 errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
113 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
114 }
115
21116 static FeatureBitset getFeatures(StringRef CPU, StringRef FS,
22117 ArrayRef ProcDesc,
23118 ArrayRef ProcFeatures) {
24119 SubtargetFeatures Features(FS);
25 return Features.getFeatureBits(CPU, ProcDesc, ProcFeatures);
120
121 if (ProcDesc.empty() || ProcFeatures.empty())
122 return FeatureBitset();
123
124 assert(std::is_sorted(std::begin(ProcDesc), std::end(ProcDesc)) &&
125 "CPU table is not sorted");
126 assert(std::is_sorted(std::begin(ProcFeatures), std::end(ProcFeatures)) &&
127 "CPU features table is not sorted");
128 // Resulting bits
129 FeatureBitset Bits;
130
131 // Check if help is needed
132 if (CPU == "help")
133 Help(ProcDesc, ProcFeatures);
134
135 // Find CPU entry if CPU name is specified.
136 else if (!CPU.empty()) {
137 const SubtargetFeatureKV *CPUEntry = Find(CPU, ProcDesc);
138
139 // If there is a match
140 if (CPUEntry) {
141 // Set the features implied by this CPU feature, if any.
142 SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
143 } else {
144 errs() << "'" << CPU << "' is not a recognized processor for this target"
145 << " (ignoring processor)\n";
146 }
147 }
148
149 // Iterate through each feature
150 for (const std::string &Feature : Features.getFeatures()) {
151 // Check for help
152 if (Feature == "+help")
153 Help(ProcDesc, ProcFeatures);
154 else
155 ApplyFeatureFlag(Bits, Feature, ProcFeatures);
156 }
157
158 return Bits;
26159 }
27160
28161 void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) {
59192 return FeatureBits;
60193 }
61194
62 FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef FS) {
63 SubtargetFeatures::ToggleFeature(FeatureBits, FS, ProcFeatures);
195 FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef Feature) {
196 // Find feature in table.
197 const SubtargetFeatureKV *FeatureEntry =
198 Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);
199 // If there is a match
200 if (FeatureEntry) {
201 if (FeatureBits.test(FeatureEntry->Value)) {
202 FeatureBits.reset(FeatureEntry->Value);
203 // For each feature that implies this, clear it.
204 ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);
205 } else {
206 FeatureBits.set(FeatureEntry->Value);
207
208 // For each feature that this implies, set it.
209 SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),
210 ProcFeatures);
211 }
212 } else {
213 errs() << "'" << Feature << "' is not a recognized feature for this target"
214 << " (ignoring feature)\n";
215 }
216
64217 return FeatureBits;
65218 }
66219
67220 FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) {
68 SubtargetFeatures::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
221 ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
69222 return FeatureBits;
70223 }
71224
73226 SubtargetFeatures T(FS);
74227 FeatureBitset Set, All;
75228 for (std::string F : T.getFeatures()) {
76 SubtargetFeatures::ApplyFeatureFlag(Set, F, ProcFeatures);
229 ::ApplyFeatureFlag(Set, F, ProcFeatures);
77230 if (F[0] == '-')
78231 F[0] = '+';
79 SubtargetFeatures::ApplyFeatureFlag(All, F, ProcFeatures);
232 ::ApplyFeatureFlag(All, F, ProcFeatures);
80233 }
81234 return (FeatureBits & All) == Set;
82235 }
1010 //===----------------------------------------------------------------------===//
1111
1212 #include "llvm/MC/SubtargetFeature.h"
13 #include "llvm/ADT/ArrayRef.h"
1413 #include "llvm/ADT/SmallVector.h"
1514 #include "llvm/ADT/StringExtras.h"
1615 #include "llvm/ADT/StringRef.h"
1817 #include "llvm/Config/llvm-config.h"
1918 #include "llvm/Support/Compiler.h"
2019 #include "llvm/Support/Debug.h"
21 #include "llvm/Support/Format.h"
2220 #include "llvm/Support/raw_ostream.h"
2321 #include
2422 #include
3028
3129 using namespace llvm;
3230
33 /// Determine if a feature has a flag; '+' or '-'
34 static inline bool hasFlag(StringRef Feature) {
35 assert(!Feature.empty() && "Empty string");
36 // Get first character
37 char Ch = Feature[0];
38 // Check if first character is '+' or '-' flag
39 return Ch == '+' || Ch =='-';
40 }
41
42 /// Return string stripped of flag.
43 static inline std::string StripFlag(StringRef Feature) {
44 return hasFlag(Feature) ? Feature.substr(1) : Feature;
45 }
46
47 /// Return true if enable flag; '+'.
48 static inline bool isEnabled(StringRef Feature) {
49 assert(!Feature.empty() && "Empty string");
50 // Get first character
51 char Ch = Feature[0];
52 // Check if first character is '+' for enabled
53 return Ch == '+';
54 }
55
5631 /// Splits a string of comma separated items in to a vector of strings.
57 static void Split(std::vector &V, StringRef S) {
32 void SubtargetFeatures::Split(std::vector &V, StringRef S) {
5833 SmallVector Tmp;
5934 S.split(Tmp, ',', -1, false /* KeepEmpty */);
6035 V.assign(Tmp.begin(), Tmp.end());
6843 : (Enable ? "+" : "-") + String.lower());
6944 }
7045
71 /// Find KV in array using binary search.
72 static const SubtargetFeatureKV *Find(StringRef S,
73 ArrayRef A) {
74 // Binary search the array
75 auto F = std::lower_bound(A.begin(), A.end(), S);
76 // If not found then return NULL
77 if (F == A.end() || StringRef(F->Key) != S) return nullptr;
78 // Return the found array item
79 return F;
80 }
81
82 /// Return the length of the longest entry in the table.
83 static size_t getLongestEntryLength(ArrayRef Table) {
84 size_t MaxLen = 0;
85 for (auto &I : Table)
86 MaxLen = std::max(MaxLen, std::strlen(I.Key));
87 return MaxLen;
88 }
89
90 /// Display help for feature choices.
91 static void Help(ArrayRef CPUTable,
92 ArrayRef FeatTable) {
93 // Determine the length of the longest CPU and Feature entries.
94 unsigned MaxCPULen = getLongestEntryLength(CPUTable);
95 unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
96
97 // Print the CPU table.
98 errs() << "Available CPUs for this target:\n\n";
99 for (auto &CPU : CPUTable)
100 errs() << format(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
101 errs() << '\n';
102
103 // Print the Feature table.
104 errs() << "Available features for this target:\n\n";
105 for (auto &Feature : FeatTable)
106 errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
107 errs() << '\n';
108
109 errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
110 "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
111 }
112
11346 SubtargetFeatures::SubtargetFeatures(StringRef Initial) {
11447 // Break up string into separate features
11548 Split(Features, Initial);
11750
11851 std::string SubtargetFeatures::getString() const {
11952 return join(Features.begin(), Features.end(), ",");
120 }
121
122 /// For each feature that is (transitively) implied by this feature, set it.
123 static
124 void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
125 ArrayRef FeatureTable) {
126 // OR the Implies bits in outside the loop. This allows the Implies for CPUs
127 // which might imply features not in FeatureTable to use this.
128 Bits |= Implies;
129 for (const SubtargetFeatureKV &FE : FeatureTable)
130 if (Implies.test(FE.Value))
131 SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
132 }
133
134 /// For each feature that (transitively) implies this feature, clear it.
135 static
136 void ClearImpliedBits(FeatureBitset &Bits, unsigned Value,
137 ArrayRef FeatureTable) {
138 for (const SubtargetFeatureKV &FE : FeatureTable) {
139 if (FE.Implies.getAsBitset().test(Value)) {
140 Bits.reset(FE.Value);
141 ClearImpliedBits(Bits, FE.Value, FeatureTable);
142 }
143 }
144 }
145
146 void
147 SubtargetFeatures::ToggleFeature(FeatureBitset &Bits, StringRef Feature,
148 ArrayRef FeatureTable) {
149 // Find feature in table.
150 const SubtargetFeatureKV *FeatureEntry =
151 Find(StripFlag(Feature), FeatureTable);
152 // If there is a match
153 if (FeatureEntry) {
154 if (Bits.test(FeatureEntry->Value)) {
155 Bits.reset(FeatureEntry->Value);
156 // For each feature that implies this, clear it.
157 ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
158 } else {
159 Bits.set(FeatureEntry->Value);
160
161 // For each feature that this implies, set it.
162 SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
163 }
164 } else {
165 errs() << "'" << Feature << "' is not a recognized feature for this target"
166 << " (ignoring feature)\n";
167 }
168 }
169
170 void SubtargetFeatures::ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
171 ArrayRef FeatureTable) {
172 assert(hasFlag(Feature));
173
174 // Find feature in table.
175 const SubtargetFeatureKV *FeatureEntry =
176 Find(StripFlag(Feature), FeatureTable);
177 // If there is a match
178 if (FeatureEntry) {
179 // Enable/disable feature in bits
180 if (isEnabled(Feature)) {
181 Bits.set(FeatureEntry->Value);
182
183 // For each feature that this implies, set it.
184 SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
185 } else {
186 Bits.reset(FeatureEntry->Value);
187
188 // For each feature that implies this, clear it.
189 ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
190 }
191 } else {
192 errs() << "'" << Feature << "' is not a recognized feature for this target"
193 << " (ignoring feature)\n";
194 }
195 }
196
197 FeatureBitset
198 SubtargetFeatures::getFeatureBits(StringRef CPU,
199 ArrayRef CPUTable,
200 ArrayRef FeatureTable) {
201 if (CPUTable.empty() || FeatureTable.empty())
202 return FeatureBitset();
203
204 assert(std::is_sorted(std::begin(CPUTable), std::end(CPUTable)) &&
205 "CPU table is not sorted");
206 assert(std::is_sorted(std::begin(FeatureTable), std::end(FeatureTable)) &&
207 "CPU features table is not sorted");
208 // Resulting bits
209 FeatureBitset Bits;
210
211 // Check if help is needed
212 if (CPU == "help")
213 Help(CPUTable, FeatureTable);
214
215 // Find CPU entry if CPU name is specified.
216 else if (!CPU.empty()) {
217 const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable);
218
219 // If there is a match
220 if (CPUEntry) {
221 // Set the features implied by this CPU feature, if any.
222 SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), FeatureTable);
223 } else {
224 errs() << "'" << CPU << "' is not a recognized processor for this target"
225 << " (ignoring processor)\n";
226 }
227 }
228
229 // Iterate through each feature
230 for (const std::string &Feature : Features) {
231 // Check for help
232 if (Feature == "+help")
233 Help(CPUTable, FeatureTable);
234 else
235 ApplyFeatureFlag(Bits, Feature, FeatureTable);
236 }
237
238 return Bits;
23953 }
24054
24155 void SubtargetFeatures::print(raw_ostream &OS) const {