mibintc updated this revision to Diff 215225.
mibintc added a comment.
I added documentation for the new floating point options into clang/docs
Repository:
rL LLVM
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D62731/new/
https://reviews.llvm.org/D62731
Files:
clang/docs/UsersManual.rst
clang/include/clang/Basic/LangOptions.h
clang/include/clang/Driver/CC1Options.td
clang/include/clang/Driver/Options.td
clang/lib/CodeGen/CodeGenFunction.cpp
clang/lib/CodeGen/CodeGenFunction.h
clang/lib/Driver/ToolChains/Clang.cpp
clang/lib/Frontend/CompilerInvocation.cpp
clang/test/CodeGen/fpconstrained.c
clang/test/Driver/clang_f_opts.c
Index: clang/test/Driver/clang_f_opts.c
===================================================================
--- clang/test/Driver/clang_f_opts.c
+++ clang/test/Driver/clang_f_opts.c
@@ -217,6 +217,11 @@
// RUN: %clang -### -S -fexec-charset=iso-8859-1 -o /dev/null %s 2>&1 | FileCheck -check-prefix=CHECK-INVALID-INPUT-CHARSET %s
// CHECK-INVALID-INPUT-CHARSET: error: invalid value 'iso-8859-1' in '-fexec-charset=iso-8859-1'
+// RUN: %clang -### -S -fp-model=fast -fp-model=except -o /dev/null %s 2>&1 | FileCheck -check-prefix=CHECK-INVALID-FAST-EXCEPT %s
+// RUN: %clang -### -S -fp-model=fast -fp-model=except -o /dev/null %s 2>&1 | FileCheck -check-prefix=CHECK-INVALID-FAST-EXCEPT %s
+// CHECK-INVALID-FAST-EXCEPT: error: invalid argument 'fp-model=fast' not allowed with 'fp-model=except'
+//
+
// Test that we don't error on these.
// RUN: %clang -### -S -Werror \
// RUN: -falign-functions -falign-functions=2 -fno-align-functions \
Index: clang/test/CodeGen/fpconstrained.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/fpconstrained.c
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -fp-model=strict -emit-llvm -o - %s | FileCheck %s -check-prefix=STRICT
+// RUN: %clang_cc1 -fp-model=strict -fp-model-except -emit-llvm -o - %s | FileCheck %s -check-prefix=STRICTEXCEPT
+// RUN: %clang_cc1 -fp-model=strict -no-fp-model-except -emit-llvm -o - %s | FileCheck %s -check-prefix=STRICTNOEXCEPT
+// RUN: %clang_cc1 -fp-model-except -emit-llvm -o - %s | FileCheck %s -check-prefix=EXCEPT
+// RUN: %clang_cc1 -no-fp-model-except -emit-llvm -o - %s | FileCheck %s -check-prefix=NOEXCEPT
+// RUN: %clang_cc1 -fp-model=precise -emit-llvm -o - %s | FileCheck %s -check-prefix=PRECISE
+// RUN: %clang_cc1 -fp-model=fast -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
+// RUN: %clang_cc1 -fp-model=fast -fp-speculation=fast -emit-llvm -o - %s | FileCheck %s -check-prefix=NOEXCEPT
+// RUN: %clang_cc1 -fp-model=fast -fp-speculation=strict -emit-llvm -o - %s | FileCheck %s -check-prefix=EXCEPT
+// RUN: %clang_cc1 -fp-model=fast -fp-speculation=safe -emit-llvm -o - %s | FileCheck %s -check-prefix=MAYTRAP
+float f0, f1, f2;
+
+void foo(void) {
+ // CHECK-LABEL: define {{.*}}void @foo()
+
+ // MAYTRAP: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.tonearest", metadata !"fpexcept.maytrap")
+ // EXCEPT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.tonearest", metadata !"fpexcept.strict")
+ // NOEXCEPT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.tonearest", metadata !"fpexcept.ignore")
+ // STRICT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ // STRICTEXCEPT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.dynamic", metadata !"fpexcept.strict")
+ // STRICTNOEXCEPT: llvm.experimental.constrained.fadd.f32(float %0, float %1, metadata !"round.dynamic", metadata !"fpexcept.ignore")
+ // PRECISE: fadd float
+ // FAST: fadd fast
+ f0 = f1 + f2;
+
+ // CHECK: ret
+}
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -3039,6 +3039,59 @@
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
}
+ LangOptions::FPModelKind FPM = LangOptions::FPM_Off;
+ if (Arg *A = Args.getLastArg(OPT_fp_model_EQ)) {
+ StringRef Val = A->getValue();
+ if (Val == "precise")
+ FPM = LangOptions::FPM_Precise;
+ else if (Val == "strict")
+ FPM = LangOptions::FPM_Strict;
+ else if (Val == "fast")
+ FPM = LangOptions::FPM_Fast;
+ else
+ llvm_unreachable("invalid -fp-model setting");
+ }
+ Opts.getFPMOptions().setFPModelSetting(FPM);
+
+ LangOptions::FPModelExceptKind FPME = LangOptions::FPME_Off;
+ if (const Arg *A =
+ Args.getLastArg(OPT_fp_model_except, OPT_no_fp_model_except))
+ switch (A->getOption().getID()) {
+ case OPT_fp_model_except:
+ FPME = LangOptions::FPME_Except;
+ break;
+ case OPT_no_fp_model_except:
+ FPME = LangOptions::FPME_NoExcept;
+ break;
+ default:
+ llvm_unreachable("invalid -fp-model-except setting");
+ }
+ Opts.getFPMOptions().setFPModelExceptSetting(FPME);
+
+ LangOptions::FPSpeculationKind FPS = LangOptions::FPS_Off;
+ if (Arg *A = Args.getLastArg(OPT_fp_speculation_EQ)) {
+ StringRef Val = A->getValue();
+ if (Val == "fast")
+ FPS = LangOptions::FPS_Fast;
+ else if (Val == "strict")
+ FPS = LangOptions::FPS_Strict;
+ else if (Val == "safe")
+ FPS = LangOptions::FPS_Safe;
+ else
+ llvm_unreachable("invalid -fp-speculation setting");
+ Opts.getFPMOptions().setFPSpeculationSetting(FPS);
+ }
+
+ if (FPM == LangOptions::FPM_Precise)
+ // This doesn't correspond to constrained fp, equivalent to -fp-contract=on
+ Opts.setDefaultFPContractMode(LangOptions::FPC_On);
+ else if (FPM == LangOptions::FPM_Fast) {
+ // This doesn't correspond to constrained fp, equivalent to -ffast-math
+ Opts.FastMath = true;
+ Opts.FiniteMathOnly = true;
+ Opts.setDefaultFPContractMode(LangOptions::FPC_Fast);
+ }
+
Opts.RetainCommentsFromSystemHeaders =
Args.hasArg(OPT_fretain_comments_from_system_headers);
@@ -3404,6 +3457,15 @@
// FIXME: Should we really be calling this for an Language::Asm input?
ParseLangArgs(LangOpts, Args, DashX, Res.getTargetOpts(),
Res.getPreprocessorOpts(), Diags);
+ auto fpm = LangOpts.getFPMOptions().getFPModelSetting();
+ if (fpm == LangOptions::FPM_Fast) {
+ auto CGOpts = Res.getCodeGenOpts();
+ CGOpts.NoInfsFPMath = true;
+ CGOpts.UnsafeFPMath = true;
+ CGOpts.ReciprocalMath = true;
+ CGOpts.NoTrappingMath = true;
+ CGOpts.NoSignedZeros = true;
+ }
if (Res.getFrontendOpts().ProgramAction == frontend::RewriteObjC)
LangOpts.ObjCExceptions = 1;
if (T.isOSDarwin() && DashX.isPreprocessed()) {
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -2277,6 +2277,11 @@
bool TrappingMath = true;
StringRef DenormalFPMath = "";
StringRef FPContract = "";
+ LangOptions::FPModelKind FPModel = LangOptions::FPM_Off;
+ LangOptions::FPModelExceptKind FPModelExcept =
+ LangOptions::FPME_Off;
+ LangOptions::FPSpeculationKind FPSpeculation =
+ LangOptions::FPS_Off;
if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
@@ -2287,6 +2292,39 @@
switch (A->getOption().getID()) {
// If this isn't an FP option skip the claim below
default: continue;
+ // Options controlling floating point model and speculation
+ case options::OPT_fp_model_EQ: {
+ StringRef Val = A->getValue();
+ if (Val == "precise")
+ FPModel = LangOptions::FPM_Precise;
+ else if (Val == "strict")
+ FPModel = LangOptions::FPM_Strict;
+ else if (Val == "except")
+ FPModelExcept = LangOptions::FPME_Except;
+ else if (Val == "except-")
+ FPModelExcept = LangOptions::FPME_NoExcept;
+ else if (Val == "fast")
+ FPModel = LangOptions::FPM_Fast;
+ else {
+ D.Diag(diag::err_drv_invalid_value) << "-fp-model" << Val;
+ continue;
+ }
+ break;
+ }
+ case options::OPT_fp_speculation_EQ: {
+ StringRef Val = A->getValue();
+ if (Val == "fast")
+ FPSpeculation = LangOptions::FPS_Fast;
+ else if (Val == "strict")
+ FPSpeculation = LangOptions::FPS_Strict;
+ else if (Val == "safe")
+ FPSpeculation = LangOptions::FPS_Safe;
+ else {
+ D.Diag(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
+ continue;
+ }
+ break;
+ }
// Options controlling individual features
case options::OPT_fhonor_infinities: HonorINFs = true; break;
@@ -2380,6 +2418,56 @@
A->claim();
}
+ if ((FPModelExcept == LangOptions::FPME_Except) &&
+ (FPModel == LangOptions::FPM_Fast))
+ D.Diag(diag::err_drv_argument_not_allowed_with) << "fp-model=fast"
+ << "fp-model=except";
+
+ switch (FPModel) {
+ case LangOptions::FPM_Precise:
+ CmdArgs.push_back("-fp-model=precise");
+ break;
+ case LangOptions::FPM_Strict:
+ CmdArgs.push_back("-fp-model=strict");
+ break;
+ case LangOptions::FPM_Fast:
+ CmdArgs.push_back("-fp-model=fast");
+ break;
+ case LangOptions::FPM_Off:
+ break;
+ default:
+ llvm_unreachable("Unrecognized FPModel");
+ }
+
+ switch (FPModelExcept) {
+ case LangOptions::FPME_Except:
+ CmdArgs.push_back("-fp-model-except");
+ break;
+ case LangOptions::FPME_NoExcept:
+ CmdArgs.push_back("-no-fpmodel-except-");
+ break;
+ case LangOptions::FPME_Off:
+ break;
+ default:
+ llvm_unreachable("Unrecognized FPModel");
+ }
+
+ switch (FPSpeculation) {
+ case LangOptions::FPS_Fast:
+ CmdArgs.push_back("-fp-speculation=fast");
+ break;
+ case LangOptions::FPS_Strict:
+ CmdArgs.push_back("-fp-speculation=strict");
+ break;
+ case LangOptions::FPS_Safe:
+ CmdArgs.push_back("-fp-speculation=safe");
+ break;
+ case LangOptions::FPS_Off:
+ break;
+ default:
+ llvm_unreachable("Unrecognized FPSpeculation");
+ }
+
if (!HonorINFs)
CmdArgs.push_back("-menable-no-infs");
Index: clang/lib/CodeGen/CodeGenFunction.h
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.h
+++ clang/lib/CodeGen/CodeGenFunction.h
@@ -4148,6 +4148,9 @@
/// point operation, expressed as the maximum relative error in ulp.
void SetFPAccuracy(llvm::Value *Val, float Accuracy);
+ /// SetFPModel - Control floating point behavior via fp-model settings.
+ void SetFPModel(void);
+
private:
llvm::MDNode *getRangeForLoadFromType(QualType Ty);
void EmitReturnOfRValue(RValue RV, QualType Ty);
Index: clang/lib/CodeGen/CodeGenFunction.cpp
===================================================================
--- clang/lib/CodeGen/CodeGenFunction.cpp
+++ clang/lib/CodeGen/CodeGenFunction.cpp
@@ -33,6 +33,7 @@
#include "clang/Frontend/FrontendDiagnostic.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Dominators.h"
+#include "llvm/IR/IntrinsicInst.h"
#include "llvm/IR/Intrinsics.h"
#include "llvm/IR/MDBuilder.h"
#include "llvm/IR/Operator.h"
@@ -90,6 +91,7 @@
FMF.setAllowReassoc();
}
Builder.setFastMathFlags(FMF);
+ SetFPModel();
}
CodeGenFunction::~CodeGenFunction() {
@@ -105,6 +107,82 @@
CGM.getOpenMPRuntime().functionFinished(*this);
}
+void CodeGenFunction::SetFPModel(void)
+{
+ auto fpModel = getLangOpts().getFPMOptions().getFPModelSetting();
+ auto fpModelExcept = getLangOpts().getFPMOptions().getFPModelExceptSetting();
+ auto fpSpeculation = getLangOpts().getFPMOptions().getFPSpeculationSetting();
+
+ // Translate the compiler options into
+ // the 3 settings that are transmitted to the IR Builder
+ bool IsConstrainedRounding = false;
+ bool IsConstrainedExcept = false;
+ llvm::ConstrainedFPIntrinsic::RoundingMode ConstrainedRoundingMD;
+ llvm::ConstrainedFPIntrinsic::ExceptionBehavior ConstrainedExceptMD;
+
+ switch (fpModel) {
+ case LangOptions::FPM_Off:
+ case LangOptions::FPM_Precise:
+ case LangOptions::FPM_Fast:
+ break;
+ case LangOptions::FPM_Strict:
+ IsConstrainedRounding = true;
+ ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmDynamic;
+ IsConstrainedExcept = true;
+ ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebStrict;
+ break;
+ default:
+ llvm_unreachable("Unsupported FP Model");
+ }
+
+ switch (fpModelExcept) {
+ case LangOptions::FPME_Off:
+ break;
+ case LangOptions::FPME_Except:
+ IsConstrainedExcept = true;
+ ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebStrict;
+ break;
+ case LangOptions::FPME_NoExcept:
+ IsConstrainedExcept = true;
+ ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebIgnore;
+ break;
+ default:
+ llvm_unreachable("Unsupported FP Except Model");
+ }
+
+ switch (fpSpeculation) {
+ case LangOptions::FPS_Off:
+ break;
+ case LangOptions::FPS_Fast:
+ IsConstrainedExcept = true;
+ ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebIgnore;
+ break;
+ case LangOptions::FPS_Strict:
+ IsConstrainedExcept = true;
+ ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebStrict;
+ break;
+ case LangOptions::FPS_Safe:
+ IsConstrainedExcept = true;
+ ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebMayTrap;
+ break;
+ default:
+ llvm_unreachable("Unsupported FP Speculation");
+ }
+
+ if (IsConstrainedExcept && !IsConstrainedRounding) {
+ // If the rounding mode isn't set explicitly above, then use ebToNearest
+ // as the value when the constrained intrinsic is created
+ IsConstrainedRounding = true;
+ ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmToNearest;
+ }
+
+ if (IsConstrainedExcept || IsConstrainedRounding) {
+ Builder.setIsFPConstrained(true);
+ Builder.setDefaultConstrainedRounding(ConstrainedRoundingMD);
+ Builder.setDefaultConstrainedExcept(ConstrainedExceptMD);
+ }
+}
+
CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
LValueBaseInfo *BaseInfo,
TBAAAccessInfo *TBAAInfo) {
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -910,6 +910,10 @@
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 fp_model_EQ : Joined<["-"], "fp-model=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Controls the semantics of floating-point calculations.">;
+def fp_speculation_EQ : Joined<["-"], "fp-speculation=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Specifies the mode in which to speculate on floating-point operations.">;
def ffast_math : Flag<["-"], "ffast-math">, Group<f_Group>, Flags<[CC1Option]>,
HelpText<"Allow aggressive, lossy floating-point optimizations">;
def fno_fast_math : Flag<["-"], "fno-fast-math">, Group<f_Group>;
Index: clang/include/clang/Driver/CC1Options.td
===================================================================
--- clang/include/clang/Driver/CC1Options.td
+++ clang/include/clang/Driver/CC1Options.td
@@ -783,6 +783,10 @@
HelpText<"Use the native __fp16 type for arguments and returns (and skip ABI-specific lowering)">;
def fallow_half_arguments_and_returns : Flag<["-"], "fallow-half-arguments-and-returns">,
HelpText<"Allow function arguments and returns of type half">;
+def fp_model_except : Flag<["-"], "fp-model-except">,
+ HelpText<"Controls the constrained exception setting of floating-point calculations.">;
+def no_fp_model_except : Flag<["-"], "no-fp-model-except">,
+ HelpText<"Exceptions in floating-point calculations are ignored.">;
def fdefault_calling_conv_EQ : Joined<["-"], "fdefault-calling-conv=">,
HelpText<"Set default calling convention">, Values<"cdecl,fastcall,stdcall,vectorcall,regcall">;
def finclude_default_header : Flag<["-"], "finclude-default-header">,
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -178,6 +178,28 @@
FEA_On
};
+ enum FPModelKind {
+ // -fp-model option is not specified
+ FPM_Off,
+ FPM_Precise,
+ FPM_Strict,
+ FPM_Fast
+ };
+
+ enum FPModelExceptKind {
+ // -fp-except option not specified
+ FPME_Off,
+ FPME_Except,
+ FPME_NoExcept
+ };
+
+ enum FPSpeculationKind {
+ // -fp-speculation option not specified
+ FPS_Off,
+ FPS_Fast,
+ FPS_Strict,
+ FPS_Safe
+ };
public:
/// Set of enabled sanitizers.
@@ -301,6 +323,43 @@
/// Return the OpenCL C or C++ version as a VersionTuple.
VersionTuple getOpenCLVersionTuple() const;
+
+ /// Floating point model options
+ class FPModelOptions {
+ public:
+ FPModelOptions() : FPM(LangOptions::FPM_Off),
+ FPME(LangOptions::FPME_Off),
+ FPS(LangOptions::FPS_Off) {}
+
+ LangOptions::FPModelKind getFPModelSetting() const {
+ return FPM;
+ }
+ void setFPModelSetting(LangOptions::FPModelKind Value) {FPM = Value;}
+
+ LangOptions::FPModelExceptKind getFPModelExceptSetting() const {
+ return FPME;
+ }
+ void setFPModelExceptSetting(LangOptions::FPModelExceptKind Value) {
+ FPME = Value;
+ }
+
+ LangOptions::FPSpeculationKind getFPSpeculationSetting() const {
+ return FPS;
+ }
+ void setFPSpeculationSetting(LangOptions::FPSpeculationKind Value) {
+ FPS = Value;
+ }
+
+ private:
+ LangOptions::FPModelKind FPM = LangOptions::FPM_Off;
+ LangOptions::FPModelExceptKind FPME = LangOptions::FPME_Off;
+ LangOptions::FPSpeculationKind FPS = LangOptions::FPS_Off;
+ };
+
+ FPModelOptions& getFPMOptions() { return fpm_options; }
+ FPModelOptions getFPMOptions() const { return fpm_options; }
+private:
+ FPModelOptions fpm_options;
};
/// Floating point control options
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -1296,6 +1296,30 @@
With the 'no-strict' option, Clang attempts to match the overflowing behavior
of the target's native float-to-int conversion instructions.
+.. option:: -fp-model=[values]
+
+ Specify floating point behavior.
+
+ Valid values are: ``precise``, ``strict``, ``fast``, ``except``,
+ and ``except-``. Note that -fp-model=except[-] can be combined with the
+ other three settings for this option.
+
+ ``precise `` Disables optimizations that are not value-safe on
+ floating-point data, although FP contraction (FMA) is enabled.
+ * ``strict`` Enables precise and except, and disables contractions (FMA).
+ * ``fast`` Equivalent to -ffast-math
+ * ``except`` Honor strict floating-point exception semantics.
+ * ``except-`` Ignore floating-point exceptions.
+
+.. option:: -fp-speculation=[values]
+
+ Specify the mode in which to speculate on floating-point operations.
+
+ Valid values are: ``fast``, ``strict``, and ``safe``.
+ * ``fast`` The compiler will speculate on floating-point operations.
+ * ``strict`` The compiler will not speculate on floating-point operations.
+ * ``safe`` Disable speculation if there is a possibility that speculation may cause a floating-point exception.
+
.. option:: -fwhole-program-vtables
Enable whole-program vtable optimizations, such as single-implementation
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits