LLVM  8.0.1
SubtargetFeature.cpp
Go to the documentation of this file.
1 //===- SubtargetFeature.cpp - CPU characteristics Implementation ----------===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 /// \file Implements the SubtargetFeature interface.
11 //
12 //===----------------------------------------------------------------------===//
13 
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/SmallVector.h"
17 #include "llvm/ADT/StringExtras.h"
18 #include "llvm/ADT/StringRef.h"
19 #include "llvm/ADT/Triple.h"
20 #include "llvm/Config/llvm-config.h"
21 #include "llvm/Support/Compiler.h"
22 #include "llvm/Support/Debug.h"
23 #include "llvm/Support/Format.h"
25 #include <algorithm>
26 #include <cassert>
27 #include <cstddef>
28 #include <cstring>
29 #include <iterator>
30 #include <string>
31 #include <vector>
32 
33 using namespace llvm;
34 
35 /// Determine if a feature has a flag; '+' or '-'
36 static inline bool hasFlag(StringRef Feature) {
37  assert(!Feature.empty() && "Empty string");
38  // Get first character
39  char Ch = Feature[0];
40  // Check if first character is '+' or '-' flag
41  return Ch == '+' || Ch =='-';
42 }
43 
44 /// Return string stripped of flag.
45 static inline std::string StripFlag(StringRef Feature) {
46  return hasFlag(Feature) ? Feature.substr(1) : Feature;
47 }
48 
49 /// Return true if enable flag; '+'.
50 static inline bool isEnabled(StringRef Feature) {
51  assert(!Feature.empty() && "Empty string");
52  // Get first character
53  char Ch = Feature[0];
54  // Check if first character is '+' for enabled
55  return Ch == '+';
56 }
57 
58 /// Splits a string of comma separated items in to a vector of strings.
59 static void Split(std::vector<std::string> &V, StringRef S) {
61  S.split(Tmp, ',', -1, false /* KeepEmpty */);
62  V.assign(Tmp.begin(), Tmp.end());
63 }
64 
65 void SubtargetFeatures::AddFeature(StringRef String, bool Enable) {
66  // Don't add empty features.
67  if (!String.empty())
68  // Convert to lowercase, prepend flag if we don't already have a flag.
69  Features.push_back(hasFlag(String) ? String.lower()
70  : (Enable ? "+" : "-") + String.lower());
71 }
72 
73 /// Find KV in array using binary search.
76  // Binary search the array
77  auto F = std::lower_bound(A.begin(), A.end(), S);
78  // If not found then return NULL
79  if (F == A.end() || StringRef(F->Key) != S) return nullptr;
80  // Return the found array item
81  return F;
82 }
83 
84 /// Return the length of the longest entry in the table.
86  size_t MaxLen = 0;
87  for (auto &I : Table)
88  MaxLen = std::max(MaxLen, std::strlen(I.Key));
89  return MaxLen;
90 }
91 
92 /// Display help for feature choices.
93 static void Help(ArrayRef<SubtargetFeatureKV> CPUTable,
94  ArrayRef<SubtargetFeatureKV> FeatTable) {
95  // Determine the length of the longest CPU and Feature entries.
96  unsigned MaxCPULen = getLongestEntryLength(CPUTable);
97  unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
98 
99  // Print the CPU table.
100  errs() << "Available CPUs for this target:\n\n";
101  for (auto &CPU : CPUTable)
102  errs() << format(" %-*s - %s.\n", MaxCPULen, CPU.Key, CPU.Desc);
103  errs() << '\n';
104 
105  // Print the Feature table.
106  errs() << "Available features for this target:\n\n";
107  for (auto &Feature : FeatTable)
108  errs() << format(" %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
109  errs() << '\n';
110 
111  errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
112  "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
113 }
114 
116  // Break up string into separate features
117  Split(Features, Initial);
118 }
119 
120 std::string SubtargetFeatures::getString() const {
121  return join(Features.begin(), Features.end(), ",");
122 }
123 
124 /// For each feature that is (transitively) implied by this feature, set it.
125 static
127  ArrayRef<SubtargetFeatureKV> FeatureTable) {
128  for (const SubtargetFeatureKV &FE : FeatureTable) {
129  if (FeatureEntry.Value == FE.Value) continue;
130 
131  if ((FeatureEntry.Implies & FE.Value).any()) {
132  Bits |= FE.Value;
133  SetImpliedBits(Bits, FE, FeatureTable);
134  }
135  }
136 }
137 
138 /// For each feature that (transitively) implies this feature, clear it.
139 static
141  const SubtargetFeatureKV &FeatureEntry,
142  ArrayRef<SubtargetFeatureKV> FeatureTable) {
143  for (const SubtargetFeatureKV &FE : FeatureTable) {
144  if (FeatureEntry.Value == FE.Value) continue;
145 
146  if ((FE.Implies & FeatureEntry.Value).any()) {
147  Bits &= ~FE.Value;
148  ClearImpliedBits(Bits, FE, FeatureTable);
149  }
150  }
151 }
152 
153 void
155  ArrayRef<SubtargetFeatureKV> FeatureTable) {
156  // Find feature in table.
157  const SubtargetFeatureKV *FeatureEntry =
158  Find(StripFlag(Feature), FeatureTable);
159  // If there is a match
160  if (FeatureEntry) {
161  if ((Bits & FeatureEntry->Value) == FeatureEntry->Value) {
162  Bits &= ~FeatureEntry->Value;
163  // For each feature that implies this, clear it.
164  ClearImpliedBits(Bits, *FeatureEntry, FeatureTable);
165  } else {
166  Bits |= FeatureEntry->Value;
167 
168  // For each feature that this implies, set it.
169  SetImpliedBits(Bits, *FeatureEntry, FeatureTable);
170  }
171  } else {
172  errs() << "'" << Feature << "' is not a recognized feature for this target"
173  << " (ignoring feature)\n";
174  }
175 }
176 
178  ArrayRef<SubtargetFeatureKV> FeatureTable) {
179  assert(hasFlag(Feature));
180 
181  // Find feature in table.
182  const SubtargetFeatureKV *FeatureEntry =
183  Find(StripFlag(Feature), FeatureTable);
184  // If there is a match
185  if (FeatureEntry) {
186  // Enable/disable feature in bits
187  if (isEnabled(Feature)) {
188  Bits |= FeatureEntry->Value;
189 
190  // For each feature that this implies, set it.
191  SetImpliedBits(Bits, *FeatureEntry, FeatureTable);
192  } else {
193  Bits &= ~FeatureEntry->Value;
194 
195  // For each feature that implies this, clear it.
196  ClearImpliedBits(Bits, *FeatureEntry, FeatureTable);
197  }
198  } else {
199  errs() << "'" << Feature << "' is not a recognized feature for this target"
200  << " (ignoring feature)\n";
201  }
202 }
203 
207  ArrayRef<SubtargetFeatureKV> FeatureTable) {
208  if (CPUTable.empty() || FeatureTable.empty())
209  return FeatureBitset();
210 
211  assert(std::is_sorted(std::begin(CPUTable), std::end(CPUTable)) &&
212  "CPU table is not sorted");
213  assert(std::is_sorted(std::begin(FeatureTable), std::end(FeatureTable)) &&
214  "CPU features table is not sorted");
215  // Resulting bits
217 
218  // Check if help is needed
219  if (CPU == "help")
220  Help(CPUTable, FeatureTable);
221 
222  // Find CPU entry if CPU name is specified.
223  else if (!CPU.empty()) {
224  const SubtargetFeatureKV *CPUEntry = Find(CPU, CPUTable);
225 
226  // If there is a match
227  if (CPUEntry) {
228  // Set base feature bits
229  Bits = CPUEntry->Value;
230 
231  // Set the feature implied by this CPU feature, if any.
232  for (auto &FE : FeatureTable) {
233  if ((CPUEntry->Value & FE.Value).any())
234  SetImpliedBits(Bits, FE, FeatureTable);
235  }
236  } else {
237  errs() << "'" << CPU << "' is not a recognized processor for this target"
238  << " (ignoring processor)\n";
239  }
240  }
241 
242  // Iterate through each feature
243  for (const std::string &Feature : Features) {
244  // Check for help
245  if (Feature == "+help")
246  Help(CPUTable, FeatureTable);
247 
248  ApplyFeatureFlag(Bits, Feature, FeatureTable);
249  }
250 
251  return Bits;
252 }
253 
255  for (auto &F : Features)
256  OS << F << " ";
257  OS << "\n";
258 }
259 
260 #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
262  print(dbgs());
263 }
264 #endif
265 
267  // FIXME: This is an inelegant way of specifying the features of a
268  // subtarget. It would be better if we could encode this information
269  // into the IR. See <rdar://5972456>.
270  if (Triple.getVendor() == Triple::Apple) {
271  if (Triple.getArch() == Triple::ppc) {
272  // powerpc-apple-*
273  AddFeature("altivec");
274  } else if (Triple.getArch() == Triple::ppc64) {
275  // powerpc64-apple-*
276  AddFeature("64bit");
277  AddFeature("altivec");
278  }
279  }
280 }
const_iterator end(StringRef path)
Get end iterator over path.
Definition: Path.cpp:259
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
GCNRegPressure max(const GCNRegPressure &P1, const GCNRegPressure &P2)
const_iterator begin(StringRef path, Style style=Style::native)
Get begin iterator over path.
Definition: Path.cpp:250
static void Help(ArrayRef< SubtargetFeatureKV > CPUTable, ArrayRef< SubtargetFeatureKV > FeatTable)
Display help for feature choices.
void print(raw_ostream &OS) const
Prints feature string.
This class represents lattice values for constants.
Definition: AllocatorList.h:24
void getDefaultSubtargetFeatures(const Triple &Triple)
Adds the default features for the specified target triple.
iterator begin() const
Definition: ArrayRef.h:137
static size_t getLongestEntryLength(ArrayRef< SubtargetFeatureKV > Table)
Return the length of the longest entry in the table.
format_object< Ts... > format(const char *Fmt, const Ts &... Vals)
These are helper functions used to produce formatted output.
Definition: Format.h:124
std::string getString() const
Returns features as a string.
static std::string StripFlag(StringRef Feature)
Return string stripped of flag.
F(f)
std::string join(IteratorT Begin, IteratorT End, StringRef Separator)
Joins the strings in the range [Begin, End), adding Separator between the elements.
Definition: StringExtras.h:371
#define LLVM_DUMP_METHOD
Definition: Compiler.h:74
void AddFeature(StringRef String, bool Enable=true)
Adds Features.
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
Definition: Triple.h:290
FeatureBitset Value
K-V integer value.
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE bool empty() const
empty - Check if the string is empty.
Definition: StringRef.h:133
Used to provide key value pairs for feature and CPU bit flags.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
auto lower_bound(R &&Range, ForwardIt I) -> decltype(adl_begin(Range))
Provide wrappers to std::lower_bound which take ranges instead of having to pass begin/end explicitly...
Definition: STLExtras.h:1282
LLVM_NODISCARD LLVM_ATTRIBUTE_ALWAYS_INLINE StringRef substr(size_t Start, size_t N=npos) const
Return a reference to the substring from [Start, Start + N).
Definition: StringRef.h:598
static void SetImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV &FeatureEntry, ArrayRef< SubtargetFeatureKV > FeatureTable)
For each feature that is (transitively) implied by this feature, set it.
static bool hasFlag(StringRef Feature)
Determine if a feature has a flag; &#39;+&#39; or &#39;-&#39;.
Container class for subtarget features.
VendorType getVendor() const
getVendor - Get the parsed vendor type of this triple.
Definition: Triple.h:296
static const SubtargetFeatureKV * Find(StringRef S, ArrayRef< SubtargetFeatureKV > A)
Find KV in array using binary search.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
Definition: SmallVector.h:129
static void ToggleFeature(FeatureBitset &Bits, StringRef String, ArrayRef< SubtargetFeatureKV > FeatureTable)
Toggles a feature and update the feature bits.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:847
LLVM_NODISCARD std::pair< StringRef, StringRef > split(char Separator) const
Split into two substrings around the first occurrence of a separator character.
Definition: StringRef.h:727
iterator end() const
Definition: ArrayRef.h:138
SubtargetFeatures(StringRef Initial="")
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:133
static void ClearImpliedBits(FeatureBitset &Bits, const SubtargetFeatureKV &FeatureEntry, ArrayRef< SubtargetFeatureKV > FeatureTable)
For each feature that (transitively) implies this feature, clear it.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Definition: SmallVector.h:133
#define I(x, y, z)
Definition: MD5.cpp:58
static bool isEnabled(StringRef Feature)
Return true if enable flag; &#39;+&#39;.
LLVM_NODISCARD std::string lower() const
Definition: StringRef.cpp:108
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature, ArrayRef< SubtargetFeatureKV > FeatureTable)
Applies the feature flag and update the feature bits.
This class implements an extremely fast bulk output stream that can only output to a stream...
Definition: raw_ostream.h:46
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
FeatureBitset Implies
K-V bit mask.
FeatureBitset getFeatureBits(StringRef CPU, ArrayRef< SubtargetFeatureKV > CPUTable, ArrayRef< SubtargetFeatureKV > FeatureTable)
Returns feature bits of a CPU.
static void Split(std::vector< std::string > &V, StringRef S)
Splits a string of comma separated items in to a vector of strings.
bool empty() const
empty - Check if the array is empty.
Definition: ArrayRef.h:144