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 + _______________________________________________ cfe-commits mailing list [email protected] http://lists.cs.uiuc.edu/mailman/listinfo/cfe-commits
