Patch updated:
1. Changed to error out on duplicate argument settings to the -mrecip option;
eg: -mrecip=divf,divf
2. Improved variable names
3. Changed refinement step token to ':' (this just looks better than '.' IMO)
4. Fixed logic bug when parsing optional refinement step arg; was allowing
correct prefix with bogus suffix ('divffoo') to get through
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
@@ -1337,6 +1337,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
@@ -480,6 +480,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
@@ -1614,6 +1614,112 @@
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 hasRefinementStep(const StringRef &In) {
+ const char REF_STEP_TOKEN = ':';
+ size_t Position = In.find(REF_STEP_TOKEN);
+ if (Position == std::string::npos)
+ return false;
+
+ 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 &OutStrings) {
+ Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
+ if (!A)
+ return;
+
+ static const char *OptionStrings[] = {
+ "divf",
+ "vec-divf",
+ "sqrtf",
+ "vec-sqrtf",
+ "divd",
+ "vec-divd",
+ "sqrtd",
+ "vec-sqrtd"
+ };
+ const unsigned NumStrings = llvm::array_lengthof(OptionStrings);
+
+ unsigned NumOptions = A->getNumValues();
+
+ // No option is the same as "all".
+ if (NumOptions == 0) {
+ OutStrings.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 == "all" || Val == "none" || Val == "default") ||
+ ((Val.startswith("all") ||
+ Val.startswith("none") ||
+ Val.startswith("default")) && hasRefinementStep(Val))) {
+ OutStrings.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.
+
+ // Do not accept duplicate specifiers for any argument.
+ bool FoundArg[NumStrings];
+ for (unsigned i = 0; i != NumStrings; ++i)
+ FoundArg[i] = false;
+
+ StringRef Out = "-mrecip=";
+ for (unsigned i = 0; i != NumOptions; ++i) {
+ StringRef Val = A->getValue(i);
+
+ // Ignore the '-' or optional '+' in string comparison.
+ bool IsDisabled = (Val[0] == '-');
+ if (IsDisabled)
+ Val = Val.substr(1);
+ else if (Val[0] == '+')
+ Val = Val.substr(1);
+
+ bool Found = false;
+ for (unsigned j = 0; j != NumStrings; ++j) {
+ if (Val == OptionStrings[j] ||
+ (Val.startswith(OptionStrings[j]) && hasRefinementStep(Val))) {
+ // A duplicate argument specifier is not allowed.
+ if (FoundArg[j]) {
+ D.Diag(diag::err_drv_invalid_value) <<
+ A->getOption().getName() << Val;
+ }
+
+ StringRef Prefix = IsDisabled ? "-" : "+";
+ Out = Args.MakeArgString(Out + Prefix + Val);
+ Found = true;
+ FoundArg[j] = true;
+ break;
+ }
+ }
+
+ // The name did not match any known option string.
+ if (!Found)
+ D.Diag(diag::err_drv_unknown_argument) << 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) {
@@ -3127,6 +3233,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
@@ -1843,7 +1843,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=divd:1,sqrtf:2,sqrtf:3,divd 2>&1 | FileCheck --check-prefix=RECIP10 %s
+// RECIP10: error: invalid value
+
+// RUN: %clang -### -S %s -mrecip=+default:10 2>&1 | FileCheck --check-prefix=RECIP11 %s
+// RECIP11: error: unknown argument
+
+// RUN: %clang -### -S %s -mrecip=-vec-divd: 2>&1 | FileCheck --check-prefix=RECIP12 %s
+// RECIP12: error: unknown argument
+
+// RUN: %clang -### -S %s -mrecip=bogus 2>&1 | FileCheck --check-prefix=RECIP13 %s
+// RECIP13: error: unknown argument
+
_______________________________________________
cfe-commits mailing list
[email protected]
http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits