Home | History | Annotate | Download | only in Target
      1 //===-------------------------- TargetRecip.cpp ---------------------------===//
      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 // This class is used to customize machine-specific reciprocal estimate code
     11 // generation in a target-independent way.
     12 // If a target does not support operations in this specification, then code
     13 // generation will default to using supported operations.
     14 //
     15 //===----------------------------------------------------------------------===//
     16 
     17 #include "llvm/ADT/StringRef.h"
     18 #include "llvm/ADT/STLExtras.h"
     19 #include "llvm/Support/ErrorHandling.h"
     20 #include "llvm/Target/TargetRecip.h"
     21 #include <map>
     22 
     23 using namespace llvm;
     24 
     25 // These are the names of the individual reciprocal operations. These are
     26 // the key strings for queries and command-line inputs.
     27 // In addition, the command-line interface recognizes the global parameters
     28 // "all", "none", and "default".
     29 static const char *const RecipOps[] = {
     30   "divd",
     31   "divf",
     32   "vec-divd",
     33   "vec-divf",
     34   "sqrtd",
     35   "sqrtf",
     36   "vec-sqrtd",
     37   "vec-sqrtf",
     38 };
     39 
     40 // The uninitialized state is needed for the enabled settings and refinement
     41 // steps because custom settings may arrive via the command-line before target
     42 // defaults are set.
     43 TargetRecip::TargetRecip() {
     44   unsigned NumStrings = llvm::array_lengthof(RecipOps);
     45   for (unsigned i = 0; i < NumStrings; ++i)
     46     RecipMap.insert(std::make_pair(RecipOps[i], RecipParams()));
     47 }
     48 
     49 static bool parseRefinementStep(StringRef In, size_t &Position,
     50                                 uint8_t &Value) {
     51   const char RefStepToken = ':';
     52   Position = In.find(RefStepToken);
     53   if (Position == StringRef::npos)
     54     return false;
     55 
     56   StringRef RefStepString = In.substr(Position + 1);
     57   // Allow exactly one numeric character for the additional refinement
     58   // step parameter.
     59   if (RefStepString.size() == 1) {
     60     char RefStepChar = RefStepString[0];
     61     if (RefStepChar >= '0' && RefStepChar <= '9') {
     62       Value = RefStepChar - '0';
     63       return true;
     64     }
     65   }
     66   report_fatal_error("Invalid refinement step for -recip.");
     67 }
     68 
     69 bool TargetRecip::parseGlobalParams(const std::string &Arg) {
     70   StringRef ArgSub = Arg;
     71 
     72   // Look for an optional setting of the number of refinement steps needed
     73   // for this type of reciprocal operation.
     74   size_t RefPos;
     75   uint8_t RefSteps;
     76   StringRef RefStepString;
     77   if (parseRefinementStep(ArgSub, RefPos, RefSteps)) {
     78     // Split the string for further processing.
     79     RefStepString = ArgSub.substr(RefPos + 1);
     80     ArgSub = ArgSub.substr(0, RefPos);
     81   }
     82   bool Enable;
     83   bool UseDefaults;
     84   if (ArgSub == "all") {
     85     UseDefaults = false;
     86     Enable = true;
     87   } else if (ArgSub == "none") {
     88     UseDefaults = false;
     89     Enable = false;
     90   } else if (ArgSub == "default") {
     91     UseDefaults = true;
     92   } else {
     93     // Any other string is invalid or an individual setting.
     94     return false;
     95   }
     96 
     97   // All enable values will be initialized to target defaults if 'default' was
     98   // specified.
     99   if (!UseDefaults)
    100     for (auto &KV : RecipMap)
    101       KV.second.Enabled = Enable;
    102 
    103   // Custom refinement count was specified with all, none, or default.
    104   if (!RefStepString.empty())
    105     for (auto &KV : RecipMap)
    106       KV.second.RefinementSteps = RefSteps;
    107 
    108   return true;
    109 }
    110 
    111 void TargetRecip::parseIndividualParams(const std::vector<std::string> &Args) {
    112   static const char DisabledPrefix = '!';
    113   unsigned NumArgs = Args.size();
    114 
    115   for (unsigned i = 0; i != NumArgs; ++i) {
    116     StringRef Val = Args[i];
    117 
    118     bool IsDisabled = Val[0] == DisabledPrefix;
    119     // Ignore the disablement token for string matching.
    120     if (IsDisabled)
    121       Val = Val.substr(1);
    122 
    123     size_t RefPos;
    124     uint8_t RefSteps;
    125     StringRef RefStepString;
    126     if (parseRefinementStep(Val, RefPos, RefSteps)) {
    127       // Split the string for further processing.
    128       RefStepString = Val.substr(RefPos + 1);
    129       Val = Val.substr(0, RefPos);
    130     }
    131 
    132     RecipIter Iter = RecipMap.find(Val);
    133     if (Iter == RecipMap.end()) {
    134       // Try again specifying float suffix.
    135       Iter = RecipMap.find(Val.str() + 'f');
    136       if (Iter == RecipMap.end()) {
    137         Iter = RecipMap.find(Val.str() + 'd');
    138         assert(Iter == RecipMap.end() && "Float entry missing from map");
    139         report_fatal_error("Invalid option for -recip.");
    140       }
    141 
    142       // The option was specified without a float or double suffix.
    143       if (RecipMap[Val.str() + 'd'].Enabled != Uninitialized) {
    144         // Make sure that the double entry was not already specified.
    145         // The float entry will be checked below.
    146         report_fatal_error("Duplicate option for -recip.");
    147       }
    148     }
    149 
    150     if (Iter->second.Enabled != Uninitialized)
    151       report_fatal_error("Duplicate option for -recip.");
    152 
    153     // Mark the matched option as found. Do not allow duplicate specifiers.
    154     Iter->second.Enabled = !IsDisabled;
    155     if (!RefStepString.empty())
    156       Iter->second.RefinementSteps = RefSteps;
    157 
    158     // If the precision was not specified, the double entry is also initialized.
    159     if (Val.back() != 'f' && Val.back() != 'd') {
    160       RecipMap[Val.str() + 'd'].Enabled = !IsDisabled;
    161       if (!RefStepString.empty())
    162         RecipMap[Val.str() + 'd'].RefinementSteps = RefSteps;
    163     }
    164   }
    165 }
    166 
    167 TargetRecip::TargetRecip(const std::vector<std::string> &Args) :
    168   TargetRecip() {
    169   unsigned NumArgs = Args.size();
    170 
    171   // Check if "all", "default", or "none" was specified.
    172   if (NumArgs == 1 && parseGlobalParams(Args[0]))
    173     return;
    174 
    175   parseIndividualParams(Args);
    176 }
    177 
    178 bool TargetRecip::isEnabled(StringRef Key) const {
    179   ConstRecipIter Iter = RecipMap.find(Key);
    180   assert(Iter != RecipMap.end() && "Unknown name for reciprocal map");
    181   assert(Iter->second.Enabled != Uninitialized &&
    182          "Enablement setting was not initialized");
    183   return Iter->second.Enabled;
    184 }
    185 
    186 unsigned TargetRecip::getRefinementSteps(StringRef Key) const {
    187   ConstRecipIter Iter = RecipMap.find(Key);
    188   assert(Iter != RecipMap.end() && "Unknown name for reciprocal map");
    189   assert(Iter->second.RefinementSteps != Uninitialized &&
    190          "Refinement step setting was not initialized");
    191   return Iter->second.RefinementSteps;
    192 }
    193 
    194 /// Custom settings (previously initialized values) override target defaults.
    195 void TargetRecip::setDefaults(StringRef Key, bool Enable,
    196                               unsigned RefSteps) {
    197   if (Key == "all") {
    198     for (auto &KV : RecipMap) {
    199       RecipParams &RP = KV.second;
    200       if (RP.Enabled == Uninitialized)
    201         RP.Enabled = Enable;
    202       if (RP.RefinementSteps == Uninitialized)
    203         RP.RefinementSteps = RefSteps;
    204     }
    205   } else {
    206     RecipParams &RP = RecipMap[Key];
    207     if (RP.Enabled == Uninitialized)
    208       RP.Enabled = Enable;
    209     if (RP.RefinementSteps == Uninitialized)
    210       RP.RefinementSteps = RefSteps;
    211   }
    212 }
    213 
    214 bool TargetRecip::operator==(const TargetRecip &Other) const {
    215   for (const auto &KV : RecipMap) {
    216     StringRef Op = KV.first;
    217     const RecipParams &RP = KV.second;
    218     const RecipParams &OtherRP = Other.RecipMap.find(Op)->second;
    219     if (RP.RefinementSteps != OtherRP.RefinementSteps)
    220       return false;
    221     if (RP.Enabled != OtherRP.Enabled)
    222       return false;
    223   }
    224   return true;
    225 }
    226