Coverage Report

Created: 2019-07-24 05:18

/Users/buildslave/jenkins/workspace/clang-stage2-coverage-R/llvm/lib/MC/MCSubtargetInfo.cpp
Line
Count
Source (jump to first uncovered line)
1
//===- MCSubtargetInfo.cpp - Subtarget Information ------------------------===//
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
#include "llvm/MC/MCSubtargetInfo.h"
10
#include "llvm/ADT/ArrayRef.h"
11
#include "llvm/ADT/StringRef.h"
12
#include "llvm/MC/MCInstrItineraries.h"
13
#include "llvm/MC/MCSchedule.h"
14
#include "llvm/MC/SubtargetFeature.h"
15
#include "llvm/Support/Format.h"
16
#include "llvm/Support/raw_ostream.h"
17
#include <algorithm>
18
#include <cassert>
19
#include <cstring>
20
21
using namespace llvm;
22
23
/// Find KV in array using binary search.
24
template <typename T>
25
1.18M
static const T *Find(StringRef S, ArrayRef<T> A) {
26
1.18M
  // Binary search the array
27
1.18M
  auto F = llvm::lower_bound(A, S);
28
1.18M
  // If not found then return NULL
29
1.18M
  if (F == A.end() || 
StringRef(F->Key) != S1.18M
)
return nullptr532
;
30
1.18M
  // Return the found array item
31
1.18M
  return F;
32
1.18M
}
MCSubtargetInfo.cpp:llvm::SubtargetFeatureKV const* Find<llvm::SubtargetFeatureKV>(llvm::StringRef, llvm::ArrayRef<llvm::SubtargetFeatureKV>)
Line
Count
Source
25
858k
static const T *Find(StringRef S, ArrayRef<T> A) {
26
858k
  // Binary search the array
27
858k
  auto F = llvm::lower_bound(A, S);
28
858k
  // If not found then return NULL
29
858k
  if (F == A.end() || 
StringRef(F->Key) != S858k
)
return nullptr212
;
30
858k
  // Return the found array item
31
858k
  return F;
32
858k
}
MCSubtargetInfo.cpp:llvm::SubtargetSubTypeKV const* Find<llvm::SubtargetSubTypeKV>(llvm::StringRef, llvm::ArrayRef<llvm::SubtargetSubTypeKV>)
Line
Count
Source
25
323k
static const T *Find(StringRef S, ArrayRef<T> A) {
26
323k
  // Binary search the array
27
323k
  auto F = llvm::lower_bound(A, S);
28
323k
  // If not found then return NULL
29
323k
  if (F == A.end() || 
StringRef(F->Key) != S323k
)
return nullptr320
;
30
322k
  // Return the found array item
31
322k
  return F;
32
322k
}
33
34
/// For each feature that is (transitively) implied by this feature, set it.
35
static
36
void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,
37
7.22M
                    ArrayRef<SubtargetFeatureKV> FeatureTable) {
38
7.22M
  // OR the Implies bits in outside the loop. This allows the Implies for CPUs
39
7.22M
  // which might imply features not in FeatureTable to use this.
40
7.22M
  Bits |= Implies;
41
7.22M
  for (const SubtargetFeatureKV &FE : FeatureTable)
42
1.02G
    if (Implies.test(FE.Value))
43
6.40M
      SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);
44
7.22M
}
45
46
/// For each feature that (transitively) implies this feature, clear it.
47
static
48
void ClearImpliedBits(FeatureBitset &Bits, unsigned Value,
49
8.63M
                      ArrayRef<SubtargetFeatureKV> FeatureTable) {
50
1.48G
  for (const SubtargetFeatureKV &FE : FeatureTable) {
51
1.48G
    if (FE.Implies.getAsBitset().test(Value)) {
52
8.44M
      Bits.reset(FE.Value);
53
8.44M
      ClearImpliedBits(Bits, FE.Value, FeatureTable);
54
8.44M
    }
55
1.48G
  }
56
8.63M
}
57
58
static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,
59
858k
                             ArrayRef<SubtargetFeatureKV> FeatureTable) {
60
858k
  assert(SubtargetFeatures::hasFlag(Feature) &&
61
858k
         "Feature flags should start with '+' or '-'");
62
858k
63
858k
  // Find feature in table.
64
858k
  const SubtargetFeatureKV *FeatureEntry =
65
858k
      Find(SubtargetFeatures::StripFlag(Feature), FeatureTable);
66
858k
  // If there is a match
67
858k
  if (FeatureEntry) {
68
858k
    // Enable/disable feature in bits
69
858k
    if (SubtargetFeatures::isEnabled(Feature)) {
70
673k
      Bits.set(FeatureEntry->Value);
71
673k
72
673k
      // For each feature that this implies, set it.
73
673k
      SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);
74
673k
    } else {
75
184k
      Bits.reset(FeatureEntry->Value);
76
184k
77
184k
      // For each feature that implies this, clear it.
78
184k
      ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);
79
184k
    }
80
858k
  } else {
81
232
    errs() << "'" << Feature << "' is not a recognized feature for this target"
82
232
           << " (ignoring feature)\n";
83
232
  }
84
858k
}
85
86
/// Return the length of the longest entry in the table.
87
template <typename T>
88
0
static size_t getLongestEntryLength(ArrayRef<T> Table) {
89
0
  size_t MaxLen = 0;
90
0
  for (auto &I : Table)
91
0
    MaxLen = std::max(MaxLen, std::strlen(I.Key));
92
0
  return MaxLen;
93
0
}
Unexecuted instantiation: MCSubtargetInfo.cpp:unsigned long getLongestEntryLength<llvm::SubtargetSubTypeKV>(llvm::ArrayRef<llvm::SubtargetSubTypeKV>)
Unexecuted instantiation: MCSubtargetInfo.cpp:unsigned long getLongestEntryLength<llvm::SubtargetFeatureKV>(llvm::ArrayRef<llvm::SubtargetFeatureKV>)
94
95
/// Display help for feature and mcpu choices.
96
static void Help(ArrayRef<SubtargetSubTypeKV> CPUTable,
97
0
                 ArrayRef<SubtargetFeatureKV> FeatTable) {
98
0
  // the static variable ensures that the help information only gets
99
0
  // printed once even though a target machine creates multiple subtargets
100
0
  static bool PrintOnce = false;
101
0
  if (PrintOnce) {
102
0
    return;
103
0
  }
104
0
105
0
  // Determine the length of the longest CPU and Feature entries.
106
0
  unsigned MaxCPULen  = getLongestEntryLength(CPUTable);
107
0
  unsigned MaxFeatLen = getLongestEntryLength(FeatTable);
108
0
109
0
  // Print the CPU table.
110
0
  errs() << "Available CPUs for this target:\n\n";
111
0
  for (auto &CPU : CPUTable)
112
0
    errs() << format("  %-*s - Select the %s processor.\n", MaxCPULen, CPU.Key,
113
0
                     CPU.Key);
114
0
  errs() << '\n';
115
0
116
0
  // Print the Feature table.
117
0
  errs() << "Available features for this target:\n\n";
118
0
  for (auto &Feature : FeatTable)
119
0
    errs() << format("  %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
120
0
  errs() << '\n';
121
0
122
0
  errs() << "Use +feature to enable a feature, or -feature to disable it.\n"
123
0
            "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";
124
0
125
0
  PrintOnce = true;
126
0
}
127
128
/// Display help for mcpu choices only
129
4
static void cpuHelp(ArrayRef<SubtargetSubTypeKV> CPUTable) {
130
4
  // the static variable ensures that the help information only gets
131
4
  // printed once even though a target machine creates multiple subtargets
132
4
  static bool PrintOnce = false;
133
4
  if (PrintOnce) {
134
0
    return;
135
0
  }
136
4
137
4
  // Print the CPU table.
138
4
  errs() << "Available CPUs for this target:\n\n";
139
4
  for (auto &CPU : CPUTable)
140
316
    errs() << "\t" << CPU.Key << "\n";
141
4
  errs() << '\n';
142
4
143
4
  errs() << "Use -mcpu or -mtune to specify the target's processor.\n"
144
4
            "For example, clang --target=aarch64-unknown-linux-gui "
145
4
            "-mcpu=cortex-a35\n";
146
4
147
4
  PrintOnce = true;
148
4
}
149
150
static FeatureBitset getFeatures(StringRef CPU, StringRef FS,
151
                                 ArrayRef<SubtargetSubTypeKV> ProcDesc,
152
180k
                                 ArrayRef<SubtargetFeatureKV> ProcFeatures) {
153
180k
  SubtargetFeatures Features(FS);
154
180k
155
180k
  if (
ProcDesc.empty()180k
|| ProcFeatures.empty())
156
227
    return FeatureBitset();
157
180k
158
180k
  assert(std::is_sorted(std::begin(ProcDesc), std::end(ProcDesc)) &&
159
180k
         "CPU table is not sorted");
160
180k
  assert(std::is_sorted(std::begin(ProcFeatures), std::end(ProcFeatures)) &&
161
180k
         "CPU features table is not sorted");
162
180k
  // Resulting bits
163
180k
  FeatureBitset Bits;
164
180k
165
180k
  // Check if help is needed
166
180k
  if (CPU == "help")
167
0
    Help(ProcDesc, ProcFeatures);
168
180k
169
180k
  // Find CPU entry if CPU name is specified.
170
180k
  else if (!CPU.empty()) {
171
145k
    const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
172
145k
173
145k
    // If there is a match
174
145k
    if (CPUEntry) {
175
144k
      // Set the features implied by this CPU feature, if any.
176
144k
      SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);
177
144k
    } else {
178
153
      errs() << "'" << CPU << "' is not a recognized processor for this target"
179
153
             << " (ignoring processor)\n";
180
153
    }
181
145k
  }
182
180k
183
180k
  // Iterate through each feature
184
801k
  for (const std::string &Feature : Features.getFeatures()) {
185
801k
    // Check for help
186
801k
    if (Feature == "+help")
187
0
      Help(ProcDesc, ProcFeatures);
188
801k
    else if (Feature == "+cpuHelp")
189
4
      cpuHelp(ProcDesc);
190
801k
    else
191
801k
      ApplyFeatureFlag(Bits, Feature, ProcFeatures);
192
801k
  }
193
180k
194
180k
  return Bits;
195
180k
}
196
197
180k
void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef FS) {
198
180k
  FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures);
199
180k
  if (!CPU.empty())
200
145k
    CPUSchedModel = &getSchedModelForCPU(CPU);
201
35.1k
  else
202
35.1k
    CPUSchedModel = &MCSchedModel::GetDefaultSchedModel();
203
180k
}
204
205
179
void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef FS) {
206
179
  FeatureBits = getFeatures(CPU, FS, ProcDesc, ProcFeatures);
207
179
}
208
209
MCSubtargetInfo::MCSubtargetInfo(
210
    const Triple &TT, StringRef C, StringRef FS,
211
    ArrayRef<SubtargetFeatureKV> PF, ArrayRef<SubtargetSubTypeKV> PD,
212
    const MCWriteProcResEntry *WPR,
213
    const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,
214
    const InstrStage *IS, const unsigned *OC, const unsigned *FP)
215
    : TargetTriple(TT), CPU(C), ProcFeatures(PF), ProcDesc(PD),
216
      WriteProcResTable(WPR), WriteLatencyTable(WL),
217
127k
      ReadAdvanceTable(RA), Stages(IS), OperandCycles(OC), ForwardingPaths(FP) {
218
127k
  InitMCProcessorInfo(CPU, FS);
219
127k
}
220
221
21.4k
FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) {
222
21.4k
  FeatureBits.flip(FB);
223
21.4k
  return FeatureBits;
224
21.4k
}
225
226
196
FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) {
227
196
  FeatureBits ^= FB;
228
196
  return FeatureBits;
229
196
}
230
231
FeatureBitset MCSubtargetInfo::SetFeatureBitsTransitively(
232
21
  const FeatureBitset &FB) {
233
21
  SetImpliedBits(FeatureBits, FB, ProcFeatures);
234
21
  return FeatureBits;
235
21
}
236
237
FeatureBitset MCSubtargetInfo::ClearFeatureBitsTransitively(
238
15
  const FeatureBitset &FB) {
239
2.89k
  for (unsigned I = 0, E = FB.size(); I < E; 
I++2.88k
) {
240
2.88k
    if (FB[I]) {
241
28
      FeatureBits.reset(I);
242
28
      ClearImpliedBits(FeatureBits, I, ProcFeatures);
243
28
    }
244
2.88k
  }
245
15
  return FeatureBits;
246
15
}
247
248
382
FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef Feature) {
249
382
  // Find feature in table.
250
382
  const SubtargetFeatureKV *FeatureEntry =
251
382
      Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);
252
382
  // If there is a match
253
382
  if (FeatureEntry) {
254
381
    if (FeatureBits.test(FeatureEntry->Value)) {
255
84
      FeatureBits.reset(FeatureEntry->Value);
256
84
      // For each feature that implies this, clear it.
257
84
      ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);
258
297
    } else {
259
297
      FeatureBits.set(FeatureEntry->Value);
260
297
261
297
      // For each feature that this implies, set it.
262
297
      SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),
263
297
                     ProcFeatures);
264
297
    }
265
381
  } else {
266
1
    errs() << "'" << Feature << "' is not a recognized feature for this target"
267
1
           << " (ignoring feature)\n";
268
1
  }
269
382
270
382
  return FeatureBits;
271
382
}
272
273
1.44k
FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) {
274
1.44k
  ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);
275
1.44k
  return FeatureBits;
276
1.44k
}
277
278
27.5k
bool MCSubtargetInfo::checkFeatures(StringRef FS) const {
279
27.5k
  SubtargetFeatures T(FS);
280
27.5k
  FeatureBitset Set, All;
281
27.5k
  for (std::string F : T.getFeatures()) {
282
27.5k
    ::ApplyFeatureFlag(Set, F, ProcFeatures);
283
27.5k
    if (F[0] == '-')
284
12.3k
      F[0] = '+';
285
27.5k
    ::ApplyFeatureFlag(All, F, ProcFeatures);
286
27.5k
  }
287
27.5k
  return (FeatureBits & All) == Set;
288
27.5k
}
289
290
178k
const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {
291
178k
  assert(std::is_sorted(ProcDesc.begin(), ProcDesc.end()) &&
292
178k
         "Processor machine model table is not sorted");
293
178k
294
178k
  // Find entry
295
178k
  const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);
296
178k
297
178k
  if (!CPUEntry) {
298
180
    if (CPU != "help") // Don't error if the user asked for help.
299
180
      errs() << "'" << CPU
300
180
             << "' is not a recognized processor for this target"
301
180
             << " (ignoring processor)\n";
302
180
    return MCSchedModel::GetDefaultSchedModel();
303
180
  }
304
177k
  assert(CPUEntry->SchedModel && "Missing processor SchedModel value");
305
177k
  return *CPUEntry->SchedModel;
306
177k
}
307
308
InstrItineraryData
309
25.5k
MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const {
310
25.5k
  const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);
311
25.5k
  return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);
312
25.5k
}
313
314
3.47M
void MCSubtargetInfo::initInstrItins(InstrItineraryData &InstrItins) const {
315
3.47M
  InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,
316
3.47M
                                  ForwardingPaths);
317
3.47M
}