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 23using 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". 29static 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. 43TargetRecip::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 49static 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 69bool 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 111void 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 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