Where was this reviewed?
On Wed, Feb 16, 2022 at 12:59 AM Zahira Ammarguellat via cfe-commits <cfe-commits@lists.llvm.org> wrote: > > > Author: Zahira Ammarguellat > Date: 2022-02-15T13:59:27-08:00 > New Revision: 4bafe65c2b2f1ce745894a509a6d80c87fb1c335 > > URL: > https://github.com/llvm/llvm-project/commit/4bafe65c2b2f1ce745894a509a6d80c87fb1c335 > DIFF: > https://github.com/llvm/llvm-project/commit/4bafe65c2b2f1ce745894a509a6d80c87fb1c335.diff > > LOG: Add support for floating-point option `ffp-eval-method` and for > `pragma clang fp eval_method`. > > Added: > clang/test/CodeGen/X86/32bit-behavior-no-eval.c > clang/test/CodeGen/X86/32bit-behavior.c > clang/test/CodeGen/X86/fp-eval-method.c > clang/test/CodeGen/flt_eval_macro.cpp > clang/test/Preprocessor/flt_eval_macro.cpp > clang/test/Sema/fp-eval-pragma.cpp > clang/test/Sema/x86-eval-method.c > clang/test/Sema/x86_64-eval-method.c > > Modified: > clang/docs/LanguageExtensions.rst > clang/docs/UsersManual.rst > clang/include/clang/Basic/DiagnosticCommonKinds.td > clang/include/clang/Basic/DiagnosticLexKinds.td > clang/include/clang/Basic/FPOptions.def > clang/include/clang/Basic/LangOptions.def > clang/include/clang/Basic/LangOptions.h > clang/include/clang/Basic/TargetInfo.h > clang/include/clang/Driver/Options.td > clang/include/clang/Lex/Preprocessor.h > clang/include/clang/Parse/Parser.h > clang/include/clang/Sema/Sema.h > clang/lib/Basic/Targets/OSTargets.h > clang/lib/Basic/Targets/X86.h > clang/lib/Driver/ToolChains/Clang.cpp > clang/lib/Frontend/InitPreprocessor.cpp > clang/lib/Lex/PPMacroExpansion.cpp > clang/lib/Parse/ParsePragma.cpp > clang/lib/Parse/ParseStmt.cpp > clang/lib/Sema/Sema.cpp > clang/lib/Sema/SemaAttr.cpp > clang/lib/Sema/SemaExpr.cpp > clang/test/CodeGen/fp-floatcontrol-pragma.cpp > clang/test/Preprocessor/init-aarch64.c > clang/test/Preprocessor/init-arm.c > clang/test/Preprocessor/init-mips.c > clang/test/Preprocessor/init-ppc.c > clang/test/Preprocessor/init-ppc64.c > clang/test/Preprocessor/init-s390x.c > clang/test/Preprocessor/init-v7k-compat.c > clang/test/Preprocessor/init-x86.c > clang/test/Preprocessor/init.c > > Removed: > > > > ################################################################################ > diff --git a/clang/docs/LanguageExtensions.rst > b/clang/docs/LanguageExtensions.rst > index f45d88092eb4a..5249d3f3f7930 100644 > --- a/clang/docs/LanguageExtensions.rst > +++ b/clang/docs/LanguageExtensions.rst > @@ -3907,6 +3907,38 @@ A ``#pragma clang fp`` pragma may contain any number > of options: > ... > } > > +``#pragma clang fp eval_method`` allows floating-point behavior to be > specified > +for a section of the source code. This pragma can appear at file or namespace > +scope, or at the start of a compound statement (excluding comments). > +The pragma is active within the scope of the compound statement. > + > +When ``pragma clang fp eval_method(source)`` is enabled, the section of code > +governed by the pragma behaves as though the command-line option > +``-ffp-eval-method=source`` is enabled. Rounds intermediate results to > +source-defined precision. > + > +When ``pragma clang fp eval_method(double)`` is enabled, the section of code > +governed by the pragma behaves as though the command-line option > +``-ffp-eval-method=double`` is enabled. Rounds intermediate results to > +``double`` precision. > + > +When ``pragma clang fp eval_method(extended)`` is enabled, the section of > code > +governed by the pragma behaves as though the command-line option > +``-ffp-eval-method=extended`` is enabled. Rounds intermediate results to > +target-dependent ``long double`` precision. In Win32 programming, for > instance, > +the long double data type maps to the double, 64-bit precision data type. > + > +The full syntax this pragma supports is > +``#pragma clang fp eval_method(source|double|extended)``. > + > +.. code-block:: c++ > + > + for(...) { > + // The compiler will use long double as the floating-point evaluation > + // method. > + #pragma clang fp eval_method(extended) > + a = b[i] * c[i] + e; > + } > > The ``#pragma float_control`` pragma allows precise floating-point > semantics and floating-point exception behavior to be specified > > diff --git a/clang/docs/UsersManual.rst b/clang/docs/UsersManual.rst > index 1df96296cb8ac..70fee29ab2a84 100644 > --- a/clang/docs/UsersManual.rst > +++ b/clang/docs/UsersManual.rst > @@ -1566,6 +1566,22 @@ Note that floating-point operations performed as part > of constant initialization > * ``maytrap`` The compiler avoids transformations that may raise > exceptions that would not have been raised by the original code. Constant > folding performed by the compiler is exempt from this option. > * ``strict`` The compiler ensures that all transformations strictly > preserve the floating point exception semantics of the original code. > > +.. option:: -ffp-eval-method=<value> > + > + Specify the floating-point evaluation method for intermediate results > within > + a single expression of the code. > + > + Valid values are: ``source``, ``double``, and ``extended``. > + For 64-bit targets, the default value is ``source``. For 32-bit x86 > targets > + however, in the case of NETBSD 6.99.26 and under, the default value is > + ``double``; in the case of NETBSD greater than 6.99.26, with NoSSE, the > + default value is ``extended``, with SSE the default value is ``source``. > + Details: > + > + * ``source`` The compiler uses the floating-point type declared in the > source program as the evaluation method. > + * ``double`` The compiler uses ``double`` as the floating-point > evaluation method for all float expressions of type that is narrower than > ``double``. > + * ``extended`` The compiler uses ``long double`` as the floating-point > evaluation method for all float expressions of type that is narrower than > ``long double``. > + > .. option:: -f[no-]protect-parens: > > This option pertains to floating-point types, complex types with > @@ -1587,6 +1603,17 @@ Note that floating-point operations performed as part > of constant initialization > has no effect because the optimizer is prohibited from making unsafe > transformations. > > +.. _FLT_EVAL_METHOD: > + > +A note about ``__FLT_EVAL_METHOD__`` > +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > +The macro ``__FLT_EVAL_METHOD__`` will expand to either the value set from > the > +command line option ``ffp-eval-method`` or to the value from the target info > +setting. The ``__FLT_EVAL_METHOD__`` macro cannot expand to the correct > +evaluation method in the presence of a ``#pragma`` which alters the > evaluation > +method. An error is issued if ``__FLT_EVAL_METHOD__`` is expanded inside a > scope > +modified by ``#pragma clang fp eval_method``. > + > .. _fp-constant-eval: > > A note about Floating Point Constant Evaluation > > diff --git a/clang/include/clang/Basic/DiagnosticCommonKinds.td > b/clang/include/clang/Basic/DiagnosticCommonKinds.td > index 421527827a4bd..bbf26d637265e 100644 > --- a/clang/include/clang/Basic/DiagnosticCommonKinds.td > +++ b/clang/include/clang/Basic/DiagnosticCommonKinds.td > @@ -318,6 +318,11 @@ def err_opt_not_valid_on_target : Error< > def err_invalid_feature_combination : Error< > "invalid feature combination: %0">; > > +// Eval method > +def warn_no_support_for_eval_method_source_on_m32 : Warning< > + "Setting FPEvalMethod to source on a 32bit target, with no SSE is" > + " not supported.">; > + > // Source manager > def err_cannot_open_file : Error<"cannot open file '%0': %1">, DefaultFatal; > def err_file_modified : Error< > > diff --git a/clang/include/clang/Basic/DiagnosticLexKinds.td > b/clang/include/clang/Basic/DiagnosticLexKinds.td > index a4436208799f9..0f424b02c812a 100644 > --- a/clang/include/clang/Basic/DiagnosticLexKinds.td > +++ b/clang/include/clang/Basic/DiagnosticLexKinds.td > @@ -321,6 +321,10 @@ def err_pragma_include_instead_system_reserved : Error< > "header '%0' is an implementation detail; #include %select{'%2'|either > '%2' " > "or '%3'|one of %2}1 instead">; > > +def err_illegal_use_of_flt_eval_macro : Error< > + "'__FLT_EVAL_METHOD__' cannot be expanded inside a scope containing " > + "'#pragma clang fp eval_method'">; > + > def pp_poisoning_existing_macro : Warning<"poisoning existing macro">; > def pp_out_of_date_dependency : Warning< > "current file is older than dependency %0">; > > diff --git a/clang/include/clang/Basic/FPOptions.def > b/clang/include/clang/Basic/FPOptions.def > index a93fa475cd5f6..224c1827144f5 100644 > --- a/clang/include/clang/Basic/FPOptions.def > +++ b/clang/include/clang/Basic/FPOptions.def > @@ -23,4 +23,5 @@ OPTION(NoHonorInfs, bool, 1, NoHonorNaNs) > OPTION(NoSignedZero, bool, 1, NoHonorInfs) > OPTION(AllowReciprocal, bool, 1, NoSignedZero) > OPTION(AllowApproxFunc, bool, 1, AllowReciprocal) > +OPTION(FPEvalMethod, LangOptions::FPEvalMethodKind, 2, AllowApproxFunc) > #undef OPTION > > diff --git a/clang/include/clang/Basic/LangOptions.def > b/clang/include/clang/Basic/LangOptions.def > index 4651f4fff6aa0..89b11fdea89b2 100644 > --- a/clang/include/clang/Basic/LangOptions.def > +++ b/clang/include/clang/Basic/LangOptions.def > @@ -301,6 +301,7 @@ BENIGN_ENUM_LANGOPT(DefaultFPContractMode, FPModeKind, 2, > FPM_Off, "FP contracti > COMPATIBLE_LANGOPT(ExpStrictFP, 1, false, "Enable experimental strict > floating point") > BENIGN_ENUM_LANGOPT(FPRoundingMode, RoundingMode, 3, > RoundingMode::NearestTiesToEven, "FP Rounding Mode type") > BENIGN_ENUM_LANGOPT(FPExceptionMode, FPExceptionModeKind, 2, FPE_Ignore, "FP > Exception Behavior Mode type") > +BENIGN_ENUM_LANGOPT(FPEvalMethod, FPEvalMethodKind, 2, > FEM_UnsetOnCommandLine, "FP type used for floating point arithmetic") > LANGOPT(NoBitFieldTypeAlign , 1, 0, "bit-field type alignment") > LANGOPT(HexagonQdsp6Compat , 1, 0, "hexagon-qdsp6 backward compatibility") > LANGOPT(ObjCAutoRefCount , 1, 0, "Objective-C automated reference counting") > > diff --git a/clang/include/clang/Basic/LangOptions.h > b/clang/include/clang/Basic/LangOptions.h > index 50c7f038fc6be..2e334e375950e 100644 > --- a/clang/include/clang/Basic/LangOptions.h > +++ b/clang/include/clang/Basic/LangOptions.h > @@ -235,6 +235,24 @@ class LangOptions : public LangOptionsBase { > FPE_Strict > }; > > + /// Possible float expression evaluation method choices. > + enum FPEvalMethodKind { > + /// The evaluation method cannot be determined or is inconsistent for > this > + /// target. > + FEM_Indeterminable = -1, > + /// Use the declared type for fp arithmetic. > + FEM_Source = 0, > + /// Use the type double for fp arithmetic. > + FEM_Double = 1, > + /// Use extended type for fp arithmetic. > + FEM_Extended = 2, > + /// Used only for FE option processing; this is only used to indicate > that > + /// the user did not specify an explicit evaluation method on the command > + /// line and so the target should be queried for its default evaluation > + /// method instead. > + FEM_UnsetOnCommandLine = 3 > + }; > + > /// Possible exception handling behavior. > enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm }; > > > diff --git a/clang/include/clang/Basic/TargetInfo.h > b/clang/include/clang/Basic/TargetInfo.h > index 22918f7e12e84..8e18ded7d3765 100644 > --- a/clang/include/clang/Basic/TargetInfo.h > +++ b/clang/include/clang/Basic/TargetInfo.h > @@ -726,7 +726,11 @@ class TargetInfo : public virtual > TransferrableTargetInfo, > } > > /// Return the value for the C99 FLT_EVAL_METHOD macro. > - virtual unsigned getFloatEvalMethod() const { return 0; } > + virtual LangOptions::FPEvalMethodKind getFPEvalMethod() const { > + return LangOptions::FPEvalMethodKind::FEM_Source; > + } > + > + virtual bool supportSourceEvalMethod() const { return true; } > > // getLargeArrayMinWidth/Align - Return the minimum array size that is > // 'large' and its alignment. > > diff --git a/clang/include/clang/Driver/Options.td > b/clang/include/clang/Driver/Options.td > index b81973155cae6..f1e8b967c78e5 100644 > --- a/clang/include/clang/Driver/Options.td > +++ b/clang/include/clang/Driver/Options.td > @@ -1495,6 +1495,11 @@ def : Flag<["-"], "fextended-identifiers">, > Group<clang_ignored_f_Group>; > def : Flag<["-"], "fno-extended-identifiers">, Group<f_Group>, > Flags<[Unsupported]>; > def fhosted : Flag<["-"], "fhosted">, Group<f_Group>; > def fdenormal_fp_math_EQ : Joined<["-"], "fdenormal-fp-math=">, > Group<f_Group>, Flags<[CC1Option]>; > +def ffp_eval_method_EQ : Joined<["-"], "ffp-eval-method=">, Group<f_Group>, > Flags<[CC1Option]>, > + HelpText<"Specifies the evaluation method to use for floating-point > arithmetic.">, > + Values<"source,double,extended">, NormalizedValuesScope<"LangOptions">, > + NormalizedValues<["FEM_Source", "FEM_Double", "FEM_Extended"]>, > + MarshallingInfoEnum<LangOpts<"FPEvalMethod">, "FEM_UnsetOnCommandLine">; > def ffp_model_EQ : Joined<["-"], "ffp-model=">, Group<f_Group>, > Flags<[NoXarchOption]>, > HelpText<"Controls the semantics of floating-point calculations.">; > def ffp_exception_behavior_EQ : Joined<["-"], "ffp-exception-behavior=">, > Group<f_Group>, Flags<[CC1Option]>, > > diff --git a/clang/include/clang/Lex/Preprocessor.h > b/clang/include/clang/Lex/Preprocessor.h > index 2802329a60220..f2c84e43ddca3 100644 > --- a/clang/include/clang/Lex/Preprocessor.h > +++ b/clang/include/clang/Lex/Preprocessor.h > @@ -179,12 +179,27 @@ class Preprocessor { > IdentifierInfo *Ident__is_target_vendor; // __is_target_vendor > IdentifierInfo *Ident__is_target_os; // __is_target_os > IdentifierInfo *Ident__is_target_environment; // __is_target_environment > + IdentifierInfo *Ident__FLT_EVAL_METHOD__; // __FLT_EVAL_METHOD > > // Weak, only valid (and set) while InMacroArgs is true. > Token* ArgMacro; > > SourceLocation DATELoc, TIMELoc; > > + // FEM_UnsetOnCommandLine means that an explicit evaluation method was > + // not specified on the command line. The target is queried to set the > + // default evaluation method. > + LangOptions::FPEvalMethodKind CurrentFPEvalMethod = > + LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine; > + > + // The most recent pragma location where the floating point evaluation > + // method was modified. This is used to determine whether the > + // 'pragma clang fp eval_method' was used whithin the current scope. > + SourceLocation LastFPEvalPragmaLocation; > + > + LangOptions::FPEvalMethodKind TUFPEvalMethod = > + LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine; > + > // Next __COUNTER__ value, starts at 0. > unsigned CounterValue = 0; > > @@ -2048,6 +2063,32 @@ class Preprocessor { > unsigned getCounterValue() const { return CounterValue; } > void setCounterValue(unsigned V) { CounterValue = V; } > > + LangOptions::FPEvalMethodKind getCurrentFPEvalMethod() const { > + assert(CurrentFPEvalMethod != LangOptions::FEM_UnsetOnCommandLine && > + "FPEvalMethod should be set either from command line or from the " > + "target info"); > + return CurrentFPEvalMethod; > + } > + > + LangOptions::FPEvalMethodKind getTUFPEvalMethod() const { > + return TUFPEvalMethod; > + } > + > + SourceLocation getLastFPEvalPragmaLocation() const { > + return LastFPEvalPragmaLocation; > + } > + > + void setCurrentFPEvalMethod(SourceLocation PragmaLoc, > + LangOptions::FPEvalMethodKind Val) { > + assert(Val != LangOptions::FEM_UnsetOnCommandLine && > + "FPEvalMethod should never be set to FEM_UnsetOnCommandLine"); > + // This is the location of the '#pragma float_control" where the > + // execution state is modifed. > + LastFPEvalPragmaLocation = PragmaLoc; > + CurrentFPEvalMethod = Val; > + TUFPEvalMethod = Val; > + } > + > /// Retrieves the module that we're currently building, if any. > Module *getCurrentModule(); > > > diff --git a/clang/include/clang/Parse/Parser.h > b/clang/include/clang/Parse/Parser.h > index 981800a7e2356..d2e588992238d 100644 > --- a/clang/include/clang/Parse/Parser.h > +++ b/clang/include/clang/Parse/Parser.h > @@ -184,6 +184,7 @@ class Parser : public CodeCompletionHandler { > std::unique_ptr<PragmaHandler> PCSectionHandler; > std::unique_ptr<PragmaHandler> MSCommentHandler; > std::unique_ptr<PragmaHandler> MSDetectMismatchHandler; > + std::unique_ptr<PragmaHandler> FPEvalMethodHandler; > std::unique_ptr<PragmaHandler> FloatControlHandler; > std::unique_ptr<PragmaHandler> MSPointersToMembers; > std::unique_ptr<PragmaHandler> MSVtorDisp; > > diff --git a/clang/include/clang/Sema/Sema.h > b/clang/include/clang/Sema/Sema.h > index c1e846c55dee7..60ee577fca06a 100644 > --- a/clang/include/clang/Sema/Sema.h > +++ b/clang/include/clang/Sema/Sema.h > @@ -1541,19 +1541,16 @@ class Sema final { > /// statements. > class FPFeaturesStateRAII { > public: > - FPFeaturesStateRAII(Sema &S) : S(S), OldFPFeaturesState(S.CurFPFeatures) > { > - OldOverrides = S.FpPragmaStack.CurrentValue; > - } > - ~FPFeaturesStateRAII() { > - S.CurFPFeatures = OldFPFeaturesState; > - S.FpPragmaStack.CurrentValue = OldOverrides; > - } > + FPFeaturesStateRAII(Sema &S); > + ~FPFeaturesStateRAII(); > FPOptionsOverride getOverrides() { return OldOverrides; } > > private: > Sema& S; > FPOptions OldFPFeaturesState; > FPOptionsOverride OldOverrides; > + LangOptions::FPEvalMethodKind OldEvalMethod; > + SourceLocation OldFPPragmaLocation; > }; > > void addImplicitTypedef(StringRef Name, QualType T); > @@ -10131,6 +10128,9 @@ class Sema final { > !CurFPFeatures.getAllowApproxFunc(); > } > > + void ActOnPragmaFPEvalMethod(SourceLocation Loc, > + LangOptions::FPEvalMethodKind Value); > + > /// ActOnPragmaFloatControl - Call on well-formed \#pragma float_control > void ActOnPragmaFloatControl(SourceLocation Loc, PragmaMsStackAction > Action, > PragmaFloatControlKind Value); > > diff --git a/clang/lib/Basic/Targets/OSTargets.h > b/clang/lib/Basic/Targets/OSTargets.h > index 3c1830d5f8e89..f61652d285a89 100644 > --- a/clang/lib/Basic/Targets/OSTargets.h > +++ b/clang/lib/Basic/Targets/OSTargets.h > @@ -749,7 +749,9 @@ class AIXTargetInfo : public OSTargetInfo<Target> { > } > > // AIX sets FLT_EVAL_METHOD to be 1. > - unsigned getFloatEvalMethod() const override { return 1; } > + LangOptions::FPEvalMethodKind getFPEvalMethod() const override { > + return LangOptions::FPEvalMethodKind::FEM_Double; > + } > > bool defaultsToAIXPowerAlignment() const override { return true; } > }; > > diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h > index d1b66432e38b4..e0bb3c344c5b6 100644 > --- a/clang/lib/Basic/Targets/X86.h > +++ b/clang/lib/Basic/Targets/X86.h > @@ -168,11 +168,15 @@ class LLVM_LIBRARY_VISIBILITY X86TargetInfo : public > TargetInfo { > return LongDoubleFormat == &llvm::APFloat::IEEEquad() ? "g" : "e"; > } > > - unsigned getFloatEvalMethod() const override { > + LangOptions::FPEvalMethodKind getFPEvalMethod() const override { > // X87 evaluates with 80 bits "long double" precision. > - return SSELevel == NoSSE ? 2 : 0; > + return SSELevel == NoSSE ? LangOptions::FPEvalMethodKind::FEM_Extended > + : LangOptions::FPEvalMethodKind::FEM_Source; > } > > + // EvalMethod `source` is not supported for targets with `NoSSE` feature. > + bool supportSourceEvalMethod() const override { return SSELevel > NoSSE; } > + > ArrayRef<const char *> getGCCRegNames() const override; > > ArrayRef<TargetInfo::GCCRegAlias> getGCCRegAliases() const override { > @@ -471,13 +475,13 @@ class LLVM_LIBRARY_VISIBILITY NetBSDI386TargetInfo > NetBSDI386TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts) > : NetBSDTargetInfo<X86_32TargetInfo>(Triple, Opts) {} > > - unsigned getFloatEvalMethod() const override { > + LangOptions::FPEvalMethodKind getFPEvalMethod() const override { > VersionTuple OsVersion = getTriple().getOSVersion(); > // New NetBSD uses the default rounding mode. > if (OsVersion >= VersionTuple(6, 99, 26) || OsVersion.getMajor() == 0) > - return X86_32TargetInfo::getFloatEvalMethod(); > + return X86_32TargetInfo::getFPEvalMethod(); > // NetBSD before 6.99.26 defaults to "double" rounding. > - return 1; > + return LangOptions::FPEvalMethodKind::FEM_Double; > } > }; > > > diff --git a/clang/lib/Driver/ToolChains/Clang.cpp > b/clang/lib/Driver/ToolChains/Clang.cpp > index 945f626977799..ee32e5849ff84 100644 > --- a/clang/lib/Driver/ToolChains/Clang.cpp > +++ b/clang/lib/Driver/ToolChains/Clang.cpp > @@ -2719,6 +2719,8 @@ static void RenderFloatingPointOptions(const ToolChain > &TC, const Driver &D, > StringRef FPModel = ""; > // -ffp-exception-behavior options: strict, maytrap, ignore > StringRef FPExceptionBehavior = ""; > + // -ffp-eval-method options: double, extended, source > + StringRef FPEvalMethod = ""; > const llvm::DenormalMode DefaultDenormalFPMath = > TC.getDefaultDenormalModeForType(Args, JA); > const llvm::DenormalMode DefaultDenormalFP32Math = > @@ -2914,6 +2916,18 @@ static void RenderFloatingPointOptions(const ToolChain > &TC, const Driver &D, > break; > } > > + // Validate and pass through -ffp-eval-method option. > + case options::OPT_ffp_eval_method_EQ: { > + StringRef Val = A->getValue(); > + if (Val.equals("double") || Val.equals("extended") || > + Val.equals("source")) > + FPEvalMethod = Val; > + else > + D.Diag(diag::err_drv_unsupported_option_argument) > + << A->getOption().getName() << Val; > + break; > + } > + > case options::OPT_ffinite_math_only: > HonorINFs = false; > HonorNaNs = false; > @@ -3069,6 +3083,9 @@ static void RenderFloatingPointOptions(const ToolChain > &TC, const Driver &D, > CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" + > FPExceptionBehavior)); > > + if (!FPEvalMethod.empty()) > + CmdArgs.push_back(Args.MakeArgString("-ffp-eval-method=" + > FPEvalMethod)); > + > ParseMRecip(D, Args, CmdArgs); > > // -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for > the > > diff --git a/clang/lib/Frontend/InitPreprocessor.cpp > b/clang/lib/Frontend/InitPreprocessor.cpp > index bf8a0b2abe22e..ff507e2c00aaa 100644 > --- a/clang/lib/Frontend/InitPreprocessor.cpp > +++ b/clang/lib/Frontend/InitPreprocessor.cpp > @@ -1136,7 +1136,6 @@ static void InitializePredefinedMacros(const TargetInfo > &TI, > } > > // Macros to control C99 numerics and <float.h> > - Builder.defineMacro("__FLT_EVAL_METHOD__", Twine(TI.getFloatEvalMethod())); > Builder.defineMacro("__FLT_RADIX__", "2"); > Builder.defineMacro("__DECIMAL_DIG__", "__LDBL_DECIMAL_DIG__"); > > > diff --git a/clang/lib/Lex/PPMacroExpansion.cpp > b/clang/lib/Lex/PPMacroExpansion.cpp > index a29ff215d7ea0..82fc57c8f2e88 100644 > --- a/clang/lib/Lex/PPMacroExpansion.cpp > +++ b/clang/lib/Lex/PPMacroExpansion.cpp > @@ -342,6 +342,7 @@ void Preprocessor::RegisterBuiltinMacros() { > Ident__TIME__ = RegisterBuiltinMacro(*this, "__TIME__"); > Ident__COUNTER__ = RegisterBuiltinMacro(*this, "__COUNTER__"); > Ident_Pragma = RegisterBuiltinMacro(*this, "_Pragma"); > + Ident__FLT_EVAL_METHOD__ = RegisterBuiltinMacro(*this, > "__FLT_EVAL_METHOD__"); > > // C++ Standing Document Extensions. > if (getLangOpts().CPlusPlus) > @@ -1574,6 +1575,17 @@ void Preprocessor::ExpandBuiltinMacro(Token &Tok) { > // Surround the string with " and strip the trailing newline. > OS << '"' << StringRef(Result).drop_back() << '"'; > Tok.setKind(tok::string_literal); > + } else if (II == Ident__FLT_EVAL_METHOD__) { > + // __FLT_EVAL_METHOD__ is set to the default value. > + OS << getTUFPEvalMethod(); > + // __FLT_EVAL_METHOD__ expands to a simple numeric value. > + Tok.setKind(tok::numeric_constant); > + if (getLastFPEvalPragmaLocation().isValid()) { > + // The program is ill-formed. The value of __FLT_EVAL_METHOD__ is > altered > + // by the pragma. > + Diag(Tok, diag::err_illegal_use_of_flt_eval_macro); > + Diag(getLastFPEvalPragmaLocation(), diag::note_pragma_entered_here); > + } > } else if (II == Ident__COUNTER__) { > // __COUNTER__ expands to a simple numeric value. > OS << CounterValue++; > > diff --git a/clang/lib/Parse/ParsePragma.cpp > b/clang/lib/Parse/ParsePragma.cpp > index 27e8501278626..5c6aa0e47635b 100644 > --- a/clang/lib/Parse/ParsePragma.cpp > +++ b/clang/lib/Parse/ParsePragma.cpp > @@ -3028,12 +3028,13 @@ void PragmaOptimizeHandler::HandlePragma(Preprocessor > &PP, > namespace { > /// Used as the annotation value for tok::annot_pragma_fp. > struct TokFPAnnotValue { > - enum FlagKinds { Contract, Reassociate, Exceptions }; > + enum FlagKinds { Contract, Reassociate, Exceptions, EvalMethod }; > enum FlagValues { On, Off, Fast }; > > llvm::Optional<LangOptions::FPModeKind> ContractValue; > llvm::Optional<LangOptions::FPModeKind> ReassociateValue; > llvm::Optional<LangOptions::FPExceptionModeKind> ExceptionsValue; > + llvm::Optional<LangOptions::FPEvalMethodKind> EvalMethodValue; > }; > } // end anonymous namespace > > @@ -3060,6 +3061,7 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP, > .Case("contract", TokFPAnnotValue::Contract) > .Case("reassociate", TokFPAnnotValue::Reassociate) > .Case("exceptions", TokFPAnnotValue::Exceptions) > + .Case("eval_method", TokFPAnnotValue::EvalMethod) > .Default(None); > if (!FlagKind) { > PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_option) > @@ -3074,8 +3076,11 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP, > return; > } > PP.Lex(Tok); > + bool isEvalMethodDouble = > + Tok.is(tok::kw_double) && FlagKind == TokFPAnnotValue::EvalMethod; > > - if (Tok.isNot(tok::identifier)) { > + // Don't diagnose if we have an eval_metod pragma with "double" kind. > + if (Tok.isNot(tok::identifier) && !isEvalMethodDouble) { > PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) > << PP.getSpelling(Tok) << OptionInfo->getName() > << static_cast<int>(*FlagKind); > @@ -3121,6 +3126,19 @@ void PragmaFPHandler::HandlePragma(Preprocessor &PP, > << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; > return; > } > + } else if (FlagKind == TokFPAnnotValue::EvalMethod) { > + AnnotValue->EvalMethodValue = > + llvm::StringSwitch<llvm::Optional<LangOptions::FPEvalMethodKind>>( > + II->getName()) > + .Case("source", LangOptions::FPEvalMethodKind::FEM_Source) > + .Case("double", LangOptions::FPEvalMethodKind::FEM_Double) > + .Case("extended", LangOptions::FPEvalMethodKind::FEM_Extended) > + .Default(llvm::None); > + if (!AnnotValue->EvalMethodValue) { > + PP.Diag(Tok.getLocation(), diag::err_pragma_fp_invalid_argument) > + << PP.getSpelling(Tok) << OptionInfo->getName() << *FlagKind; > + return; > + } > } > PP.Lex(Tok); > > @@ -3223,6 +3241,9 @@ void Parser::HandlePragmaFP() { > if (AnnotValue->ExceptionsValue) > Actions.ActOnPragmaFPExceptions(Tok.getLocation(), > *AnnotValue->ExceptionsValue); > + if (AnnotValue->EvalMethodValue) > + Actions.ActOnPragmaFPEvalMethod(Tok.getLocation(), > + *AnnotValue->EvalMethodValue); > ConsumeAnnotationToken(); > } > > > diff --git a/clang/lib/Parse/ParseStmt.cpp b/clang/lib/Parse/ParseStmt.cpp > index ee07775b6346f..cadedf6d98dbd 100644 > --- a/clang/lib/Parse/ParseStmt.cpp > +++ b/clang/lib/Parse/ParseStmt.cpp > @@ -1153,6 +1153,16 @@ StmtResult Parser::ParseCompoundStatementBody(bool > isStmtExpr) { > if (R.isUsable()) > Stmts.push_back(R.get()); > } > + // Warn the user that using option `-ffp-eval-method=source` on a > + // 32-bit target and feature `sse` disabled, or using > + // `pragma clang fp eval_method=source` and feature `sse` disabled, is not > + // supported. > + if (!PP.getTargetInfo().supportSourceEvalMethod() && > + (PP.getLastFPEvalPragmaLocation().isValid() || > + PP.getCurrentFPEvalMethod() == > + LangOptions::FPEvalMethodKind::FEM_Source)) > + Diag(Tok.getLocation(), > + diag::warn_no_support_for_eval_method_source_on_m32); > > SourceLocation CloseLoc = Tok.getLocation(); > > > diff --git a/clang/lib/Sema/Sema.cpp b/clang/lib/Sema/Sema.cpp > index 7b57c8da4e9cc..db3eda622639f 100644 > --- a/clang/lib/Sema/Sema.cpp > +++ b/clang/lib/Sema/Sema.cpp > @@ -242,6 +242,15 @@ Sema::Sema(Preprocessor &pp, ASTContext &ctxt, > ASTConsumer &consumer, > SemaPPCallbackHandler = Callbacks.get(); > PP.addPPCallbacks(std::move(Callbacks)); > SemaPPCallbackHandler->set(*this); > + if (getLangOpts().getFPEvalMethod() == LangOptions::FEM_UnsetOnCommandLine) > + // Use setting from TargetInfo. > + PP.setCurrentFPEvalMethod(SourceLocation(), > + ctxt.getTargetInfo().getFPEvalMethod()); > + else > + // Set initial value of __FLT_EVAL_METHOD__ from the command line. > + PP.setCurrentFPEvalMethod(SourceLocation(), > + getLangOpts().getFPEvalMethod()); > + CurFPFeatures.setFPEvalMethod(PP.getCurrentFPEvalMethod()); > } > > // Anchor Sema's type info to this TU. > @@ -2630,3 +2639,15 @@ const llvm::MapVector<FieldDecl *, Sema::DeleteLocs> & > Sema::getMismatchingDeleteExpressions() const { > return DeleteExprs; > } > + > +Sema::FPFeaturesStateRAII::FPFeaturesStateRAII(Sema &S) > + : S(S), OldFPFeaturesState(S.CurFPFeatures), > + OldOverrides(S.FpPragmaStack.CurrentValue), > + OldEvalMethod(S.PP.getCurrentFPEvalMethod()), > + OldFPPragmaLocation(S.PP.getLastFPEvalPragmaLocation()) {} > + > +Sema::FPFeaturesStateRAII::~FPFeaturesStateRAII() { > + S.CurFPFeatures = OldFPFeaturesState; > + S.FpPragmaStack.CurrentValue = OldOverrides; > + S.PP.setCurrentFPEvalMethod(OldFPPragmaLocation, OldEvalMethod); > +} > > diff --git a/clang/lib/Sema/SemaAttr.cpp b/clang/lib/Sema/SemaAttr.cpp > index 38e6e60af90db..d623060fd10cf 100644 > --- a/clang/lib/Sema/SemaAttr.cpp > +++ b/clang/lib/Sema/SemaAttr.cpp > @@ -470,6 +470,27 @@ void Sema::ActOnPragmaDetectMismatch(SourceLocation Loc, > StringRef Name, > Consumer.HandleTopLevelDecl(DeclGroupRef(PDMD)); > } > > +void Sema::ActOnPragmaFPEvalMethod(SourceLocation Loc, > + LangOptions::FPEvalMethodKind Value) { > + FPOptionsOverride NewFPFeatures = CurFPFeatureOverrides(); > + switch (Value) { > + default: > + llvm_unreachable("invalid pragma eval_method kind"); > + case LangOptions::FEM_Source: > + NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Source); > + break; > + case LangOptions::FEM_Double: > + NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Double); > + break; > + case LangOptions::FEM_Extended: > + NewFPFeatures.setFPEvalMethodOverride(LangOptions::FEM_Extended); > + break; > + } > + FpPragmaStack.Act(Loc, PSK_Set, StringRef(), NewFPFeatures); > + CurFPFeatures = NewFPFeatures.applyOverrides(getLangOpts()); > + PP.setCurrentFPEvalMethod(Loc, Value); > +} > + > void Sema::ActOnPragmaFloatControl(SourceLocation Loc, > PragmaMsStackAction Action, > PragmaFloatControlKind Value) { > > diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp > index 22b3f371afe79..88fc89bec629a 100644 > --- a/clang/lib/Sema/SemaExpr.cpp > +++ b/clang/lib/Sema/SemaExpr.cpp > @@ -773,6 +773,40 @@ ExprResult Sema::UsualUnaryConversions(Expr *E) { > QualType Ty = E->getType(); > assert(!Ty.isNull() && "UsualUnaryConversions - missing type"); > > + LangOptions::FPEvalMethodKind EvalMethod = CurFPFeatures.getFPEvalMethod(); > + if (EvalMethod != LangOptions::FEM_Source && Ty->isFloatingType() && > + (getLangOpts().getFPEvalMethod() != > + LangOptions::FPEvalMethodKind::FEM_UnsetOnCommandLine || > + PP.getLastFPEvalPragmaLocation().isValid())) { > + switch (EvalMethod) { > + default: > + llvm_unreachable("Unrecognized float evaluation method"); > + break; > + case LangOptions::FEM_UnsetOnCommandLine: > + llvm_unreachable("Float evaluation method should be set by now"); > + break; > + case LangOptions::FEM_Double: > + if (Context.getFloatingTypeOrder(Context.DoubleTy, Ty) > 0) > + // Widen the expression to double. > + return Ty->isComplexType() > + ? ImpCastExprToType(E, > + > Context.getComplexType(Context.DoubleTy), > + CK_FloatingComplexCast) > + : ImpCastExprToType(E, Context.DoubleTy, CK_FloatingCast); > + break; > + case LangOptions::FEM_Extended: > + if (Context.getFloatingTypeOrder(Context.LongDoubleTy, Ty) > 0) > + // Widen the expression to long double. > + return Ty->isComplexType() > + ? ImpCastExprToType( > + E, Context.getComplexType(Context.LongDoubleTy), > + CK_FloatingComplexCast) > + : ImpCastExprToType(E, Context.LongDoubleTy, > + CK_FloatingCast); > + break; > + } > + } > + > // Half FP have to be promoted to float unless it is natively supported > if (Ty->isHalfType() && !getLangOpts().NativeHalfType) > return ImpCastExprToType(Res.get(), Context.FloatTy, CK_FloatingCast); > > diff --git a/clang/test/CodeGen/X86/32bit-behavior-no-eval.c > b/clang/test/CodeGen/X86/32bit-behavior-no-eval.c > new file mode 100644 > index 0000000000000..d040e827ce31c > --- /dev/null > +++ b/clang/test/CodeGen/X86/32bit-behavior-no-eval.c > @@ -0,0 +1,30 @@ > +// SSE > +// RUN: %clang_cc1 \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \ > +// RUN: -emit-llvm -o - %s | FileCheck -check-prefix=CHECK %s > + > +// NO SSE > +// RUN: %clang_cc1 \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \ > +// RUN: -emit-llvm -o - %s | FileCheck -check-prefix=CHECK %s > + > +// NO SSE Fast Math > +// RUN: %clang_cc1 \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \ > +// RUN: -ffast-math -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-FM %s > + > +float addit(float a, float b, float c) { > + // CHECK: load float, float* > + // CHECK: load float, float* > + // CHECK: fadd float > + // CHECK: load float, float* > + // CHECK: fadd float > + > + // CHECK-FM: load float, float* > + // CHECK-FM: load float, float* > + // CHECK-FM: fadd reassoc nnan ninf nsz arcp afn float > + // CHECK-FM: load float, float* > + // CHECK-FM: fadd reassoc nnan ninf nsz arcp afn float > + > + return a + b + c; > +} > > diff --git a/clang/test/CodeGen/X86/32bit-behavior.c > b/clang/test/CodeGen/X86/32bit-behavior.c > new file mode 100644 > index 0000000000000..a7e0f008c9f35 > --- /dev/null > +++ b/clang/test/CodeGen/X86/32bit-behavior.c > @@ -0,0 +1,109 @@ > +// SSE > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=source \ > +// RUN: | FileCheck -check-prefix=CHECK-SRC %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=double \ > +// RUN: | FileCheck -check-prefix=CHECK-DBL %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=extended \ > +// RUN: | FileCheck -check-prefix=CHECK-DBL %s > + > +// SSE Fast Math > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=source \ > +// RUN: -ffast-math | FileCheck -check-prefix=CHECK-FM-SRC %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=double \ > +// RUN: -ffast-math | FileCheck -check-prefix=CHECK-FM %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature +sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=extended \ > +// RUN: -ffast-math | FileCheck -check-prefix=CHECK-FM %s > + > +// NO SSE > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=source \ > +// RUN: | FileCheck -check-prefix=CHECK-SRC %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=double \ > +// RUN: | FileCheck -check-prefix=CHECK-DBL %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=extended \ > +// RUN: | FileCheck -check-prefix=CHECK-DBL %s > + > +// NO SSE Fast Math > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=source \ > +// RUN: -ffast-math | FileCheck -check-prefix=CHECK %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=double \ > +// RUN: -ffast-math | FileCheck -check-prefix=CHECK-DBL-FM %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=extended \ > +// RUN: -ffast-math | FileCheck -check-prefix=CHECK-DBL-FM %s > + > +float addit(float a, float b, float c) { > + // CHECK-SRC: load float, float* > + // CHECK-SRC: load float, float* > + // CHECK-SRC: fadd float > + // CHECK-SRC: load float, float* > + // CHECK-SRC: fadd float > + > + // CHECK-FM-SRC: load float, float* > + // CHECK-FM-SRC: load float, float* > + // CHECK-FM-SRC: fadd reassoc nnan ninf nsz arcp afn float > + // CHECK-FM-SRC: load float, float* > + // CHECK-FM-SRC: fadd reassoc nnan ninf nsz arcp afn float > + > + // CHECK-FM: load float, float* > + // CHECK-FM: fpext float {{.*}} to double > + // CHECK-FM: load float, float* > + // CHECK-FM: fpext float {{.*}} to double > + // CHECK-FM: fadd reassoc nnan ninf nsz arcp afn double > + // CHECK-FM: load float, float* > + // CHECK-FM: fadd reassoc nnan ninf nsz arcp afn double > + // CHECK-FM: fptrunc double {{.*}} to float > + > + // CHECK-DBL: load float, float* > + // CHECK-DBL: fpext float {{.*}} to double > + // CHECK-DBL: load float, float* > + // CHECK-DBL: fpext float {{.*}} to double > + // CHECK-DBL: fadd double > + // CHECK-DBL: load float, float* > + // CHECK-DBL: fpext float {{.*}} to double > + // CHECK-DBL: fadd double > + // CHECK-DBL: fptrunc double {{.*}} to float > + > + // CHECK-DBL-FM: load float, float* > + // CHECK-DBL-FM: fpext float {{.*}} to double > + // CHECK-DBL-FM: load float, float* > + // CHECK-DBL-FM: fpext float {{.*}} to double > + // CHECK-DBL-FM: fadd reassoc nnan ninf nsz arcp afn double > + // CHECK-DBL-FM: load float, float* > + // CHECK-DBL-FM: fpext float {{.*}} to double > + // CHECK-DBL-FM: fadd reassoc nnan ninf nsz arcp afn double > + // CHECK-DBL-FM: fptrunc double {{.*}} to float > + > + // CHECK: ret float > + return a + b + c; > +} > > diff --git a/clang/test/CodeGen/X86/fp-eval-method.c > b/clang/test/CodeGen/X86/fp-eval-method.c > new file mode 100644 > index 0000000000000..5bfc3701050f5 > --- /dev/null > +++ b/clang/test/CodeGen/X86/fp-eval-method.c > @@ -0,0 +1,20 @@ > +// RUN: %clang_cc1 -triple i386-unknown-netbsd6 -emit-llvm -o - %s \ > +// RUN: | FileCheck %s -check-prefixes=CHECK > + > +// RUN: %clang_cc1 -triple i386-unknown-netbsd7 -emit-llvm -o - %s \ > +// RUN: | FileCheck %s -check-prefixes=CHECK-EXT > + > +// RUN: %clang_cc1 -triple i386--linux -emit-llvm -o - %s \ > +// RUN: | FileCheck %s -check-prefixes=CHECK-EXT > + > +float f(float x, float y) { > + // CHECK: define{{.*}} float @f > + // CHECK: fadd float > + return 2.0f + x + y; > +} > + > +int getEvalMethod() { > + // CHECK: ret i32 1 > + // CHECK-EXT: ret i32 2 > + return __FLT_EVAL_METHOD__; > +} > > diff --git a/clang/test/CodeGen/flt_eval_macro.cpp > b/clang/test/CodeGen/flt_eval_macro.cpp > new file mode 100644 > index 0000000000000..aa7455f0efe0b > --- /dev/null > +++ b/clang/test/CodeGen/flt_eval_macro.cpp > @@ -0,0 +1,79 @@ > +// RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 \ > +// RUN: -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s \ > +// RUN: | FileCheck -check-prefix=CHECK-SRC %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \ > +// RUN: | FileCheck -check-prefix=CHECK-SRC %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=double \ > +// RUN: | FileCheck -check-prefixes=CHECK-DBL %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s > -ffp-eval-method=extended \ > +// RUN: | FileCheck -check-prefixes=CHECK-EXT-FLT %s > + > +// RUN: %clang_cc1 -triple powerpc-unknown-aix -emit-llvm -o - %s \ > +// RUN: | FileCheck %s -check-prefix=CHECK-DBL-PPC > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple > i386-linux-gnu \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=extended -mlong-double-80 \ > +// RUN: | FileCheck %s -check-prefix=CHECK-EXT-FLT > + > +int getFEM() { > + // LABEL: define {{.*}}getFEM{{.*}} > + return __FLT_EVAL_METHOD__; > + // CHECK-SRC: ret {{.*}} 0 > + // CHECK-DBL: ret {{.*}} 1 > + // CHECK-DBL-PPC: ret {{.*}} 1 > + // CHECK-EXT-FLT: ret {{.*}} 2 > +} > + > +float func() { > + // LABEL: define {{.*}}@_Z4func{{.*}} > + float X = 100.0f; > + float Y = -45.3f; > + float Z = 393.78f; > + float temp; > +#if __FLT_EVAL_METHOD__ == 0 > + temp = X + Y + Z; > +#elif __FLT_EVAL_METHOD__ == 1 > + temp = X * Y * Z; > +#elif __FLT_EVAL_METHOD__ == 2 > + temp = X * Y - Z; > +#endif > + // CHECK-SRC: load float, float* > + // CHECK-SRC: load float, float* > + // CHECK-SRC: fadd float > + // CHECK-SRC: load float, float* > + // CHECK-SRC: fadd float > + > + // CHECK-DBL: load float, float* > + // CHECK-DBL: fpext float > + // CHECK-DBL: load float, float* > + // CHECK-DBL: fpext float > + // CHECK-DBL: fmul double > + // CHECK-DBL: load float, float* > + // CHECK-DBL: fpext float > + // CHECK-DBL: fmul double > + // CHECK-DBL: fptrunc double > + > + // CHECK-EXT-FLT: load float, float* > + // CHECK-EXT-FLT: fpext float > + // CHECK-EXT-FLT: load float, float* > + // CHECK-EXT-FLT: fpext float > + // CHECK-EXT-FLT: fmul x86_fp80 > + // CHECK-EXT-FLT: load float, float* > + // CHECK-EXT-FLT: fpext float > + // CHECK-EXT-FLT: fsub x86_fp80 > + // CHECK-EXT-FLT: fptrunc x86_fp80 > + > + // CHECK-DBL-PPC: load float, float* > + // CHECK-DBL-PPC: load float, float* > + // CHECK-DBL-PPC: fmul float > + // CHECK-DBL-PPC: load float, float* > + // CHECK-DBL-PPC: fmul float > + > + return temp; > +} > > diff --git a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp > b/clang/test/CodeGen/fp-floatcontrol-pragma.cpp > index ef29d24de1dbc..966eaf6053970 100644 > --- a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp > +++ b/clang/test/CodeGen/fp-floatcontrol-pragma.cpp > @@ -1,7 +1,53 @@ > -// RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 > -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck > -check-prefix=CHECK-NS %s > -// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple > x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s > -// RUN: %clang_cc1 -fexperimental-strict-floating-point -DFENV_ON=1 -triple > x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-FENV %s > -// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple > %itanium_abi_triple -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-O3 > %s > +// RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 \ > +// RUN: -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s \ > +// RUN: | FileCheck -check-prefix=CHECK-NS %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s \ > +// RUN: -check-prefixes=CHECK-DEFAULT,CHECK-CONST-ARGS > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point -DFENV_ON=1 \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s \ > +// RUN: | FileCheck -check-prefix=CHECK-FENV %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point -DNF128 \ > +// RUN: -triple %itanium_abi_triple -O3 -emit-llvm -o - %s \ > +// RUN: | FileCheck -check-prefix=CHECK-O3 %s > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \ > +// RUN: | FileCheck %s -check-prefixes=CHECK-SOURCE,CHECK-CONST-ARGS > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=double \ > +// RUN: | FileCheck %s -check-prefixes=CHECK-DOUBLE,CHECK-CONST-ARGS > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s > -ffp-eval-method=extended \ > +// RUN: -mlong-double-80 | FileCheck %s \ > +// RUN: -check-prefixes=CHECK-EXTENDED,CHECK-CONST-ARGS > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \ > +// RUN: | FileCheck %s -check-prefix=CHECK-SOURCE > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple > i386-linux-gnu \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=double | FileCheck %s \ > +// RUN: -check-prefix=CHECK-DOUBLE > + > +// RUN: %clang_cc1 -fexperimental-strict-floating-point -triple > i386-linux-gnu \ > +// RUN: -emit-llvm -o - %s -ffp-eval-method=extended -mlong-double-80 \ > +// RUN: | FileCheck %s -check-prefix=CHECK-EXTENDED > + > +// RUN: %clang_cc1 -triple powerpc-unknown-aix -DNF128 -emit-llvm -o - %s \ > +// RUN: | FileCheck %s -check-prefix=CHECK-AIX > + > +bool f() { > + // CHECK: define {{.*}}f{{.*}} > + return __FLT_EVAL_METHOD__ < 0 && > + __FLT_EVAL_METHOD__ == -1; > + // CHECK: ret {{.*}} true > +} > > // Verify float_control(precise, off) enables fast math flags on fp > operations. > float fp_precise_1(float a, float b, float c) { > @@ -229,3 +275,115 @@ float try_lam(float x, unsigned n) { > result = x + t; > return result; > } > + > +float mySub(float x, float y) { > + // CHECK: define {{.*}}float {{.*}}mySub{{.*}} > + // CHECK-NS: fsub float > + // CHECK-SOURCE: fsub float > + // CHECK-DOUBLE: fpext float > + // CHECK-DOUBLE: fpext float > + // CHECK-DOUBLE: fsub double > + // CHECK-DOUBLE: fptrunc double {{.*}} to float > + // CHECK-EXTENDED: fpext float > + // CHECK-EXTENDED: fpext float > + // CHECK-EXTENDED: fsub double > + // CHECK-EXTENDED: fptrunc double {{.*}} to float > + return x - y; > +} > + > +float mySubSource(float x, float y) { > +// CHECK: define {{.*}}float {{.*}}mySubSource{{.*}} > +#pragma clang fp eval_method(source) > + return x - y; > + // CHECK: fsub float > +} > + > +float mySubExtended(float x, float y) { > +// CHECK: define {{.*}}float {{.*}}mySubExtended{{.*}} > +#pragma clang fp eval_method(extended) > + return x - y; > + // CHECK: fpext float > + // CHECK: fpext float > + // CHECK: fsub x86_fp80 > + // CHECK: fptrunc x86_fp80 {{.*}} to float > + // CHECK-AIX: fsub double > + // CHECK-AIX: fptrunc double > +} > + > +float mySubDouble(float x, float y) { > +// CHECK: define {{.*}}float {{.*}}mySubDouble{{.*}} > +#pragma clang fp eval_method(double) > + return x - y; > + // CHECK: fpext float > + // CHECK: fpext float > + // CHECK: fsub double > + // CHECK: fptrunc double {{.*}} to float > +} > + > +#ifndef NF128 > +__float128 mySub128(__float128 x, __float128 y) { > + // CHECK: define {{.*}}mySub128{{.*}} > + // Expect no fpext since fp128 is already widest > + // CHECK: load fp128 > + // CHECK-NEXT: load fp128 > + // CHECK-NEXT: fsub fp128 > + // CHECK-NEXT: ret fp128 > + return x - y; > +} > +#endif > + > +void mySubfp16(__fp16 *res, __fp16 *x, __fp16 *y) { > + // CHECK: define {{.*}}mySubfp16{{.*}} > + *res = *x - *y; > + // CHECK: load half > + // CHECK-NEXT: load half > + // CHECK-NEXT: fpext half{{.*}} > + // CHECK-NEXT: load half > + // CHECK-NEXT: load half > + // CHECK-NS: fpext half{{.*}} to float > + // CHECK-DEFAULT: fpext half{{.*}} to float > + // CHECK-DOUBLE: fpext half{{.*}} to float > + // CHECK-EXTENDED: fpext half{{.*}} to float > + // CHECK-NEXT: fsub > + // CHECK-NEXT: fptrunc {{.*}}to half > + // CHECK-NS: fptrunc float {{.*}} to half > + // CHECK-DOUBLE: fptrunc float {{.*}} to half > + // CHECK-EXTENDED: fptrunc float {{.*}} to half > +} > + > +float Div(float x, float y, float z) { > + // CHECK: define{{.*}}float {{.*}}Div{{.*}} > + // CHECK-CONST-ARGS: fdiv float > + return x / (y / z); > +} > + > +float DivExtended(float x, float y, float z) { > +// CHECK: define{{.*}}float {{.*}}DivExtended{{.*}} > +#pragma clang fp eval_method(extended) > + // CHECK-CONST-ARGS: fdiv x86_fp80 > + // CHECK-CONST-ARGS: fptrunc x86_fp80 > + return x / (y / z); > +} > + > +float DivDouble(float x, float y, float z) { > +// CHECK: define{{.*}}float {{.*}}DivDouble{{.*}} > +#pragma clang fp eval_method(double) > + // CHECK-CONST-ARGS: fdiv double > + // CHECK-CONST-ARGS: fptrunc double > + return x / (y / z); > +} > + > +float DivSource(float x, float y, float z) { > +// CHECK: define{{.*}}float {{.*}}DivSource{{.*}} > +#pragma clang fp eval_method(source) > + // CHECK-CONST-ARGS: fdiv float > + return x / (y / z); > +} > + > +int main() { > + float f = Div(4.2f, 1.0f, 3.0f); > + float fextended = DivExtended(4.2f, 1.0f, 3.0f); > + float fdouble = DivDouble(4.2f, 1.0f, 3.0f); > + float fsource = DivSource(4.2f, 1.0f, 3.0f); > + // CHECK: store float > +} > > diff --git a/clang/test/Preprocessor/flt_eval_macro.cpp > b/clang/test/Preprocessor/flt_eval_macro.cpp > new file mode 100644 > index 0000000000000..47f2592e261bd > --- /dev/null > +++ b/clang/test/Preprocessor/flt_eval_macro.cpp > @@ -0,0 +1,59 @@ > +// RUN: %clang_cc1 -E -dM %s -o - | FileCheck %s -strict-whitespace > + > +#ifdef __FLT_EVAL_METHOD__ > +#if __FLT_EVAL_METHOD__ == 3 > +#define __GLIBC_FLT_EVAL_METHOD 2 > +#else > +#define __GLIBC_FLT_EVAL_METHOD __FLT_EVAL_METHOD__ > +#endif > +#elif defined __x86_64__ > +#define __GLIBC_FLT_EVAL_METHOD 0 > +#else > +#define __GLIBC_FLT_EVAL_METHOD 2 > +#endif > + > +#if __GLIBC_FLT_EVAL_METHOD == 0 || __GLIBC_FLT_EVAL_METHOD == 16 > +#define Name "One" > +#elif __GLIBC_FLT_EVAL_METHOD == 1 > +#define Name "Two" > +#elif __GLIBC_FLT_EVAL_METHOD == 2 > +#define Name "Unset on command line" > +#elif __GLIBC_FLT_EVAL_METHOD == 32 > +#define Name "Four" > +#elif __GLIBC_FLT_EVAL_METHOD == 33 > +#define Name "Five" > +#elif __GLIBC_FLT_EVAL_METHOD == 64 > +#define Name "Six" > +#elif __GLIBC_FLT_EVAL_METHOD == 65 > +#define Name "Seven" > +#elif __GLIBC_FLT_EVAL_METHOD == 128 > +#define Name "Eight" > +#elif __GLIBC_FLT_EVAL_METHOD == 129 > +#define Name "Nine" > +#else > +#error "Unknown __GLIBC_FLT_EVAL_METHOD" > +#endif > + > +int foo() { > + // CHECK: #define Name "Unset on command line" > + return Name; > +} > + > +#if __FLT_EVAL_METHOD__ == 3 > +#define Val "val0" > +#endif > + > +#pragma fp eval_method(double) > + > +#if __FLT_EVAL_METHOD__ == 0 > +#define Val "val1" > +#elif __FLT_EVAL_METHOD__ == 1 > +#define Val "val2" > +#elif __FLT_EVAL_METHOD__ == 2 > +#define Val "val3" > +#endif > + > +int goo() { > + // CHECK: #define Val "val0" > + return Name; > +} > > diff --git a/clang/test/Preprocessor/init-aarch64.c > b/clang/test/Preprocessor/init-aarch64.c > index f6809d8d9b48f..66cab8b1f8d04 100644 > --- a/clang/test/Preprocessor/init-aarch64.c > +++ b/clang/test/Preprocessor/init-aarch64.c > @@ -93,7 +93,6 @@ > // AARCH64-NEXT: #define __FLT_DENORM_MIN__ 1.40129846e-45F > // AARCH64-NEXT: #define __FLT_DIG__ 6 > // AARCH64-NEXT: #define __FLT_EPSILON__ 1.19209290e-7F > -// AARCH64-NEXT: #define __FLT_EVAL_METHOD__ 0 > // AARCH64-NEXT: #define __FLT_HAS_DENORM__ 1 > // AARCH64-NEXT: #define __FLT_HAS_INFINITY__ 1 > // AARCH64-NEXT: #define __FLT_HAS_QUIET_NAN__ 1 > @@ -388,7 +387,6 @@ > // AARCH64-DARWIN: #define __FLT_DENORM_MIN__ 1.40129846e-45F > // AARCH64-DARWIN: #define __FLT_DIG__ 6 > // AARCH64-DARWIN: #define __FLT_EPSILON__ 1.19209290e-7F > -// AARCH64-DARWIN: #define __FLT_EVAL_METHOD__ 0 > // AARCH64-DARWIN: #define __FLT_HAS_DENORM__ 1 > // AARCH64-DARWIN: #define __FLT_HAS_INFINITY__ 1 > // AARCH64-DARWIN: #define __FLT_HAS_QUIET_NAN__ 1 > @@ -604,7 +602,6 @@ > // AARCH64-MSVC: #define __FLT_DENORM_MIN__ 1.40129846e-45F > // AARCH64-MSVC: #define __FLT_DIG__ 6 > // AARCH64-MSVC: #define __FLT_EPSILON__ 1.19209290e-7F > -// AARCH64-MSVC: #define __FLT_EVAL_METHOD__ 0 > // AARCH64-MSVC: #define __FLT_HAS_DENORM__ 1 > // AARCH64-MSVC: #define __FLT_HAS_INFINITY__ 1 > // AARCH64-MSVC: #define __FLT_HAS_QUIET_NAN__ 1 > > diff --git a/clang/test/Preprocessor/init-arm.c > b/clang/test/Preprocessor/init-arm.c > index 32eb2c513f8b0..2d1503c18560e 100644 > --- a/clang/test/Preprocessor/init-arm.c > +++ b/clang/test/Preprocessor/init-arm.c > @@ -35,7 +35,6 @@ > // ARM:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // ARM:#define __FLT_DIG__ 6 > // ARM:#define __FLT_EPSILON__ 1.19209290e-7F > -// ARM:#define __FLT_EVAL_METHOD__ 0 > // ARM:#define __FLT_HAS_DENORM__ 1 > // ARM:#define __FLT_HAS_INFINITY__ 1 > // ARM:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -235,7 +234,6 @@ > // ARM-BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // ARM-BE:#define __FLT_DIG__ 6 > // ARM-BE:#define __FLT_EPSILON__ 1.19209290e-7F > -// ARM-BE:#define __FLT_EVAL_METHOD__ 0 > // ARM-BE:#define __FLT_HAS_DENORM__ 1 > // ARM-BE:#define __FLT_HAS_INFINITY__ 1 > // ARM-BE:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -428,7 +426,6 @@ > // ARMEABISOFTFP:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // ARMEABISOFTFP:#define __FLT_DIG__ 6 > // ARMEABISOFTFP:#define __FLT_EPSILON__ 1.19209290e-7F > -// ARMEABISOFTFP:#define __FLT_EVAL_METHOD__ 0 > // ARMEABISOFTFP:#define __FLT_HAS_DENORM__ 1 > // ARMEABISOFTFP:#define __FLT_HAS_INFINITY__ 1 > // ARMEABISOFTFP:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -623,7 +620,6 @@ > // ARMEABIHARDFP:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // ARMEABIHARDFP:#define __FLT_DIG__ 6 > // ARMEABIHARDFP:#define __FLT_EPSILON__ 1.19209290e-7F > -// ARMEABIHARDFP:#define __FLT_EVAL_METHOD__ 0 > // ARMEABIHARDFP:#define __FLT_HAS_DENORM__ 1 > // ARMEABIHARDFP:#define __FLT_HAS_INFINITY__ 1 > // ARMEABIHARDFP:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -821,7 +817,6 @@ > // ARM-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // ARM-NETBSD:#define __FLT_DIG__ 6 > // ARM-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F > -// ARM-NETBSD:#define __FLT_EVAL_METHOD__ 0 > // ARM-NETBSD:#define __FLT_HAS_DENORM__ 1 > // ARM-NETBSD:#define __FLT_HAS_INFINITY__ 1 > // ARM-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1 > > diff --git a/clang/test/Preprocessor/init-mips.c > b/clang/test/Preprocessor/init-mips.c > index d76396aa35c91..a07cee64e6848 100644 > --- a/clang/test/Preprocessor/init-mips.c > +++ b/clang/test/Preprocessor/init-mips.c > @@ -37,7 +37,6 @@ > // MIPS32BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // MIPS32BE:#define __FLT_DIG__ 6 > // MIPS32BE:#define __FLT_EPSILON__ 1.19209290e-7F > -// MIPS32BE:#define __FLT_EVAL_METHOD__ 0 > // MIPS32BE:#define __FLT_HAS_DENORM__ 1 > // MIPS32BE:#define __FLT_HAS_INFINITY__ 1 > // MIPS32BE:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -247,7 +246,6 @@ > // MIPS32EL:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // MIPS32EL:#define __FLT_DIG__ 6 > // MIPS32EL:#define __FLT_EPSILON__ 1.19209290e-7F > -// MIPS32EL:#define __FLT_EVAL_METHOD__ 0 > // MIPS32EL:#define __FLT_HAS_DENORM__ 1 > // MIPS32EL:#define __FLT_HAS_INFINITY__ 1 > // MIPS32EL:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -467,7 +465,6 @@ > // MIPSN32BE: #define __FLT_DENORM_MIN__ 1.40129846e-45F > // MIPSN32BE: #define __FLT_DIG__ 6 > // MIPSN32BE: #define __FLT_EPSILON__ 1.19209290e-7F > -// MIPSN32BE: #define __FLT_EVAL_METHOD__ 0 > // MIPSN32BE: #define __FLT_HAS_DENORM__ 1 > // MIPSN32BE: #define __FLT_HAS_INFINITY__ 1 > // MIPSN32BE: #define __FLT_HAS_QUIET_NAN__ 1 > @@ -774,7 +771,6 @@ > // MIPSN32EL: #define __FLT_DENORM_MIN__ 1.40129846e-45F > // MIPSN32EL: #define __FLT_DIG__ 6 > // MIPSN32EL: #define __FLT_EPSILON__ 1.19209290e-7F > -// MIPSN32EL: #define __FLT_EVAL_METHOD__ 0 > // MIPSN32EL: #define __FLT_HAS_DENORM__ 1 > // MIPSN32EL: #define __FLT_HAS_INFINITY__ 1 > // MIPSN32EL: #define __FLT_HAS_QUIET_NAN__ 1 > @@ -1074,7 +1070,6 @@ > // MIPS64BE:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // MIPS64BE:#define __FLT_DIG__ 6 > // MIPS64BE:#define __FLT_EPSILON__ 1.19209290e-7F > -// MIPS64BE:#define __FLT_EVAL_METHOD__ 0 > // MIPS64BE:#define __FLT_HAS_DENORM__ 1 > // MIPS64BE:#define __FLT_HAS_INFINITY__ 1 > // MIPS64BE:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -1284,7 +1279,6 @@ > // MIPS64EL:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // MIPS64EL:#define __FLT_DIG__ 6 > // MIPS64EL:#define __FLT_EPSILON__ 1.19209290e-7F > -// MIPS64EL:#define __FLT_EVAL_METHOD__ 0 > // MIPS64EL:#define __FLT_HAS_DENORM__ 1 > // MIPS64EL:#define __FLT_HAS_INFINITY__ 1 > // MIPS64EL:#define __FLT_HAS_QUIET_NAN__ 1 > > diff --git a/clang/test/Preprocessor/init-ppc.c > b/clang/test/Preprocessor/init-ppc.c > index 611b16dfb8f7e..45c8a5e53ad4f 100644 > --- a/clang/test/Preprocessor/init-ppc.c > +++ b/clang/test/Preprocessor/init-ppc.c > @@ -30,7 +30,6 @@ > // PPC603E:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PPC603E:#define __FLT_DIG__ 6 > // PPC603E:#define __FLT_EPSILON__ 1.19209290e-7F > -// PPC603E:#define __FLT_EVAL_METHOD__ 0 > // PPC603E:#define __FLT_HAS_DENORM__ 1 > // PPC603E:#define __FLT_HAS_INFINITY__ 1 > // PPC603E:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -224,7 +223,6 @@ > // PPC:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PPC:#define __FLT_DIG__ 6 > // PPC:#define __FLT_EPSILON__ 1.19209290e-7F > -// PPC:#define __FLT_EVAL_METHOD__ 0 > // PPC:#define __FLT_HAS_DENORM__ 1 > // PPC:#define __FLT_HAS_INFINITY__ 1 > // PPC:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -425,7 +423,6 @@ > // PPC-AIX:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PPC-AIX:#define __FLT_DIG__ 6 > // PPC-AIX:#define __FLT_EPSILON__ 1.19209290e-7F > -// PPC-AIX:#define __FLT_EVAL_METHOD__ 1 > // PPC-AIX:#define __FLT_HAS_DENORM__ 1 > // PPC-AIX:#define __FLT_HAS_INFINITY__ 1 > // PPC-AIX:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -798,7 +795,6 @@ > // PPC-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PPC-LINUX:#define __FLT_DIG__ 6 > // PPC-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F > -// PPC-LINUX:#define __FLT_EVAL_METHOD__ 0 > // PPC-LINUX:#define __FLT_HAS_DENORM__ 1 > // PPC-LINUX:#define __FLT_HAS_INFINITY__ 1 > // PPC-LINUX:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -1006,7 +1002,6 @@ > // PPC-DARWIN:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PPC-DARWIN:#define __FLT_DIG__ 6 > // PPC-DARWIN:#define __FLT_EPSILON__ 1.19209290e-7F > -// PPC-DARWIN:#define __FLT_EVAL_METHOD__ 0 > // PPC-DARWIN:#define __FLT_HAS_DENORM__ 1 > // PPC-DARWIN:#define __FLT_HAS_INFINITY__ 1 > // PPC-DARWIN:#define __FLT_HAS_QUIET_NAN__ 1 > > diff --git a/clang/test/Preprocessor/init-ppc64.c > b/clang/test/Preprocessor/init-ppc64.c > index 7a9525228c3b6..f0ccd1638c04d 100644 > --- a/clang/test/Preprocessor/init-ppc64.c > +++ b/clang/test/Preprocessor/init-ppc64.c > @@ -35,7 +35,6 @@ > // PPC64:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PPC64:#define __FLT_DIG__ 6 > // PPC64:#define __FLT_EPSILON__ 1.19209290e-7F > -// PPC64:#define __FLT_EVAL_METHOD__ 0 > // PPC64:#define __FLT_HAS_DENORM__ 1 > // PPC64:#define __FLT_HAS_INFINITY__ 1 > // PPC64:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -240,7 +239,6 @@ > // PPC64LE:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PPC64LE:#define __FLT_DIG__ 6 > // PPC64LE:#define __FLT_EPSILON__ 1.19209290e-7F > -// PPC64LE:#define __FLT_EVAL_METHOD__ 0 > // PPC64LE:#define __FLT_HAS_DENORM__ 1 > // PPC64LE:#define __FLT_HAS_INFINITY__ 1 > // PPC64LE:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -703,7 +701,6 @@ > // PPC64-AIX:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PPC64-AIX:#define __FLT_DIG__ 6 > // PPC64-AIX:#define __FLT_EPSILON__ 1.19209290e-7F > -// PPC64-AIX:#define __FLT_EVAL_METHOD__ 1 > // PPC64-AIX:#define __FLT_HAS_DENORM__ 1 > // PPC64-AIX:#define __FLT_HAS_INFINITY__ 1 > // PPC64-AIX:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -902,7 +899,6 @@ > // PPC64-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PPC64-LINUX:#define __FLT_DIG__ 6 > // PPC64-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F > -// PPC64-LINUX:#define __FLT_EVAL_METHOD__ 0 > // PPC64-LINUX:#define __FLT_HAS_DENORM__ 1 > // PPC64-LINUX:#define __FLT_HAS_INFINITY__ 1 > // PPC64-LINUX:#define __FLT_HAS_QUIET_NAN__ 1 > > diff --git a/clang/test/Preprocessor/init-s390x.c > b/clang/test/Preprocessor/init-s390x.c > index b0e45b5348ce9..6c646527f50f7 100644 > --- a/clang/test/Preprocessor/init-s390x.c > +++ b/clang/test/Preprocessor/init-s390x.c > @@ -23,7 +23,6 @@ > // S390X:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // S390X:#define __FLT_DIG__ 6 > // S390X:#define __FLT_EPSILON__ 1.19209290e-7F > -// S390X:#define __FLT_EVAL_METHOD__ 0 > // S390X:#define __FLT_HAS_DENORM__ 1 > // S390X:#define __FLT_HAS_INFINITY__ 1 > // S390X:#define __FLT_HAS_QUIET_NAN__ 1 > > diff --git a/clang/test/Preprocessor/init-v7k-compat.c > b/clang/test/Preprocessor/init-v7k-compat.c > index 482c7ad6ff687..ff5d4bbdea53a 100644 > --- a/clang/test/Preprocessor/init-v7k-compat.c > +++ b/clang/test/Preprocessor/init-v7k-compat.c > @@ -28,7 +28,6 @@ > // CHECK: #define __FLT_DENORM_MIN__ 1.40129846e-45F > // CHECK: #define __FLT_DIG__ 6 > // CHECK: #define __FLT_EPSILON__ 1.19209290e-7F > -// CHECK: #define __FLT_EVAL_METHOD__ 0 > // CHECK: #define __FLT_HAS_DENORM__ 1 > // CHECK: #define __FLT_HAS_INFINITY__ 1 > // CHECK: #define __FLT_HAS_QUIET_NAN__ 1 > > diff --git a/clang/test/Preprocessor/init-x86.c > b/clang/test/Preprocessor/init-x86.c > index 527cd39508889..aa2e05ec807c7 100644 > --- a/clang/test/Preprocessor/init-x86.c > +++ b/clang/test/Preprocessor/init-x86.c > @@ -24,7 +24,6 @@ > // I386:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // I386:#define __FLT_DIG__ 6 > // I386:#define __FLT_EPSILON__ 1.19209290e-7F > -// I386:#define __FLT_EVAL_METHOD__ 2 > // I386:#define __FLT_HAS_DENORM__ 1 > // I386:#define __FLT_HAS_INFINITY__ 1 > // I386:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -213,7 +212,6 @@ > // I386-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // I386-LINUX:#define __FLT_DIG__ 6 > // I386-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F > -// I386-LINUX:#define __FLT_EVAL_METHOD__ 0 > // I386-LINUX:#define __FLT_HAS_DENORM__ 1 > // I386-LINUX:#define __FLT_HAS_INFINITY__ 1 > // I386-LINUX:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -416,7 +414,6 @@ > // I386-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // I386-NETBSD:#define __FLT_DIG__ 6 > // I386-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F > -// I386-NETBSD:#define __FLT_EVAL_METHOD__ 2 > // I386-NETBSD:#define __FLT_HAS_DENORM__ 1 > // I386-NETBSD:#define __FLT_HAS_INFINITY__ 1 > // I386-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -590,13 +587,6 @@ > // I386-NETBSD:#define __i386__ 1 > // I386-NETBSD:#define i386 1 > > -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd -target-feature > +sse2 < /dev/null | FileCheck -match-full-lines -check-prefix I386-NETBSD-SSE > %s > -// I386-NETBSD-SSE:#define __FLT_EVAL_METHOD__ 0 > -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd6 < /dev/null | > FileCheck -match-full-lines -check-prefix I386-NETBSD6 %s > -// I386-NETBSD6:#define __FLT_EVAL_METHOD__ 1 > -// RUN: %clang_cc1 -E -dM -ffreestanding -triple=i386-netbsd6 > -target-feature +sse2 < /dev/null | FileCheck -match-full-lines -check-prefix > I386-NETBSD6-SSE %s > -// I386-NETBSD6-SSE:#define __FLT_EVAL_METHOD__ 1 > - > // RUN: %clang_cc1 -E -dM -triple=i686-pc-mingw32 < /dev/null | FileCheck > -match-full-lines -check-prefix I386-DECLSPEC %s > // RUN: %clang_cc1 -E -dM -fms-extensions -triple=i686-pc-mingw32 < > /dev/null | FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s > // RUN: %clang_cc1 -E -dM -triple=i686-unknown-cygwin < /dev/null | > FileCheck -match-full-lines -check-prefix I386-DECLSPEC %s > @@ -631,7 +621,6 @@ > // X86_64:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // X86_64:#define __FLT_DIG__ 6 > // X86_64:#define __FLT_EPSILON__ 1.19209290e-7F > -// X86_64:#define __FLT_EVAL_METHOD__ 0 > // X86_64:#define __FLT_HAS_DENORM__ 1 > // X86_64:#define __FLT_HAS_INFINITY__ 1 > // X86_64:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -839,7 +828,6 @@ > // X32:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // X32:#define __FLT_DIG__ 6 > // X32:#define __FLT_EPSILON__ 1.19209290e-7F > -// X32:#define __FLT_EVAL_METHOD__ 0 > // X32:#define __FLT_HAS_DENORM__ 1 > // X32:#define __FLT_HAS_INFINITY__ 1 > // X32:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -1046,7 +1034,6 @@ > // X86_64-CLOUDABI:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // X86_64-CLOUDABI:#define __FLT_DIG__ 6 > // X86_64-CLOUDABI:#define __FLT_EPSILON__ 1.19209290e-7F > -// X86_64-CLOUDABI:#define __FLT_EVAL_METHOD__ 0 > // X86_64-CLOUDABI:#define __FLT_HAS_DENORM__ 1 > // X86_64-CLOUDABI:#define __FLT_HAS_INFINITY__ 1 > // X86_64-CLOUDABI:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -1341,7 +1328,6 @@ > // X86_64-LINUX:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // X86_64-LINUX:#define __FLT_DIG__ 6 > // X86_64-LINUX:#define __FLT_EPSILON__ 1.19209290e-7F > -// X86_64-LINUX:#define __FLT_EVAL_METHOD__ 0 > // X86_64-LINUX:#define __FLT_HAS_DENORM__ 1 > // X86_64-LINUX:#define __FLT_HAS_INFINITY__ 1 > // X86_64-LINUX:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -1554,7 +1540,6 @@ > // X86_64-NETBSD:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // X86_64-NETBSD:#define __FLT_DIG__ 6 > // X86_64-NETBSD:#define __FLT_EPSILON__ 1.19209290e-7F > -// X86_64-NETBSD:#define __FLT_EVAL_METHOD__ 0 > // X86_64-NETBSD:#define __FLT_HAS_DENORM__ 1 > // X86_64-NETBSD:#define __FLT_HAS_INFINITY__ 1 > // X86_64-NETBSD:#define __FLT_HAS_QUIET_NAN__ 1 > > diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c > index dd645bf6003ce..a08e503570723 100644 > --- a/clang/test/Preprocessor/init.c > +++ b/clang/test/Preprocessor/init.c > @@ -325,7 +325,6 @@ > // MSP430:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // MSP430:#define __FLT_DIG__ 6 > // MSP430:#define __FLT_EPSILON__ 1.19209290e-7F > -// MSP430:#define __FLT_EVAL_METHOD__ 0 > // MSP430:#define __FLT_HAS_DENORM__ 1 > // MSP430:#define __FLT_HAS_INFINITY__ 1 > // MSP430:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -513,7 +512,6 @@ > // NVPTX32:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // NVPTX32:#define __FLT_DIG__ 6 > // NVPTX32:#define __FLT_EPSILON__ 1.19209290e-7F > -// NVPTX32:#define __FLT_EVAL_METHOD__ 0 > // NVPTX32:#define __FLT_HAS_DENORM__ 1 > // NVPTX32:#define __FLT_HAS_INFINITY__ 1 > // NVPTX32:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -702,7 +700,6 @@ > // NVPTX64:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // NVPTX64:#define __FLT_DIG__ 6 > // NVPTX64:#define __FLT_EPSILON__ 1.19209290e-7F > -// NVPTX64:#define __FLT_EVAL_METHOD__ 0 > // NVPTX64:#define __FLT_HAS_DENORM__ 1 > // NVPTX64:#define __FLT_HAS_INFINITY__ 1 > // NVPTX64:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -906,7 +903,6 @@ > // SPARC:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // SPARC:#define __FLT_DIG__ 6 > // SPARC:#define __FLT_EPSILON__ 1.19209290e-7F > -// SPARC:#define __FLT_EVAL_METHOD__ 0 > // SPARC:#define __FLT_HAS_DENORM__ 1 > // SPARC:#define __FLT_HAS_INFINITY__ 1 > // SPARC:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -1107,7 +1103,6 @@ > // TCE:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // TCE:#define __FLT_DIG__ 6 > // TCE:#define __FLT_EPSILON__ 1.19209290e-7F > -// TCE:#define __FLT_EVAL_METHOD__ 0 > // TCE:#define __FLT_HAS_DENORM__ 1 > // TCE:#define __FLT_HAS_INFINITY__ 1 > // TCE:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -1274,7 +1269,6 @@ > // PS4:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // PS4:#define __FLT_DIG__ 6 > // PS4:#define __FLT_EPSILON__ 1.19209290e-7F > -// PS4:#define __FLT_EVAL_METHOD__ 0 > // PS4:#define __FLT_HAS_DENORM__ 1 > // PS4:#define __FLT_HAS_INFINITY__ 1 > // PS4:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -1576,7 +1570,6 @@ > // WEBASSEMBLY-NEXT:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // WEBASSEMBLY-NEXT:#define __FLT_DIG__ 6 > // WEBASSEMBLY-NEXT:#define __FLT_EPSILON__ 1.19209290e-7F > -// WEBASSEMBLY-NEXT:#define __FLT_EVAL_METHOD__ 0 > // WEBASSEMBLY-NEXT:#define __FLT_HAS_DENORM__ 1 > // WEBASSEMBLY-NEXT:#define __FLT_HAS_INFINITY__ 1 > // WEBASSEMBLY-NEXT:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -1946,7 +1939,6 @@ > // AVR:#define __FLT_DENORM_MIN__ 1.40129846e-45F > // AVR:#define __FLT_DIG__ 6 > // AVR:#define __FLT_EPSILON__ 1.19209290e-7F > -// AVR:#define __FLT_EVAL_METHOD__ 0 > // AVR:#define __FLT_HAS_DENORM__ 1 > // AVR:#define __FLT_HAS_INFINITY__ 1 > // AVR:#define __FLT_HAS_QUIET_NAN__ 1 > @@ -2083,7 +2075,6 @@ > // AVR:#define __WCHAR_TYPE__ int > // AVR:#define __WINT_TYPE__ int > > - > // RUN: %clang_cc1 -E -dM -ffreestanding \ > // RUN: -triple i686-windows-msvc -fms-compatibility -x c++ < /dev/null \ > // RUN: | FileCheck -match-full-lines -check-prefix MSVC-X32 %s > @@ -2229,7 +2220,6 @@ > // RISCV32: #define __FLT_DENORM_MIN__ 1.40129846e-45F > // RISCV32: #define __FLT_DIG__ 6 > // RISCV32: #define __FLT_EPSILON__ 1.19209290e-7F > -// RISCV32: #define __FLT_EVAL_METHOD__ 0 > // RISCV32: #define __FLT_HAS_DENORM__ 1 > // RISCV32: #define __FLT_HAS_INFINITY__ 1 > // RISCV32: #define __FLT_HAS_QUIET_NAN__ 1 > @@ -2437,7 +2427,6 @@ > // RISCV64: #define __FLT_DENORM_MIN__ 1.40129846e-45F > // RISCV64: #define __FLT_DIG__ 6 > // RISCV64: #define __FLT_EPSILON__ 1.19209290e-7F > -// RISCV64: #define __FLT_EVAL_METHOD__ 0 > // RISCV64: #define __FLT_HAS_DENORM__ 1 > // RISCV64: #define __FLT_HAS_INFINITY__ 1 > // RISCV64: #define __FLT_HAS_QUIET_NAN__ 1 > > diff --git a/clang/test/Sema/fp-eval-pragma.cpp > b/clang/test/Sema/fp-eval-pragma.cpp > new file mode 100644 > index 0000000000000..42d88fd438e81 > --- /dev/null > +++ b/clang/test/Sema/fp-eval-pragma.cpp > @@ -0,0 +1,87 @@ > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - -verify %s > +// > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - -verify %s \ > +// RUN: -ffp-eval-method=source > +// > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - -verify %s \ > +// RUN: -ffp-eval-method=double > + > +extern "C" int printf(const char *, ...); > + > +void foo1() { > + printf("FP: %d\n", __FLT_EVAL_METHOD__); > +} > + > +void apply_pragma() { > + // expected-note@+1{{#pragma entered here}} > +#pragma clang fp eval_method(double) > + // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a > scope containing '#pragma clang fp eval_method'}} > + printf("FP: %d\n", __FLT_EVAL_METHOD__); > +} > + > +int foo2() { > + apply_pragma(); > + return 0; > +} > + > +void foo() { > + auto a = __FLT_EVAL_METHOD__; > + { > + // expected-note@+1{{#pragma entered here}} > +#pragma clang fp eval_method(double) > + // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a > scope containing '#pragma clang fp eval_method'}} > + auto b = __FLT_EVAL_METHOD__; > + } > + auto c = __FLT_EVAL_METHOD__; > +} > + > +void func() { > + { > + { > +#pragma clang fp eval_method(source) > + } > + int i = __FLT_EVAL_METHOD__; // ok, not in a scope changed by the pragma > + } > + { > + // expected-note@+1{{#pragma entered here}} > +#pragma clang fp eval_method(source) > + // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a > scope containing '#pragma clang fp eval_method'}} > + int i = __FLT_EVAL_METHOD__; > + } > +} > + > +float G; > + > +int f(float x, float y, float z) { > + G = x * y + z; > + return __FLT_EVAL_METHOD__; > +} > + > +int foo(int flag, float x, float y, float z) { > + if (flag) { > + // expected-note@+1{{#pragma entered here}} > +#pragma clang fp eval_method(double) > + G = x + y + z; > + // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a > scope containing '#pragma clang fp eval_method'}} > + return __FLT_EVAL_METHOD__; > + } else { > + // expected-note@+1{{#pragma entered here}} > +#pragma clang fp eval_method(extended) > + G = x + y + z; > + // expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a > scope containing '#pragma clang fp eval_method'}} > + return __FLT_EVAL_METHOD__; > + } > +} > + > +#if __FLT_EVAL_METHOD__ == 1 > +#endif > +#pragma clang fp eval_method(source) > + > +// expected-note@+1{{#pragma entered here}} > +#pragma clang fp eval_method(double) > +// expected-error@+1{{'__FLT_EVAL_METHOD__' cannot be expanded inside a > scope containing '#pragma clang fp eval_method'}} > +#if __FLT_EVAL_METHOD__ == 1 > +#endif > > diff --git a/clang/test/Sema/x86-eval-method.c > b/clang/test/Sema/x86-eval-method.c > new file mode 100644 > index 0000000000000..90f2fefc511c0 > --- /dev/null > +++ b/clang/test/Sema/x86-eval-method.c > @@ -0,0 +1,18 @@ > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 -target-feature -sse \ > +// RUN: -emit-llvm -ffp-eval-method=source -o - -verify=warn %s > +// > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple i386-pc-windows -target-cpu pentium4 \ > +// RUN: -emit-llvm -ffp-eval-method=source -o - -verify=no-warn %s > + > +// no-warn-no-diagnostics > + > +float add1(float a, float b, float c) { > + return a + b + c; > +} // warn-warning{{Setting FPEvalMethod to source on a 32bit target, with no > SSE is not supported.}} > + > +float add2(float a, float b, float c) { > +#pragma clang fp eval_method(source) > + return a + b + c; > +} // warn-warning{{Setting FPEvalMethod to source on a 32bit target, with no > SSE is not supported.}} > > diff --git a/clang/test/Sema/x86_64-eval-method.c > b/clang/test/Sema/x86_64-eval-method.c > new file mode 100644 > index 0000000000000..728423dd1b65b > --- /dev/null > +++ b/clang/test/Sema/x86_64-eval-method.c > @@ -0,0 +1,12 @@ > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -target-feature -sse -emit-llvm -o - > -verify %s > +// > +// RUN: %clang_cc1 -fexperimental-strict-floating-point \ > +// RUN: -triple x86_64-linux-gnu -emit-llvm -o - -verify=no-warn %s > + > +// no-warn-no-diagnostics > + > +float add2(float a, float b, float c) { > +#pragma clang fp eval_method(source) > + return a + b + c; > +} // expected-warning{{Setting FPEvalMethod to source on a 32bit target, > with no SSE is not supported.}} > > > > _______________________________________________ > cfe-commits mailing list > cfe-commits@lists.llvm.org > https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits