summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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