@@ -1629,6 +1629,138 @@ static void AddGoldPlugin(const ToolChain &ToolChain, const ArgList &Args,
1629
1629
CmdArgs.push_back (Args.MakeArgString (Twine (" -plugin-opt=mcpu=" ) + CPU));
1630
1630
}
1631
1631
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
+
1632
1764
static void getX86TargetFeatures (const Driver &D, const llvm::Triple &Triple,
1633
1765
const ArgList &Args,
1634
1766
std::vector<const char *> &Features) {
@@ -3142,6 +3274,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
3142
3274
CmdArgs.push_back (Args.MakeArgString (" -ffp-contract=fast" ));
3143
3275
}
3144
3276
}
3277
+
3278
+ ParseMRecip (getToolChain ().getDriver (), Args, CmdArgs);
3145
3279
3146
3280
// We separately look for the '-ffast-math' and '-ffinite-math-only' flags,
3147
3281
// and if we find them, tell the frontend to provide the appropriate
0 commit comments