From c9686716d2ceb5518178dca98670ec34c472a1be Mon Sep 17 00:00:00 2001 From: Lang Hames Date: Fri, 6 Jul 2012 00:59:19 +0000 Subject: [PATCH] Add -ffp-contract = { fast | on | off } command line option support. This flag sets the 'fp-contract' mode, which controls the formation of fused floating point operations. Available modes are: - Fast: Form fused operations anywhere. - On: Form fused operations where allowed by FP_CONTRACT. This is the default mode. - Off: Don't form fused operations (in future this may be relaxed to forming fused operations where it can be proved that the result won't be affected). Currently clang doesn't support the FP_CONTRACT pragma, so the 'On' and 'Off' modes are equivalent. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@159794 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/LangOptions.def | 1 + include/clang/Basic/LangOptions.h | 6 ++++++ include/clang/Driver/Options.td | 3 +++ lib/CodeGen/BackendUtil.cpp | 13 +++++++++++++ lib/Driver/Tools.cpp | 18 ++++++++++++++++++ lib/Frontend/CompilerInvocation.cpp | 17 +++++++++++++++++ test/CodeGen/fp-contract.c | 8 ++++++++ test/Driver/clang_f_opts.c | 6 ++++++ 8 files changed, 72 insertions(+) create mode 100644 test/CodeGen/fp-contract.c diff --git a/include/clang/Basic/LangOptions.def b/include/clang/Basic/LangOptions.def index 381b1ba2f0..aa4d25c1b1 100644 --- a/include/clang/Basic/LangOptions.def +++ b/include/clang/Basic/LangOptions.def @@ -148,6 +148,7 @@ ENUM_LANGOPT(StackProtector, StackProtectorMode, 2, SSPOff, "stack protector mode") ENUM_LANGOPT(SignedOverflowBehavior, SignedOverflowBehaviorTy, 2, SOB_Undefined, "signed integer overflow handling") +ENUM_LANGOPT(FPContractMode, FPContractModeTy, 2, FPC_On, "FP_CONTRACT mode") BENIGN_LANGOPT(InstantiationDepth, 32, 512, "maximum template instantiation depth") diff --git a/include/clang/Basic/LangOptions.h b/include/clang/Basic/LangOptions.h index 10f496fd39..fbb014e967 100644 --- a/include/clang/Basic/LangOptions.h +++ b/include/clang/Basic/LangOptions.h @@ -56,6 +56,12 @@ public: SOB_Trapping // -ftrapv }; + enum FPContractModeKind { + FPC_Off, // Form fused FP ops only where result will not be affected. + FPC_On, // Form fused FP ops according to FP_CONTRACT rules. + FPC_Fast // Aggressively fuse FP ops (E.g. FMA). + }; + public: clang::ObjCRuntime ObjCRuntime; diff --git a/include/clang/Driver/Options.td b/include/clang/Driver/Options.td index 4d23f47d85..48f9cd68b8 100644 --- a/include/clang/Driver/Options.td +++ b/include/clang/Driver/Options.td @@ -410,6 +410,9 @@ def fhonor_infinites : Flag<"-fhonor-infinites">, Alias; def fno_honor_infinites : Flag<"-fno-honor-infinites">, Alias; def ftrapping_math : Flag<"-ftrapping-math">, Group; def fno_trapping_math : Flag<"-fno-trapping-math">, Group; +def ffp_contract : Joined<"-ffp-contract=">, Group, + Flags<[CC1Option]>, HelpText<"Form fused FP ops (e.g. FMAs): fast (everywhere)" + " | on (according to FP_CONTRACT pragma, default) | off (never fuse)">; def ffor_scope : Flag<"-ffor-scope">, Group; def fno_for_scope : Flag<"-fno-for-scope">, Group; diff --git a/lib/CodeGen/BackendUtil.cpp b/lib/CodeGen/BackendUtil.cpp index 5a97875ef4..0a1915b485 100644 --- a/lib/CodeGen/BackendUtil.cpp +++ b/lib/CodeGen/BackendUtil.cpp @@ -351,6 +351,19 @@ bool EmitAssemblyHelper::AddEmitPasses(BackendAction Action, Options.FloatABIType = llvm::FloatABI::Default; } + // Set FP fusion mode. + switch (LangOpts.getFPContractMode()) { + case LangOptions::FPC_Off: + Options.AllowFPOpFusion = llvm::FPOpFusion::Strict; + break; + case LangOptions::FPC_On: + Options.AllowFPOpFusion = llvm::FPOpFusion::Standard; + break; + case LangOptions::FPC_Fast: + Options.AllowFPOpFusion = llvm::FPOpFusion::Fast; + break; + } + Options.LessPreciseFPMADOption = CodeGenOpts.LessPreciseFPMAD; Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath; Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath; diff --git a/lib/Driver/Tools.cpp b/lib/Driver/Tools.cpp index 98beb2234a..dd198a1e9d 100644 --- a/lib/Driver/Tools.cpp +++ b/lib/Driver/Tools.cpp @@ -1805,6 +1805,24 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, !TrappingMath) CmdArgs.push_back("-menable-unsafe-fp-math"); + + // Validate and pass through -fp-contract option. + if (Arg *A = Args.getLastArg(options::OPT_ffast_math, + options::OPT_ffp_contract)) { + if (A->getOption().getID() == options::OPT_ffp_contract) { + StringRef Val = A->getValue(Args); + if (Val == "fast" || Val == "on" || Val == "off") { + CmdArgs.push_back(Args.MakeArgString("-ffp-contract=" + Val)); + } else { + D.Diag(diag::err_drv_unsupported_option_argument) + << A->getOption().getName() << Val; + } + } else { // A is OPT_ffast_math + // If fast-math is set then set the fp-contract mode to fast. + CmdArgs.push_back(Args.MakeArgString("-ffp-contract=fast")); + } + } + // We separately look for the '-ffast-math' flag, and if we find it, tell the // frontend to provide the appropriate preprocessor macros. This is distinct // from enabling any optimizations as it induces a language change which must diff --git a/lib/Frontend/CompilerInvocation.cpp b/lib/Frontend/CompilerInvocation.cpp index 943cb20e2d..cf08913e3b 100644 --- a/lib/Frontend/CompilerInvocation.cpp +++ b/lib/Frontend/CompilerInvocation.cpp @@ -759,6 +759,11 @@ static void LangOptsToArgs(const LangOptions &Opts, ToArgsList &Res) { Res.push_back("-ftrapv-handler", Opts.OverflowHandler); break; } + switch (Opts.getFPContractMode()) { + case LangOptions::FPC_Off: Res.push_back("-ffp-contract=off"); break; + case LangOptions::FPC_On: Res.push_back("-ffp-contract=on"); break; + case LangOptions::FPC_Fast: Res.push_back("-ffp-contract=fast"); break; + } if (Opts.HeinousExtensions) Res.push_back("-fheinous-gnu-extensions"); // Optimize is implicit. @@ -1975,6 +1980,18 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Diags.Report(diag::err_drv_invalid_value) << Args.getLastArg(OPT_fvisibility)->getAsString(Args) << Vis; + if (Arg *A = Args.getLastArg(OPT_ffp_contract)) { + StringRef Val = A->getValue(Args); + if (Val == "fast") + Opts.setFPContractMode(LangOptions::FPC_Fast); + else if (Val == "on") + Opts.setFPContractMode(LangOptions::FPC_On); + else if (Val == "off") + Opts.setFPContractMode(LangOptions::FPC_Off); + else + Diags.Report(diag::err_drv_invalid_value) << A->getAsString(Args) << Val; + } + if (Args.hasArg(OPT_fvisibility_inlines_hidden)) Opts.InlineVisibilityHidden = 1; diff --git a/test/CodeGen/fp-contract.c b/test/CodeGen/fp-contract.c new file mode 100644 index 0000000000..c048d69586 --- /dev/null +++ b/test/CodeGen/fp-contract.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -O3 -ffp-contract=fast -triple=powerpc-apple-darwin10 -S -o - %s | FileCheck %s + +float fma_test1(float a, float b, float c) { +// CHECK: fmadds + float x = a * b; + float y = x + c; + return y; +} diff --git a/test/Driver/clang_f_opts.c b/test/Driver/clang_f_opts.c index 4eed4aa06f..b74b285501 100644 --- a/test/Driver/clang_f_opts.c +++ b/test/Driver/clang_f_opts.c @@ -29,3 +29,9 @@ // RUN: %clang -### -c -Wdeprecated %s 2>&1 | FileCheck -check-prefix=DEPRECATED-OFF-CHECK %s // DEPRECATED-ON-CHECK: -fdeprecated-macro // DEPRECATED-OFF-CHECK-NOT: -fdeprecated-macro + +// RUN: %clang -### -S -ffp-contract=fast %s 2>&1 | FileCheck -check-prefix=FP-CONTRACT-FAST-CHECK %s +// RUN: %clang -### -S -ffast-math %s 2>&1 | FileCheck -check-prefix=FP-CONTRACT-FAST-CHECK %s +// RUN: %clang -### -S -ffp-contract=off %s 2>&1 | FileCheck -check-prefix=FP-CONTRACT-OFF-CHECK %s +// FP-CONTRACT-FAST-CHECK: -ffp-contract=fast +// FP-CONTRACT-OFF-CHECK: -ffp-contract=off -- 2.40.0