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/Target/TargetRecip.h" 18#include "llvm/ADT/STLExtras.h" 19#include "llvm/ADT/StringRef.h" 20#include "llvm/Support/ErrorHandling.h" 21 22using namespace llvm; 23 24// These are the names of the individual reciprocal operations. These are 25// the key strings for queries and command-line inputs. 26// In addition, the command-line interface recognizes the global parameters 27// "all", "none", and "default". 28static const char *const RecipOps[] = { 29 "divd", 30 "divf", 31 "vec-divd", 32 "vec-divf", 33 "sqrtd", 34 "sqrtf", 35 "vec-sqrtd", 36 "vec-sqrtf", 37}; 38 39// The uninitialized state is needed for the enabled settings and refinement 40// steps because custom settings may arrive via the command-line before target 41// defaults are set. 42TargetRecip::TargetRecip() { 43 unsigned NumStrings = llvm::array_lengthof(RecipOps); 44 for (unsigned i = 0; i < NumStrings; ++i) 45 RecipMap.insert(std::make_pair(RecipOps[i], RecipParams())); 46} 47 48static bool parseRefinementStep(StringRef In, size_t &Position, 49 uint8_t &Value) { 50 const char RefStepToken = ':'; 51 Position = In.find(RefStepToken); 52 if (Position == StringRef::npos) 53 return false; 54 55 StringRef RefStepString = In.substr(Position + 1); 56 // Allow exactly one numeric character for the additional refinement 57 // step parameter. 58 if (RefStepString.size() == 1) { 59 char RefStepChar = RefStepString[0]; 60 if (RefStepChar >= '0' && RefStepChar <= '9') { 61 Value = RefStepChar - '0'; 62 return true; 63 } 64 } 65 report_fatal_error("Invalid refinement step for -recip."); 66} 67 68bool TargetRecip::parseGlobalParams(const std::string &Arg) { 69 StringRef ArgSub = Arg; 70 71 // Look for an optional setting of the number of refinement steps needed 72 // for this type of reciprocal operation. 73 size_t RefPos; 74 uint8_t RefSteps; 75 StringRef RefStepString; 76 if (parseRefinementStep(ArgSub, RefPos, RefSteps)) { 77 // Split the string for further processing. 78 RefStepString = ArgSub.substr(RefPos + 1); 79 ArgSub = ArgSub.substr(0, RefPos); 80 } 81 bool Enable; 82 bool UseDefaults; 83 if (ArgSub == "all") { 84 UseDefaults = false; 85 Enable = true; 86 } else if (ArgSub == "none") { 87 UseDefaults = false; 88 Enable = false; 89 } else if (ArgSub == "default") { 90 UseDefaults = true; 91 } else { 92 // Any other string is invalid or an individual setting. 93 return false; 94 } 95 96 // All enable values will be initialized to target defaults if 'default' was 97 // specified. 98 if (!UseDefaults) 99 for (auto &KV : RecipMap) 100 KV.second.Enabled = Enable; 101 102 // Custom refinement count was specified with all, none, or default. 103 if (!RefStepString.empty()) 104 for (auto &KV : RecipMap) 105 KV.second.RefinementSteps = RefSteps; 106 107 return true; 108} 109 110void TargetRecip::parseIndividualParams(const std::vector<std::string> &Args) { 111 static const char DisabledPrefix = '!'; 112 unsigned NumArgs = Args.size(); 113 114 for (unsigned i = 0; i != NumArgs; ++i) { 115 StringRef Val = Args[i]; 116 117 bool IsDisabled = Val[0] == DisabledPrefix; 118 // Ignore the disablement token for string matching. 119 if (IsDisabled) 120 Val = Val.substr(1); 121 122 size_t RefPos; 123 uint8_t RefSteps; 124 StringRef RefStepString; 125 if (parseRefinementStep(Val, RefPos, RefSteps)) { 126 // Split the string for further processing. 127 RefStepString = Val.substr(RefPos + 1); 128 Val = Val.substr(0, RefPos); 129 } 130 131 RecipIter Iter = RecipMap.find(Val); 132 if (Iter == RecipMap.end()) { 133 // Try again specifying float suffix. 134 Iter = RecipMap.find(Val.str() + 'f'); 135 if (Iter == RecipMap.end()) { 136 Iter = RecipMap.find(Val.str() + 'd'); 137 assert(Iter == RecipMap.end() && "Float entry missing from map"); 138 report_fatal_error("Invalid option for -recip."); 139 } 140 141 // The option was specified without a float or double suffix. 142 if (RecipMap[Val.str() + 'd'].Enabled != Uninitialized) { 143 // Make sure that the double entry was not already specified. 144 // The float entry will be checked below. 145 report_fatal_error("Duplicate option for -recip."); 146 } 147 } 148 149 if (Iter->second.Enabled != Uninitialized) 150 report_fatal_error("Duplicate option for -recip."); 151 152 // Mark the matched option as found. Do not allow duplicate specifiers. 153 Iter->second.Enabled = !IsDisabled; 154 if (!RefStepString.empty()) 155 Iter->second.RefinementSteps = RefSteps; 156 157 // If the precision was not specified, the double entry is also initialized. 158 if (Val.back() != 'f' && Val.back() != 'd') { 159 RecipParams &Params = RecipMap[Val.str() + 'd']; 160 Params.Enabled = !IsDisabled; 161 if (!RefStepString.empty()) 162 Params.RefinementSteps = RefSteps; 163 } 164 } 165} 166 167TargetRecip::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 178bool 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 186unsigned 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. 195void 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 214bool 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