mibintc updated this revision to Diff 223940.
mibintc added a comment.
I added a test case to show the warning diagnostics when options conflicting
with fp-model are provided. I fixed a couple bugs in RenderFloatingPointOptions
when issueing diagnostics. still owe a test case showing how the fp-model,
rounding, and trapping options are rendered by the Driver for cc1
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/CodeGenOptions.def
clang/include/clang/Basic/LangOptions.h
clang/include/clang/Driver/Options.td
clang/lib/CodeGen/BackendUtil.cpp
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
clang/test/Driver/fast-math.c
clang/test/Driver/fp-model.c
llvm/include/llvm/Target/TargetOptions.h
Index: llvm/include/llvm/Target/TargetOptions.h
===================================================================
--- llvm/include/llvm/Target/TargetOptions.h
+++ llvm/include/llvm/Target/TargetOptions.h
@@ -107,7 +107,7 @@
public:
TargetOptions()
: PrintMachineCode(false), UnsafeFPMath(false), NoInfsFPMath(false),
- NoNaNsFPMath(false), NoTrappingFPMath(false),
+ NoNaNsFPMath(false), NoTrappingFPMath(true), RoundingFPMath(false),
NoSignedZerosFPMath(false),
HonorSignDependentRoundingFPMathOption(false), NoZerosInBSS(false),
GuaranteedTailCallOpt(false), StackSymbolOrdering(true),
@@ -154,6 +154,11 @@
/// specifies that there are no trap handlers to handle exceptions.
unsigned NoTrappingFPMath : 1;
+ /// RoundingFPMath - This flag is enabled when the
+ /// -enable-rounding-fp-math is specified on the command line. This
+ /// specifies dynamic rounding mode.
+ unsigned RoundingFPMath : 1;
+
/// NoSignedZerosFPMath - This flag is enabled when the
/// -enable-no-signed-zeros-fp-math is specified on the command line. This
/// specifies that optimizations are allowed to treat the sign of a zero
Index: clang/test/Driver/fp-model.c
===================================================================
--- /dev/null
+++ clang/test/Driver/fp-model.c
@@ -0,0 +1,64 @@
+// Test that incompatible combinations of -ffp-model= options
+// and other floating point options get a warning diagnostic.
+//
+// REQUIRES: clang-driver
+
+// RUN: %clang -### -ffp-model=fast -ffp-contract=off -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN %s
+// WARN: warning: overriding '-ffp-model=fast' option with '-ffp-contract=off' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=fast -ffp-contract=on -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN1 %s
+// WARN1: warning: overriding '-ffp-model=fast' option with '-ffp-contract=on' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -fassociative-math -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN2 %s
+// WARN2: warning: overriding '-ffp-model=strict' option with '-fassociative-math' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -ffast-math -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN3 %s
+// WARN3: warning: overriding '-ffp-model=strict' option with '-ffast-math' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -ffinite-math-only -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN4 %s
+// WARN4: warning: overriding '-ffp-model=strict' option with '-ffinite-math-only' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -ffp-contract=fast -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN5 %s
+// WARN5: warning: overriding '-ffp-model=strict' option with '-ffp-contract=fast' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -ffp-contract=off -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN6 %s
+// WARN6: warning: overriding '-ffp-model=strict' option with '-ffp-contract=off' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -ffp-contract=on -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN7 %s
+// WARN7: warning: overriding '-ffp-model=strict' option with '-ffp-contract=on' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -fno-honor-infinities -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN8 %s
+// WARN8: warning: overriding '-ffp-model=strict' option with '-fno-honor-infinities' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -fno-honor-nans -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARN9 %s
+// WARN9: warning: overriding '-ffp-model=strict' option with '-fno-honor-nans' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -fno-rounding-math -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARNa %s
+// WARNa: warning: overriding '-ffp-model=strict' option with '-fno-rounding-math' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -fno-signed-zeros -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARNb %s
+// WARNb: warning: overriding '-ffp-model=strict' option with '-fno-signed-zeros' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -fno-trapping-math -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARNc %s
+// WARNc: warning: overriding '-ffp-model=strict' option with '-fno-trapping-math' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -freciprocal-math -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARNd %s
+// WARNd: warning: overriding '-ffp-model=strict' option with '-freciprocal-math' [-Woverriding-t-option]
+
+// RUN: %clang -### -ffp-model=strict -funsafe-math-optimizations -c %s 2>&1 \
+// RUN: | FileCheck --check-prefix=WARNe %s
+// WARNe: warning: overriding '-ffp-model=strict' option with '-funsafe-math-optimizations' [-Woverriding-t-option]
Index: clang/test/Driver/fast-math.c
===================================================================
--- clang/test/Driver/fast-math.c
+++ clang/test/Driver/fast-math.c
@@ -170,11 +170,11 @@
// RUN: %clang -### -fno-fast-math -ffast-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FAST-MATH %s
// RUN: %clang -### -funsafe-math-optimizations -ffinite-math-only \
-// RUN: -fno-math-errno -ffp-contract=fast -c %s 2>&1 \
+// RUN: -fno-math-errno -ffp-contract=fast -fno-rounding-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FAST-MATH %s
// RUN: %clang -### -fno-honor-infinities -fno-honor-nans -fno-math-errno \
// RUN: -fassociative-math -freciprocal-math -fno-signed-zeros \
-// RUN: -fno-trapping-math -ffp-contract=fast -c %s 2>&1 \
+// RUN: -fno-trapping-math -ffp-contract=fast -fno-rounding-math -c %s 2>&1 \
// RUN: | FileCheck --check-prefix=CHECK-FAST-MATH %s
// CHECK-FAST-MATH: "-cc1"
// CHECK-FAST-MATH: "-ffast-math"
Index: clang/test/Driver/clang_f_opts.c
===================================================================
--- clang/test/Driver/clang_f_opts.c
+++ clang/test/Driver/clang_f_opts.c
@@ -320,7 +320,6 @@
// RUN: -fprefetch-loop-arrays \
// RUN: -fprofile-correction \
// RUN: -fprofile-values \
-// RUN: -frounding-math \
// RUN: -fschedule-insns \
// RUN: -fsignaling-nans \
// RUN: -fstrength-reduce \
@@ -385,7 +384,6 @@
// CHECK-WARNING-DAG: optimization flag '-fprefetch-loop-arrays' is not supported
// CHECK-WARNING-DAG: optimization flag '-fprofile-correction' is not supported
// CHECK-WARNING-DAG: optimization flag '-fprofile-values' is not supported
-// CHECK-WARNING-DAG: optimization flag '-frounding-math' is not supported
// CHECK-WARNING-DAG: optimization flag '-fschedule-insns' is not supported
// CHECK-WARNING-DAG: optimization flag '-fsignaling-nans' is not supported
// CHECK-WARNING-DAG: optimization flag '-fstrength-reduce' is not supported
Index: clang/test/CodeGen/fpconstrained.c
===================================================================
--- /dev/null
+++ clang/test/CodeGen/fpconstrained.c
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -ftrapping-math -frounding-math -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck %s -check-prefix=FPMODELSTRICT
+// RUN: %clang_cc1 -ffp-contract=fast -emit-llvm -o - %s | FileCheck %s -check-prefix=PRECISE
+// RUN: %clang_cc1 -ffast-math -ffp-contract=fast -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
+// RUN: %clang_cc1 -ffast-math -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
+// RUN: %clang_cc1 -ffast-math -ffp-contract=fast -ffp-exception-behavior=ignore -emit-llvm -o - %s | FileCheck %s -check-prefix=FAST
+// RUN: %clang_cc1 -ffast-math -ffp-contract=fast -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck %s -check-prefix=EXCEPT
+// RUN: %clang_cc1 -ffast-math -ffp-contract=fast -ffp-exception-behavior=maytrap -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")
+ // FPMODELSTRICT: 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 contract float %0, %1
+ // FAST: fadd fast
+ f0 = f1 + f2;
+
+ // CHECK: ret
+}
Index: clang/lib/Frontend/CompilerInvocation.cpp
===================================================================
--- clang/lib/Frontend/CompilerInvocation.cpp
+++ clang/lib/Frontend/CompilerInvocation.cpp
@@ -3090,6 +3090,36 @@
Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
}
+ if (Args.hasArg(OPT_frounding_math)) {
+ Opts.getFPMOptions().setFPRoundingModeSetting(LangOptions::FPRM_Dynamic);
+ }
+
+ if (Args.hasArg(OPT_fno_rounding_math)) {
+ Opts.getFPMOptions().setFPRoundingModeSetting(LangOptions::FPRM_ToNearest);
+ }
+
+ if (Args.hasArg(OPT_ftrapping_math)) {
+ Opts.getFPMOptions().setFPExceptionBehaviorSetting(LangOptions::FPEB_Strict);
+ }
+
+ if (Args.hasArg(OPT_fno_trapping_math)) {
+ Opts.getFPMOptions().setFPExceptionBehaviorSetting(LangOptions::FPEB_Ignore);
+ }
+
+ LangOptions::FPExceptionBehaviorKind FPEB = LangOptions::FPEB_Ignore;
+ if (Arg *A = Args.getLastArg(OPT_ffp_exception_behavior_EQ)) {
+ StringRef Val = A->getValue();
+ if (Val.equals("ignore"))
+ FPEB = LangOptions::FPEB_Ignore;
+ else if (Val.equals("maytrap"))
+ FPEB = LangOptions::FPEB_MayTrap;
+ else if (Val.equals("strict"))
+ FPEB = LangOptions::FPEB_Strict;
+ else
+ Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val;
+ Opts.getFPMOptions().setFPExceptionBehaviorSetting(FPEB);
+ }
+
Opts.RetainCommentsFromSystemHeaders =
Args.hasArg(OPT_fretain_comments_from_system_headers);
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -2323,9 +2323,22 @@
bool AssociativeMath = false;
bool ReciprocalMath = false;
bool SignedZeros = true;
- bool TrappingMath = true;
+ bool TrappingMath = false;
+ bool RoundingFPMath = false;
+ bool RoundingMathPresent = false;
+ // -fp-model options:
+ StringRef FPModel = "";
+ //bool FPM_Precise = false;
+ //bool FPM_Strict = false;
+ //bool FPM_Fast = false;
+ // -fp-exception-behavior options:
+ StringRef FPExceptionBehavior = "";
+ //bool FPE_Ignore = false;
+ //bool FPE_MayTrap = false;
+ //bool FPE_Stric = false;
StringRef DenormalFPMath = "";
StringRef FPContract = "";
+ bool StrictFPModel = false;
if (const Arg *A = Args.getLastArg(options::OPT_flimited_precision_EQ)) {
CmdArgs.push_back("-mlimit-float-precision");
@@ -2333,7 +2346,74 @@
}
for (const Arg *A : Args) {
- switch (A->getOption().getID()) {
+ auto optID = A->getOption().getID();
+ bool PreciseFPModel = false;
+ switch (optID) {
+ default:
+ break;
+ case options::OPT_ffp_model_EQ: {
+ StrictFPModel = false;
+ PreciseFPModel = true;
+ // ffp-model= is a Driver option, it is entirely rewritten into more
+ // granular options before being passed into cc1.
+ // Use the gcc option in the switch below.
+ StringRef Val = A->getValue();
+ if (!FPModel.empty() && !FPModel.equals(Val)) {
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-model=" + FPModel)
+ << Args.MakeArgString("-ffp-model=" + Val);
+ FPContract = "";
+ }
+ if (Val.equals("fast")) {
+ if (!FPContract.empty() && !FPContract.equals("fast"))
+ // FPContract has already been set to something else
+ // so warn about the override.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-contract=" + FPContract)
+ << "-ffp-contract=fast";
+ optID = options::OPT_ffast_math;
+ FPModel = Val;
+ FPContract = "fast";
+ } else if (Val.equals("precise")) {
+ if (!FPContract.empty() && !FPContract.equals("fast"))
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-contract=" + FPContract)
+ << "-ffp-contract=fast";
+ optID = options::OPT_ffp_contract;
+ FPModel = Val;
+ FPContract = "fast";
+ PreciseFPModel = true;
+ } else if (Val.equals("strict")) {
+ StrictFPModel = true;
+ if (!FPContract.empty() && !FPContract.equals("strict"))
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-contract=" + FPContract)
+ << "-ffp-contract=strict";
+ optID = options::OPT_frounding_math;
+ FPModel = Val;
+ // fp-model=strict also enables fno-fast-math
+ HonorINFs = true;
+ HonorNaNs = true;
+ // Turning on -ffast-math (with either flag) removes the need for
+ // MathErrno. However, turning *off* -ffast-math merely restores the
+ // toolchain default (which may be false).
+ MathErrno = TC.IsMathErrnoDefault();
+ AssociativeMath = false;
+ ReciprocalMath = false;
+ SignedZeros = true;
+ TrappingMath = true;
+ RoundingFPMath = true;
+ // -fno_fast_math restores default denormal and fpcontract handling
+ DenormalFPMath = "";
+ FPContract = "";
+ } else
+ D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+ }
+
+ switch (optID) {
// If this isn't an FP option skip the claim below
default: continue;
@@ -2350,8 +2430,24 @@
case options::OPT_fno_reciprocal_math: ReciprocalMath = false; break;
case options::OPT_fsigned_zeros: SignedZeros = true; break;
case options::OPT_fno_signed_zeros: SignedZeros = false; break;
- case options::OPT_ftrapping_math: TrappingMath = true; break;
+ case options::OPT_ftrapping_math:
+ TrappingMath = true;
+ FPExceptionBehavior = "strict";
+ break;
case options::OPT_fno_trapping_math: TrappingMath = false; break;
+ case options::OPT_frounding_math:
+ // The default setting for frounding-math is True and ffast-math
+ // sets fno-rounding-math, but we only want to use constrained
+ // floating point intrinsics if the option is specifically requested.
+ RoundingFPMath = true;
+ RoundingMathPresent = true;
+ FPExceptionBehavior = "strict";
+ break;
+ case options::OPT_fno_rounding_math:
+ RoundingFPMath = false;
+ RoundingMathPresent = false;
+ FPExceptionBehavior = "";
+ break;
case options::OPT_fdenormal_fp_math_EQ:
DenormalFPMath = A->getValue();
@@ -2360,10 +2456,38 @@
// Validate and pass through -fp-contract option.
case options::OPT_ffp_contract: {
StringRef Val = A->getValue();
- if (Val == "fast" || Val == "on" || Val == "off")
+ if (PreciseFPModel) {
+ // -fp-model=precise enables fp-contract=fast as a side effect
+ // the FPContract value has already been set to a string literal
+ // and the Val string isn't a pertinent value.
+ ;
+ } else if (Val.equals("fast") || Val.equals("on") || Val.equals("off"))
FPContract = Val;
else
D.Diag(diag::err_drv_unsupported_option_argument)
+ << A->getOption().getName() << Val;
+ break;
+ }
+
+ // Validate and pass through -ffp-model option.
+ case options::OPT_ffp_model_EQ:
+ // This should only occur in the error case
+ // since the optID has been replaced by a more granular
+ // floating point option.
+ break;
+
+ // Validate and pass through -ffp-exception-behavior option.
+ case options::OPT_ffp_exception_behavior_EQ: {
+ StringRef Val = A->getValue();
+ if (!FPExceptionBehavior.empty() && !FPExceptionBehavior.equals(Val))
+ // Warn that previous value of option is overridden.
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << Args.MakeArgString("-ffp-exception-behavior=" + FPExceptionBehavior)
+ << Args.MakeArgString("-ffp-exception-behavior=" + Val);
+ if (Val.equals("ignore") || Val.equals("maytrap") || Val.equals("strict"))
+ FPExceptionBehavior = Val;
+ else
+ D.Diag(diag::err_drv_unsupported_option_argument)
<< A->getOption().getName() << Val;
break;
}
@@ -2405,6 +2529,7 @@
ReciprocalMath = true;
SignedZeros = false;
TrappingMath = false;
+ RoundingFPMath = false;
// If fast-math is set then set the fp-contract mode to fast.
FPContract = "fast";
break;
@@ -2419,11 +2544,30 @@
ReciprocalMath = false;
SignedZeros = true;
TrappingMath = true;
+ RoundingFPMath = true;
// -fno_fast_math restores default denormal and fpcontract handling
DenormalFPMath = "";
FPContract = "";
break;
}
+ if (StrictFPModel) {
+ // If fp-model=strict has been specified on command line but
+ // subsequent options conflict then emit warning diagnostic.
+ if (HonorINFs && HonorNaNs &&
+ !AssociativeMath && !ReciprocalMath &&
+ SignedZeros && TrappingMath && RoundingFPMath &&
+ DenormalFPMath.empty() && FPContract.empty())
+ // OK: Current Arg doesn't conflict with fp-model=strict
+ ;
+ else {
+ StrictFPModel = false;
+ FPModel = "";
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << "-ffp-model=strict" <<
+ ((A->getNumValues() == 0) ? A->getSpelling()
+ : Args.MakeArgString(A->getSpelling() + A->getValue()));
+ }
+ }
// If we handled this option claim it
A->claim();
@@ -2451,7 +2595,10 @@
if (ReciprocalMath)
CmdArgs.push_back("-freciprocal-math");
- if (!TrappingMath)
+ if (TrappingMath)
+ // Note: FP Exception Behavior is also set to strict
+ CmdArgs.push_back("-ftrapping-math");
+ else
CmdArgs.push_back("-fno-trapping-math");
if (!DenormalFPMath.empty())
@@ -2461,14 +2608,37 @@
if (!FPContract.empty())
CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + FPContract));
+ if (!RoundingFPMath)
+ CmdArgs.push_back(Args.MakeArgString("-fno-rounding-math"));
+
+ if (RoundingFPMath && RoundingMathPresent)
+ CmdArgs.push_back(Args.MakeArgString("-frounding-math"));
+
+ if (!FPExceptionBehavior.empty())
+ CmdArgs.push_back(Args.MakeArgString("-ffp-exception-behavior=" +
+ FPExceptionBehavior));
+
ParseMRecip(D, Args, CmdArgs);
// -ffast-math enables the __FAST_MATH__ preprocessor macro, but check for the
// individual features enabled by -ffast-math instead of the option itself as
// that's consistent with gcc's behaviour.
if (!HonorINFs && !HonorNaNs && !MathErrno && AssociativeMath &&
- ReciprocalMath && !SignedZeros && !TrappingMath)
+ ReciprocalMath && !SignedZeros && !TrappingMath && !RoundingFPMath) {
CmdArgs.push_back("-ffast-math");
+ if (FPModel.equals("fast")) {
+ if (FPContract.equals("fast"))
+ // All set, do nothing.
+ ;
+ else if (FPContract.empty())
+ // Enable fp-contract=fast
+ CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast"));
+ else
+ D.Diag(clang::diag::warn_drv_overriding_flag_option)
+ << "-ffp-model=fast"
+ << Args.MakeArgString("-ffp-contract=" + FPContract);
+ }
+ }
// Handle __FINITE_MATH_ONLY__ similarly.
if (!HonorINFs && !HonorNaNs)
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"
@@ -87,6 +88,7 @@
FMF.setAllowReassoc();
}
Builder.setFastMathFlags(FMF);
+ SetFPModel();
}
CodeGenFunction::~CodeGenFunction() {
@@ -102,6 +104,62 @@
CGM.getOpenMPRuntime().functionFinished(*this);
}
+void CodeGenFunction::SetFPModel(void)
+{
+ auto fpRoundingMode = getLangOpts().getFPMOptions().getFPRoundingModeSetting();
+ auto fpExceptionBehavior =
+ getLangOpts().getFPMOptions().getFPExceptionBehaviorSetting();
+
+ // Translate the compiler options into
+ // the settings that are transmitted to the IR Builder
+ llvm::ConstrainedFPIntrinsic::RoundingMode ConstrainedRoundingMD;
+ llvm::ConstrainedFPIntrinsic::ExceptionBehavior ConstrainedExceptMD;
+
+ switch (fpRoundingMode) {
+ case LangOptions::FPRM_ToNearest:
+ ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmToNearest;
+ break;
+ case LangOptions::FPRM_Downward:
+ ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmDownward;
+ break;
+ case LangOptions::FPRM_Upward:
+ ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmUpward;
+ break;
+ case LangOptions::FPRM_ToZero:
+ ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmTowardZero;
+ break;
+ case LangOptions::FPRM_Dynamic:
+ ConstrainedRoundingMD = llvm::ConstrainedFPIntrinsic::rmDynamic;
+ break;
+ default:
+ llvm_unreachable("Unsupported FP RoundingMode");
+ }
+
+ switch (fpExceptionBehavior) {
+ case LangOptions::FPEB_Ignore:
+ ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebIgnore;
+ break;
+ case LangOptions::FPEB_MayTrap:
+ ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebMayTrap;
+ break;
+ case LangOptions::FPEB_Strict:
+ ConstrainedExceptMD = llvm::ConstrainedFPIntrinsic::ebStrict;
+ break;
+ default:
+ llvm_unreachable("Unsupported FP Exception Behavior");
+ }
+
+ if (fpExceptionBehavior == LangOptions::FPEB_Ignore &&
+ fpRoundingMode == LangOptions::FPRM_ToNearest)
+ // Constrained intrinsics are not used.
+ ;
+ else {
+ Builder.setIsFPConstrained(true);
+ Builder.setDefaultConstrainedRounding(ConstrainedRoundingMD);
+ Builder.setDefaultConstrainedExcept(ConstrainedExceptMD);
+ }
+}
+
CharUnits CodeGenFunction::getNaturalPointeeTypeAlignment(QualType T,
LValueBaseInfo *BaseInfo,
TBAAAccessInfo *TBAAInfo) {
Index: clang/lib/CodeGen/BackendUtil.cpp
===================================================================
--- clang/lib/CodeGen/BackendUtil.cpp
+++ clang/lib/CodeGen/BackendUtil.cpp
@@ -475,6 +475,7 @@
Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath;
Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
Options.UnsafeFPMath = CodeGenOpts.UnsafeFPMath;
+ Options.RoundingFPMath = CodeGenOpts.RoundingFPMath;
Options.StackAlignmentOverride = CodeGenOpts.StackAlignment;
Options.FunctionSections = CodeGenOpts.FunctionSections;
Options.DataSections = CodeGenOpts.DataSections;
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -924,6 +924,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 ffp_model_EQ : Joined<["-"], "ffp-model=">, Group<f_Group>, Flags<[DriverOption]>,
+ HelpText<"Controls the semantics of floating-point calculations.">;
+def ffp_exception_behavior_EQ : Joined<["-"], "ffp-exception-behavior=">, Group<f_Group>, Flags<[CC1Option]>,
+ HelpText<"Specifies the exception behavior of floating-point operations.">;
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>;
@@ -1140,6 +1144,8 @@
// This option was originally misspelt "infinites" [sic].
def : Flag<["-"], "fhonor-infinites">, Alias<fhonor_infinities>;
def : Flag<["-"], "fno-honor-infinites">, Alias<fno_honor_infinities>;
+def frounding_math : Flag<["-"], "frounding-math">, Group<f_Group>, Flags<[CC1Option]>;
+def fno_rounding_math : Flag<["-"], "fno-rounding-math">, Group<f_Group>, Flags<[CC1Option]>;
def ftrapping_math : Flag<["-"], "ftrapping-math">, Group<f_Group>, Flags<[CC1Option]>;
def fno_trapping_math : Flag<["-"], "fno-trapping-math">, Group<f_Group>, Flags<[CC1Option]>;
def ffp_contract : Joined<["-"], "ffp-contract=">, Group<f_Group>,
@@ -3168,7 +3174,6 @@
defm regs_graph : BooleanFFlag<"regs-graph">, Group<clang_ignored_f_Group>;
defm rename_registers : BooleanFFlag<"rename-registers">, Group<clang_ignored_gcc_optimization_f_Group>;
defm ripa : BooleanFFlag<"ripa">, Group<clang_ignored_f_Group>;
-defm rounding_math : BooleanFFlag<"rounding-math">, Group<clang_ignored_gcc_optimization_f_Group>;
defm schedule_insns : BooleanFFlag<"schedule-insns">, Group<clang_ignored_gcc_optimization_f_Group>;
defm schedule_insns2 : BooleanFFlag<"schedule-insns2">, Group<clang_ignored_gcc_optimization_f_Group>;
defm see : BooleanFFlag<"see">, Group<clang_ignored_f_Group>;
Index: clang/include/clang/Basic/LangOptions.h
===================================================================
--- clang/include/clang/Basic/LangOptions.h
+++ clang/include/clang/Basic/LangOptions.h
@@ -184,6 +184,31 @@
FEA_On
};
+ enum FPRoundingModeKind {
+ // Round to the nearest integer - IEEE rounding mode
+ FPRM_ToNearest, // This is the default
+ // Rounding mode is dynamic: optimizer assumes that rounding mode
+ // is unknown.
+ FPRM_Dynamic,
+ // Round down - IEEE rounding mode
+ FPRM_Downward,
+ // Round up - IEEE rounding mode
+ FPRM_Upward,
+ // Round towards zero - IEEE rounding mode
+ FPRM_ToZero
+ };
+
+ enum FPExceptionBehaviorKind {
+ // Floating point exceptions are not handled: fp exceptions are masked.
+ FPEB_Ignore, // This is the default
+ // Optimizer will avoid transformations that may raise exceptions that would
+ // not have been raised by unoptimized code
+ FPEB_MayTrap,
+ // Optimizer will strictly preserve the fp exception semantics of the
+ // unoptimized code
+ FPEB_Strict
+ };
+
enum class LaxVectorConversionKind {
/// Permit no implicit vector bitcasts.
None,
@@ -317,6 +342,38 @@
/// Return the OpenCL C or C++ version as a VersionTuple.
VersionTuple getOpenCLVersionTuple() const;
+
+ /// Floating point model options
+ class FPModelOptions {
+ public:
+ FPModelOptions() : FPRM(LangOptions::FPRM_ToNearest),
+ FPEB(LangOptions::FPEB_Ignore) {}
+
+ LangOptions::FPRoundingModeKind getFPRoundingModeSetting() const {
+ return FPRM;
+ }
+ void setFPRoundingModeSetting(LangOptions::FPRoundingModeKind Value) {
+ FPRM = Value;
+ }
+
+ LangOptions::FPExceptionBehaviorKind getFPExceptionBehaviorSetting() const
+ {
+ return FPEB;
+ }
+ void setFPExceptionBehaviorSetting(
+ LangOptions::FPExceptionBehaviorKind Value) {
+ FPEB = Value;
+ }
+
+ private:
+ LangOptions::FPRoundingModeKind FPRM = LangOptions::FPRM_ToNearest;
+ LangOptions::FPExceptionBehaviorKind FPEB = LangOptions::FPEB_Ignore;
+ };
+
+ FPModelOptions& getFPMOptions() { return fpm_options; }
+ FPModelOptions getFPMOptions() const { return fpm_options; }
+private:
+ FPModelOptions fpm_options;
};
/// Floating point control options
Index: clang/include/clang/Basic/CodeGenOptions.def
===================================================================
--- clang/include/clang/Basic/CodeGenOptions.def
+++ clang/include/clang/Basic/CodeGenOptions.def
@@ -234,6 +234,7 @@
CODEGENOPT(RerollLoops , 1, 0) ///< Control whether loops are rerolled.
CODEGENOPT(NoUseJumpTables , 1, 0) ///< Set when -fno-jump-tables is enabled.
CODEGENOPT(UnsafeFPMath , 1, 0) ///< Allow unsafe floating point optzns.
+CODEGENOPT(RoundingFPMath , 1, 0) ///< Rounding floating point optzns.
CODEGENOPT(UnwindTables , 1, 0) ///< Emit unwind tables.
CODEGENOPT(VectorizeLoop , 1, 0) ///< Run loop vectorizer.
CODEGENOPT(VectorizeSLP , 1, 0) ///< Run SLP vectorizer.
Index: clang/docs/UsersManual.rst
===================================================================
--- clang/docs/UsersManual.rst
+++ clang/docs/UsersManual.rst
@@ -1219,10 +1219,10 @@
**-f[no-]trapping-math**
- ``-fno-trapping-math`` allows optimizations that assume that
- floating point operations cannot generate traps such as divide-by-zero,
- overflow and underflow. Defaults to ``-ftrapping-math``.
- Currently this option has no effect.
+ Control floating point exception behavior. ``-fno-trapping-math`` allows optimizations that assume that floating point operations cannot generate traps such as divide-by-zero, overflow and underflow.
+
+- The option ``-ftrapping-math`` behaves identically to ``-ffp-exception-behavior=strict``.
+- The option ``-fno-trapping-math`` behaves identically to ``-ffp-exception-behavior=ignore``. This is the default.
.. option:: -ffp-contract=<value>
@@ -1307,6 +1307,53 @@
Defaults to ``-fno-finite-math``.
+.. _opt_frounding-math:
+
+**-f[no-]rounding-math**
+
+ LLVM constrained floating point supports five rounding modes: ``tonearest``,
+ ``downward``, ``upward``, ``towardzero`` and ``dynamic``. The first four
+ values represent the corresponding IEEE rounding rules, and the ``dynamic``
+ mode informs the compiler that it must not assume any particular
+ rounding mode.
+
+- The option ``-fno-rounding-math`` specifies ``tonearest`` rounding mode. This is the default.
+- The option ``-frounding-math`` specifies ``dynamic`` rounding mode.
+- The option ``-frounding-math`` behaves identically to ``-ffp-model=strict``. Consequently, this option also sets ``-ffp-exception-behavior=strict``.
+
+.. option:: -ffp-model=<value>
+
+ Specify floating point behavior. ``-ffp-model`` is an umbrella
+ option that encompasses functionality provided by other, single
+ purpose, clang floating point options. Valid values are: ``precise``, ``strict``,
+ and ``fast``.
+ Details:
+
+ * ``precise`` Disables optimizations that are not value-safe on floating-point data, although FP contraction (FMA) is enabled (``-ffp-contract=fast``). This is clang's default behavior.
+ * ``strict`` Enables ``-frounding-math`` and ``-ffp-exception-behavior=strict``, and disables contractions (FMA). All of the ``-ffast-math`` enablements are disabled.
+ * ``fast`` Behaves identically to specifying both ``-ffast-math`` and ``ffp-contract=fast``
+
+ Note: If your command line specifies multiple instances
+ of the ``-ffp-model`` option, or if your command line option specifies
+ ``-ffp-model`` and later on the command line selects a floating point
+ option that has the effect of negating part of the ``ffp-model`` that
+ has been selected, then the compiler will issue a diagnostic warning
+ that the override has occurred.
+
+.. option:: -ffp-exception-behavior=<value>
+
+ Specify the floating-point exception behavior.
+
+ Valid values are: ``ignore``, ``maytrap``, and ``strict``.
+ The default value is ``ignore``. Details:
+
+ * ``ignore`` The compiler assumes that the exception status flags will not be read and that floating point exceptions will be masked.
+ * ``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.
+
+
+
+
.. _controlling-code-generation:
Controlling Code Generation
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits