Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
5 changes: 5 additions & 0 deletions clang/include/clang/Driver/CommonArgs.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,11 @@ void handleVectorizeSLPArgs(const llvm::opt::ArgList &Args,
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
143 changes: 3 additions & 140 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
141 changes: 141 additions & 0 deletions clang/lib/Driver/ToolChains/CommonArgs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Most functions defined/moved to this file are named with a lowercase starting letter. It might be worth doing the same for this (and I did miss this in prefer-vector-width implementation earlier)

Suggested change
StringRef tools::ParseMRecipOption(clang::DiagnosticsEngine &Diags,
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;
}
3 changes: 3 additions & 0 deletions flang/include/flang/Frontend/CodeGenOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class CodeGenOptions : public CodeGenOptionsBase {
// The prefered vector width, if requested by -mprefer-vector-width.
std::string PreferVectorWidth;

// List of reciprocal estimate sub-options.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a documentation comment?

Suggested change
// List of reciprocal estimate sub-options.
/// 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
2 changes: 2 additions & 0 deletions flang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -310,6 +310,8 @@ static void parseCodeGenArgs(Fortran::frontend::CodeGenOptions &opts,
for (auto *a : args.filtered(clang::driver::options::OPT_fpass_plugin_EQ))
opts.LLVMPassPlugins.push_back(a->getValue());

opts.Reciprocals = clang::driver::tools::ParseMRecipOption(diags, args);

opts.PreferVectorWidth =
clang::driver::tools::ParseMPreferVectorWidthOption(diags, args);

Expand Down
1 change: 1 addition & 0 deletions flang/lib/Frontend/FrontendActions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -741,6 +741,7 @@ void CodeGenAction::generateLLVMIR() {
config.VScaleMax = vsr->second;
}

config.Reciprocals = opts.Reciprocals;
config.PreferVectorWidth = opts.PreferVectorWidth;

if (ci.getInvocation().getFrontendOpts().features.IsEnabled(
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Optimizer/Passes/Pipelines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -369,7 +369,8 @@ void createDefaultFIRCodeGenPassPipeline(mlir::PassManager &pm,
{framePointerKind, config.InstrumentFunctionEntry,
config.InstrumentFunctionExit, config.NoInfsFPMath, config.NoNaNsFPMath,
config.ApproxFuncFPMath, config.NoSignedZerosFPMath, config.UnsafeFPMath,
config.PreferVectorWidth, /*tuneCPU=*/"", setNoCapture, setNoAlias}));
config.Reciprocals, config.PreferVectorWidth, /*tuneCPU=*/"",
setNoCapture, setNoAlias}));

if (config.EnableOpenMP) {
pm.addNestedPass<mlir::func::FuncOp>(
Expand Down
Loading
Loading