Hi hfinkel, andreadb, alexr,

This is the front-end counterpart to D8982. 

The option parsing implementation is based on maintaining compatibility with 
gcc; gcc documentation for this flag:
https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/i386-and-x86-64-Options.html#index-mrecip_003dopt-1627

Note that PowerPC could have its own -mrecip options if further compatibility 
is desired:
https://gcc.gnu.org/onlinedocs/gcc-4.9.2/gcc/RS_002f6000-and-PowerPC-Options.html#index-mrecip-2289

With this flag in place, customers will have fine-grain control over reciprocal 
estimate codegen, so we may choose to align with gcc's optimization behavior 
for that. Eg, LLVM could generate reciprocal square root by default when 
-ffast-math is on. This was requested in PR21385 ( 
https://llvm.org/bugs/show_bug.cgi?id=21385 ).

http://reviews.llvm.org/D8989

Files:
  include/clang/Driver/Options.td
  lib/Driver/Tools.cpp
  test/Driver/x86_features.c

EMAIL PREFERENCES
  http://reviews.llvm.org/settings/panel/emailpreferences/
Index: include/clang/Driver/Options.td
===================================================================
--- include/clang/Driver/Options.td
+++ include/clang/Driver/Options.td
@@ -1320,6 +1320,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>;
 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/Driver/Tools.cpp
===================================================================
--- lib/Driver/Tools.cpp
+++ lib/Driver/Tools.cpp
@@ -1578,6 +1578,71 @@
     CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
 }
 
+// The -mrecip flag is not unique to x86, but it sets x86-specific target
+// features. It requires processing of many optional parameters.
+static void ParseRecip(const Driver &D, const ArgList &Args,
+                       std::vector<const char *> &Features) {
+  Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
+  if (!A)
+    return;
+
+  const char *OptionStrings[] = {
+    "div",
+    "vec-div",
+    "sqrt",
+    "vec-sqrt"
+  };
+  
+  std::string Prefix = "+recip-";
+  
+  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.";
+  }
+  
+  // If "none" is specified, negate the prefix and proceed as if no option was
+  // specified.
+  if (NumOptions == 1 && strcmp(A->getValue(0), "none") == 0) {
+    Prefix[0] = '-';
+    NumOptions = 0;
+  }
+
+  // If "all", "default" or no options are specified, set all features.
+  if (NumOptions == 0 ||
+      (NumOptions == 1 && strcmp(A->getValue(0), "all") == 0) ||
+      (NumOptions == 1 && strcmp(A->getValue(0), "default") == 0)) {
+    for (unsigned i = 0; i != NumStrings ; ++i)
+      Features.push_back(Args.MakeArgString(Prefix + OptionStrings[i]));
+    return;
+  }
+
+  // Each reciprocal type may be enabled or disabled ("!") individually.
+  for (unsigned i = 0; i != NumOptions; ++i) {
+    const char *Value = A->getValue(i);
+    // Ignore the '!' in string comparison.
+    bool IsNegative = (Value[0] == '!');
+    if (IsNegative)
+      Value++;
+    
+    bool Found = false;
+    for (unsigned j = 0; j != NumStrings; ++j) {
+      if (strcmp(OptionStrings[j], Value) == 0) {
+        Prefix[0] = IsNegative ? '-' : '+';
+        Features.push_back(Args.MakeArgString(Prefix + OptionStrings[j]));
+        Found = true;
+        break;
+      }
+    }
+    if (!Found) {
+      D.Diag(diag::err_drv_unsupported_option_argument) <<
+        A->getOption().getName() << Value;
+    }
+  }
+}
+
 static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                  const ArgList &Args,
                                  std::vector<const char *> &Features) {
@@ -1655,6 +1720,8 @@
 
     Features.push_back(Args.MakeArgString((IsNegative ? "-" : "+") + Name));
   }
+  
+  ParseRecip(D, Args, Features);
 }
 
 void Clang::AddX86TargetArgs(const ArgList &Args,
Index: test/Driver/x86_features.c
===================================================================
--- test/Driver/x86_features.c
+++ test/Driver/x86_features.c
@@ -5,3 +5,48 @@
 // Test that we don't produce an error with -mieee-fp.
 // RUN: %clang -### %s -mieee-fp -S 2>&1 | FileCheck --check-prefix=IEEE %s
 // IEEE-NOT: error: unknown argument
+
+// Test various options for the -mrecip flag.
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip  2>&1 | FileCheck --check-prefix=RECIP0 %s
+// RECIP0: "-target-feature" "+recip-div" "-target-feature" "+recip-vec-div" "-target-feature" "+recip-sqrt" "-target-feature" "+recip-vec-sqrt"
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=all  2>&1 | FileCheck --check-prefix=RECIP1 %s
+// RECIP1: "-target-feature" "+recip-div" "-target-feature" "+recip-vec-div" "-target-feature" "+recip-sqrt" "-target-feature" "+recip-vec-sqrt"
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=default  2>&1 | FileCheck --check-prefix=RECIP2 %s
+// RECIP2: "-target-feature" "+recip-div" "-target-feature" "+recip-vec-div" "-target-feature" "+recip-sqrt" "-target-feature" "+recip-vec-sqrt"
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=none  2>&1 | FileCheck --check-prefix=RECIP3 %s
+// RECIP3: "-target-feature" "-recip-div" "-target-feature" "-recip-vec-div" "-target-feature" "-recip-sqrt" "-target-feature" "-recip-vec-sqrt"
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=div,sqrt,vec-div,vec-sqrt  2>&1 | FileCheck --check-prefix=RECIP4 %s
+// RECIP4: "-target-feature" "+recip-div" "-target-feature" "+recip-sqrt" "-target-feature" "+recip-vec-div" "-target-feature" "+recip-vec-sqrt"
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=div  2>&1 | FileCheck --check-prefix=RECIP5 %s
+// RECIP5: "-target-feature" "+recip-div" 
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=vec-div  2>&1 | FileCheck --check-prefix=RECIP6 %s
+// RECIP6: "-target-feature" "+recip-vec-div" 
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=sqrt  2>&1 | FileCheck --check-prefix=RECIP7 %s
+// RECIP7: "-target-feature" "+recip-sqrt" 
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=vec-sqrt  2>&1 | FileCheck --check-prefix=RECIP8 %s
+// RECIP8: "-target-feature" "+recip-vec-sqrt" 
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=div,vec-div  2>&1 | FileCheck --check-prefix=RECIP9 %s
+// RECIP9: "-target-feature" "+recip-div" "-target-feature" "+recip-vec-div"
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=div,sqrt  2>&1 | FileCheck --check-prefix=RECIP10 %s
+// RECIP10: "-target-feature" "+recip-div" "-target-feature" "+recip-sqrt"
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=div,!vec-sqrt  2>&1 | FileCheck --check-prefix=RECIP11 %s
+// RECIP11: "-target-feature" "+recip-div" "-target-feature" "-recip-vec-sqrt"
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=bogus  2>&1 | FileCheck --check-prefix=RECIP12 %s
+// RECIP12: error: unsupported argument 
+
+// RUN: %clang -target i386-unknown-unknown -### -S %s -mrecip=div,div,div,div,div  2>&1 | FileCheck --check-prefix=RECIP13 %s
+// RECIP13: error: invalid argument 
+
_______________________________________________
cfe-commits mailing list
cfe-commits@cs.uiuc.edu
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits

Reply via email to