r238055 - add the -mrecip driver flag and process its options

Sanjay Patel spatel at rotateright.com
Fri May 22 14:42:10 PDT 2015


Author: spatel
Date: Fri May 22 16:42:10 2015
New Revision: 238055

URL: http://llvm.org/viewvc/llvm-project?rev=238055&view=rev
Log:
add the -mrecip driver flag and process its options

This is the front-end counterpart to D8982 (LLVM r238051).

The -mrecip option interface is based on maintaining compatibility with gcc:
https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/i386-and-x86-64-Options.html#index-mrecip_003dopt-1627
https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/RS_002f6000-and-PowerPC-Options.html#index-mrecip-2289

...while adding more functionality (allowing users to specify the number of refinement steps for each
estimate type).

Differential Revision: http://reviews.llvm.org/D8989


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

Modified: cfe/trunk/include/clang/Basic/TargetOptions.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Basic/TargetOptions.h?rev=238055&r1=238054&r2=238055&view=diff
==============================================================================
--- cfe/trunk/include/clang/Basic/TargetOptions.h (original)
+++ cfe/trunk/include/clang/Basic/TargetOptions.h Fri May 22 16:42:10 2015
@@ -45,6 +45,8 @@ public:
   /// 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

Modified: cfe/trunk/include/clang/Driver/Options.td
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Driver/Options.td?rev=238055&r1=238054&r2=238055&view=diff
==============================================================================
--- cfe/trunk/include/clang/Driver/Options.td (original)
+++ cfe/trunk/include/clang/Driver/Options.td Fri May 22 16:42:10 2015
@@ -1337,6 +1337,8 @@ def msoft_float : Flag<["-"], "msoft-flo
 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>;

Modified: cfe/trunk/lib/CodeGen/BackendUtil.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/BackendUtil.cpp?rev=238055&r1=238054&r2=238055&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/BackendUtil.cpp (original)
+++ cfe/trunk/lib/CodeGen/BackendUtil.cpp Fri May 22 16:42:10 2015
@@ -480,6 +480,9 @@ TargetMachine *EmitAssemblyHelper::Creat
 
   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)

Modified: cfe/trunk/lib/Driver/Tools.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Driver/Tools.cpp?rev=238055&r1=238054&r2=238055&view=diff
==============================================================================
--- cfe/trunk/lib/Driver/Tools.cpp (original)
+++ cfe/trunk/lib/Driver/Tools.cpp Fri May 22 16:42:10 2015
@@ -1629,6 +1629,138 @@ static void AddGoldPlugin(const ToolChai
     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. 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(const 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) {
+  static const char DisabledPrefixIn = '!';
+  static const char DisabledPrefixOut = '!';
+  static const char EnabledPrefixOut = '\0';
+  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("vec-divd",   false));
+  OptionStrings.insert(std::make_pair("vec-divf",   false));
+  OptionStrings.insert(std::make_pair("sqrtd",      false));
+  OptionStrings.insert(std::make_pair("sqrtf",      false));
+  OptionStrings.insert(std::make_pair("vec-sqrtd",  false));
+  OptionStrings.insert(std::make_pair("vec-sqrtf",  false));
+
+  for (unsigned i = 0; i != NumOptions; ++i) {
+    StringRef Val = A->getValue(i);
+
+    bool IsDisabled = Val[0] == 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 float or double suffix.
+      // Make sure that the double entry was not already specified.
+      // The float entry will be checked below.
+      if (OptionStrings[ValBase.str() + 'd']) {
+        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 entry as found.
+    if (ValBase.back() != 'f' && ValBase.back() != 'd')
+      OptionStrings[ValBase.str() + 'd'] = true;
+
+    // Build the output string.
+    const char *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 void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                  const ArgList &Args,
                                  std::vector<const char *> &Features) {
@@ -3142,6 +3274,8 @@ void Clang::ConstructJob(Compilation &C,
       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

Modified: cfe/trunk/lib/Frontend/CompilerInvocation.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Frontend/CompilerInvocation.cpp?rev=238055&r1=238054&r2=238055&view=diff
==============================================================================
--- cfe/trunk/lib/Frontend/CompilerInvocation.cpp (original)
+++ cfe/trunk/lib/Frontend/CompilerInvocation.cpp Fri May 22 16:42:10 2015
@@ -1846,7 +1846,7 @@ static void ParseTargetArgs(TargetOption
   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();

Added: cfe/trunk/test/Driver/mrecip.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Driver/mrecip.c?rev=238055&view=auto
==============================================================================
--- cfe/trunk/test/Driver/mrecip.c (added)
+++ cfe/trunk/test/Driver/mrecip.c Fri May 22 16:42:10 2015
@@ -0,0 +1,70 @@
+////
+//// 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 options that do not specify float or double.
+
+// RUN: %clang -### -S %s -mrecip=vec-sqrt  2>&1 | FileCheck --check-prefix=RECIP4 %s
+// RECIP4: "-mrecip=vec-sqrt"
+
+// RUN: %clang -### -S %s -mrecip=!div,vec-div  2>&1 | FileCheck --check-prefix=RECIP5 %s
+// RECIP5: "-mrecip=!div,vec-div"
+
+//// Check individual option types.
+
+// RUN: %clang -### -S %s -mrecip=vec-sqrtd  2>&1 | FileCheck --check-prefix=RECIP6 %s
+// RECIP6: "-mrecip=vec-sqrtd"
+
+// RUN: %clang -### -S %s -mrecip=!divf  2>&1 | FileCheck --check-prefix=RECIP7 %s
+// RECIP7: "-mrecip=!divf"
+
+// RUN: %clang -### -S %s -mrecip=divf,sqrtd,vec-divd,vec-sqrtf  2>&1 | FileCheck --check-prefix=RECIP8 %s
+// RECIP8: "-mrecip=divf,sqrtd,vec-divd,vec-sqrtf"
+
+//// Check optional refinement step specifiers.
+
+// RUN: %clang -### -S %s -mrecip=all:1  2>&1 | FileCheck --check-prefix=RECIP9 %s
+// RECIP9: "-mrecip=all:1"
+
+// RUN: %clang -### -S %s -mrecip=sqrtf:3  2>&1 | FileCheck --check-prefix=RECIP10 %s
+// RECIP10: "-mrecip=sqrtf:3"
+
+// RUN: %clang -### -S %s -mrecip=div:5  2>&1 | FileCheck --check-prefix=RECIP11 %s
+// RECIP11: "-mrecip=div:5"
+
+// RUN: %clang -### -S %s -mrecip=divd:1,!sqrtf:2,vec-divf:9,vec-sqrtd:0  2>&1 | FileCheck --check-prefix=RECIP12 %s
+// RECIP12: "-mrecip=divd:1,!sqrtf:2,vec-divf:9,vec-sqrtd:0"
+
+//// Check invalid parameters.
+
+// RUN: %clang -### -S %s -mrecip=bogus  2>&1 | FileCheck --check-prefix=RECIP13 %s
+// RECIP13: error: unknown argument
+
+// RUN: %clang -### -S %s -mrecip=divd:1,divd  2>&1 | FileCheck --check-prefix=RECIP14 %s
+// RECIP14: error: invalid value 
+
+// RUN: %clang -### -S %s -mrecip=sqrt,sqrtf  2>&1 | FileCheck --check-prefix=RECIP15 %s
+// RECIP15: error: invalid value 
+
+// RUN: %clang -### -S %s -mrecip=+default:10  2>&1 | FileCheck --check-prefix=RECIP16 %s
+// RECIP16: error: invalid value 
+
+// RUN: %clang -### -S %s -mrecip=!vec-divd:  2>&1 | FileCheck --check-prefix=RECIP17 %s
+// RECIP17: error: invalid value 
+





More information about the cfe-commits mailing list