summaryrefslogtreecommitdiffstats
path: root/clang
diff options
context:
space:
mode:
authorSebastian Pop <sebpop@gmail.com>2016-09-23 16:16:25 +0000
committerSebastian Pop <sebpop@gmail.com>2016-09-23 16:16:25 +0000
commit6919ae5abc74f897d9bbcff7e198dcf298740e6a (patch)
tree059438d0f2b43faf5d90cedcabcd2eff69897920 /clang
parent72525622b2f2f558dfd2a5a37577b0f6e3ae16a1 (diff)
downloadbcm5719-llvm-6919ae5abc74f897d9bbcff7e198dcf298740e6a.tar.gz
bcm5719-llvm-6919ae5abc74f897d9bbcff7e198dcf298740e6a.zip
set the underlying value of “#pragma STDC FP_CONTRACT” on by default
Clang has the default FP contraction setting of “-ffp-contract=on”, which doesn't really mean “on” in the conventional sense of the word, but rather really means “according to the per-statement effective value of the relevant pragma”. Before this patch, Clang has that pragma defaulting to “off”. Since the “-ffp-contract=on” mode is really an AND of two booleans and the second of them defaults to “off”, the whole thing effectively defaults to “off”. This patch changes the default value of the pragma to “on”, thus making the default pair of booleans (on, on) rather than (on, off). This makes FP optimization slightly more aggressive than before when not using either “-Ofast”, “-ffast-math”, or “-ffp-contract=fast”. Even with this patch the compiler still respects “-ffp-contract=off”. As per a suggestion by Steve Canon, the added code does _not_ require “-O3” or higher. This is so as to try our best to preserve identical floating-point results for unchanged source code compiling for an unchanged target when only changing from any optimization level in the set (“-O0”, “-O1”, “-O2”, “-O3”) to any other optimization level in that set. “-Os” and “-Oz” seem to be behaving identically, i.e. should probably be considered a part of the aforementioned set, but I have not reviewed this rigorously. “-Ofast” is explicitly _not_ a member of that set. Patch authored by Abe Skolnik [a.skolnik@samsung.com] and Stephen Canon [scanon@apple.com]. Differential Revision: https://reviews.llvm.org/D24481 llvm-svn: 282259
Diffstat (limited to 'clang')
-rw-r--r--clang/lib/Frontend/CompilerInvocation.cpp6
-rw-r--r--clang/test/CodeGen/aarch64-neon-fma.c2
-rw-r--r--clang/test/CodeGen/aarch64-scalar-fma.c177
-rw-r--r--clang/test/CodeGen/fp-contract-pragma.cpp24
-rw-r--r--clang/test/CodeGen/fp-contract-pragma___on-by-default.c21
-rw-r--r--clang/test/Driver/clang_f_opts.c9
6 files changed, 226 insertions, 13 deletions
diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp
index c3fbda114ef..52282e94f4d 100644
--- a/clang/lib/Frontend/CompilerInvocation.cpp
+++ b/clang/lib/Frontend/CompilerInvocation.cpp
@@ -2445,6 +2445,12 @@ bool CompilerInvocation::CreateFromArgs(CompilerInvocation &Res,
if (Arch == llvm::Triple::spir || Arch == llvm::Triple::spir64) {
Res.getDiagnosticOpts().Warnings.push_back("spir-compat");
}
+
+ if ((LangOpts.C11 || LangOpts.C99 || LangOpts.CPlusPlus) &&
+ (CodeGenOptions::FPC_On == Res.getCodeGenOpts().getFPContractMode()) &&
+ !LangOpts.CUDA)
+ LangOpts.DefaultFPContract = 1;
+
return Success;
}
diff --git a/clang/test/CodeGen/aarch64-neon-fma.c b/clang/test/CodeGen/aarch64-neon-fma.c
index 6ada533c66e..be7ed95f393 100644
--- a/clang/test/CodeGen/aarch64-neon-fma.c
+++ b/clang/test/CodeGen/aarch64-neon-fma.c
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
+// RUN: %clang_cc1 -triple arm64-none-linux-gnu -target-feature +neon -ffp-contract=off -S -emit-llvm -o - %s | opt -S -mem2reg | FileCheck %s
// Test new aarch64 intrinsics and types
diff --git a/clang/test/CodeGen/aarch64-scalar-fma.c b/clang/test/CodeGen/aarch64-scalar-fma.c
new file mode 100644
index 00000000000..ee4bd5065fc
--- /dev/null
+++ b/clang/test/CodeGen/aarch64-scalar-fma.c
@@ -0,0 +1,177 @@
+// RUN: %clang_cc1 -triple=aarch64-unknown -Os -ffp-contract=fast -S -o - %s | FileCheck -check-prefix=CHECK-FAST -check-prefix=CHECK-ALL %s
+// RUN: %clang_cc1 -triple=aarch64-unknown -Os -ffp-contract=on -S -o - %s | FileCheck -check-prefix=CHECK-ON -check-prefix=CHECK-ALL %s
+// RUN: %clang_cc1 -triple=aarch64-unknown -Os -ffp-contract=off -S -o - %s | FileCheck -check-prefix=CHECK-OFF -check-prefix=CHECK-ALL %s
+// RUN: %clang_cc1 -triple=aarch64-unknown -Os -S -o - %s | FileCheck -check-prefix=CHECK-ON -check-prefix=CHECK-ALL %s
+// REQUIRES: aarch64-registered-target
+
+float test1(float x, float y, float z) {
+ return x*y + z;
+ // CHECK-ALL-LABEL: test1:
+ // CHECK-FAST: fmadd
+ // CHECK-ON: fmadd
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fadd
+}
+
+double test2(double x, double y, double z) {
+ z -= x*y;
+ return z;
+ // CHECK-ALL-LABEL: test2:
+ // CHECK-FAST: fmsub
+ // CHECK-ON: fmsub
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fsub
+}
+
+float test3(float x, float y, float z) {
+ float tmp = x*y;
+ return tmp + z;
+ // CHECK-ALL-LABEL: test3:
+ // CHECK-FAST: fmadd
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fadd
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fadd
+}
+
+double test4(double x, double y, double z) {
+ double tmp = x*y;
+ return tmp - z;
+ // CHECK-ALL-LABEL: test4:
+ // CHECK-FAST: fnmsub
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fsub
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fsub
+}
+
+#pragma STDC FP_CONTRACT ON
+
+float test5(float x, float y, float z) {
+ return x*y + z;
+ // CHECK-ALL-LABEL: test5:
+ // CHECK-FAST: fmadd
+ // CHECK-ON: fmadd
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fadd
+}
+
+double test6(double x, double y, double z) {
+ z -= x*y;
+ return z;
+ // CHECK-ALL-LABEL: test6:
+ // CHECK-FAST: fmsub
+ // CHECK-ON: fmsub
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fsub
+}
+
+float test7(float x, float y, float z) {
+ float tmp = x*y;
+ return tmp + z;
+ // CHECK-ALL-LABEL: test7:
+ // CHECK-FAST: fmadd
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fadd
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fadd
+}
+
+double test8(double x, double y, double z) {
+ double tmp = x*y;
+ return tmp - z;
+ // CHECK-ALL-LABEL: test8:
+ // CHECK-FAST: fnmsub
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fsub
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fsub
+}
+
+#pragma STDC FP_CONTRACT OFF
+
+float test9(float x, float y, float z) {
+ return x*y + z;
+ // CHECK-ALL-LABEL: test9:
+ // CHECK-FAST: fmadd
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fadd
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fadd
+}
+
+double test10(double x, double y, double z) {
+ z -= x*y;
+ return z;
+ // CHECK-ALL-LABEL: test10:
+ // CHECK-FAST: fmsub
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fsub
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fsub
+}
+
+float test11(float x, float y, float z) {
+ float tmp = x*y;
+ return tmp + z;
+ // CHECK-ALL-LABEL: test11:
+ // CHECK-FAST: fmadd
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fadd
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fadd
+}
+
+double test12(double x, double y, double z) {
+ double tmp = x*y;
+ return tmp - z;
+ // CHECK-ALL-LABEL: test12:
+ // CHECK-FAST: fnmsub
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fsub
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fsub
+}
+
+#pragma STDC FP_CONTRACT DEFAULT
+
+float test17(float x, float y, float z) {
+ return x*y + z;
+ // CHECK-ALL-LABEL: test17:
+ // CHECK-FAST: fmadd
+ // CHECK-ON: fmadd
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fadd
+}
+
+double test18(double x, double y, double z) {
+ z -= x*y;
+ return z;
+ // CHECK-ALL-LABEL: test18:
+ // CHECK-FAST: fmsub
+ // CHECK-ON: fmsub
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fsub
+}
+
+float test19(float x, float y, float z) {
+ float tmp = x*y;
+ return tmp + z;
+ // CHECK-ALL-LABEL: test19:
+ // CHECK-FAST: fmadd
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fadd
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fadd
+}
+
+double test20(double x, double y, double z) {
+ double tmp = x*y;
+ return tmp - z;
+ // CHECK-ALL-LABEL: test20:
+ // CHECK-FAST: fnmsub
+ // CHECK-ON: fmul
+ // CHECK-ON-NEXT: fsub
+ // CHECK-OFF: fmul
+ // CHECK-OFF-NEXT: fsub
+}
diff --git a/clang/test/CodeGen/fp-contract-pragma.cpp b/clang/test/CodeGen/fp-contract-pragma.cpp
index 1c5921a53f9..ceedfd25e48 100644
--- a/clang/test/CodeGen/fp-contract-pragma.cpp
+++ b/clang/test/CodeGen/fp-contract-pragma.cpp
@@ -1,10 +1,9 @@
// RUN: %clang_cc1 -O3 -triple %itanium_abi_triple -emit-llvm -o - %s | FileCheck %s
-// Is FP_CONTRACT honored in a simple case?
-float fp_contract_1(float a, float b, float c) {
-// CHECK: _Z13fp_contract_1fff
+// Is FP_CONTRACT on by default, at least at -O3?
+float fp_contract_8(float a, float b, float c) {
+// CHECK: _Z13fp_contract_8fff
// CHECK: tail call float @llvm.fmuladd
- #pragma STDC FP_CONTRACT ON
return a * b + c;
}
@@ -13,6 +12,7 @@ float fp_contract_2(float a, float b, float c) {
// CHECK: _Z13fp_contract_2fff
// CHECK: %[[M:.+]] = fmul float %a, %b
// CHECK-NEXT: fadd float %[[M]], %c
+ #pragma STDC FP_CONTRACT OFF
{
#pragma STDC FP_CONTRACT ON
}
@@ -20,8 +20,6 @@ float fp_contract_2(float a, float b, float c) {
}
// Does FP_CONTRACT survive template instantiation?
-class Foo {};
-Foo operator+(Foo, Foo);
template <typename T>
T template_muladd(T a, T b, T c) {
@@ -62,15 +60,23 @@ float fp_contract_6(float a, float b, float c) {
return a * b + c;
}
+// Does FP_CONTRACT inside a function override the same in the file scope?
+float fp_contract_1(float a, float b, float c) {
+// CHECK: _Z13fp_contract_1fff
+// CHECK: tail call float @llvm.fmuladd
+ #pragma STDC FP_CONTRACT ON
+ return a * b + c;
+}
+
+
// If the multiply has multiple uses, don't produce fmuladd.
// This used to assert (PR25719):
// https://llvm.org/bugs/show_bug.cgi?id=25719
-float fp_contract_7(float a, float b, float c) {
+float fp_contract_7(float a, float b, float c, float& d_passed_by_ref) {
// CHECK: _Z13fp_contract_7fff
// CHECK: %[[M:.+]] = fmul float %b, 2.000000e+00
-// CHECK-NEXT: fsub float %[[M]], %c
#pragma STDC FP_CONTRACT ON
- return (a = 2 * b) - c;
+ return (d_passed_by_ref = 2 * b) - c;
}
diff --git a/clang/test/CodeGen/fp-contract-pragma___on-by-default.c b/clang/test/CodeGen/fp-contract-pragma___on-by-default.c
new file mode 100644
index 00000000000..549f9847d31
--- /dev/null
+++ b/clang/test/CodeGen/fp-contract-pragma___on-by-default.c
@@ -0,0 +1,21 @@
+// RUN: %clang_cc1 -triple aarch64 -O0 -S -o - %s | FileCheck %s --check-prefix ALL_BUILDS
+// RUN: %clang_cc1 -triple aarch64 -O1 -S -o - %s | FileCheck %s --check-prefixes ALL_BUILDS,NON_O0
+// RUN: %clang_cc1 -triple aarch64 -O2 -S -o - %s | FileCheck %s --check-prefixes ALL_BUILDS,NON_O0
+// RUN: %clang_cc1 -triple aarch64 -O3 -S -o - %s | FileCheck %s --check-prefixes ALL_BUILDS,NON_O0
+
+// REQUIRES: aarch64-registered-target
+
+// ALL_BUILDS-LABEL: fmadd_double:
+// ALL_BUILDS: fmadd d0, d{{[0-7]}}, d{{[0-7]}}, d{{[0-7]}}
+// NON_O0-NEXT: ret
+double fmadd_double(double a, double b, double c) {
+ return a*b+c;
+}
+
+// ALL_BUILDS: fmadd_single:
+// ALL_BUILDS: fmadd s0, s{{[0-7]}}, s{{[0-7]}}, s{{[0-7]}}
+// NON_O0-NEXT: ret
+float fmadd_single(float a, float b, float c) {
+ return a*b+c;
+}
+
diff --git a/clang/test/Driver/clang_f_opts.c b/clang/test/Driver/clang_f_opts.c
index 2952d0e1117..1f6c2bae72f 100644
--- a/clang/test/Driver/clang_f_opts.c
+++ b/clang/test/Driver/clang_f_opts.c
@@ -34,10 +34,13 @@
// 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
+// 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
+// RUN: %clang -### -S -ffp-contract=on %s 2>&1 | FileCheck -check-prefix=FP-CONTRACT-ON-CHECK %s
+
// FP-CONTRACT-FAST-CHECK: -ffp-contract=fast
-// FP-CONTRACT-OFF-CHECK: -ffp-contract=off
+// FP-CONTRACT-OFF-CHECK: -ffp-contract=off
+// FP-CONTRACT-ON-CHECK: -ffp-contract=on
// RUN: %clang -### -S -funroll-loops %s 2>&1 | FileCheck -check-prefix=CHECK-UNROLL-LOOPS %s
// RUN: %clang -### -S -fno-unroll-loops %s 2>&1 | FileCheck -check-prefix=CHECK-NO-UNROLL-LOOPS %s
OpenPOWER on IntegriCloud