https://github.com/mcinally updated 
https://github.com/llvm/llvm-project/pull/143418

>From f4812aacb17aaf535f454c82e4ef29c5c9950a12 Mon Sep 17 00:00:00 2001
From: Cameron McInally <cmcina...@nvidia.com>
Date: Mon, 9 Jun 2025 11:19:36 -0700
Subject: [PATCH 1/2] [flang] Add support for -mrecip[=<list>]

This patch adds support for the -mrecip command line option. The parsing of
this options is equivalent to Clang's and it is implemented by setting the
"reciprocal-estimates" function attribute.

Also move the ParseMRecip(...) function to CommonArgs, so that Flang is able to
make use of it as well.
---
 clang/include/clang/Driver/CommonArgs.h       |   5 +
 clang/include/clang/Driver/Options.td         |   3 +-
 clang/lib/Driver/ToolChains/Clang.cpp         | 143 +-----------------
 clang/lib/Driver/ToolChains/CommonArgs.cpp    | 141 +++++++++++++++++
 flang/include/flang/Frontend/CodeGenOptions.h |   3 +
 .../flang/Optimizer/Transforms/Passes.td      |   3 +
 flang/include/flang/Tools/CrossToolHelpers.h  |   3 +
 flang/lib/Frontend/CompilerInvocation.cpp     |   2 +
 flang/lib/Frontend/FrontendActions.cpp        |   1 +
 flang/lib/Optimizer/Passes/Pipelines.cpp      |   3 +-
 .../lib/Optimizer/Transforms/FunctionAttr.cpp |   4 +
 flang/test/Driver/mrecip.f90                  |  27 ++++
 mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td   |   1 +
 mlir/lib/Target/LLVMIR/ModuleImport.cpp       |   5 +
 mlir/lib/Target/LLVMIR/ModuleTranslation.cpp  |   3 +
 mlir/test/Target/LLVMIR/Import/mrecip.ll      |   9 ++
 mlir/test/Target/LLVMIR/mrecip.mlir           |   8 +
 17 files changed, 222 insertions(+), 142 deletions(-)
 create mode 100644 flang/test/Driver/mrecip.f90
 create mode 100644 mlir/test/Target/LLVMIR/Import/mrecip.ll
 create mode 100644 mlir/test/Target/LLVMIR/mrecip.mlir

diff --git a/clang/include/clang/Driver/CommonArgs.h 
b/clang/include/clang/Driver/CommonArgs.h
index 59b68030a4d65..9d0da81b47bba 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -276,6 +276,11 @@ void handleVectorizeSLPArgs(const llvm::opt::ArgList &Args,
 StringRef ParseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
                                         const llvm::opt::ArgList &Args);
 
+// Parse -mrecip. Return the Value string if well-formed.
+// Otherwise, return an empty string and issue a diagnosic message if needed.
+StringRef ParseMRecipOption(clang::DiagnosticsEngine &Diags,
+                            const llvm::opt::ArgList &Args);
+
 } // end namespace tools
 } // end namespace driver
 } // end namespace clang
diff --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 89c63fb3397d3..3582efd7721b0 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -5474,9 +5474,10 @@ def mno_implicit_float : Flag<["-"], 
"mno-implicit-float">, Group<m_Group>,
   HelpText<"Don't generate implicit floating point or vector instructions">;
 def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>;
 def mrecip : Flag<["-"], "mrecip">, Group<m_Group>,
+  Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
   HelpText<"Equivalent to '-mrecip=all'">;
 def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>,
-  Visibility<[ClangOption, CC1Option]>,
+  Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
   HelpText<"Control use of approximate reciprocal and reciprocal square root 
instructions followed by <n> iterations of "
            "Newton-Raphson refinement. "
            "<value> = ( ['!'] ['vec-'] ('rcp'|'sqrt') [('h'|'s'|'d')] [':'<n>] 
) | 'all' | 'default' | 'none'">,
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index 65f101ddf1d0a..df3edcc3cd6bd 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -125,145 +125,6 @@ forAllAssociatedToolChains(Compilation &C, const 
JobAction &JA,
   //
 }
 
-/// 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.
-static bool getRefinementStep(StringRef In, const Driver &D,
-                              const Arg &A, size_t &Position) {
-  const char RefinementStepToken = ':';
-  Position = In.find(RefinementStepToken);
-  if (Position != StringRef::npos) {
-    StringRef Option = A.getOption().getName();
-    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) {
-      D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
-      return false;
-    }
-    char RefStepChar = RefStep[0];
-    if (RefStepChar < '0' || RefStepChar > '9') {
-      D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
-      return false;
-    }
-  }
-  return true;
-}
-
-/// The -mrecip flag requires processing of many optional parameters.
-static void ParseMRecip(const Driver &D, const ArgList &Args,
-                        ArgStringList &OutStrings) {
-  StringRef DisabledPrefixIn = "!";
-  StringRef DisabledPrefixOut = "!";
-  StringRef EnabledPrefixOut = "";
-  StringRef Out = "-mrecip=";
-
-  Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
-  if (!A)
-    return;
-
-  unsigned NumOptions = A->getNumValues();
-  if (NumOptions == 0) {
-    // No option is the same as "all".
-    OutStrings.push_back(Args.MakeArgString(Out + "all"));
-    return;
-  }
-
-  // Pass through "all", "none", or "default" with an optional refinement step.
-  if (NumOptions == 1) {
-    StringRef Val = A->getValue(0);
-    size_t RefStepLoc;
-    if (!getRefinementStep(Val, D, *A, RefStepLoc))
-      return;
-    StringRef ValBase = Val.slice(0, RefStepLoc);
-    if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
-      OutStrings.push_back(Args.MakeArgString(Out + Val));
-      return;
-    }
-  }
-
-  // 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));
-
-  for (unsigned i = 0; i != NumOptions; ++i) {
-    StringRef Val = A->getValue(i);
-
-    bool IsDisabled = Val.starts_with(DisabledPrefixIn);
-    // Ignore the disablement token for string matching.
-    if (IsDisabled)
-      Val = Val.substr(1);
-
-    size_t RefStep;
-    if (!getRefinementStep(Val, D, *A, RefStep))
-      return;
-
-    StringRef ValBase = Val.slice(0, RefStep);
-    llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase);
-    if (OptionIter == OptionStrings.end()) {
-      // Try again specifying float suffix.
-      OptionIter = OptionStrings.find(ValBase.str() + 'f');
-      if (OptionIter == OptionStrings.end()) {
-        // The input name did not match any known option string.
-        D.Diag(diag::err_drv_unknown_argument) << Val;
-        return;
-      }
-      // The option was specified without a half or float or double suffix.
-      // Make sure that the double or half entry was not already specified.
-      // The float entry will be checked below.
-      if (OptionStrings[ValBase.str() + 'd'] ||
-          OptionStrings[ValBase.str() + 'h']) {
-        D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
-        return;
-      }
-    }
-
-    if (OptionIter->second == true) {
-      // Duplicate option specified.
-      D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
-      return;
-    }
-
-    // Mark the matched option as found. Do not allow duplicate specifiers.
-    OptionIter->second = true;
-
-    // If the precision was not specified, also mark the double and half entry
-    // as found.
-    if (ValBase.back() != 'f' && ValBase.back() != 'd' && ValBase.back() != 
'h') {
-      OptionStrings[ValBase.str() + 'd'] = true;
-      OptionStrings[ValBase.str() + 'h'] = true;
-    }
-
-    // Build the output string.
-    StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
-    Out = Args.MakeArgString(Out + Prefix + Val);
-    if (i != NumOptions - 1)
-      Out = Args.MakeArgString(Out + ",");
-  }
-
-  OutStrings.push_back(Args.MakeArgString(Out));
-}
-
 static bool
 shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
                                           const llvm::Triple &Triple) {
@@ -3490,7 +3351,9 @@ static void RenderFloatingPointOptions(const ToolChain 
&TC, const Driver &D,
     CmdArgs.push_back(Args.MakeArgString("-fbfloat16-excess-precision=" +
                                          BFloat16ExcessPrecision));
 
-  ParseMRecip(D, Args, CmdArgs);
+  StringRef Recip = ParseMRecipOption(D.getDiags(), Args);
+  if (!Recip.empty())
+    CmdArgs.push_back(Args.MakeArgString("-mrecip=" + Recip));
 
   // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for 
the
   // individual features enabled by -ffast-math instead of the option itself as
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 02b6e23835486..238c72dbda8a6 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -3189,3 +3189,144 @@ StringRef 
tools::ParseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
 
   return Value;
 }
+
+// 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.
+static bool getRefinementStep(StringRef In, clang::DiagnosticsEngine &Diags,
+                              const Arg &A, size_t &Position) {
+  const char RefinementStepToken = ':';
+  Position = In.find(RefinementStepToken);
+  if (Position != StringRef::npos) {
+    StringRef Option = A.getOption().getName();
+    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(diag::err_drv_invalid_value) << Option << RefStep;
+      return false;
+    }
+    char RefStepChar = RefStep[0];
+    if (RefStepChar < '0' || RefStepChar > '9') {
+      Diags.Report(diag::err_drv_invalid_value) << Option << RefStep;
+      return false;
+    }
+  }
+  return true;
+}
+
+// Parse -mrecip. Return the Value string if well-formed.
+// Otherwise, return an empty string and issue a diagnosic message if needed.
+StringRef tools::ParseMRecipOption(clang::DiagnosticsEngine &Diags,
+                                   const ArgList &Args) {
+  StringRef DisabledPrefixIn = "!";
+  StringRef DisabledPrefixOut = "!";
+  StringRef EnabledPrefixOut = "";
+  StringRef Out = "";
+
+  Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
+  if (!A)
+    return "";
+
+  unsigned NumOptions = A->getNumValues();
+  if (NumOptions == 0) {
+    // No option is the same as "all".
+    return "all";
+  }
+
+  // Pass through "all", "none", or "default" with an optional refinement step.
+  if (NumOptions == 1) {
+    StringRef Val = A->getValue(0);
+    size_t RefStepLoc;
+    if (!getRefinementStep(Val, Diags, *A, RefStepLoc))
+      return "";
+    StringRef ValBase = Val.slice(0, RefStepLoc);
+    if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
+      return Val;
+    }
+  }
+
+  // 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));
+
+  for (unsigned i = 0; i != NumOptions; ++i) {
+    StringRef Val = A->getValue(i);
+
+    bool IsDisabled = Val.starts_with(DisabledPrefixIn);
+    // Ignore the disablement token for string matching.
+    if (IsDisabled)
+      Val = Val.substr(1);
+
+    size_t RefStep;
+    if (!getRefinementStep(Val, Diags, *A, RefStep))
+      return "";
+
+    StringRef ValBase = Val.slice(0, RefStep);
+    llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase);
+    if (OptionIter == OptionStrings.end()) {
+      // Try again specifying float suffix.
+      OptionIter = OptionStrings.find(ValBase.str() + 'f');
+      if (OptionIter == OptionStrings.end()) {
+        // The input name did not match any known option string.
+        Diags.Report(diag::err_drv_unknown_argument) << Val;
+        return "";
+      }
+      // The option was specified without a half or float or double suffix.
+      // Make sure that the double or half entry was not already specified.
+      // The float entry will be checked below.
+      if (OptionStrings[ValBase.str() + 'd'] ||
+          OptionStrings[ValBase.str() + 'h']) {
+        Diags.Report(diag::err_drv_invalid_value)
+            << A->getOption().getName() << Val;
+        return "";
+      }
+    }
+
+    if (OptionIter->second == true) {
+      // Duplicate option specified.
+      Diags.Report(diag::err_drv_invalid_value)
+          << A->getOption().getName() << Val;
+      return "";
+    }
+
+    // Mark the matched option as found. Do not allow duplicate specifiers.
+    OptionIter->second = true;
+
+    // If the precision was not specified, also mark the double and half entry
+    // as found.
+    if (ValBase.back() != 'f' && ValBase.back() != 'd' &&
+        ValBase.back() != 'h') {
+      OptionStrings[ValBase.str() + 'd'] = true;
+      OptionStrings[ValBase.str() + 'h'] = true;
+    }
+
+    // Build the output string.
+    StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
+    Out = Args.MakeArgString(Out + Prefix + Val);
+    if (i != NumOptions - 1)
+      Out = Args.MakeArgString(Out + ",");
+  }
+
+  return Out;
+}
diff --git a/flang/include/flang/Frontend/CodeGenOptions.h 
b/flang/include/flang/Frontend/CodeGenOptions.h
index 61e56e51c4bbb..5c1f7ef52ca14 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.h
+++ b/flang/include/flang/Frontend/CodeGenOptions.h
@@ -56,6 +56,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
   // The prefered vector width, if requested by -mprefer-vector-width.
   std::string PreferVectorWidth;
 
+  // List of reciprocal estimate sub-options.
+  std::string Reciprocals;
+
   /// List of filenames passed in using the -fembed-offload-object option. 
These
   /// are offloading binaries containing device images and metadata.
   std::vector<std::string> OffloadObjects;
diff --git a/flang/include/flang/Optimizer/Transforms/Passes.td 
b/flang/include/flang/Optimizer/Transforms/Passes.td
index 1b1970412676d..34842f9785942 100644
--- a/flang/include/flang/Optimizer/Transforms/Passes.td
+++ b/flang/include/flang/Optimizer/Transforms/Passes.td
@@ -429,6 +429,9 @@ def FunctionAttr : Pass<"function-attr", 
"mlir::func::FuncOp"> {
               "module.">,
        Option<"unsafeFPMath", "unsafe-fp-math", "bool", /*default=*/"false",
               "Set the unsafe-fp-math attribute on functions in the module.">,
+       Option<"reciprocals", "mrecip", "std::string", /*default=*/"",
+              "Set the reciprocal-estimates attribute on functions in the "
+              "module.">,
        Option<"preferVectorWidth", "prefer-vector-width", "std::string",
               /*default=*/"",
               "Set the prefer-vector-width attribute on functions in the "
diff --git a/flang/include/flang/Tools/CrossToolHelpers.h 
b/flang/include/flang/Tools/CrossToolHelpers.h
index 058024a4a04c5..337685c82af5f 100644
--- a/flang/include/flang/Tools/CrossToolHelpers.h
+++ b/flang/include/flang/Tools/CrossToolHelpers.h
@@ -102,6 +102,7 @@ struct MLIRToLLVMPassPipelineConfig : public 
FlangEPCallBacks {
     UnsafeFPMath = mathOpts.getAssociativeMath() &&
         mathOpts.getReciprocalMath() && NoSignedZerosFPMath &&
         ApproxFuncFPMath && mathOpts.getFPContractEnabled();
+    Reciprocals = opts.Reciprocals;
     PreferVectorWidth = opts.PreferVectorWidth;
     if (opts.InstrumentFunctions) {
       InstrumentFunctionEntry = "__cyg_profile_func_enter";
@@ -127,6 +128,8 @@ struct MLIRToLLVMPassPipelineConfig : public 
FlangEPCallBacks {
   bool NoSignedZerosFPMath =
       false; ///< Set no-signed-zeros-fp-math attribute for functions.
   bool UnsafeFPMath = false; ///< Set unsafe-fp-math attribute for functions.
+  std::string Reciprocals = ""; ///< Set reciprocal-estimate attribute for
+                                ///< functions.
   std::string PreferVectorWidth = ""; ///< Set prefer-vector-width attribute 
for
                                       ///< functions.
   bool NSWOnLoopVarInc = true; ///< Add nsw flag to loop variable increments.
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index fb9d0ad303985..fcaf959a16a09 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -310,6 +310,8 @@ static void 
parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
   for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ))
     opts.LLVMPassPlugins.push_back(a->getValue());
 
+  opts.Reciprocals = clang::driver::tools::ParseMRecipOption(diags, args);
+
   opts.PreferVectorWidth =
       clang::driver::tools::ParseMPreferVectorWidthOption(diags, args);
 
diff --git a/flang/lib/Frontend/FrontendActions.cpp 
b/flang/lib/Frontend/FrontendActions.cpp
index 012d0fdfe645f..1c8a419188b89 100644
--- a/flang/lib/Frontend/FrontendActions.cpp
+++ b/flang/lib/Frontend/FrontendActions.cpp
@@ -741,6 +741,7 @@ void CodeGenAction::generateLLVMIR() {
     config.VScaleMax = vsr->second;
   }
 
+  config.Reciprocals = opts.Reciprocals;
   config.PreferVectorWidth = opts.PreferVectorWidth;
 
   if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
diff --git a/flang/lib/Optimizer/Passes/Pipelines.cpp 
b/flang/lib/Optimizer/Passes/Pipelines.cpp
index c28c8dd1730b0..70f57bdeddd3f 100644
--- a/flang/lib/Optimizer/Passes/Pipelines.cpp
+++ b/flang/lib/Optimizer/Passes/Pipelines.cpp
@@ -369,7 +369,8 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager 
&pm,
       {framePointerKind, config.InstrumentFunctionEntry,
        config.InstrumentFunctionExit, config.NoInfsFPMath, config.NoNaNsFPMath,
        config.ApproxFuncFPMath, config.NoSignedZerosFPMath, 
config.UnsafeFPMath,
-       config.PreferVectorWidth, /*tuneCPU=*/"", setNoCapture, setNoAlias}));
+       config.Reciprocals, config.PreferVectorWidth, /*tuneCPU=*/"",
+       setNoCapture, setNoAlias}));
 
   if (config.EnableOpenMP) {
     pm.addNestedPass<mlir::func::FuncOp>(
diff --git a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp 
b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
index 041aa8717d20e..5ac4ed8a93b6b 100644
--- a/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
+++ b/flang/lib/Optimizer/Transforms/FunctionAttr.cpp
@@ -107,6 +107,10 @@ void FunctionAttrPass::runOnOperation() {
     func->setAttr(
         mlir::LLVM::LLVMFuncOp::getUnsafeFpMathAttrName(llvmFuncOpName),
         mlir::BoolAttr::get(context, true));
+  if (!reciprocals.empty())
+    func->setAttr(
+        mlir::LLVM::LLVMFuncOp::getReciprocalEstimatesAttrName(llvmFuncOpName),
+        mlir::StringAttr::get(context, reciprocals));
   if (!preferVectorWidth.empty())
     func->setAttr(
         mlir::LLVM::LLVMFuncOp::getPreferVectorWidthAttrName(llvmFuncOpName),
diff --git a/flang/test/Driver/mrecip.f90 b/flang/test/Driver/mrecip.f90
new file mode 100644
index 0000000000000..612be1fac44df
--- /dev/null
+++ b/flang/test/Driver/mrecip.f90
@@ -0,0 +1,27 @@
+! Test that -mrecip[=<list>] works as expected.
+
+! RUN: %flang_fc1 -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-OMIT
+! RUN: %flang_fc1 -mrecip -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-NOARG
+! RUN: %flang_fc1 -mrecip=all -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-ALL
+! RUN: %flang_fc1 -mrecip=none -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-NONE
+! RUN: %flang_fc1 -mrecip=default -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-DEF
+! RUN: %flang_fc1 
-mrecip=divd,divf,divh,vec-divd,vec-divf,vec-divh,sqrtd,sqrtf,sqrth,vec-sqrtd,vec-sqrtf,vec-sqrth
 -emit-llvm -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-POS
+! RUN: %flang_fc1 
-mrecip=!divd,!divf,!divh,!vec-divd,!vec-divf,!vec-divh,!sqrtd,!sqrtf,!sqrth,!vec-sqrtd,!vec-sqrtf,!vec-sqrth
+! -emit-llvm -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-NEG
+! RUN: %flang_fc1 -mrecip=!divd,divf,!divh,sqrtd,!sqrtf,sqrth -emit-llvm -o - 
%s 2>&1| FileCheck %s --check-prefix=CHECK-MIX
+! RUN: not %flang_fc1 -mrecip=xxx  -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-INV
+! RUN: not %flang_fc1 -mrecip=divd,divd  -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-DUP
+
+subroutine func
+end subroutine func
+
+! CHECK-OMIT-NOT: attributes #0 = { "reciprocal-estimates"={{.*}} }
+! CHECK-NOARG: attributes #0 = { "reciprocal-estimates"="all" }
+! CHECK-ALL: attributes #0 = { "reciprocal-estimates"="all" }
+! CHECK-NONE: attributes #0 = { "reciprocal-estimates"="none" }
+! CHECK-DEF: attributes #0 = { "reciprocal-estimates"="default" }
+! CHECK-POS: attributes #0 = { 
"reciprocal-estimates"="divd,divf,divh,vec-divd,vec-divf,vec-divh,sqrtd,sqrtf,sqrth,vec-sqrtd,vec-sqrtf,vec-sqrth"
 }
+! CHECK-NEG: attributes #0 = { 
"reciprocal-estimates"="!divd,!divf,!divh,!vec-divd,!vec-divf,!vec-divh,!sqrtd,!sqrtf,!sqrth,!vec-sqrtd,!vec-sqrtf,!vec-sqrth"
 }
+! CHECK-MIX: attributes #0 = { 
"reciprocal-estimates"="!divd,divf,!divh,sqrtd,!sqrtf,sqrth" }
+! CHECK-INV: error: unknown argument: 'xxx'
+! CHECK-DUP: error: invalid value 'divd' in 'mrecip='
diff --git a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td 
b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
index c0324d561b77b..eda1d544cd81c 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
+++ b/mlir/include/mlir/Dialect/LLVMIR/LLVMOps.td
@@ -1893,6 +1893,7 @@ def LLVM_LLVMFuncOp : LLVM_Op<"func", [
     OptionalAttr<FramePointerKindAttr>:$frame_pointer,
     OptionalAttr<StrAttr>:$target_cpu,
     OptionalAttr<StrAttr>:$tune_cpu,
+    OptionalAttr<StrAttr>:$reciprocal_estimates,
     OptionalAttr<StrAttr>:$prefer_vector_width,
     OptionalAttr<LLVM_TargetFeaturesAttr>:$target_features,
     OptionalAttr<BoolAttr>:$unsafe_fp_math,
diff --git a/mlir/lib/Target/LLVMIR/ModuleImport.cpp 
b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
index 85417da798b22..803ecb39f4daf 100644
--- a/mlir/lib/Target/LLVMIR/ModuleImport.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleImport.cpp
@@ -2636,6 +2636,11 @@ void 
ModuleImport::processFunctionAttributes(llvm::Function *func,
     funcOp.setTargetFeaturesAttr(
         LLVM::TargetFeaturesAttr::get(context, attr.getValueAsString()));
 
+  if (llvm::Attribute attr = func->getFnAttribute("reciprocal-estimates");
+      attr.isStringAttribute())
+    funcOp.setReciprocalEstimatesAttr(
+        StringAttr::get(context, attr.getValueAsString()));
+
   if (llvm::Attribute attr = func->getFnAttribute("prefer-vector-width");
       attr.isStringAttribute())
     funcOp.setPreferVectorWidth(attr.getValueAsString());
diff --git a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp 
b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
index 4cc419c7cde5b..4c9016ce21360 100644
--- a/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
+++ b/mlir/lib/Target/LLVMIR/ModuleTranslation.cpp
@@ -1549,6 +1549,9 @@ LogicalResult 
ModuleTranslation::convertOneFunction(LLVMFuncOp func) {
   if (auto tuneCpu = func.getTuneCpu())
     llvmFunc->addFnAttr("tune-cpu", *tuneCpu);
 
+  if (auto reciprocalEstimates = func.getReciprocalEstimates())
+    llvmFunc->addFnAttr("reciprocal-estimates", *reciprocalEstimates);
+
   if (auto preferVectorWidth = func.getPreferVectorWidth())
     llvmFunc->addFnAttr("prefer-vector-width", *preferVectorWidth);
 
diff --git a/mlir/test/Target/LLVMIR/Import/mrecip.ll 
b/mlir/test/Target/LLVMIR/Import/mrecip.ll
new file mode 100644
index 0000000000000..01814cce70059
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/Import/mrecip.ll
@@ -0,0 +1,9 @@
+; RUN: mlir-translate -import-llvm -split-input-file %s | FileCheck %s
+
+; CHECK-LABEL: llvm.func @reciprocal_estimates()
+; CHECK-SAME: reciprocal_estimates = "all"
+define void @reciprocal_estimates() #0 {
+  ret void
+}
+
+attributes #0 = { "reciprocal-estimates" = "all" }
diff --git a/mlir/test/Target/LLVMIR/mrecip.mlir 
b/mlir/test/Target/LLVMIR/mrecip.mlir
new file mode 100644
index 0000000000000..e0bc66c272f6a
--- /dev/null
+++ b/mlir/test/Target/LLVMIR/mrecip.mlir
@@ -0,0 +1,8 @@
+// RUN: mlir-translate -mlir-to-llvmir %s | FileCheck %s
+
+// CHECK: define void @reciprocal_estimates() #[[ATTRS:.*]] {
+// CHECK: attributes #[[ATTRS]] = { "reciprocal-estimates"="all" }
+
+llvm.func @reciprocal_estimates() attributes {reciprocal_estimates = "all"} {
+  llvm.return
+}

>From c64c74c831c9ab277bfe9a389697d1b5c2443638 Mon Sep 17 00:00:00 2001
From: Cameron McInally <cmcina...@nvidia.com>
Date: Mon, 9 Jun 2025 13:04:36 -0700
Subject: [PATCH 2/2] Address a handful of review comments:

1) Rename utility functions. Use camelCase, not PascalCase.
2) Change header comments to be documentation comments.
3) Update Frontend tests to account for implicit attributes.
4) Add Compilation Driver support and test case.
---
 clang/include/clang/Driver/CommonArgs.h       |  4 +-
 clang/lib/Driver/ToolChains/Clang.cpp         |  4 +-
 clang/lib/Driver/ToolChains/CommonArgs.cpp    |  4 +-
 clang/lib/Driver/ToolChains/Flang.cpp         |  4 ++
 flang/include/flang/Frontend/CodeGenOptions.h |  4 +-
 flang/lib/Frontend/CompilerInvocation.cpp     |  4 +-
 flang/test/Driver/mrecip.f90                  | 65 +++++++++++++------
 7 files changed, 59 insertions(+), 30 deletions(-)

diff --git a/clang/include/clang/Driver/CommonArgs.h 
b/clang/include/clang/Driver/CommonArgs.h
index 9d0da81b47bba..ddb21c1e8a8b8 100644
--- a/clang/include/clang/Driver/CommonArgs.h
+++ b/clang/include/clang/Driver/CommonArgs.h
@@ -273,12 +273,12 @@ void handleVectorizeSLPArgs(const llvm::opt::ArgList 
&Args,
 
 // Parse -mprefer-vector-width=. Return the Value string if well-formed.
 // Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef ParseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
+StringRef parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
                                         const llvm::opt::ArgList &Args);
 
 // Parse -mrecip. Return the Value string if well-formed.
 // Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef ParseMRecipOption(clang::DiagnosticsEngine &Diags,
+StringRef parseMRecipOption(clang::DiagnosticsEngine &Diags,
                             const llvm::opt::ArgList &Args);
 
 } // end namespace tools
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index df3edcc3cd6bd..70b2912797da9 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -3351,7 +3351,7 @@ static void RenderFloatingPointOptions(const ToolChain 
&TC, const Driver &D,
     CmdArgs.push_back(Args.MakeArgString("-fbfloat16-excess-precision=" +
                                          BFloat16ExcessPrecision));
 
-  StringRef Recip = ParseMRecipOption(D.getDiags(), Args);
+  StringRef Recip = parseMRecipOption(D.getDiags(), Args);
   if (!Recip.empty())
     CmdArgs.push_back(Args.MakeArgString("-mrecip=" + Recip));
 
@@ -7450,7 +7450,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   handleVectorizeLoopsArgs(Args, CmdArgs);
   handleVectorizeSLPArgs(Args, CmdArgs);
 
-  StringRef VecWidth = ParseMPreferVectorWidthOption(D.getDiags(), Args);
+  StringRef VecWidth = parseMPreferVectorWidthOption(D.getDiags(), Args);
   if (!VecWidth.empty())
     CmdArgs.push_back(Args.MakeArgString("-mprefer-vector-width=" + VecWidth));
 
diff --git a/clang/lib/Driver/ToolChains/CommonArgs.cpp 
b/clang/lib/Driver/ToolChains/CommonArgs.cpp
index 238c72dbda8a6..d5b2c5c1e199e 100644
--- a/clang/lib/Driver/ToolChains/CommonArgs.cpp
+++ b/clang/lib/Driver/ToolChains/CommonArgs.cpp
@@ -3170,7 +3170,7 @@ void tools::handleInterchangeLoopsArgs(const ArgList 
&Args,
 
 // Parse -mprefer-vector-width=. Return the Value string if well-formed.
 // Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef tools::ParseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
+StringRef tools::parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
                                                const llvm::opt::ArgList &Args) 
{
   Arg *A = 
Args.getLastArg(clang::driver::options::OPT_mprefer_vector_width_EQ);
   if (!A)
@@ -3223,7 +3223,7 @@ static bool getRefinementStep(StringRef In, 
clang::DiagnosticsEngine &Diags,
 
 // Parse -mrecip. Return the Value string if well-formed.
 // Otherwise, return an empty string and issue a diagnosic message if needed.
-StringRef tools::ParseMRecipOption(clang::DiagnosticsEngine &Diags,
+StringRef tools::parseMRecipOption(clang::DiagnosticsEngine &Diags,
                                    const ArgList &Args) {
   StringRef DisabledPrefixIn = "!";
   StringRef DisabledPrefixOut = "!";
diff --git a/clang/lib/Driver/ToolChains/Flang.cpp 
b/clang/lib/Driver/ToolChains/Flang.cpp
index e0a366bfb9225..a20879dad94d4 100644
--- a/clang/lib/Driver/ToolChains/Flang.cpp
+++ b/clang/lib/Driver/ToolChains/Flang.cpp
@@ -695,6 +695,10 @@ static void addFloatingPointOptions(const Driver &D, const 
ArgList &Args,
     A->claim();
   }
 
+  StringRef Recip = parseMRecipOption(D.getDiags(), Args);
+  if (!Recip.empty())
+    CmdArgs.push_back(Args.MakeArgString("-mrecip=" + Recip));
+
   if (!HonorINFs && !HonorNaNs && AssociativeMath && ReciprocalMath &&
       ApproxFunc && !SignedZeros &&
       (FPContract == "fast" || FPContract.empty())) {
diff --git a/flang/include/flang/Frontend/CodeGenOptions.h 
b/flang/include/flang/Frontend/CodeGenOptions.h
index 5c1f7ef52ca14..e939f10f3c3e7 100644
--- a/flang/include/flang/Frontend/CodeGenOptions.h
+++ b/flang/include/flang/Frontend/CodeGenOptions.h
@@ -53,10 +53,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
   /// The paths to the pass plugins that were registered using -fpass-plugin.
   std::vector<std::string> LLVMPassPlugins;
 
-  // The prefered vector width, if requested by -mprefer-vector-width.
+  /// The prefered vector width, if requested by -mprefer-vector-width.
   std::string PreferVectorWidth;
 
-  // List of reciprocal estimate sub-options.
+  /// List of reciprocal estimate sub-options.
   std::string Reciprocals;
 
   /// List of filenames passed in using the -fembed-offload-object option. 
These
diff --git a/flang/lib/Frontend/CompilerInvocation.cpp 
b/flang/lib/Frontend/CompilerInvocation.cpp
index fcaf959a16a09..783e271e99419 100644
--- a/flang/lib/Frontend/CompilerInvocation.cpp
+++ b/flang/lib/Frontend/CompilerInvocation.cpp
@@ -310,10 +310,10 @@ static void 
parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
   for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ))
     opts.LLVMPassPlugins.push_back(a->getValue());
 
-  opts.Reciprocals = clang::driver::tools::ParseMRecipOption(diags, args);
+  opts.Reciprocals = clang::driver::tools::parseMRecipOption(diags, args);
 
   opts.PreferVectorWidth =
-      clang::driver::tools::ParseMPreferVectorWidthOption(diags, args);
+      clang::driver::tools::parseMPreferVectorWidthOption(diags, args);
 
   // -fembed-offload-object option
   for (auto *a :
diff --git a/flang/test/Driver/mrecip.f90 b/flang/test/Driver/mrecip.f90
index 612be1fac44df..aed7cfad4c2a7 100644
--- a/flang/test/Driver/mrecip.f90
+++ b/flang/test/Driver/mrecip.f90
@@ -1,27 +1,52 @@
 ! Test that -mrecip[=<list>] works as expected.
 
-! RUN: %flang_fc1 -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-OMIT
-! RUN: %flang_fc1 -mrecip -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-NOARG
-! RUN: %flang_fc1 -mrecip=all -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-ALL
-! RUN: %flang_fc1 -mrecip=none -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-NONE
-! RUN: %flang_fc1 -mrecip=default -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-DEF
-! RUN: %flang_fc1 
-mrecip=divd,divf,divh,vec-divd,vec-divf,vec-divh,sqrtd,sqrtf,sqrth,vec-sqrtd,vec-sqrtf,vec-sqrth
 -emit-llvm -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-POS
+! RUN: %flang -### -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FLANG,CHECK-FLANG-OMIT
+! RUN: %flang -mrecip -### -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FLANG,CHECK-FLANG-NOARG
+! RUN: %flang -mrecip=all -### -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FLANG,CHECK-FLANG-ALL
+! RUN: %flang -mrecip=none -### -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FLANG,CHECK-FLANG-NONE
+! RUN: %flang -mrecip=default -### -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FLANG,CHECK-FLANG-DEF
+! RUN: %flang 
-mrecip=divd,divf,divh,vec-divd,vec-divf,vec-divh,sqrtd,sqrtf,sqrth,vec-sqrtd,vec-sqrtf,vec-sqrth
 -### -o - %s 2>&1| FileCheck %s --check-prefixes=CHECK-FLANG,CHECK-FLANG-POS
+! RUN: %flang 
-mrecip=!divd,!divf,!divh,!vec-divd,!vec-divf,!vec-divh,!sqrtd,!sqrtf,!sqrth,!vec-sqrtd,!vec-sqrtf,!vec-sqrth
 -### -o - %s 2>&1| FileCheck %s --check-prefixes=CHECK-FLANG,CHECK-FLANG-NEG
+! RUN: %flang -mrecip=!divd,divf,!divh,sqrtd,!sqrtf,sqrth -### -o - %s 2>&1| 
FileCheck %s --check-prefixes=CHECK-FLANG,CHECK-FLANG-MIX
+! RUN: not %flang -mrecip=xxx  -### -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FLANG-INV
+! RUN: not %flang -mrecip=divd,divd  -### -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FLANG-DUP
+
+! RUN: %flang_fc1 -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-FC1-OMIT
+! RUN: %flang_fc1 -mrecip -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FC1,CHECK-FC1-NOARG
+! RUN: %flang_fc1 -mrecip=all -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FC1,CHECK-FC1-ALL
+! RUN: %flang_fc1 -mrecip=none -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FC1,CHECK-FC1-NONE
+! RUN: %flang_fc1 -mrecip=default -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FC1,CHECK-FC1-DEF
+! RUN: %flang_fc1 
-mrecip=divd,divf,divh,vec-divd,vec-divf,vec-divh,sqrtd,sqrtf,sqrth,vec-sqrtd,vec-sqrtf,vec-sqrth
 -emit-llvm -o - %s 2>&1| FileCheck %s --check-prefixes=CHECK-FC1,CHECK-FC1-POS
 ! RUN: %flang_fc1 
-mrecip=!divd,!divf,!divh,!vec-divd,!vec-divf,!vec-divh,!sqrtd,!sqrtf,!sqrth,!vec-sqrtd,!vec-sqrtf,!vec-sqrth
-! -emit-llvm -o - %s 2>&1| FileCheck %s --check-prefix=CHECK-NEG
-! RUN: %flang_fc1 -mrecip=!divd,divf,!divh,sqrtd,!sqrtf,sqrth -emit-llvm -o - 
%s 2>&1| FileCheck %s --check-prefix=CHECK-MIX
-! RUN: not %flang_fc1 -mrecip=xxx  -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-INV
-! RUN: not %flang_fc1 -mrecip=divd,divd  -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefix=CHECK-DUP
+! -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FC1,CHECK-FC1-NEG
+! RUN: %flang_fc1 -mrecip=!divd,divf,!divh,sqrtd,!sqrtf,sqrth -emit-llvm -o - 
%s 2>&1| FileCheck %s --check-prefixes=CHECK-FC1,CHECK-FC1-MIX
+! RUN: not %flang_fc1 -mrecip=xxx  -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FC1-INV
+! RUN: not %flang_fc1 -mrecip=divd,divd  -emit-llvm -o - %s 2>&1| FileCheck %s 
--check-prefixes=CHECK-FC1-DUP
 
 subroutine func
 end subroutine func
 
-! CHECK-OMIT-NOT: attributes #0 = { "reciprocal-estimates"={{.*}} }
-! CHECK-NOARG: attributes #0 = { "reciprocal-estimates"="all" }
-! CHECK-ALL: attributes #0 = { "reciprocal-estimates"="all" }
-! CHECK-NONE: attributes #0 = { "reciprocal-estimates"="none" }
-! CHECK-DEF: attributes #0 = { "reciprocal-estimates"="default" }
-! CHECK-POS: attributes #0 = { 
"reciprocal-estimates"="divd,divf,divh,vec-divd,vec-divf,vec-divh,sqrtd,sqrtf,sqrth,vec-sqrtd,vec-sqrtf,vec-sqrth"
 }
-! CHECK-NEG: attributes #0 = { 
"reciprocal-estimates"="!divd,!divf,!divh,!vec-divd,!vec-divf,!vec-divh,!sqrtd,!sqrtf,!sqrth,!vec-sqrtd,!vec-sqrtf,!vec-sqrth"
 }
-! CHECK-MIX: attributes #0 = { 
"reciprocal-estimates"="!divd,divf,!divh,sqrtd,!sqrtf,sqrth" }
-! CHECK-INV: error: unknown argument: 'xxx'
-! CHECK-DUP: error: invalid value 'divd' in 'mrecip='
+! CHECK-FLANG: "-fc1"
+! CHECK-FLANG-OMIT-NOT: "-mrecip="
+! CHECK-FLANG-NOARG-SAME: "-mrecip=all"
+! CHECK-FLANG-ALL-SAME: "-mrecip=all"
+! CHECK-FLANG-NONE-SAME: "-mrecip=none"
+! CHECK-FLANG-DEF-SAME: "-mrecip=default"
+! CHECK-FLANG-POS-SAME: 
"-mrecip=divd,divf,divh,vec-divd,vec-divf,vec-divh,sqrtd,sqrtf,sqrth,vec-sqrtd,vec-sqrtf,vec-sqrth"
+! CHECK-FLANG-NEG-SAME: 
"-mrecip=!divd,!divf,!divh,!vec-divd,!vec-divf,!vec-divh,!sqrtd,!sqrtf,!sqrth,!vec-sqrtd,!vec-sqrtf,!vec-sqrth"
+! CHECK-FLANG-MIX-SAME: "-mrecip=!divd,divf,!divh,sqrtd,!sqrtf,sqrth"
+! CHECK-FLANG-INV: error: unknown argument: 'xxx'
+! CHECK-FLANG-DUP: error: invalid value 'divd' in 'mrecip='
+
+! CHECK-FC1: define {{.+}} @func{{.*}} #[[ATTRS:[0-9]+]]
+! CHECK-FC1: attributes #[[ATTRS]] =
+! CHECK-FC1-OMIT-NOT: "reciprocal-estimates"
+! CHECK-FC1-NOARG-SAME: "reciprocal-estimates"="all"
+! CHECK-FC1-ALL-SAME: "reciprocal-estimates"="all"
+! CHECK-FC1-NONE-SAME: "reciprocal-estimates"="none"
+! CHECK-FC1-DEF-SAME: "reciprocal-estimates"="default"
+! CHECK-FC1-POS-SAME: 
"reciprocal-estimates"="divd,divf,divh,vec-divd,vec-divf,vec-divh,sqrtd,sqrtf,sqrth,vec-sqrtd,vec-sqrtf,vec-sqrth"
+! CHECK-FC1-NEG-SAME: 
"reciprocal-estimates"="!divd,!divf,!divh,!vec-divd,!vec-divf,!vec-divh,!sqrtd,!sqrtf,!sqrth,!vec-sqrtd,!vec-sqrtf,!vec-sqrth"
+! CHECK-FC1-MIX-SAME: 
"reciprocal-estimates"="!divd,divf,!divh,sqrtd,!sqrtf,sqrth"
+! CHECK-FC1-INV: error: unknown argument: 'xxx'
+! CHECK-FC1-DUP: error: invalid value 'divd' in 'mrecip='

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to