Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion clang/include/clang/Driver/CommonArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,9 +273,14 @@ void handleVectorizeSLPArgs(const llvm::opt::ArgList &Args,

// Parse -mprefer-vector-width=. Return the Value string if well-formed.
// Otherwise, return an empty string and issue a diagnosic message if needed.
StringRef ParseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
StringRef parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
const llvm::opt::ArgList &Args);

// Parse -mrecip. Return the Value string if well-formed.
// Otherwise, return an empty string and issue a diagnosic message if needed.
StringRef parseMRecipOption(clang::DiagnosticsEngine &Diags,
const llvm::opt::ArgList &Args);

} // end namespace tools
} // end namespace driver
} // end namespace clang
Expand Down
3 changes: 2 additions & 1 deletion clang/include/clang/Driver/Options.td
Original file line number Diff line number Diff line change
Expand Up @@ -5474,9 +5474,10 @@ def mno_implicit_float : Flag<["-"], "mno-implicit-float">, Group<m_Group>,
HelpText<"Don't generate implicit floating point or vector instructions">;
def mimplicit_float : Flag<["-"], "mimplicit-float">, Group<m_Group>;
def mrecip : Flag<["-"], "mrecip">, Group<m_Group>,
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
HelpText<"Equivalent to '-mrecip=all'">;
def mrecip_EQ : CommaJoined<["-"], "mrecip=">, Group<m_Group>,
Visibility<[ClangOption, CC1Option]>,
Visibility<[ClangOption, CC1Option, FlangOption, FC1Option]>,
HelpText<"Control use of approximate reciprocal and reciprocal square root instructions followed by <n> iterations of "
"Newton-Raphson refinement. "
"<value> = ( ['!'] ['vec-'] ('rcp'|'sqrt') [('h'|'s'|'d')] [':'<n>] ) | 'all' | 'default' | 'none'">,
Expand Down
145 changes: 4 additions & 141 deletions clang/lib/Driver/ToolChains/Clang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,145 +125,6 @@ forAllAssociatedToolChains(Compilation &C, const JobAction &JA,
//
}

/// 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(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) {
StringRef DisabledPrefixIn = "!";
StringRef DisabledPrefixOut = "!";
StringRef EnabledPrefixOut = "";
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("divh", false));
OptionStrings.insert(std::make_pair("vec-divd", false));
OptionStrings.insert(std::make_pair("vec-divf", false));
OptionStrings.insert(std::make_pair("vec-divh", false));
OptionStrings.insert(std::make_pair("sqrtd", false));
OptionStrings.insert(std::make_pair("sqrtf", false));
OptionStrings.insert(std::make_pair("sqrth", false));
OptionStrings.insert(std::make_pair("vec-sqrtd", false));
OptionStrings.insert(std::make_pair("vec-sqrtf", false));
OptionStrings.insert(std::make_pair("vec-sqrth", false));

for (unsigned i = 0; i != NumOptions; ++i) {
StringRef Val = A->getValue(i);

bool IsDisabled = Val.starts_with(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 half or float or double suffix.
// Make sure that the double or half entry was not already specified.
// The float entry will be checked below.
if (OptionStrings[ValBase.str() + 'd'] ||
OptionStrings[ValBase.str() + 'h']) {
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 and half entry
// as found.
if (ValBase.back() != 'f' && ValBase.back() != 'd' && ValBase.back() != 'h') {
OptionStrings[ValBase.str() + 'd'] = true;
OptionStrings[ValBase.str() + 'h'] = true;
}

// Build the output string.
StringRef 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 bool
shouldUseExceptionTablesForObjCExceptions(const ObjCRuntime &runtime,
const llvm::Triple &Triple) {
Expand Down Expand Up @@ -3490,7 +3351,9 @@ static void RenderFloatingPointOptions(const ToolChain &TC, const Driver &D,
CmdArgs.push_back(Args.MakeArgString("-fbfloat16-excess-precision=" +
BFloat16ExcessPrecision));

ParseMRecip(D, Args, CmdArgs);
StringRef Recip = parseMRecipOption(D.getDiags(), Args);
if (!Recip.empty())
CmdArgs.push_back(Args.MakeArgString("-mrecip=" + Recip));

// -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
// individual features enabled by -ffast-math instead of the option itself as
Expand Down Expand Up @@ -7587,7 +7450,7 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
handleVectorizeLoopsArgs(Args, CmdArgs);
handleVectorizeSLPArgs(Args, CmdArgs);

StringRef VecWidth = ParseMPreferVectorWidthOption(D.getDiags(), Args);
StringRef VecWidth = parseMPreferVectorWidthOption(D.getDiags(), Args);
if (!VecWidth.empty())
CmdArgs.push_back(Args.MakeArgString("-mprefer-vector-width=" + VecWidth));

Expand Down
143 changes: 142 additions & 1 deletion clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3170,7 +3170,7 @@ void tools::handleInterchangeLoopsArgs(const ArgList &Args,

// Parse -mprefer-vector-width=. Return the Value string if well-formed.
// Otherwise, return an empty string and issue a diagnosic message if needed.
StringRef tools::ParseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
StringRef tools::parseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,
const llvm::opt::ArgList &Args) {
Arg *A = Args.getLastArg(clang::driver::options::OPT_mprefer_vector_width_EQ);
if (!A)
Expand All @@ -3189,3 +3189,144 @@ StringRef tools::ParseMPreferVectorWidthOption(clang::DiagnosticsEngine &Diags,

return Value;
}

// 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(StringRef In, clang::DiagnosticsEngine &Diags,
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) {
Diags.Report(diag::err_drv_invalid_value) << Option << RefStep;
return false;
}
char RefStepChar = RefStep[0];
if (RefStepChar < '0' || RefStepChar > '9') {
Diags.Report(diag::err_drv_invalid_value) << Option << RefStep;
return false;
}
}
return true;
}

// Parse -mrecip. Return the Value string if well-formed.
// Otherwise, return an empty string and issue a diagnosic message if needed.
StringRef tools::parseMRecipOption(clang::DiagnosticsEngine &Diags,
const ArgList &Args) {
StringRef DisabledPrefixIn = "!";
StringRef DisabledPrefixOut = "!";
StringRef EnabledPrefixOut = "";
StringRef Out = "";

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".
return "all";
}

// 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, Diags, *A, RefStepLoc))
return "";
StringRef ValBase = Val.slice(0, RefStepLoc);
if (ValBase == "all" || ValBase == "none" || ValBase == "default") {
return Val;
}
}

// 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("divh", false));
OptionStrings.insert(std::make_pair("vec-divd", false));
OptionStrings.insert(std::make_pair("vec-divf", false));
OptionStrings.insert(std::make_pair("vec-divh", false));
OptionStrings.insert(std::make_pair("sqrtd", false));
OptionStrings.insert(std::make_pair("sqrtf", false));
OptionStrings.insert(std::make_pair("sqrth", false));
OptionStrings.insert(std::make_pair("vec-sqrtd", false));
OptionStrings.insert(std::make_pair("vec-sqrtf", false));
OptionStrings.insert(std::make_pair("vec-sqrth", false));

for (unsigned i = 0; i != NumOptions; ++i) {
StringRef Val = A->getValue(i);

bool IsDisabled = Val.starts_with(DisabledPrefixIn);
// Ignore the disablement token for string matching.
if (IsDisabled)
Val = Val.substr(1);

size_t RefStep;
if (!getRefinementStep(Val, Diags, *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.
Diags.Report(diag::err_drv_unknown_argument) << Val;
return "";
}
// The option was specified without a half or float or double suffix.
// Make sure that the double or half entry was not already specified.
// The float entry will be checked below.
if (OptionStrings[ValBase.str() + 'd'] ||
OptionStrings[ValBase.str() + 'h']) {
Diags.Report(diag::err_drv_invalid_value)
<< A->getOption().getName() << Val;
return "";
}
}

if (OptionIter->second == true) {
// Duplicate option specified.
Diags.Report(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 and half entry
// as found.
if (ValBase.back() != 'f' && ValBase.back() != 'd' &&
ValBase.back() != 'h') {
OptionStrings[ValBase.str() + 'd'] = true;
OptionStrings[ValBase.str() + 'h'] = true;
}

// Build the output string.
StringRef Prefix = IsDisabled ? DisabledPrefixOut : EnabledPrefixOut;
Out = Args.MakeArgString(Out + Prefix + Val);
if (i != NumOptions - 1)
Out = Args.MakeArgString(Out + ",");
}

return Out;
}
4 changes: 4 additions & 0 deletions clang/lib/Driver/ToolChains/Flang.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,10 @@ static void addFloatingPointOptions(const Driver &D, const ArgList &Args,
A->claim();
}

StringRef Recip = parseMRecipOption(D.getDiags(), Args);
if (!Recip.empty())
CmdArgs.push_back(Args.MakeArgString("-mrecip=" + Recip));

if (!HonorINFs && !HonorNaNs && AssociativeMath && ReciprocalMath &&
ApproxFunc && !SignedZeros &&
(FPContract == "fast" || FPContract.empty())) {
Expand Down
5 changes: 4 additions & 1 deletion flang/include/flang/Frontend/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,9 +53,12 @@ class CodeGenOptions : public CodeGenOptionsBase {
/// The paths to the pass plugins that were registered using -fpass-plugin.
std::vector<std::string> LLVMPassPlugins;

// The prefered vector width, if requested by -mprefer-vector-width.
/// The prefered vector width, if requested by -mprefer-vector-width.
std::string PreferVectorWidth;

/// List of reciprocal estimate sub-options.
std::string Reciprocals;

/// List of filenames passed in using the -fembed-offload-object option. These
/// are offloading binaries containing device images and metadata.
std::vector<std::string> OffloadObjects;
Expand Down
3 changes: 3 additions & 0 deletions flang/include/flang/Optimizer/Transforms/Passes.td
Original file line number Diff line number Diff line change
Expand Up @@ -429,6 +429,9 @@ def FunctionAttr : Pass<"function-attr", "mlir::func::FuncOp"> {
"module.">,
Option<"unsafeFPMath", "unsafe-fp-math", "bool", /*default=*/"false",
"Set the unsafe-fp-math attribute on functions in the module.">,
Option<"reciprocals", "mrecip", "std::string", /*default=*/"",
"Set the reciprocal-estimates attribute on functions in the "
"module.">,
Option<"preferVectorWidth", "prefer-vector-width", "std::string",
/*default=*/"",
"Set the prefer-vector-width attribute on functions in the "
Expand Down
3 changes: 3 additions & 0 deletions flang/include/flang/Tools/CrossToolHelpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
UnsafeFPMath = mathOpts.getAssociativeMath() &&
mathOpts.getReciprocalMath() && NoSignedZerosFPMath &&
ApproxFuncFPMath && mathOpts.getFPContractEnabled();
Reciprocals = opts.Reciprocals;
PreferVectorWidth = opts.PreferVectorWidth;
if (opts.InstrumentFunctions) {
InstrumentFunctionEntry = "__cyg_profile_func_enter";
Expand All @@ -127,6 +128,8 @@ struct MLIRToLLVMPassPipelineConfig : public FlangEPCallBacks {
bool NoSignedZerosFPMath =
false; ///< Set no-signed-zeros-fp-math attribute for functions.
bool UnsafeFPMath = false; ///< Set unsafe-fp-math attribute for functions.
std::string Reciprocals = ""; ///< Set reciprocal-estimate attribute for
///< functions.
std::string PreferVectorWidth = ""; ///< Set prefer-vector-width attribute for
///< functions.
bool NSWOnLoopVarInc = true; ///< Add nsw flag to loop variable increments.
Expand Down
Loading