[clang] [flang] [mlir] [flang] Add support for -mrecip[=<list>] (PR #142172)

Eugene Epshteyn via cfe-commits cfe-commits at lists.llvm.org
Fri May 30 09:29:52 PDT 2025


================
@@ -1251,6 +1251,164 @@ static bool parseIntegerOverflowArgs(CompilerInvocation &invoc,
   return true;
 }
 
+/// This is a helper function for validating the optional refinement step
+/// parameter in reciprocal argument strings. Return false if there is an error
+/// parsing the refinement step. Otherwise, return true and set the Position
+/// of the refinement step in the input string.
+///
+/// \param [in] in The input string
+/// \param [in] a The compiler invocation arguments to parse
+/// \param [out] position The position of the refinement step in input string
+/// \param [out] diags DiagnosticsEngine to report erros with
+static bool getRefinementStep(llvm::StringRef in, const llvm::opt::Arg &a,
+                              size_t &position,
+                              clang::DiagnosticsEngine &diags) {
+  const char refinementStepToken = ':';
+  position = in.find(refinementStepToken);
+  if (position != llvm::StringRef::npos) {
+    llvm::StringRef option = a.getOption().getName();
+    llvm::StringRef refStep = in.substr(position + 1);
+    // Allow exactly one numeric character for the additional refinement
+    // step parameter. This is reasonable for all currently-supported
+    // operations and architectures because we would expect that a larger value
+    // of refinement steps would cause the estimate "optimization" to
+    // under-perform the native operation. Also, if the estimate does not
+    // converge quickly, it probably will not ever converge, so further
+    // refinement steps will not produce a better answer.
+    if (refStep.size() != 1) {
+      diags.Report(clang::diag::err_drv_invalid_value) << option << refStep;
+      return false;
+    }
+    char refStepChar = refStep[0];
+    if (refStepChar < '0' || refStepChar > '9') {
+      diags.Report(clang::diag::err_drv_invalid_value) << option << refStep;
+      return false;
+    }
+  }
+  return true;
+}
+
+/// Parses all -mrecip=<list> arguments and populates the
+/// CompilerInvocation accordingly. Returns false if new errors are generated.
+///
+/// \param [out] invoc Stores the processed arguments
+/// \param [in] args The compiler invocation arguments to parse
+/// \param [out] diags DiagnosticsEngine to report erros with
+static bool parseMRecip(CompilerInvocation &invoc, llvm::opt::ArgList &args,
+                        clang::DiagnosticsEngine &diags) {
+  llvm::StringRef disabledPrefixIn = "!";
+  llvm::StringRef disabledPrefixOut = "!";
+  llvm::StringRef enabledPrefixOut = "";
+  llvm::StringRef out = "";
+  Fortran::frontend::CodeGenOptions &opts = invoc.getCodeGenOpts();
+
+  const llvm::opt::Arg *a =
+      args.getLastArg(clang::driver::options::OPT_mrecip,
+                      clang::driver::options::OPT_mrecip_EQ);
+  if (!a)
+    return true;
+
+  unsigned numOptions = a->getNumValues();
+  if (numOptions == 0) {
+    // No option is the same as "all".
+    opts.Reciprocals = "all";
+    return true;
+  }
+
+  // Pass through "all", "none", or "default" with an optional refinement step.
+  if (numOptions == 1) {
+    llvm::StringRef val = a->getValue(0);
+    size_t refStepLoc;
+    if (!getRefinementStep(val, *a, refStepLoc, diags))
+      return false;
+    llvm::StringRef valBase = val.slice(0, refStepLoc);
+    if (valBase == "all" || valBase == "none" || valBase == "default") {
+      opts.Reciprocals = args.MakeArgString(val);
+      return true;
+    }
+  }
+
+  // Each reciprocal type may be enabled or disabled individually.
+  // Check each input value for validity, concatenate them all back together,
+  // and pass through.
+
+  llvm::StringMap<bool> optionStrings;
+  optionStrings.insert(std::make_pair("divd", false));
+  optionStrings.insert(std::make_pair("divf", false));
+  optionStrings.insert(std::make_pair("divh", false));
+  optionStrings.insert(std::make_pair("vec-divd", false));
+  optionStrings.insert(std::make_pair("vec-divf", false));
+  optionStrings.insert(std::make_pair("vec-divh", false));
+  optionStrings.insert(std::make_pair("sqrtd", false));
+  optionStrings.insert(std::make_pair("sqrtf", false));
+  optionStrings.insert(std::make_pair("sqrth", false));
+  optionStrings.insert(std::make_pair("vec-sqrtd", false));
+  optionStrings.insert(std::make_pair("vec-sqrtf", false));
+  optionStrings.insert(std::make_pair("vec-sqrth", false));
----------------
eugeneepshteyn wrote:

FYI, it may be cleaner to do something like this: `optionStrings["divd"] = false;`, etc.

https://github.com/llvm/llvm-project/pull/142172


More information about the cfe-commits mailing list