xref: /llvm-project/clang/test/CodeGen/fp-floatcontrol-pragma.cpp (revision 9518763d710bfbbf9315fa88972c55898be44a0e)
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 // RUN: %clang_cc1 -triple %itanium_abi_triple -O3 -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-O3 %s
5 
6 // Verify float_control(precise, off) enables fast math flags on fp operations.
7 float fp_precise_1(float a, float b, float c) {
8 // CHECK-O3: _Z12fp_precise_1fff
9 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}
10 // CHECK-O3: fadd fast float %[[M]], %c
11 #pragma float_control(precise, off)
12   return a * b + c;
13 }
14 
15 // Is float_control state cleared on exiting compound statements?
16 float fp_precise_2(float a, float b, float c) {
17   // CHECK-O3: _Z12fp_precise_2fff
18   // CHECK-O3: %[[M:.+]] = fmul float{{.*}}
19   // CHECK-O3: fadd float %[[M]], %c
20   {
21 #pragma float_control(precise, off)
22   }
23   return a * b + c;
24 }
25 
26 // Does float_control survive template instantiation?
27 class Foo {};
28 Foo operator+(Foo, Foo);
29 
30 template <typename T>
31 T template_muladd(T a, T b, T c) {
32 #pragma float_control(precise, off)
33   return a * b + c;
34 }
35 
36 float fp_precise_3(float a, float b, float c) {
37   // CHECK-O3: _Z12fp_precise_3fff
38   // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}
39   // CHECK-O3: fadd fast float %[[M]], %c
40   return template_muladd<float>(a, b, c);
41 }
42 
43 template <typename T>
44 class fp_precise_4 {
45   float method(float a, float b, float c) {
46 #pragma float_control(precise, off)
47     return a * b + c;
48   }
49 };
50 
51 template class fp_precise_4<int>;
52 // CHECK-O3: _ZN12fp_precise_4IiE6methodEfff
53 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}
54 // CHECK-O3: fadd fast float %[[M]], %c
55 
56 // Check file-scoped float_control
57 #pragma float_control(push)
58 #pragma float_control(precise, off)
59 float fp_precise_5(float a, float b, float c) {
60   // CHECK-O3: _Z12fp_precise_5fff
61   // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}
62   // CHECK-O3: fadd fast float %[[M]], %c
63   return a * b + c;
64 }
65 #pragma float_control(pop)
66 
67 float fff(float x, float y) {
68 // CHECK-LABEL: define float @_Z3fffff{{.*}}
69 // CHECK: entry
70 #pragma float_control(except, on)
71   float z;
72   z = z * z;
73   //CHECK: llvm.experimental.constrained.fmul{{.*}}
74   {
75     z = x * y;
76     //CHECK: llvm.experimental.constrained.fmul{{.*}}
77   }
78   {
79 // This pragma has no effect since if there are any fp intrin in the
80 // function then all the operations need to be fp intrin
81 #pragma float_control(except, off)
82     z = z + x * y;
83     //CHECK: llvm.experimental.constrained.fmul{{.*}}
84   }
85   z = z * z;
86   //CHECK: llvm.experimental.constrained.fmul{{.*}}
87   return z;
88 }
89 float check_precise(float x, float y) {
90   // CHECK-LABEL: define float @_Z13check_preciseff{{.*}}
91   float z;
92   {
93 #pragma float_control(precise, on)
94     z = x * y + z;
95     //CHECK: llvm.fmuladd{{.*}}
96   }
97   {
98 #pragma float_control(precise, off)
99     z = x * y + z;
100     //CHECK: fmul fast float
101     //CHECK: fadd fast float
102   }
103   return z;
104 }
105 
106 float fma_test2(float a, float b, float c) {
107 // CHECK-LABEL define float @_Z9fma_test2fff{{.*}}
108 #pragma float_control(precise, off)
109   float x = a * b + c;
110   //CHECK: fmuladd
111   return x;
112 }
113 
114 float fma_test1(float a, float b, float c) {
115 // CHECK-LABEL define float @_Z9fma_test1fff{{.*}}
116 #pragma float_control(precise, on)
117   float x = a * b + c;
118   //CHECK: fmuladd
119   return x;
120 }
121 
122 #pragma float_control(push)
123 #pragma float_control(precise, on)
124 struct Distance {};
125 Distance operator+(Distance, Distance);
126 
127 template <class T>
128 T add(T lhs, T rhs) {
129 #pragma float_control(except, on)
130   return lhs + rhs;
131 }
132 #pragma float_control(pop)
133 
134 float test_OperatorCall() {
135   return add(1.0f, 2.0f);
136   //CHECK: llvm.experimental.constrained.fadd{{.*}}fpexcept.strict
137 }
138 // CHECK-LABEL define float  {{.*}}test_OperatorCall{{.*}}
139 
140 #if FENV_ON
141 // expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
142 #pragma STDC FENV_ACCESS ON
143 #endif
144 // CHECK-LABEL: define {{.*}}callt{{.*}}
145 
146 void callt() {
147   volatile float z;
148   z = z * z;
149 //CHECK: = fmul float
150 }
151 
152 #if EXCEPT
153 namespace ns {
154 // Check that pragma float_control can appear in namespace.
155 #pragma float_control(except, on, push)
156 float exc_on(double x, float zero) {
157 // CHECK-NS: define {{.*}}exc_on{{.*}}
158   {} try {
159     x = 1.0 / zero; /* division by zero, the result unused */
160 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
161   } catch (...) {}
162   return zero;
163 }
164 }
165 
166 // Check pragma is still effective after namespace closes
167 float exc_still_on(double x, float zero) {
168 // CHECK-NS: define {{.*}}exc_still_on{{.*}}
169   {} try {
170     x = 1.0 / zero; /* division by zero, the result unused */
171 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
172   } catch (...) {}
173   return zero;
174 }
175 
176 #pragma float_control(pop)
177 float exc_off(double x, float zero) {
178 // CHECK-NS: define {{.*}}exc_off{{.*}}
179   {} try {
180     x = 1.0 / zero; /* division by zero, the result unused */
181 //CHECK-NS: fdiv double
182   } catch (...) {}
183   return zero;
184 }
185 
186 namespace fc_template_namespace {
187 #pragma float_control(except, on, push)
188 template <class T>
189 T exc_on(double x, T zero) {
190 // CHECK-NS: define {{.*}}fc_template_namespace{{.*}}
191   {} try {
192     x = 1.0 / zero; /* division by zero, the result unused */
193 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
194   } catch (...) {}
195   return zero;
196 }
197 }
198 
199 #pragma float_control(pop)
200 float xx(double x, float z) {
201   return fc_template_namespace::exc_on<float>(x, z);
202 }
203 #endif // EXCEPT
204