Patch updated to treat -mrecip as a target-independent flag. Clang just does 
some simple transforms and error-checking on the input strings and passes them 
through to the backend. The backend is responsible for further processing and 
target-specific default settings.


http://reviews.llvm.org/D8989

Files:
  include/clang/Basic/TargetOptions.h
  include/clang/Driver/Options.td
  lib/CodeGen/BackendUtil.cpp
  lib/Driver/Tools.cpp
  lib/Frontend/CompilerInvocation.cpp
  test/Driver/mrecip.c

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Basic/TargetOptions.h
===================================================================
--- include/clang/Basic/TargetOptions.h
+++ include/clang/Basic/TargetOptions.h
@@ -45,6 +45,8 @@
   /// The list of target specific features to enable or disable -- this should
   /// be a list of strings starting with by '+' or '-'.
   std::vector<std::string> Features;
+  
+  std::vector<std::string> Reciprocals;
 };
 
 }  // end namespace clang
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1323,6 +1323,8 @@
 def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>,
   HelpText<"Don't generate implicit floating point instructions">;
 def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>;
+def mrecip : Flag<["-"], "mrecip">, Group<m_Group>;
+def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>;
 def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>;
 def msse3 : Flag<["-"], "msse3">, Group<m_x86_Features_Group>;
 def msse4a : Flag<["-"], "msse4a">, Group<m_x86_Features_Group>;
Index: lib/CodeGen/BackendUtil.cpp
===================================================================
--- lib/CodeGen/BackendUtil.cpp
+++ lib/CodeGen/BackendUtil.cpp
@@ -470,6 +470,9 @@
 
   llvm::TargetOptions Options;
 
+  if (!TargetOpts.Reciprocals.empty())
+    Options.Reciprocals = TargetRecip(TargetOpts.Reciprocals);
+
   Options.ThreadModel =
     llvm::StringSwitch<llvm::ThreadModel::Model>(CodeGenOpts.ThreadModel)
       .Case("posix", llvm::ThreadModel::POSIX)
Index: lib/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1588,6 +1588,101 @@
     CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
 }
 
+/// This is a helper function for validating the optional refinement step
+/// parameter in reciprocal argument strings.
+static bool hasRefinementStepOrNot(const StringRef &In) {
+  const char REF_STEP_TOKEN = '.';
+  size_t Position = In.find(REF_STEP_TOKEN);
+  if (Position == std::string::npos)
+    return true;
+  
+  StringRef RefStepString = In.substr(Position + 1);
+  // Allow exactly one numeric character for the additional refinement
+  // step parameter.
+  if (RefStepString.size() != 1)
+    return false;
+  char RefStepChar = RefStepString[0];
+  if (RefStepChar < '0' || RefStepChar > '9')
+    return false;
+  return true;
+}
+
+/// The -mrecip flag requires processing of many optional parameters.
+static void ParseMRecip(const Driver &D, const ArgList &Args,
+                       ArgStringList &Features) {
+  Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
+  if (!A)
+    return;
+
+  const char *OptionStrings[] = {
+    "divf",
+    "vec-divf",
+    "sqrtf",
+    "vec-sqrtf",
+    "divd",
+    "vec-divd",
+    "sqrtd",
+    "vec-sqrtd"
+  };
+  
+  unsigned NumOptions = A->getNumValues();
+  unsigned NumStrings = llvm::array_lengthof(OptionStrings);
+
+  if (NumOptions > NumStrings) {
+    D.Diag(diag::err_drv_argument_not_allowed_with)
+      << A->getOption().getName() << "Too many options specified.";
+  }
+  
+  // No option is the same as "all".
+  if (NumOptions == 0) {
+    Features.push_back(Args.MakeArgString("-mrecip=all"));
+    return;
+  }
+
+  // Pass through "all", "none", or "default" with an optional refinement step.
+  if (NumOptions == 1) {
+    StringRef Val = A->getValue(0);
+    if (Val.startswith("all") ||
+        Val.startswith("none") ||
+        Val.startswith("default")) {
+      if (hasRefinementStepOrNot(Val)) {
+        Features.push_back(Args.MakeArgString("-mrecip=" + 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.
+  StringRef Out = "-mrecip=";
+  for (unsigned i = 0; i != NumOptions; ++i) {
+    StringRef Val = A->getValue(i);
+    // Ignore the '-' or optional '+' in string comparison.
+    bool IsNegative = (Val[0] == '-');
+    if (IsNegative)
+      Val = Val.substr(1);
+    else if (Val[0] == '+')
+      Val = Val.substr(1);
+    bool Found = false;
+    for (unsigned j = 0; j != NumStrings; ++j) {
+      if (Val.startswith(OptionStrings[j]) && hasRefinementStepOrNot(Val)) {
+        StringRef Prefix = IsNegative ? "-" : "+";
+        Out = Args.MakeArgString(Out + Prefix + Val);
+        Found = true;
+        break;
+      }
+    }
+    if (!Found) {
+      D.Diag(diag::err_drv_unsupported_option_argument) <<
+        A->getOption().getName() << Val;
+    }
+    if (i != NumOptions - 1)
+      Out = Args.MakeArgString(Out + ",");
+  }
+  Features.push_back(Args.MakeArgString(Out));
+}
+
 static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                  const ArgList &Args,
                                  std::vector<const char *> &Features) {
@@ -3104,6 +3199,8 @@
       CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
     }
   }
+  
+  ParseMRecip(getToolChain().getDriver(), Args, CmdArgs);
 
   // We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
   // and if we find them, tell the frontend to provide the appropriate
Index: lib/Frontend/CompilerInvocation.cpp
===================================================================
--- lib/Frontend/CompilerInvocation.cpp
+++ lib/Frontend/CompilerInvocation.cpp
@@ -1823,7 +1823,7 @@
   Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
   Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
   Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
-
+  Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
   // Use the default target triple if unspecified.
   if (Opts.Triple.empty())
     Opts.Triple = llvm::sys::getDefaultTargetTriple();
Index: test/Driver/mrecip.c
===================================================================
--- test/Driver/mrecip.c
+++ test/Driver/mrecip.c
@@ -0,0 +1,56 @@
+////
+//// Verify that valid options for the -mrecip flag are passed through and invalid options cause an error.
+////
+
+//// If there are no options, convert to 'all'.
+
+// RUN: %clang -### -S %s -mrecip  2>&1 | FileCheck --check-prefix=RECIP0 %s
+// RECIP0: "-mrecip=all"
+
+//// Check options that cover all types.
+
+// RUN: %clang -### -S %s -mrecip=all  2>&1 | FileCheck --check-prefix=RECIP1 %s
+// RECIP1: "-mrecip=all"
+
+// RUN: %clang -### -S %s -mrecip=default  2>&1 | FileCheck --check-prefix=RECIP2 %s
+// RECIP2: "-mrecip=default"
+
+// RUN: %clang -### -S %s -mrecip=none  2>&1 | FileCheck --check-prefix=RECIP3 %s
+// RECIP3: "-mrecip=none"
+
+//// Check individual option types.
+
+// RUN: %clang -### -S %s -mrecip=vec-sqrtd  2>&1 | FileCheck --check-prefix=RECIP4 %s
+// RECIP4: "-mrecip=+vec-sqrtd"
+
+// RUN: %clang -### -S %s -mrecip=-divf  2>&1 | FileCheck --check-prefix=RECIP5 %s
+// RECIP5: "-mrecip=-divf"
+
+// RUN: %clang -### -S %s -mrecip=divf,sqrtd,vec-divd,vec-sqrtf  2>&1 | FileCheck --check-prefix=RECIP6 %s
+// RECIP6: "-mrecip=+divf,+sqrtd,+vec-divd,+vec-sqrtf"
+
+//// Check optional refinement step specifiers.
+
+// RUN: %clang -### -S %s -mrecip=all.1  2>&1 | FileCheck --check-prefix=RECIP7 %s
+// RECIP7: "-mrecip=all.1"
+
+// RUN: %clang -### -S %s -mrecip=sqrtf.3  2>&1 | FileCheck --check-prefix=RECIP8 %s
+// RECIP8: "-mrecip=+sqrtf.3"
+
+// RUN: %clang -### -S %s -mrecip=divd.1,sqrtf.2,vec-divf.9,vec-sqrtd.0  2>&1 | FileCheck --check-prefix=RECIP9 %s
+// RECIP9: "-mrecip=+divd.1,+sqrtf.2,+vec-divf.9,+vec-sqrtd.0"
+
+//// Check invalid parameters.
+
+// RUN: %clang -### -S %s -mrecip=divf,divf,divf,divf,divf,divf,divf,divf,divf  2>&1 | FileCheck --check-prefix=RECIP10 %s
+// RECIP10: error: invalid argument
+
+// RUN: %clang -### -S %s -mrecip=+default.10  2>&1 | FileCheck --check-prefix=RECIP11 %s
+// RECIP11: error: unsupported argument 
+
+// RUN: %clang -### -S %s -mrecip=-vec-divd.  2>&1 | FileCheck --check-prefix=RECIP12 %s
+// RECIP12: error: unsupported argument 
+
+// RUN: %clang -### -S %s -mrecip=bogus  2>&1 | FileCheck --check-prefix=RECIP13 %s
+// RECIP13: error: unsupported argument
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to