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, HelpText<"Don't generate implicit floating point instructions">; def mimplicit_float : Flag<["-"], "mimplicit-float">, Group; +def mrecip : Flag<["-"], "mrecip">, Group; +def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group; def msse2 : Flag<["-"], "msse2">, Group; def msse3 : Flag<["-"], "msse3">, Group; def msse4a : Flag<["-"], "msse4a">, 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 &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 &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 +