Reland D81869 "Modify FPFeatures to use delta not absolute settings"
This reverts commit defd43a5b393bb63a902042adf578081b03b171d.
with correction to solve msan report

To solve https://bugs.llvm.org/show_bug.cgi?id=46166 where the
floating point settings in PCH files aren't compatible, rewrite
FPFeatures to use a delta in the settings rather than absolute settings.
With this patch, these floating point options can be benign.

Reviewers: rjmccall

Differential Revision: https://reviews.llvm.org/D81869
diff --git a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp b/clang/test/CodeGen/fp-floatcontrol-pragma.cpp
index 7d88432..5488095 100644
--- a/clang/test/CodeGen/fp-floatcontrol-pragma.cpp
+++ b/clang/test/CodeGen/fp-floatcontrol-pragma.cpp
@@ -119,6 +119,24 @@
   return x;
 }
 
+#pragma float_control(push)
+#pragma float_control(precise, on)
+struct Distance {};
+Distance operator+(Distance, Distance);
+
+template <class T>
+T add(T lhs, T rhs) {
+#pragma float_control(except, on)
+  return lhs + rhs;
+}
+#pragma float_control(pop)
+
+float test_OperatorCall() {
+  return add(1.0f, 2.0f);
+  //CHECK: llvm.experimental.constrained.fadd{{.*}}fpexcept.strict
+}
+// CHECK-LABEL define float  {{.*}}test_OperatorCall{{.*}}
+
 #if FENV_ON
 // expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
 #pragma STDC FENV_ACCESS ON
diff --git a/clang/test/CodeGenOpenCL/relaxed-fpmath.cl b/clang/test/CodeGenOpenCL/relaxed-fpmath.cl
index ced15f6..1f12392 100644
--- a/clang/test/CodeGenOpenCL/relaxed-fpmath.cl
+++ b/clang/test/CodeGenOpenCL/relaxed-fpmath.cl
@@ -5,6 +5,17 @@
 // RUN: %clang_cc1 %s -emit-llvm -cl-mad-enable -o - | FileCheck %s -check-prefix=MAD
 // RUN: %clang_cc1 %s -emit-llvm -cl-no-signed-zeros -o - | FileCheck %s -check-prefix=NOSIGNED
 
+// Check the fp options are correct with PCH.
+// RUN: %clang_cc1 %s -DGEN_PCH=1 -finclude-default-header -triple spir-unknown-unknown -emit-pch -o %t.pch
+// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -o - | FileCheck %s -check-prefix=NORMAL
+// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-fast-relaxed-math -o - | FileCheck %s -check-prefix=FAST
+// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-finite-math-only -o - | FileCheck %s -check-prefix=FINITE
+// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-unsafe-math-optimizations -o - | FileCheck %s -check-prefix=UNSAFE
+// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-mad-enable -o - | FileCheck %s -check-prefix=MAD
+// RUN: %clang_cc1 %s -include-pch %t.pch -fno-validate-pch -emit-llvm -cl-no-signed-zeros -o - | FileCheck %s -check-prefix=NOSIGNED
+
+#if !GEN_PCH
+
 float spscalardiv(float a, float b) {
   // CHECK: @spscalardiv(
 
@@ -53,3 +64,8 @@
 // NOSIGNED: "no-nans-fp-math"="false"
 // NOSIGNED: "no-signed-zeros-fp-math"="true"
 // NOSIGNED: "unsafe-fp-math"="false"
+
+#else
+// Undefine this to avoid putting it in the PCH.
+#undef GEN_PCH
+#endif
diff --git a/clang/test/PCH/pragma-floatcontrol.c b/clang/test/PCH/pragma-floatcontrol.c
index a0918dd..8be46db 100644
--- a/clang/test/PCH/pragma-floatcontrol.c
+++ b/clang/test/PCH/pragma-floatcontrol.c
@@ -6,6 +6,18 @@
 // Test with pch.
 // RUN: %clang_cc1 %s -DSET -emit-pch -o %t
 // RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
+// RUN: %clang_cc1 %s -ffp-contract=on -DSET -emit-pch -o %t
+// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
+// RUN: %clang_cc1 %s -menable-no-nans -DSET -emit-pch -o %t
+// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
+// RUN: %clang_cc1 %s -frounding-math -DSET -emit-pch -o %t
+// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
+// RUN: %clang_cc1 %s -ffp-exception-behavior=maytrap -DSET -emit-pch -o %t
+// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
+// RUN: %clang_cc1 %s -ffp-contract=fast -DSET -emit-pch -o %t
+// RUN: %clang_cc1 %s -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-EBSTRICT %s
+// RUN: %clang_cc1 %s -DSET -emit-pch -o %t
+// RUN: %clang_cc1 %s -ffp-contract=on -DSET -include-pch %t -emit-llvm -o - | FileCheck --check-prefix=CHECK-CONTRACT %s
 // RUN: %clang_cc1 %s -DPUSH -emit-pch -o %t
 // RUN: %clang_cc1 %s -DPUSH -verify -include-pch %t
 // RUN: %clang_cc1 %s -DPUSH_POP -emit-pch -o %t
@@ -36,6 +48,7 @@
   // CHECK-LABEL: define float @fun{{.*}}
   //CHECK-EBSTRICT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict
   //CHECK-EBSTRICT: llvm.experimental.constrained.fadd{{.*}}tonearest{{.*}}strict
+  //CHECK-CONTRACT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict
   return a * b + 2;
 }
 #pragma float_control(pop) // expected-warning {{#pragma float_control(pop, ...) failed: stack empty}}
diff --git a/clang/test/SemaOpenCL/fp-options.cl b/clang/test/SemaOpenCL/fp-options.cl
new file mode 100644
index 0000000..413afd6
--- /dev/null
+++ b/clang/test/SemaOpenCL/fp-options.cl
@@ -0,0 +1,4 @@
+// RUN: %clang_cc1 %s -finclude-default-header -triple spir-unknown-unknown -emit-pch -o %t.pch
+// RUN: %clang_cc1 %s -finclude-default-header -cl-no-signed-zeros -triple spir-unknown-unknown -include-pch %t.pch -fsyntax-only -verify
+// expected-no-diagnostics
+