1 // RUN: %clang_cc1 -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s
2 // RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
3 // RUN: %clang_cc1 -verify -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
4 
5 float fff(float x, float y) {
6 // CHECK-LABEL: define float @_Z3fffff{{.*}}
7 // CHECK: entry
8 #pragma float_control(except, on)
9   float z;
10   z = z * z;
11   //CHECK: llvm.experimental.constrained.fmul{{.*}}
12   {
13     z = x * y;
14     //CHECK: llvm.experimental.constrained.fmul{{.*}}
15   }
16   {
17 // This pragma has no effect since if there are any fp intrin in the
18 // function then all the operations need to be fp intrin
19 #pragma float_control(except, off)
20     z = z + x * y;
21     //CHECK: llvm.experimental.constrained.fmul{{.*}}
22   }
23   z = z * z;
24   //CHECK: llvm.experimental.constrained.fmul{{.*}}
25   return z;
26 }
27 float check_precise(float x, float y) {
28   // CHECK-LABEL: define float @_Z13check_preciseff{{.*}}
29   float z;
30   {
31 #pragma float_control(precise, on)
32     z = x * y + z;
33     //CHECK: llvm.fmuladd{{.*}}
34   }
35   {
36 #pragma float_control(precise, off)
37     z = x * y + z;
38     //CHECK: fmul fast float
39     //CHECK: fadd fast float
40   }
41   return z;
42 }
43 
44 float fma_test1(float a, float b, float c) {
45 // CHECK-LABEL define float @_Z9fma_test1fff{{.*}}
46 #pragma float_control(precise, on)
47   float x = a * b + c;
48   //CHECK: fmuladd
49   return x;
50 }
51 
52 #if FENV_ON
53 // expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
54 #pragma STDC FENV_ACCESS ON
55 #endif
56 // CHECK-LABEL: define {{.*}}callt{{.*}}
57 
58 void callt() {
59   volatile float z;
60   z = z * z;
61 //CHECK: = fmul float
62 }
63 
64 #if EXCEPT
65 namespace ns {
66 // Check that pragma float_control can appear in namespace.
67 #pragma float_control(except, on, push)
68 float exc_on(double x, float zero) {
69 // CHECK-NS: define {{.*}}exc_on{{.*}}
70   {} try {
71     x = 1.0 / zero; /* division by zero, the result unused */
72 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
73   } catch (...) {}
74   return zero;
75 }
76 }
77 
78 // Check pragma is still effective after namespace closes
79 float exc_still_on(double x, float zero) {
80 // CHECK-NS: define {{.*}}exc_still_on{{.*}}
81   {} try {
82     x = 1.0 / zero; /* division by zero, the result unused */
83 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
84   } catch (...) {}
85   return zero;
86 }
87 
88 #pragma float_control(pop)
89 float exc_off(double x, float zero) {
90 // CHECK-NS: define {{.*}}exc_off{{.*}}
91   {} try {
92     x = 1.0 / zero; /* division by zero, the result unused */
93 //CHECK-NS: fdiv contract double
94   } catch (...) {}
95   return zero;
96 }
97 
98 namespace fc_template_namespace {
99 #pragma float_control(except, on, push)
100 template <class T>
101 T exc_on(double x, T zero) {
102 // CHECK-NS: define {{.*}}fc_template_namespace{{.*}}
103   {} try {
104     x = 1.0 / zero; /* division by zero, the result unused */
105 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
106   } catch (...) {}
107   return zero;
108 }
109 }
110 
111 #pragma float_control(pop)
112 float xx(double x, float z) {
113   return fc_template_namespace::exc_on<float>(x, z);
114 }
115 #endif // EXCEPT
116