Author: Jan Svoboda
Date: 2020-11-09T18:00:10-05:00
New Revision: dbfa69c5024cfe58b8029a3766ec46c857cddb1e

URL: 
https://github.com/llvm/llvm-project/commit/dbfa69c5024cfe58b8029a3766ec46c857cddb1e
DIFF: 
https://github.com/llvm/llvm-project/commit/dbfa69c5024cfe58b8029a3766ec46c857cddb1e.diff

LOG: Port some floating point options to new option marshalling infrastructure

This ports a number of OpenCL and fast-math flags for floating point
over to the new marshalling infrastructure.

As part of this, `Opt{In,Out}FFlag` were enhanced to allow other flags to
imply them, via `DefaultAnyOf<>`. For example:
```
defm signed_zeros : OptOutFFlag<"signed-zeros", ...,
  "LangOpts->NoSignedZero",
  DefaultAnyOf<[cl_no_signed_zeros, menable_unsafe_fp_math]>>;
```
defines `-fsigned-zeros` (`false`) and `-fno-signed-zeros` (`true`)
linked to the keypath `LangOpts->NoSignedZero`, defaulting to `false`,
but set to `true` implicitly if one of `-cl-no-signed-zeros` or
`-menable-unsafe-fp-math` is on.

Note that the initial patch was written Daniel Grumberg.

Differential Revision: https://reviews.llvm.org/D82756

Added: 
    llvm/unittests/Option/OptionMarshallingTest.cpp

Modified: 
    clang/include/clang/Basic/LangOptions.def
    clang/include/clang/Driver/Options.td
    clang/lib/Frontend/CompilerInvocation.cpp
    clang/unittests/Frontend/CompilerInvocationTest.cpp
    llvm/include/llvm/Option/OptParser.td
    llvm/unittests/Option/CMakeLists.txt
    llvm/unittests/Option/Opts.td
    llvm/utils/TableGen/OptParserEmitter.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/LangOptions.def 
b/clang/include/clang/Basic/LangOptions.def
index 1d203f8489eb..3788ae87f6b9 100644
--- a/clang/include/clang/Basic/LangOptions.def
+++ b/clang/include/clang/Basic/LangOptions.def
@@ -274,6 +274,9 @@ BENIGN_LANGOPT(DebuggerObjCLiteral , 1, 0, "debugger 
Objective-C literals and su
 BENIGN_LANGOPT(SpellChecking , 1, 1, "spell-checking")
 LANGOPT(SinglePrecisionConstants , 1, 0, "treating double-precision floating 
point constants as single precision constants")
 LANGOPT(FastRelaxedMath , 1, 0, "OpenCL fast relaxed math")
+BENIGN_LANGOPT(CLNoSignedZero , 1, 0, "Permit Floating Point optimization 
without regard to signed zeros")
+COMPATIBLE_LANGOPT(CLUnsafeMath , 1, 0, "Unsafe Floating Point Math")
+COMPATIBLE_LANGOPT(CLFiniteMathOnly , 1, 0, "__FINITE_MATH_ONLY__ predefined 
macro")
 /// FP_CONTRACT mode (on/off/fast).
 BENIGN_ENUM_LANGOPT(DefaultFPContractMode, FPModeKind, 2, FPM_Off, "FP 
contraction type")
 COMPATIBLE_LANGOPT(ExpStrictFP, 1, false, "Enable experimental strict floating 
point")

diff  --git a/clang/include/clang/Driver/Options.td 
b/clang/include/clang/Driver/Options.td
index 33cfa72c0888..e13946f98ea4 100644
--- a/clang/include/clang/Driver/Options.td
+++ b/clang/include/clang/Driver/Options.td
@@ -245,9 +245,11 @@ def clang_ignored_gcc_optimization_f_Group : OptionGroup<
 // Args.hasArg(OPT_ffoo) is used to check that the flag is enabled.
 // This is useful if the option is usually disabled.
 multiclass OptInFFlag<string name, string pos_prefix, string neg_prefix="",
-                      string help="", list<OptionFlag> flags=[]> {
+                      string help="", list<OptionFlag> flags=[], code 
keypath="",
+                      DefaultAnyOf defaults = DefaultAnyOf<[]>> {
   def f#NAME : Flag<["-"], "f"#name>, Flags<!listconcat([CC1Option], flags)>,
-               Group<f_Group>, HelpText<!strconcat(pos_prefix, help)>;
+               Group<f_Group>, HelpText<!strconcat(pos_prefix, help)>,
+               MarshallingInfoFlag<keypath, defaults>;
   def fno_#NAME : Flag<["-"], "fno-"#name>, Flags<flags>,
                Group<f_Group>, HelpText<!strconcat(neg_prefix, help)>;
 }
@@ -255,11 +257,13 @@ multiclass OptInFFlag<string name, string pos_prefix, 
string neg_prefix="",
 // A boolean option which is opt-out in CC1. The negative option exists in CC1 
and
 // Args.hasArg(OPT_fno_foo) is used to check that the flag is disabled.
 multiclass OptOutFFlag<string name, string pos_prefix, string neg_prefix,
-                       string help="", list<OptionFlag> flags=[]> {
+                       string help="", list<OptionFlag> flags=[], code 
keypath="",
+                       DefaultAnyOf defaults = DefaultAnyOf<[]>> {
   def f#NAME : Flag<["-"], "f"#name>, Flags<flags>,
                Group<f_Group>, HelpText<!strconcat(pos_prefix, help)>;
   def fno_#NAME : Flag<["-"], "fno-"#name>, Flags<!listconcat([CC1Option], 
flags)>,
-               Group<f_Group>, HelpText<!strconcat(neg_prefix, help)>;
+               Group<f_Group>, HelpText<!strconcat(neg_prefix, help)>,
+               MarshallingInfoFlag<keypath, defaults>;
 }
 
 /////////
@@ -563,27 +567,36 @@ def cl_opt_disable : Flag<["-"], "cl-opt-disable">, 
Group<opencl_Group>, Flags<[
 def cl_strict_aliasing : Flag<["-"], "cl-strict-aliasing">, 
Group<opencl_Group>, Flags<[CC1Option]>,
   HelpText<"OpenCL only. This option is added for compatibility with OpenCL 
1.0.">;
 def cl_single_precision_constant : Flag<["-"], 
"cl-single-precision-constant">, Group<opencl_Group>, Flags<[CC1Option]>,
-  HelpText<"OpenCL only. Treat double precision floating-point constant as 
single precision constant.">;
+  HelpText<"OpenCL only. Treat double precision floating-point constant as 
single precision constant.">,
+  MarshallingInfoFlag<"LangOpts->SinglePrecisionConstants">;
 def cl_finite_math_only : Flag<["-"], "cl-finite-math-only">, 
Group<opencl_Group>, Flags<[CC1Option]>,
-  HelpText<"OpenCL only. Allow floating-point optimizations that assume 
arguments and results are not NaNs or +-Inf.">;
+  HelpText<"OpenCL only. Allow floating-point optimizations that assume 
arguments and results are not NaNs or +-Inf.">,
+  MarshallingInfoFlag<"LangOpts->CLFiniteMathOnly">;
 def cl_kernel_arg_info : Flag<["-"], "cl-kernel-arg-info">, 
Group<opencl_Group>, Flags<[CC1Option]>,
-  HelpText<"OpenCL only. Generate kernel argument metadata.">;
+  HelpText<"OpenCL only. Generate kernel argument metadata.">,
+  MarshallingInfoFlag<"CodeGenOpts.EmitOpenCLArgMetadata">;
 def cl_unsafe_math_optimizations : Flag<["-"], 
"cl-unsafe-math-optimizations">, Group<opencl_Group>, Flags<[CC1Option]>,
-  HelpText<"OpenCL only. Allow unsafe floating-point optimizations.  Also 
implies -cl-no-signed-zeros and -cl-mad-enable.">;
+  HelpText<"OpenCL only. Allow unsafe floating-point optimizations.  Also 
implies -cl-no-signed-zeros and -cl-mad-enable.">,
+  MarshallingInfoFlag<"LangOpts->CLUnsafeMath">;
 def cl_fast_relaxed_math : Flag<["-"], "cl-fast-relaxed-math">, 
Group<opencl_Group>, Flags<[CC1Option]>,
-  HelpText<"OpenCL only. Sets -cl-finite-math-only and 
-cl-unsafe-math-optimizations, and defines __FAST_RELAXED_MATH__.">;
+  HelpText<"OpenCL only. Sets -cl-finite-math-only and 
-cl-unsafe-math-optimizations, and defines __FAST_RELAXED_MATH__.">,
+  MarshallingInfoFlag<"LangOpts->FastRelaxedMath">;
 def cl_mad_enable : Flag<["-"], "cl-mad-enable">, Group<opencl_Group>, 
Flags<[CC1Option]>,
-  HelpText<"OpenCL only. Allow use of less precise MAD computations in the 
generated binary.">;
+  HelpText<"OpenCL only. Allow use of less precise MAD computations in the 
generated binary.">,
+  MarshallingInfoFlag<"CodeGenOpts.LessPreciseFPMAD", 
DefaultAnyOf<[cl_unsafe_math_optimizations, cl_fast_relaxed_math]>>;
 def cl_no_signed_zeros : Flag<["-"], "cl-no-signed-zeros">, 
Group<opencl_Group>, Flags<[CC1Option]>,
-  HelpText<"OpenCL only. Allow use of less precise no signed zeros 
computations in the generated binary.">;
+  HelpText<"OpenCL only. Allow use of less precise no signed zeros 
computations in the generated binary.">,
+  MarshallingInfoFlag<"LangOpts->CLNoSignedZero">;
 def cl_std_EQ : Joined<["-"], "cl-std=">, Group<opencl_Group>, 
Flags<[CC1Option]>,
   HelpText<"OpenCL language standard to compile for.">, 
Values<"cl,CL,cl1.1,CL1.1,cl1.2,CL1.2,cl2.0,CL2.0,cl3.0,CL3.0,clc++,CLC++">;
 def cl_denorms_are_zero : Flag<["-"], "cl-denorms-are-zero">, 
Group<opencl_Group>,
   HelpText<"OpenCL only. Allow denormals to be flushed to zero.">;
 def cl_fp32_correctly_rounded_divide_sqrt : Flag<["-"], 
"cl-fp32-correctly-rounded-divide-sqrt">, Group<opencl_Group>, 
Flags<[CC1Option]>,
-  HelpText<"OpenCL only. Specify that single precision floating-point divide 
and sqrt used in the program source are correctly rounded.">;
+  HelpText<"OpenCL only. Specify that single precision floating-point divide 
and sqrt used in the program source are correctly rounded.">,
+  MarshallingInfoFlag<"CodeGenOpts.CorrectlyRoundedDivSqrt">;
 def cl_uniform_work_group_size : Flag<["-"], "cl-uniform-work-group-size">, 
Group<opencl_Group>, Flags<[CC1Option]>,
-  HelpText<"OpenCL only. Defines that the global work-size be a multiple of 
the work-group size specified to clEnqueueNDRangeKernel">;
+  HelpText<"OpenCL only. Defines that the global work-size be a multiple of 
the work-group size specified to clEnqueueNDRangeKernel">,
+  MarshallingInfoFlag<"CodeGenOpts.UniformWGSize">;
 def client__name : JoinedOrSeparate<["-"], "client_name">;
 def combine : Flag<["-", "--"], "combine">, Flags<[NoXarchOption, 
Unsupported]>;
 def compatibility__version : JoinedOrSeparate<["-"], "compatibility_version">;
@@ -890,7 +903,7 @@ def fdiagnostics_color : Flag<["-"], "fdiagnostics-color">, 
Group<f_Group>,
 def fdiagnostics_color_EQ : Joined<["-"], "fdiagnostics-color=">, 
Group<f_Group>;
 def fansi_escape_codes : Flag<["-"], "fansi-escape-codes">, Group<f_Group>,
   Flags<[CoreOption, CC1Option]>, HelpText<"Use ANSI escape codes for 
diagnostics">,
-  MarshallingInfoFlag<"DiagnosticOpts->UseANSIEscapeCodes", "false">;
+  MarshallingInfoFlag<"DiagnosticOpts->UseANSIEscapeCodes">;
 def fcomment_block_commands : CommaJoined<["-"], "fcomment-block-commands=">, 
Group<f_clang_Group>, Flags<[CC1Option]>,
   HelpText<"Treat each comma separated argument in <arg> as a documentation 
comment block command">,
   MetaVarName<"<arg>">;
@@ -1002,7 +1015,11 @@ def ffp_model_EQ : Joined<["-"], "ffp-model=">, 
Group<f_Group>, Flags<[NoXarchOp
   HelpText<"Controls the semantics of floating-point calculations.">;
 def ffp_exception_behavior_EQ : Joined<["-"], "ffp-exception-behavior=">, 
Group<f_Group>, Flags<[CC1Option]>,
   HelpText<"Specifies the exception behavior of floating-point operations.">;
-defm fast_math : OptInFFlag<"fast-math", "Allow aggressive, lossy 
floating-point optimizations">;
+defm fast_math : OptInFFlag<"fast-math", "Allow aggressive, lossy 
floating-point optimizations", "", "", [],
+  "LangOpts->FastMath", DefaultAnyOf<[cl_fast_relaxed_math]>>;
+def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">, 
Flags<[CC1Option]>,
+  HelpText<"Allow unsafe floating-point math optimizations which may decrease 
precision">,
+  MarshallingInfoFlag<"LangOpts->UnsafeFPMath", 
DefaultAnyOf<[cl_unsafe_math_optimizations, ffast_math]>>;
 defm math_errno : OptInFFlag<"math-errno", "Require math functions to indicate 
errors by setting errno">;
 def fbracket_depth_EQ : Joined<["-"], "fbracket-depth=">, Group<f_Group>, 
Flags<[CoreOption]>;
 def fsignaling_math : Flag<["-"], "fsignaling-math">, Group<f_Group>;
@@ -1215,16 +1232,14 @@ def fno_unsafe_math_optimizations : Flag<["-"], 
"fno-unsafe-math-optimizations">
   Group<f_Group>;
 def fassociative_math : Flag<["-"], "fassociative-math">, Group<f_Group>;
 def fno_associative_math : Flag<["-"], "fno-associative-math">, Group<f_Group>;
-def freciprocal_math :
-  Flag<["-"], "freciprocal-math">, Group<f_Group>, Flags<[CC1Option]>,
-  HelpText<"Allow division operations to be reassociated">;
-def fno_reciprocal_math : Flag<["-"], "fno-reciprocal-math">, Group<f_Group>;
-def ffinite_math_only : Flag<["-"], "ffinite-math-only">, Group<f_Group>, 
Flags<[CC1Option]>;
-def fno_finite_math_only : Flag<["-"], "fno-finite-math-only">, Group<f_Group>;
-def fsigned_zeros : Flag<["-"], "fsigned-zeros">, Group<f_Group>;
-def fno_signed_zeros :
-  Flag<["-"], "fno-signed-zeros">, Group<f_Group>, Flags<[CC1Option]>,
-  HelpText<"Allow optimizations that ignore the sign of floating point zeros">;
+defm reciprocal_math : OptInFFlag<"reciprocal-math", "Allow division 
operations to be reassociated", "", "", [],
+  "LangOpts->AllowRecip", DefaultAnyOf<[menable_unsafe_fp_math]>>;
+def fapprox_func : Flag<["-"], "fapprox-func">, Group<f_Group>, 
Flags<[CC1Option, NoDriverOption]>,
+  MarshallingInfoFlag<"LangOpts->ApproxFunc", 
DefaultAnyOf<[menable_unsafe_fp_math]>>;
+defm finite_math_only : OptInFFlag<"finite-math-only", "", "", "", [],
+  "LangOpts->FiniteMathOnly", DefaultAnyOf<[cl_finite_math_only, ffast_math]>>;
+defm signed_zeros : OptOutFFlag<"signed-zeros", "Allow optimizations that 
ignore the sign of floating point zeros", "", "", [],
+  "LangOpts->NoSignedZero", DefaultAnyOf<[cl_no_signed_zeros, 
menable_unsafe_fp_math]>>;
 def fhonor_nans : Flag<["-"], "fhonor-nans">, Group<f_Group>;
 def fno_honor_nans : Flag<["-"], "fno-honor-nans">, Group<f_Group>;
 def fhonor_infinities : Flag<["-"], "fhonor-infinities">, Group<f_Group>;
@@ -3847,14 +3862,14 @@ def mframe_pointer_EQ : Joined<["-"], 
"mframe-pointer=">,
 def mdisable_tail_calls : Flag<["-"], "mdisable-tail-calls">,
   HelpText<"Disable tail call optimization, keeping the call stack accurate">;
 def menable_no_infinities : Flag<["-"], "menable-no-infs">,
-  HelpText<"Allow optimization to assume there are no infinities.">;
+  HelpText<"Allow optimization to assume there are no infinities.">,
+  MarshallingInfoFlag<"LangOpts->NoHonorInfs", 
DefaultAnyOf<[ffinite_math_only]>>;
 def menable_no_nans : Flag<["-"], "menable-no-nans">,
-  HelpText<"Allow optimization to assume there are no NaNs.">;
-def menable_unsafe_fp_math : Flag<["-"], "menable-unsafe-fp-math">,
-  HelpText<"Allow unsafe floating-point math optimizations which may decrease "
-           "precision">;
+  HelpText<"Allow optimization to assume there are no NaNs.">,
+  MarshallingInfoFlag<"LangOpts->NoHonorNaNs", 
DefaultAnyOf<[ffinite_math_only]>>;
 def mreassociate : Flag<["-"], "mreassociate">,
-  HelpText<"Allow reassociation transformations for floating-point 
instructions">;
+  HelpText<"Allow reassociation transformations for floating-point 
instructions">,
+  MarshallingInfoFlag<"LangOpts->AllowFPReassoc", 
DefaultAnyOf<[menable_unsafe_fp_math]>>;
 def mabi_EQ_ieeelongdouble : Flag<["-"], "mabi=ieeelongdouble">,
   HelpText<"Use IEEE 754 quadruple-precision for long double">;
 def mfloat_abi : Separate<["-"], "mfloat-abi">,
@@ -4405,7 +4420,7 @@ def fmodules_hash_content : Flag<["-"], 
"fmodules-hash-content">,
 def fmodules_strict_context_hash : Flag<["-"], "fmodules-strict-context-hash">,
   HelpText<"Enable hashing of all compiler options that could impact the "
            "semantics of a module in an implicit build">,
-  MarshallingInfoFlag<"HeaderSearchOpts->ModulesStrictContextHash", "false">;
+  MarshallingInfoFlag<"HeaderSearchOpts->ModulesStrictContextHash">;
 def c_isystem : JoinedOrSeparate<["-"], "c-isystem">, 
MetaVarName<"<directory>">,
   HelpText<"Add directory to the C SYSTEM include search path">;
 def objc_isystem : JoinedOrSeparate<["-"], "objc-isystem">,

diff  --git a/clang/lib/Frontend/CompilerInvocation.cpp 
b/clang/lib/Frontend/CompilerInvocation.cpp
index 7b8554c0fe49..d2c4482972b0 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -941,15 +941,8 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, ArgList 
&Args, InputKind IK,
   Opts.NoEscapingBlockTailCalls =
       Args.hasArg(OPT_fno_escaping_block_tail_calls);
   Opts.FloatABI = std::string(Args.getLastArgValue(OPT_mfloat_abi));
-  Opts.LessPreciseFPMAD = Args.hasArg(OPT_cl_mad_enable) ||
-                          Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
-                          Args.hasArg(OPT_cl_fast_relaxed_math);
   Opts.LimitFloatPrecision =
       std::string(Args.getLastArgValue(OPT_mlimit_float_precision));
-  Opts.CorrectlyRoundedDivSqrt =
-      Args.hasArg(OPT_cl_fp32_correctly_rounded_divide_sqrt);
-  Opts.UniformWGSize =
-      Args.hasArg(OPT_cl_uniform_work_group_size);
   Opts.Reciprocals = Args.getAllArgValues(OPT_mrecip_EQ);
   Opts.StrictFloatCastOverflow =
       !Args.hasArg(OPT_fno_strict_float_cast_overflow);
@@ -1161,7 +1154,6 @@ static bool ParseCodeGenArgs(CodeGenOptions &Opts, 
ArgList &Args, InputKind IK,
   Opts.MNopMCount = Args.hasArg(OPT_mnop_mcount);
   Opts.RecordMCount = Args.hasArg(OPT_mrecord_mcount);
   Opts.PackedStack = Args.hasArg(OPT_mpacked_stack);
-  Opts.EmitOpenCLArgMetadata = Args.hasArg(OPT_cl_kernel_arg_info);
 
   if (const Arg *A = Args.getLastArg(OPT_fcf_protection_EQ)) {
     StringRef Name = A->getValue();
@@ -3061,8 +3053,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList 
&Args, InputKind IK,
   Opts.DumpVTableLayouts = Args.hasArg(OPT_fdump_vtable_layouts);
   Opts.SpellChecking = !Args.hasArg(OPT_fno_spell_checking);
   Opts.NoBitFieldTypeAlign = Args.hasArg(OPT_fno_bitfield_type_align);
-  Opts.SinglePrecisionConstants = 
Args.hasArg(OPT_cl_single_precision_constant);
-  Opts.FastRelaxedMath = Args.hasArg(OPT_cl_fast_relaxed_math);
   if (Opts.FastRelaxedMath)
     Opts.setDefaultFPContractMode(LangOptions::FPM_Fast);
   Opts.HexagonQdsp6Compat = Args.hasArg(OPT_mqdsp6_compat);
@@ -3330,47 +3320,6 @@ static void ParseLangArgs(LangOptions &Opts, ArgList 
&Args, InputKind IK,
     if (InlineArg->getOption().matches(options::OPT_fno_inline))
       Opts.NoInlineDefine = true;
 
-  Opts.FastMath =
-      Args.hasArg(OPT_ffast_math) || Args.hasArg(OPT_cl_fast_relaxed_math);
-  Opts.FiniteMathOnly = Args.hasArg(OPT_ffinite_math_only) ||
-                        Args.hasArg(OPT_ffast_math) ||
-                        Args.hasArg(OPT_cl_finite_math_only) ||
-                        Args.hasArg(OPT_cl_fast_relaxed_math);
-  Opts.UnsafeFPMath = Args.hasArg(OPT_menable_unsafe_fp_math) ||
-                      Args.hasArg(OPT_ffast_math) ||
-                      Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
-                      Args.hasArg(OPT_cl_fast_relaxed_math);
-  Opts.AllowFPReassoc = Args.hasArg(OPT_mreassociate) ||
-                        Args.hasArg(OPT_menable_unsafe_fp_math) ||
-                        Args.hasArg(OPT_ffast_math) ||
-                        Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
-                        Args.hasArg(OPT_cl_fast_relaxed_math);
-  Opts.NoHonorNaNs =
-      Args.hasArg(OPT_menable_no_nans) || Args.hasArg(OPT_ffinite_math_only) ||
-      Args.hasArg(OPT_ffast_math) || Args.hasArg(OPT_cl_finite_math_only) ||
-      Args.hasArg(OPT_cl_fast_relaxed_math);
-  Opts.NoHonorInfs = Args.hasArg(OPT_menable_no_infinities) ||
-                     Args.hasArg(OPT_ffinite_math_only) ||
-                     Args.hasArg(OPT_ffast_math) ||
-                     Args.hasArg(OPT_cl_finite_math_only) ||
-                     Args.hasArg(OPT_cl_fast_relaxed_math);
-  Opts.NoSignedZero = Args.hasArg(OPT_fno_signed_zeros) ||
-                      Args.hasArg(OPT_menable_unsafe_fp_math) ||
-                      Args.hasArg(OPT_ffast_math) ||
-                      Args.hasArg(OPT_cl_no_signed_zeros) ||
-                      Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
-                      Args.hasArg(OPT_cl_fast_relaxed_math);
-  Opts.AllowRecip = Args.hasArg(OPT_freciprocal_math) ||
-                    Args.hasArg(OPT_menable_unsafe_fp_math) ||
-                    Args.hasArg(OPT_ffast_math) ||
-                    Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
-                    Args.hasArg(OPT_cl_fast_relaxed_math);
-  // Currently there's no clang option to enable this individually
-  Opts.ApproxFunc = Args.hasArg(OPT_menable_unsafe_fp_math) ||
-                    Args.hasArg(OPT_ffast_math) ||
-                    Args.hasArg(OPT_cl_unsafe_math_optimizations) ||
-                    Args.hasArg(OPT_cl_fast_relaxed_math);
-
   if (Arg *A = Args.getLastArg(OPT_ffp_contract)) {
     StringRef Val = A->getValue();
     if (Val == "fast")
@@ -3777,7 +3726,7 @@ bool CompilerInvocation::parseSimpleArgs(const ArgList 
&Args,
                                      ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, 
\
                                      METAVAR, VALUES, SPELLING, ALWAYS_EMIT,   
\
                                      KEYPATH, DEFAULT_VALUE, IS_POSITIVE)      
\
-  this->KEYPATH = Args.hasArg(OPT_##ID) && IS_POSITIVE;
+  this->KEYPATH = (Args.hasArg(OPT_##ID) && IS_POSITIVE) || (DEFAULT_VALUE);
 
 #define OPTION_WITH_MARSHALLING_STRING(                                        
\
     PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        
\
@@ -4051,15 +4000,15 @@ void CompilerInvocation::generateCC1CommandLine(
                                      ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, 
\
                                      METAVAR, VALUES, SPELLING, ALWAYS_EMIT,   
\
                                      KEYPATH, DEFAULT_VALUE, IS_POSITIVE)      
\
-  if ((FLAGS) & options::CC1Option &&                                          
  \
-      (ALWAYS_EMIT || this->KEYPATH != DEFAULT_VALUE))                         
\
+  if ((FLAGS) & options::CC1Option &&                                          
\
+      (ALWAYS_EMIT || this->KEYPATH != (DEFAULT_VALUE)))                       
\
     Args.push_back(SPELLING);
 
 #define OPTION_WITH_MARSHALLING_STRING(                                        
\
     PREFIX_TYPE, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM,        
\
     HELPTEXT, METAVAR, VALUES, SPELLING, ALWAYS_EMIT, KEYPATH, DEFAULT_VALUE,  
\
     NORMALIZER_RET_TY, NORMALIZER, DENORMALIZER, TABLE_INDEX)                  
\
-  if (((FLAGS) & options::CC1Option) &&                                        
  \
+  if (((FLAGS) & options::CC1Option) &&                                        
\
       (ALWAYS_EMIT || this->KEYPATH != DEFAULT_VALUE)) {                       
\
     if (Option::KIND##Class == Option::SeparateClass) {                        
\
       Args.push_back(SPELLING);                                                
\

diff  --git a/clang/unittests/Frontend/CompilerInvocationTest.cpp 
b/clang/unittests/Frontend/CompilerInvocationTest.cpp
index ed82d678462f..d9b55f0ae5ba 100644
--- a/clang/unittests/Frontend/CompilerInvocationTest.cpp
+++ b/clang/unittests/Frontend/CompilerInvocationTest.cpp
@@ -37,6 +37,25 @@ class CC1CommandLineGenerationTest : public ::testing::Test {
       : Diags(CompilerInstance::createDiagnostics(new DiagnosticOptions())) {}
 };
 
+TEST(OptsPopulationTest, CanPopulateOptsWithImpliedFlags) {
+  const char *Args[] = {"clang", "-xc++", "-cl-unsafe-math-optimizations"};
+
+  auto Diags = CompilerInstance::createDiagnostics(new DiagnosticOptions());
+
+  CompilerInvocation CInvok;
+  CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags);
+
+  // Explicitly provided flag.
+  ASSERT_EQ(CInvok.getLangOpts()->CLUnsafeMath, true);
+
+  // Flags directly implied by explicitly provided flag.
+  ASSERT_EQ(CInvok.getCodeGenOpts().LessPreciseFPMAD, true);
+  ASSERT_EQ(CInvok.getLangOpts()->UnsafeFPMath, true);
+
+  // Flag transitively implied by explicitly provided flag.
+  ASSERT_EQ(CInvok.getLangOpts()->AllowRecip, true);
+}
+
 TEST_F(CC1CommandLineGenerationTest, CanGenerateCC1CommandLineFlag) {
   const char *Args[] = {"clang", "-xc++", "-fmodules-strict-context-hash", 
"-"};
 
@@ -115,4 +134,20 @@ TEST_F(CC1CommandLineGenerationTest, 
CanGenerateCC1CommandLineSeparateEnum) {
   ASSERT_THAT(GeneratedArgs, Each(StrNe(RelocationModelCStr)));
 }
 
+TEST_F(CC1CommandLineGenerationTest, CanGenerateCC1CommandLineImpliedFlags) {
+  const char *Args[] = {"clang", "-xc++", "-cl-unsafe-math-optimizations",
+                        "-cl-mad-enable", "-menable-unsafe-fp-math"};
+
+  CompilerInvocation CInvok;
+  CompilerInvocation::CreateFromArgs(CInvok, Args, *Diags);
+
+  CInvok.generateCC1CommandLine(GeneratedArgs, *this);
+
+  // Explicitly provided flags that were also implied by another flag are not
+  // generated.
+  ASSERT_THAT(GeneratedArgs, Contains(StrEq("-cl-unsafe-math-optimizations")));
+  ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-cl-mad-enable"))));
+  ASSERT_THAT(GeneratedArgs, Not(Contains(StrEq("-menable-unsafe-fp-math"))));
+}
+
 } // anonymous namespace

diff  --git a/llvm/include/llvm/Option/OptParser.td 
b/llvm/include/llvm/Option/OptParser.td
index e32355444d7b..47b4788b2209 100644
--- a/llvm/include/llvm/Option/OptParser.td
+++ b/llvm/include/llvm/Option/OptParser.td
@@ -144,6 +144,11 @@ class ValuesCode<code valuecode> { code ValuesCode = 
valuecode; }
 
 // Helpers for defining marshalling information.
 
+class DefaultAnyOf<list<Option> defaults> {
+  code DefaultValue = !foldl("false", defaults, accumulator, option,
+                             !strconcat(accumulator, " || ", 
!cast<string>(option.KeyPath)));
+}
+
 class MarshallingInfo<code keypath, code defaultvalue> {
   code KeyPath = keypath;
   code DefaultValue = defaultvalue;
@@ -154,8 +159,8 @@ class MarshallingInfoString<code keypath, code 
defaultvalue, code normalizerrett
   code NormalizerRetTy = normalizerretty;
 }
 
-class MarshallingInfoFlag<code keypath, code defaultvalue>
-  : MarshallingInfo<keypath, defaultvalue> {
+class MarshallingInfoFlag<code keypath, DefaultAnyOf defaults = 
DefaultAnyOf<[]>>
+  : MarshallingInfo<keypath, defaults.DefaultValue> {
   string MarshallingKind = "flag";
 }
 

diff  --git a/llvm/unittests/Option/CMakeLists.txt 
b/llvm/unittests/Option/CMakeLists.txt
index 07f7b91d5f5b..7be4300c0f3d 100644
--- a/llvm/unittests/Option/CMakeLists.txt
+++ b/llvm/unittests/Option/CMakeLists.txt
@@ -10,4 +10,5 @@ add_public_tablegen_target(OptsTestTableGen)
 
 add_llvm_unittest(OptionTests
   OptionParsingTest.cpp
+  OptionMarshallingTest.cpp
   )

diff  --git a/llvm/unittests/Option/OptionMarshallingTest.cpp 
b/llvm/unittests/Option/OptionMarshallingTest.cpp
new file mode 100644
index 000000000000..bf26a767bba1
--- /dev/null
+++ b/llvm/unittests/Option/OptionMarshallingTest.cpp
@@ -0,0 +1,47 @@
+//===- unittest/Support/OptionMarshallingTest.cpp - OptParserEmitter tests 
===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM 
Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "gtest/gtest.h"
+
+struct OptionWithMarshallingInfo {
+  const char *Name;
+  const char *KeyPath;
+  const char *DefaultValue;
+};
+
+static const OptionWithMarshallingInfo MarshallingTable[] = {
+#define OPTION_WITH_MARSHALLING_FLAG(PREFIX_TYPE, NAME, ID, KIND, GROUP,       
\
+                                     ALIAS, ALIASARGS, FLAGS, PARAM, HELPTEXT, 
\
+                                     METAVAR, VALUES, SPELLING, ALWAYS_EMIT,   
\
+                                     KEYPATH, DEFAULT_VALUE, IS_POSITIVE)      
\
+  { NAME, #KEYPATH, #DEFAULT_VALUE },
+#include "Opts.inc"
+#undef OPTION_WITH_MARSHALLING_FLAG
+};
+
+TEST(OptionMarshalling, EmittedOrderSameAsDefinitionOrder) {
+  ASSERT_STREQ(MarshallingTable[0].Name, "marshalled-flag-0");
+  ASSERT_STREQ(MarshallingTable[1].Name, "marshalled-flag-1");
+  ASSERT_STREQ(MarshallingTable[2].Name, "marshalled-flag-2");
+  ASSERT_STREQ(MarshallingTable[3].Name, "marshalled-flag-3");
+}
+
+TEST(OptionMarshalling, EmittedSpecifiedKeyPath) {
+  ASSERT_STREQ(MarshallingTable[0].KeyPath, "MarshalledFlag0");
+  ASSERT_STREQ(MarshallingTable[1].KeyPath, "MarshalledFlag1");
+  ASSERT_STREQ(MarshallingTable[2].KeyPath, "MarshalledFlag2");
+  ASSERT_STREQ(MarshallingTable[3].KeyPath, "MarshalledFlag3");
+}
+
+TEST(OptionMarshalling, DefaultAnyOfConstructedDisjunctionOfKeypaths) {
+  ASSERT_STREQ(MarshallingTable[0].DefaultValue, "false");
+  ASSERT_STREQ(MarshallingTable[1].DefaultValue, "false || MarshalledFlag0");
+  ASSERT_STREQ(MarshallingTable[2].DefaultValue, "false || MarshalledFlag0");
+  ASSERT_STREQ(MarshallingTable[3].DefaultValue,
+            "false || MarshalledFlag1 || MarshalledFlag2");
+}

diff  --git a/llvm/unittests/Option/Opts.td b/llvm/unittests/Option/Opts.td
index e1ebffd1881f..3bbf210b0b74 100644
--- a/llvm/unittests/Option/Opts.td
+++ b/llvm/unittests/Option/Opts.td
@@ -44,3 +44,12 @@ def Blurmpq : Flag<["--"], "blurmp">;
 def Blurmpq_eq : Flag<["--"], "blurmp=">;
 
 def DashDash : Option<["--"], "", KIND_REMAINING_ARGS>;
+
+def marshalled_flag_0 : Flag<["-"], "marshalled-flag-0">,
+  MarshallingInfoFlag<"MarshalledFlag0", DefaultAnyOf<[]>>;
+def marshalled_flag_1 : Flag<["-"], "marshalled-flag-1">,
+  MarshallingInfoFlag<"MarshalledFlag1", DefaultAnyOf<[marshalled_flag_0]>>;
+def marshalled_flag_2 : Flag<["-"], "marshalled-flag-2">,
+  MarshallingInfoFlag<"MarshalledFlag2", DefaultAnyOf<[marshalled_flag_0]>>;
+def marshalled_flag_3 : Flag<["-"], "marshalled-flag-3">,
+  MarshallingInfoFlag<"MarshalledFlag3", DefaultAnyOf<[marshalled_flag_1, 
marshalled_flag_2]>>;

diff  --git a/llvm/utils/TableGen/OptParserEmitter.cpp 
b/llvm/utils/TableGen/OptParserEmitter.cpp
index 6e49e248e4b8..0c30a2dd28dc 100644
--- a/llvm/utils/TableGen/OptParserEmitter.cpp
+++ b/llvm/utils/TableGen/OptParserEmitter.cpp
@@ -435,7 +435,12 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) 
{
       OS << "nullptr";
   };
 
-  std::vector<std::unique_ptr<MarshallingKindInfo>> OptsWithMarshalling;
+  auto IsMarshallingOption = [](const Record &R) {
+    return !isa<UnsetInit>(R.getValueInit("MarshallingKind")) &&
+           !R.getValueAsString("KeyPath").empty();
+  };
+
+  std::vector<const Record *> OptsWithMarshalling;
   for (unsigned I = 0, E = Opts.size(); I != E; ++I) {
     const Record &R = *Opts[I];
 
@@ -443,12 +448,33 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream 
&OS) {
     OS << "OPTION(";
     WriteOptRecordFields(OS, R);
     OS << ")\n";
-    if (!isa<UnsetInit>(R.getValueInit("MarshallingKind")))
-      OptsWithMarshalling.push_back(MarshallingKindInfo::create(R));
+    if (IsMarshallingOption(R))
+      OptsWithMarshalling.push_back(&R);
   }
   OS << "#endif // OPTION\n";
 
-  for (const auto &KindInfo : OptsWithMarshalling) {
+  auto CmpMarshallingOpts = [](const Record *const *A, const Record *const *B) 
{
+    unsigned AID = (*A)->getID();
+    unsigned BID = (*B)->getID();
+
+    if (AID < BID)
+      return -1;
+    if (AID > BID)
+      return 1;
+    return 0;
+  };
+  // The RecordKeeper stores records (options) in lexicographical order, and we
+  // have reordered the options again when generating prefix groups. We need to
+  // restore the original definition order of options with marshalling to honor
+  // the topology of the dependency graph implied by `DefaultAnyOf`.
+  array_pod_sort(OptsWithMarshalling.begin(), OptsWithMarshalling.end(),
+                 CmpMarshallingOpts);
+
+  std::vector<std::unique_ptr<MarshallingKindInfo>> MarshallingKindInfos;
+  for (const auto *R : OptsWithMarshalling)
+    MarshallingKindInfos.push_back(MarshallingKindInfo::create(*R));
+
+  for (const auto &KindInfo : MarshallingKindInfos) {
     OS << "#ifdef " << KindInfo->MacroName << "\n";
     OS << KindInfo->MacroName << "(";
     WriteOptRecordFields(OS, KindInfo->R);
@@ -463,7 +489,7 @@ void EmitOptParser(RecordKeeper &Records, raw_ostream &OS) {
   OS << "\n";
   OS << MarshallingStringInfo::ValueTablePreamble;
   std::vector<StringRef> ValueTableNames;
-  for (const auto &KindInfo : OptsWithMarshalling)
+  for (const auto &KindInfo : MarshallingKindInfos)
     if (auto MaybeValueTableName = KindInfo->emitValueTable(OS))
       ValueTableNames.push_back(*MaybeValueTableName);
 


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to