brintos

brintos / llvm-project-archived public Read only

0
0
Text · 13.4 KiB · 89a0832 Raw
410 lines · cpp
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-exception6//7//===----------------------------------------------------------------------===//8 9#include "llvm/MC/MCSubtargetInfo.h"10#include "llvm/ADT/ArrayRef.h"11#include "llvm/ADT/StringRef.h"12#include "llvm/ADT/Twine.h"13#include "llvm/MC/MCInstrItineraries.h"14#include "llvm/MC/MCSchedule.h"15#include "llvm/Support/Format.h"16#include "llvm/Support/raw_ostream.h"17#include "llvm/TargetParser/SubtargetFeature.h"18#include <algorithm>19#include <cassert>20#include <cstring>21#include <optional>22 23using namespace llvm;24 25/// Find KV in array using binary search.26template <typename T>27static const T *Find(StringRef S, ArrayRef<T> A) {28  // Binary search the array29  auto F = llvm::lower_bound(A, S);30  // If not found then return NULL31  if (F == A.end() || StringRef(F->Key) != S) return nullptr;32  // Return the found array item33  return F;34}35 36/// For each feature that is (transitively) implied by this feature, set it.37static38void SetImpliedBits(FeatureBitset &Bits, const FeatureBitset &Implies,39                    ArrayRef<SubtargetFeatureKV> FeatureTable) {40  // OR the Implies bits in outside the loop. This allows the Implies for CPUs41  // which might imply features not in FeatureTable to use this.42  Bits |= Implies;43  for (const SubtargetFeatureKV &FE : FeatureTable)44    if (Implies.test(FE.Value))45      SetImpliedBits(Bits, FE.Implies.getAsBitset(), FeatureTable);46}47 48/// For each feature that (transitively) implies this feature, clear it.49static50void ClearImpliedBits(FeatureBitset &Bits, unsigned Value,51                      ArrayRef<SubtargetFeatureKV> FeatureTable) {52  for (const SubtargetFeatureKV &FE : FeatureTable) {53    if (FE.Implies.getAsBitset().test(Value)) {54      Bits.reset(FE.Value);55      ClearImpliedBits(Bits, FE.Value, FeatureTable);56    }57  }58}59 60static void ApplyFeatureFlag(FeatureBitset &Bits, StringRef Feature,61                             ArrayRef<SubtargetFeatureKV> FeatureTable) {62  assert(SubtargetFeatures::hasFlag(Feature) &&63         "Feature flags should start with '+' or '-'");64 65  // Find feature in table.66  const SubtargetFeatureKV *FeatureEntry =67      Find(SubtargetFeatures::StripFlag(Feature), FeatureTable);68  // If there is a match69  if (FeatureEntry) {70    // Enable/disable feature in bits71    if (SubtargetFeatures::isEnabled(Feature)) {72      Bits.set(FeatureEntry->Value);73 74      // For each feature that this implies, set it.75      SetImpliedBits(Bits, FeatureEntry->Implies.getAsBitset(), FeatureTable);76    } else {77      Bits.reset(FeatureEntry->Value);78 79      // For each feature that implies this, clear it.80      ClearImpliedBits(Bits, FeatureEntry->Value, FeatureTable);81    }82  } else {83    errs() << "'" << Feature << "' is not a recognized feature for this target"84           << " (ignoring feature)\n";85  }86}87 88/// Return the length of the longest entry in the table.89static size_t getLongestEntryLength(ArrayRef<SubtargetFeatureKV> Table) {90  size_t MaxLen = 0;91  for (auto &I : Table)92    MaxLen = std::max(MaxLen, std::strlen(I.Key));93  return MaxLen;94}95 96static size_t getLongestEntryLength(ArrayRef<StringRef> Table) {97  size_t MaxLen = 0;98  for (StringRef I : Table)99    MaxLen = std::max(MaxLen, I.size());100  return MaxLen;101}102 103/// Display help for feature and mcpu choices.104static void Help(ArrayRef<StringRef> CPUNames,105                 ArrayRef<SubtargetFeatureKV> FeatTable) {106  // the static variable ensures that the help information only gets107  // printed once even though a target machine creates multiple subtargets108  static bool PrintOnce = false;109  if (PrintOnce) {110    return;111  }112 113  // Determine the length of the longest CPU and Feature entries.114  unsigned MaxCPULen = getLongestEntryLength(CPUNames);115  unsigned MaxFeatLen = getLongestEntryLength(FeatTable);116 117  // Print the CPU table.118  errs() << "Available CPUs for this target:\n\n";119  for (auto &CPUName : CPUNames) {120    // Skip apple-latest, as that's only meant to be used in121    // disassemblers/debuggers, and we don't want normal code to be built with122    // it as an -mcpu=123    if (CPUName == "apple-latest")124      continue;125    errs() << format("  %-*s - Select the %s processor.\n", MaxCPULen,126                     CPUName.str().c_str(), CPUName.str().c_str());127  }128  errs() << '\n';129 130  // Print the Feature table.131  errs() << "Available features for this target:\n\n";132  for (auto &Feature : FeatTable)133    errs() << format("  %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);134  errs() << '\n';135 136  errs() << "Use +feature to enable a feature, or -feature to disable it.\n"137            "For example, llc -mcpu=mycpu -mattr=+feature1,-feature2\n";138 139  PrintOnce = true;140}141 142/// Display help for mcpu choices only143static void cpuHelp(ArrayRef<StringRef> CPUNames) {144  // the static variable ensures that the help information only gets145  // printed once even though a target machine creates multiple subtargets146  static bool PrintOnce = false;147  if (PrintOnce) {148    return;149  }150 151  // Print the CPU table.152  errs() << "Available CPUs for this target:\n\n";153  for (auto &CPU : CPUNames) {154    // Skip apple-latest, as that's only meant to be used in155    // disassemblers/debuggers, and we don't want normal code to be built with156    // it as an -mcpu=157    if (CPU == "apple-latest")158      continue;159    errs() << "\t" << CPU << "\n";160  }161  errs() << '\n';162 163  errs() << "Use -mcpu or -mtune to specify the target's processor.\n"164            "For example, clang --target=aarch64-unknown-linux-gnu "165            "-mcpu=cortex-a35\n";166 167  PrintOnce = true;168}169 170static FeatureBitset getFeatures(MCSubtargetInfo &STI, StringRef CPU,171                                 StringRef TuneCPU, StringRef FS,172                                 ArrayRef<StringRef> ProcNames,173                                 ArrayRef<SubtargetSubTypeKV> ProcDesc,174                                 ArrayRef<SubtargetFeatureKV> ProcFeatures) {175  SubtargetFeatures Features(FS);176 177  if (ProcDesc.empty() || ProcFeatures.empty())178    return FeatureBitset();179 180  assert(llvm::is_sorted(ProcDesc) && "CPU table is not sorted");181  assert(llvm::is_sorted(ProcFeatures) && "CPU features table is not sorted");182  // Resulting bits183  FeatureBitset Bits;184 185  // Check if help is needed186  if (CPU == "help")187    Help(ProcNames, ProcFeatures);188 189  // Find CPU entry if CPU name is specified.190  else if (!CPU.empty()) {191    const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);192 193    // If there is a match194    if (CPUEntry) {195      // Set the features implied by this CPU feature, if any.196      SetImpliedBits(Bits, CPUEntry->Implies.getAsBitset(), ProcFeatures);197    } else {198      errs() << "'" << CPU << "' is not a recognized processor for this target"199             << " (ignoring processor)\n";200    }201  }202 203  if (!TuneCPU.empty()) {204    const SubtargetSubTypeKV *CPUEntry = Find(TuneCPU, ProcDesc);205 206    // If there is a match207    if (CPUEntry) {208      // Set the features implied by this CPU feature, if any.209      SetImpliedBits(Bits, CPUEntry->TuneImplies.getAsBitset(), ProcFeatures);210    } else if (TuneCPU != CPU) {211      errs() << "'" << TuneCPU << "' is not a recognized processor for this "212             << "target (ignoring processor)\n";213    }214  }215 216  // Iterate through each feature217  for (const std::string &Feature : Features.getFeatures()) {218    // Check for help219    if (Feature == "+help")220      Help(ProcNames, ProcFeatures);221    else if (Feature == "+cpuhelp")222      cpuHelp(ProcNames);223    else224      ApplyFeatureFlag(Bits, Feature, ProcFeatures);225  }226 227  return Bits;228}229 230void MCSubtargetInfo::InitMCProcessorInfo(StringRef CPU, StringRef TuneCPU,231                                          StringRef FS) {232  FeatureBits =233      getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);234  FeatureString = std::string(FS);235 236  if (!TuneCPU.empty())237    CPUSchedModel = &getSchedModelForCPU(TuneCPU);238  else239    CPUSchedModel = &MCSchedModel::Default;240}241 242void MCSubtargetInfo::setDefaultFeatures(StringRef CPU, StringRef TuneCPU,243                                         StringRef FS) {244  FeatureBits =245      getFeatures(*this, CPU, TuneCPU, FS, ProcNames, ProcDesc, ProcFeatures);246  FeatureString = std::string(FS);247}248 249MCSubtargetInfo::MCSubtargetInfo(250    const Triple &TT, StringRef C, StringRef TC, StringRef FS,251    ArrayRef<StringRef> PN, ArrayRef<SubtargetFeatureKV> PF,252    ArrayRef<SubtargetSubTypeKV> PD, const MCWriteProcResEntry *WPR,253    const MCWriteLatencyEntry *WL, const MCReadAdvanceEntry *RA,254    const InstrStage *IS, const unsigned *OC, const unsigned *FP)255    : TargetTriple(TT), CPU(std::string(C)), TuneCPU(std::string(TC)),256      ProcNames(PN), ProcFeatures(PF), ProcDesc(PD), WriteProcResTable(WPR),257      WriteLatencyTable(WL), ReadAdvanceTable(RA), Stages(IS),258      OperandCycles(OC), ForwardingPaths(FP) {259  InitMCProcessorInfo(CPU, TuneCPU, FS);260}261 262FeatureBitset MCSubtargetInfo::ToggleFeature(uint64_t FB) {263  FeatureBits.flip(FB);264  return FeatureBits;265}266 267FeatureBitset MCSubtargetInfo::ToggleFeature(const FeatureBitset &FB) {268  FeatureBits ^= FB;269  return FeatureBits;270}271 272FeatureBitset MCSubtargetInfo::SetFeatureBitsTransitively(273  const FeatureBitset &FB) {274  SetImpliedBits(FeatureBits, FB, ProcFeatures);275  return FeatureBits;276}277 278FeatureBitset MCSubtargetInfo::ClearFeatureBitsTransitively(279  const FeatureBitset &FB) {280  for (unsigned I = 0, E = FB.size(); I < E; I++) {281    if (FB[I]) {282      FeatureBits.reset(I);283      ClearImpliedBits(FeatureBits, I, ProcFeatures);284    }285  }286  return FeatureBits;287}288 289FeatureBitset MCSubtargetInfo::ToggleFeature(StringRef Feature) {290  // Find feature in table.291  const SubtargetFeatureKV *FeatureEntry =292      Find(SubtargetFeatures::StripFlag(Feature), ProcFeatures);293  // If there is a match294  if (FeatureEntry) {295    if (FeatureBits.test(FeatureEntry->Value)) {296      FeatureBits.reset(FeatureEntry->Value);297      // For each feature that implies this, clear it.298      ClearImpliedBits(FeatureBits, FeatureEntry->Value, ProcFeatures);299    } else {300      FeatureBits.set(FeatureEntry->Value);301 302      // For each feature that this implies, set it.303      SetImpliedBits(FeatureBits, FeatureEntry->Implies.getAsBitset(),304                     ProcFeatures);305    }306  } else {307    errs() << "'" << Feature << "' is not a recognized feature for this target"308           << " (ignoring feature)\n";309  }310 311  return FeatureBits;312}313 314FeatureBitset MCSubtargetInfo::ApplyFeatureFlag(StringRef FS) {315  ::ApplyFeatureFlag(FeatureBits, FS, ProcFeatures);316  return FeatureBits;317}318 319bool MCSubtargetInfo::checkFeatures(StringRef FS) const {320  SubtargetFeatures T(FS);321  return all_of(T.getFeatures(), [this](const std::string &F) {322    assert(SubtargetFeatures::hasFlag(F) &&323           "Feature flags should start with '+' or '-'");324    const SubtargetFeatureKV *FeatureEntry =325        Find(SubtargetFeatures::StripFlag(F), ProcFeatures);326    if (!FeatureEntry)327      report_fatal_error(Twine("'") + F +328                         "' is not a recognized feature for this target");329 330    return FeatureBits.test(FeatureEntry->Value) ==331           SubtargetFeatures::isEnabled(F);332  });333}334 335const MCSchedModel &MCSubtargetInfo::getSchedModelForCPU(StringRef CPU) const {336  assert(llvm::is_sorted(ProcDesc) &&337         "Processor machine model table is not sorted");338 339  // Find entry340  const SubtargetSubTypeKV *CPUEntry = Find(CPU, ProcDesc);341 342  if (!CPUEntry) {343    if (CPU != "help") // Don't error if the user asked for help.344      errs() << "'" << CPU345             << "' is not a recognized processor for this target"346             << " (ignoring processor)\n";347    return MCSchedModel::Default;348  }349  assert(CPUEntry->SchedModel && "Missing processor SchedModel value");350  return *CPUEntry->SchedModel;351}352 353InstrItineraryData354MCSubtargetInfo::getInstrItineraryForCPU(StringRef CPU) const {355  const MCSchedModel &SchedModel = getSchedModelForCPU(CPU);356  return InstrItineraryData(SchedModel, Stages, OperandCycles, ForwardingPaths);357}358 359void MCSubtargetInfo::initInstrItins(InstrItineraryData &InstrItins) const {360  InstrItins = InstrItineraryData(getSchedModel(), Stages, OperandCycles,361                                  ForwardingPaths);362}363 364std::vector<SubtargetFeatureKV>365MCSubtargetInfo::getEnabledProcessorFeatures() const {366  std::vector<SubtargetFeatureKV> EnabledFeatures;367  auto IsEnabled = [&](const SubtargetFeatureKV &FeatureKV) {368    return FeatureBits.test(FeatureKV.Value);369  };370  llvm::copy_if(ProcFeatures, std::back_inserter(EnabledFeatures), IsEnabled);371  return EnabledFeatures;372}373 374std::optional<unsigned> MCSubtargetInfo::getCacheSize(unsigned Level) const {375  return std::nullopt;376}377 378std::optional<unsigned>379MCSubtargetInfo::getCacheAssociativity(unsigned Level) const {380  return std::nullopt;381}382 383std::optional<unsigned>384MCSubtargetInfo::getCacheLineSize(unsigned Level) const {385  return std::nullopt;386}387 388unsigned MCSubtargetInfo::getPrefetchDistance() const {389  return 0;390}391 392unsigned MCSubtargetInfo::getMaxPrefetchIterationsAhead() const {393  return UINT_MAX;394}395 396bool MCSubtargetInfo::enableWritePrefetching() const {397  return false;398}399 400unsigned MCSubtargetInfo::getMinPrefetchStride(unsigned NumMemAccesses,401                                               unsigned NumStridedMemAccesses,402                                               unsigned NumPrefetches,403                                               bool HasCall) const {404  return 1;405}406 407bool MCSubtargetInfo::shouldPrefetchAddressSpace(unsigned AS) const {408  return !AS;409}410