Skip to content

Commit f5019e6

Browse files
committedMay 22, 2015
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 llvm-svn: 238055
1 parent 236f904 commit f5019e6

File tree

6 files changed

+212
-1
lines changed

6 files changed

+212
-1
lines changed
 

Diff for: ‎clang/include/clang/Basic/TargetOptions.h

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ class TargetOptions {
4545
/// The list of target specific features to enable or disable -- this should
4646
/// be a list of strings starting with by '+' or '-'.
4747
std::vector<std::string> Features;
48+
49+
std::vector<std::string> Reciprocals;
4850
};
4951

5052
} // end namespace clang

Diff for: ‎clang/include/clang/Driver/Options.td

+2
Original file line numberDiff line numberDiff line change
@@ -1337,6 +1337,8 @@ def msoft_float : Flag<["-"], "msoft-float">, Group<m_Group>, Flags<[CC1Option]>
13371337
def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>,
13381338
HelpText<"Don't generate implicit floating point instructions">;
13391339
def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>;
1340+
def mrecip : Flag<["-"], "mrecip">, Group<m_Group>;
1341+
def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>, Flags<[CC1Option]>;
13401342
def msse2 : Flag<["-"], "msse2">, Group<m_x86_Features_Group>;
13411343
def msse3 : Flag<["-"], "msse3">, Group<m_x86_Features_Group>;
13421344
def msse4a : Flag<["-"], "msse4a">, Group<m_x86_Features_Group>;

Diff for: ‎clang/lib/CodeGen/BackendUtil.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -480,6 +480,9 @@ TargetMachine *EmitAssemblyHelper::CreateTargetMachine(bool MustCreateTM) {
480480

481481
llvm::TargetOptions Options;
482482

483+
if (!TargetOpts.Reciprocals.empty())
484+
Options.Reciprocals = TargetRecip(TargetOpts.Reciprocals);
485+
483486
Options.ThreadModel =
484487
llvm::StringSwitch<llvm::ThreadModel::Model>(CodeGenOpts.ThreadModel)
485488
.Case("posix", llvm::ThreadModel::POSIX)

Diff for: ‎clang/lib/Driver/Tools.cpp

+134
Original file line numberDiff line numberDiff line change
@@ -1629,6 +1629,138 @@ static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
16291629
CmdArgs.push_back(Args.MakeArgString(Twine("-plugin-opt=mcpu=") + CPU));
16301630
}
16311631

1632+
/// This is a helper function for validating the optional refinement step
1633+
/// parameter in reciprocal argument strings. Return false if there is an error
1634+
/// parsing the refinement step. Otherwise, return true and set the Position
1635+
/// of the refinement step in the input string.
1636+
static bool getRefinementStep(const StringRef &In, const Driver &D,
1637+
const Arg &A, size_t &Position) {
1638+
const char RefinementStepToken = ':';
1639+
Position = In.find(RefinementStepToken);
1640+
if (Position != StringRef::npos) {
1641+
StringRef Option = A.getOption().getName();
1642+
StringRef RefStep = In.substr(Position + 1);
1643+
// Allow exactly one numeric character for the additional refinement
1644+
// step parameter. This is reasonable for all currently-supported
1645+
// operations and architectures because we would expect that a larger value
1646+
// of refinement steps would cause the estimate "optimization" to
1647+
// under-perform the native operation. Also, if the estimate does not
1648+
// converge quickly, it probably will not ever converge, so further
1649+
// refinement steps will not produce a better answer.
1650+
if (RefStep.size() != 1) {
1651+
D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
1652+
return false;
1653+
}
1654+
char RefStepChar = RefStep[0];
1655+
if (RefStepChar < '0' || RefStepChar > '9') {
1656+
D.Diag(diag::err_drv_invalid_value) << Option << RefStep;
1657+
return false;
1658+
}
1659+
}
1660+
return true;
1661+
}
1662+
1663+
/// The -mrecip flag requires processing of many optional parameters.
1664+
static void ParseMRecip(const Driver &D, const ArgList &Args,
1665+
ArgStringList &OutStrings) {
1666+
static const char DisabledPrefixIn = '!';
1667+
static const char DisabledPrefixOut = '!';
1668+
static const char EnabledPrefixOut = '\0';
1669+
StringRef Out = "-mrecip=";
1670+
1671+
Arg *A = Args.getLastArg(options::OPT_mrecip, options::OPT_mrecip_EQ);
1672+
if (!A)
1673+
return;
1674+
1675+
unsigned NumOptions = A->getNumValues();
1676+
if (NumOptions == 0) {
1677+
// No option is the same as "all".
1678+
OutStrings.push_back(Args.MakeArgString(Out + "all"));
1679+
return;
1680+
}
1681+
1682+
// Pass through "all", "none", or "default" with an optional refinement step.
1683+
if (NumOptions == 1) {
1684+
StringRef Val = A->getValue(0);
1685+
size_t RefStepLoc;
1686+
if (!getRefinementStep(Val, D, *A, RefStepLoc))
1687+
return;
1688+
StringRef ValBase = Val.slice(0, RefStepLoc);
1689+
if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
1690+
OutStrings.push_back(Args.MakeArgString(Out + Val));
1691+
return;
1692+
}
1693+
}
1694+
1695+
// Each reciprocal type may be enabled or disabled individually.
1696+
// Check each input value for validity, concatenate them all back together,
1697+
// and pass through.
1698+
1699+
llvm::StringMap<bool> OptionStrings;
1700+
OptionStrings.insert(std::make_pair("divd", false));
1701+
OptionStrings.insert(std::make_pair("divf", false));
1702+
OptionStrings.insert(std::make_pair("vec-divd", false));
1703+
OptionStrings.insert(std::make_pair("vec-divf", false));
1704+
OptionStrings.insert(std::make_pair("sqrtd", false));
1705+
OptionStrings.insert(std::make_pair("sqrtf", false));
1706+
OptionStrings.insert(std::make_pair("vec-sqrtd", false));
1707+
OptionStrings.insert(std::make_pair("vec-sqrtf", false));
1708+
1709+
for (unsigned i = 0; i != NumOptions; ++i) {
1710+
StringRef Val = A->getValue(i);
1711+
1712+
bool IsDisabled = Val[0] == DisabledPrefixIn;
1713+
// Ignore the disablement token for string matching.
1714+
if (IsDisabled)
1715+
Val = Val.substr(1);
1716+
1717+
size_t RefStep;
1718+
if (!getRefinementStep(Val, D, *A, RefStep))
1719+
return;
1720+
1721+
StringRef ValBase = Val.slice(0, RefStep);
1722+
llvm::StringMap<bool>::iterator OptionIter = OptionStrings.find(ValBase);
1723+
if (OptionIter == OptionStrings.end()) {
1724+
// Try again specifying float suffix.
1725+
OptionIter = OptionStrings.find(ValBase.str() + 'f');
1726+
if (OptionIter == OptionStrings.end()) {
1727+
// The input name did not match any known option string.
1728+
D.Diag(diag::err_drv_unknown_argument) << Val;
1729+
return;
1730+
}
1731+
// The option was specified without a float or double suffix.
1732+
// Make sure that the double entry was not already specified.
1733+
// The float entry will be checked below.
1734+
if (OptionStrings[ValBase.str() + 'd']) {
1735+
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
1736+
return;
1737+
}
1738+
}
1739+
1740+
if (OptionIter->second == true) {
1741+
// Duplicate option specified.
1742+
D.Diag(diag::err_drv_invalid_value) << A->getOption().getName() << Val;
1743+
return;
1744+
}
1745+
1746+
// Mark the matched option as found. Do not allow duplicate specifiers.
1747+
OptionIter->second = true;
1748+
1749+
// If the precision was not specified, also mark the double entry as found.
1750+
if (ValBase.back() != 'f' && ValBase.back() != 'd')
1751+
OptionStrings[ValBase.str() + 'd'] = true;
1752+
1753+
// Build the output string.
1754+
const char *Prefix = IsDisabled ?
1755+
&DisabledPrefixOut : &EnabledPrefixOut;
1756+
Out = Args.MakeArgString(Out + Prefix + Val);
1757+
if (i != NumOptions - 1)
1758+
Out = Args.MakeArgString(Out + ",");
1759+
}
1760+
1761+
OutStrings.push_back(Args.MakeArgString(Out));
1762+
}
1763+
16321764
static void getX86TargetFeatures(const Driver &D, const llvm::Triple &Triple,
16331765
const ArgList &Args,
16341766
std::vector<const char *> &Features) {
@@ -3142,6 +3274,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
31423274
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
31433275
}
31443276
}
3277+
3278+
ParseMRecip(getToolChain().getDriver(), Args, CmdArgs);
31453279

31463280
// We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
31473281
// and if we find them, tell the frontend to provide the appropriate

Diff for: ‎clang/lib/Frontend/CompilerInvocation.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -1846,7 +1846,7 @@ static void ParseTargetArgs(TargetOptions &Opts, ArgList &Args) {
18461846
Opts.FeaturesAsWritten = Args.getAllArgValues(OPT_target_feature);
18471847
Opts.LinkerVersion = Args.getLastArgValue(OPT_target_linker_version);
18481848
Opts.Triple = llvm::Triple::normalize(Args.getLastArgValue(OPT_triple));
1849-
1849+
Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
18501850
// Use the default target triple if unspecified.
18511851
if (Opts.Triple.empty())
18521852
Opts.Triple = llvm::sys::getDefaultTargetTriple();

Diff for: ‎clang/test/Driver/mrecip.c

+70
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
////
2+
//// Verify that valid options for the -mrecip flag are passed through and invalid options cause an error.
3+
////
4+
5+
//// If there are no options, convert to 'all'.
6+
7+
// RUN: %clang -### -S %s -mrecip 2>&1 | FileCheck --check-prefix=RECIP0 %s
8+
// RECIP0: "-mrecip=all"
9+
10+
//// Check options that cover all types.
11+
12+
// RUN: %clang -### -S %s -mrecip=all 2>&1 | FileCheck --check-prefix=RECIP1 %s
13+
// RECIP1: "-mrecip=all"
14+
15+
// RUN: %clang -### -S %s -mrecip=default 2>&1 | FileCheck --check-prefix=RECIP2 %s
16+
// RECIP2: "-mrecip=default"
17+
18+
// RUN: %clang -### -S %s -mrecip=none 2>&1 | FileCheck --check-prefix=RECIP3 %s
19+
// RECIP3: "-mrecip=none"
20+
21+
//// Check options that do not specify float or double.
22+
23+
// RUN: %clang -### -S %s -mrecip=vec-sqrt 2>&1 | FileCheck --check-prefix=RECIP4 %s
24+
// RECIP4: "-mrecip=vec-sqrt"
25+
26+
// RUN: %clang -### -S %s -mrecip=!div,vec-div 2>&1 | FileCheck --check-prefix=RECIP5 %s
27+
// RECIP5: "-mrecip=!div,vec-div"
28+
29+
//// Check individual option types.
30+
31+
// RUN: %clang -### -S %s -mrecip=vec-sqrtd 2>&1 | FileCheck --check-prefix=RECIP6 %s
32+
// RECIP6: "-mrecip=vec-sqrtd"
33+
34+
// RUN: %clang -### -S %s -mrecip=!divf 2>&1 | FileCheck --check-prefix=RECIP7 %s
35+
// RECIP7: "-mrecip=!divf"
36+
37+
// RUN: %clang -### -S %s -mrecip=divf,sqrtd,vec-divd,vec-sqrtf 2>&1 | FileCheck --check-prefix=RECIP8 %s
38+
// RECIP8: "-mrecip=divf,sqrtd,vec-divd,vec-sqrtf"
39+
40+
//// Check optional refinement step specifiers.
41+
42+
// RUN: %clang -### -S %s -mrecip=all:1 2>&1 | FileCheck --check-prefix=RECIP9 %s
43+
// RECIP9: "-mrecip=all:1"
44+
45+
// RUN: %clang -### -S %s -mrecip=sqrtf:3 2>&1 | FileCheck --check-prefix=RECIP10 %s
46+
// RECIP10: "-mrecip=sqrtf:3"
47+
48+
// RUN: %clang -### -S %s -mrecip=div:5 2>&1 | FileCheck --check-prefix=RECIP11 %s
49+
// RECIP11: "-mrecip=div:5"
50+
51+
// RUN: %clang -### -S %s -mrecip=divd:1,!sqrtf:2,vec-divf:9,vec-sqrtd:0 2>&1 | FileCheck --check-prefix=RECIP12 %s
52+
// RECIP12: "-mrecip=divd:1,!sqrtf:2,vec-divf:9,vec-sqrtd:0"
53+
54+
//// Check invalid parameters.
55+
56+
// RUN: %clang -### -S %s -mrecip=bogus 2>&1 | FileCheck --check-prefix=RECIP13 %s
57+
// RECIP13: error: unknown argument
58+
59+
// RUN: %clang -### -S %s -mrecip=divd:1,divd 2>&1 | FileCheck --check-prefix=RECIP14 %s
60+
// RECIP14: error: invalid value
61+
62+
// RUN: %clang -### -S %s -mrecip=sqrt,sqrtf 2>&1 | FileCheck --check-prefix=RECIP15 %s
63+
// RECIP15: error: invalid value
64+
65+
// RUN: %clang -### -S %s -mrecip=+default:10 2>&1 | FileCheck --check-prefix=RECIP16 %s
66+
// RECIP16: error: invalid value
67+
68+
// RUN: %clang -### -S %s -mrecip=!vec-divd: 2>&1 | FileCheck --check-prefix=RECIP17 %s
69+
// RECIP17: error: invalid value
70+

0 commit comments

Comments
 (0)
Please sign in to comment.