Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CodeGen / fp-floatcontrol-pragma.cpp
blob966eaf6053970ad1a2a25737e2e6d9ddf26bbc6b
1 // RUN: %clang_cc1 -fexperimental-strict-floating-point -DEXCEPT=1 \
2 // RUN: -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s \
3 // RUN: | FileCheck -check-prefix=CHECK-NS %s
5 // RUN: %clang_cc1 -fexperimental-strict-floating-point \
6 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s \
7 // RUN: -check-prefixes=CHECK-DEFAULT,CHECK-CONST-ARGS
9 // RUN: %clang_cc1 -fexperimental-strict-floating-point -DFENV_ON=1 \
10 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s \
11 // RUN: | FileCheck -check-prefix=CHECK-FENV %s
13 // RUN: %clang_cc1 -fexperimental-strict-floating-point -DNF128 \
14 // RUN: -triple %itanium_abi_triple -O3 -emit-llvm -o - %s \
15 // RUN: | FileCheck -check-prefix=CHECK-O3 %s
17 // RUN: %clang_cc1 -fexperimental-strict-floating-point \
18 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \
19 // RUN: | FileCheck %s -check-prefixes=CHECK-SOURCE,CHECK-CONST-ARGS
21 // RUN: %clang_cc1 -fexperimental-strict-floating-point \
22 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=double \
23 // RUN: | FileCheck %s -check-prefixes=CHECK-DOUBLE,CHECK-CONST-ARGS
25 // RUN: %clang_cc1 -fexperimental-strict-floating-point \
26 // RUN: -triple x86_64-linux-gnu -emit-llvm -o - %s -ffp-eval-method=extended \
27 // RUN: -mlong-double-80 | FileCheck %s \
28 // RUN: -check-prefixes=CHECK-EXTENDED,CHECK-CONST-ARGS
30 // RUN: %clang_cc1 -fexperimental-strict-floating-point \
31 // RUN: -triple i386-linux-gnu -emit-llvm -o - %s -ffp-eval-method=source \
32 // RUN: | FileCheck %s -check-prefix=CHECK-SOURCE
34 // RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu \
35 // RUN: -emit-llvm -o - %s -ffp-eval-method=double | FileCheck %s \
36 // RUN: -check-prefix=CHECK-DOUBLE
38 // RUN: %clang_cc1 -fexperimental-strict-floating-point -triple i386-linux-gnu \
39 // RUN: -emit-llvm -o - %s -ffp-eval-method=extended -mlong-double-80 \
40 // RUN: | FileCheck %s -check-prefix=CHECK-EXTENDED
42 // RUN: %clang_cc1 -triple powerpc-unknown-aix -DNF128 -emit-llvm -o - %s \
43 // RUN: | FileCheck %s -check-prefix=CHECK-AIX
45 bool f() {
46 // CHECK: define {{.*}}f{{.*}}
47 return __FLT_EVAL_METHOD__ < 0 &&
48 __FLT_EVAL_METHOD__ == -1;
49 // CHECK: ret {{.*}} true
52 // Verify float_control(precise, off) enables fast math flags on fp operations.
53 float fp_precise_1(float a, float b, float c) {
54 // CHECK-O3: _Z12fp_precise_1fff
55 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}
56 // CHECK-O3: fadd fast float %[[M]], %c
57 #pragma float_control(precise, off)
58 return a * b + c;
61 // Is float_control state cleared on exiting compound statements?
62 float fp_precise_2(float a, float b, float c) {
63 // CHECK-O3: _Z12fp_precise_2fff
64 // CHECK-O3: %[[M:.+]] = fmul float{{.*}}
65 // CHECK-O3: fadd float %[[M]], %c
67 #pragma float_control(precise, off)
69 return a * b + c;
72 // Does float_control survive template instantiation?
73 class Foo {};
74 Foo operator+(Foo, Foo);
76 template <typename T>
77 T template_muladd(T a, T b, T c) {
78 #pragma float_control(precise, off)
79 return a * b + c;
82 float fp_precise_3(float a, float b, float c) {
83 // CHECK-O3: _Z12fp_precise_3fff
84 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}
85 // CHECK-O3: fadd fast float %[[M]], %c
86 return template_muladd<float>(a, b, c);
89 template <typename T>
90 class fp_precise_4 {
91 float method(float a, float b, float c) {
92 #pragma float_control(precise, off)
93 return a * b + c;
97 template class fp_precise_4<int>;
98 // CHECK-O3: _ZN12fp_precise_4IiE6methodEfff
99 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}
100 // CHECK-O3: fadd fast float %[[M]], %c
102 // Check file-scoped float_control
103 #pragma float_control(push)
104 #pragma float_control(precise, off)
105 float fp_precise_5(float a, float b, float c) {
106 // CHECK-O3: _Z12fp_precise_5fff
107 // CHECK-O3: %[[M:.+]] = fmul fast float{{.*}}
108 // CHECK-O3: fadd fast float %[[M]], %c
109 return a * b + c;
111 #pragma float_control(pop)
113 float fff(float x, float y) {
114 // CHECK-LABEL: define{{.*}} float @_Z3fffff{{.*}}
115 // CHECK: entry
116 #pragma float_control(except, on)
117 float z;
118 z = z * z;
119 //CHECK: llvm.experimental.constrained.fmul{{.*}}
121 z = x * y;
122 //CHECK: llvm.experimental.constrained.fmul{{.*}}
125 // This pragma has no effect since if there are any fp intrin in the
126 // function then all the operations need to be fp intrin
127 #pragma float_control(except, off)
128 z = z + x * y;
129 //CHECK: llvm.experimental.constrained.fmul{{.*}}
131 z = z * z;
132 //CHECK: llvm.experimental.constrained.fmul{{.*}}
133 return z;
135 float check_precise(float x, float y) {
136 // CHECK-LABEL: define{{.*}} float @_Z13check_preciseff{{.*}}
137 float z;
139 #pragma float_control(precise, on)
140 z = x * y + z;
141 //CHECK: llvm.fmuladd{{.*}}
144 #pragma float_control(precise, off)
145 z = x * y + z;
146 //CHECK: fmul fast float
147 //CHECK: fadd fast float
149 return z;
152 float fma_test2(float a, float b, float c) {
153 // CHECK-LABEL define{{.*}} float @_Z9fma_test2fff{{.*}}
154 #pragma float_control(precise, off)
155 float x = a * b + c;
156 //CHECK: fmuladd
157 return x;
160 float fma_test1(float a, float b, float c) {
161 // CHECK-LABEL define{{.*}} float @_Z9fma_test1fff{{.*}}
162 #pragma float_control(precise, on)
163 float x = a * b + c;
164 //CHECK: fmuladd
165 return x;
168 #pragma float_control(push)
169 #pragma float_control(precise, on)
170 struct Distance {};
171 Distance operator+(Distance, Distance);
173 template <class T>
174 T add(T lhs, T rhs) {
175 #pragma float_control(except, on)
176 return lhs + rhs;
178 #pragma float_control(pop)
180 float test_OperatorCall() {
181 return add(1.0f, 2.0f);
182 //CHECK: llvm.experimental.constrained.fadd{{.*}}fpexcept.strict
184 // CHECK-LABEL define{{.*}} float {{.*}}test_OperatorCall{{.*}}
186 #if FENV_ON
187 #pragma STDC FENV_ACCESS ON
188 #endif
189 // CHECK-LABEL: define {{.*}}callt{{.*}}
191 void callt() {
192 volatile float z;
193 z = z * z;
194 //CHECK-FENV: llvm.experimental.constrained.fmul{{.*}}
197 // CHECK-LABEL: define {{.*}}myAdd{{.*}}
198 float myAdd(int i, float f) {
199 if (i<0)
200 return 1.0 + 2.0;
201 // Check that floating point constant folding doesn't occur if
202 // #pragma STC FENV_ACCESS is enabled.
203 //CHECK-FENV: llvm.experimental.constrained.fadd{{.*}}double 1.0{{.*}}double 2.0{{.*}}
204 //CHECK: store float 3.0{{.*}}retval{{.*}}
205 static double v = 1.0 / 3.0;
206 //CHECK-FENV: llvm.experimental.constrained.fptrunc.f32.f64{{.*}}
207 //CHECK-NOT: fdiv
208 return v;
211 #if EXCEPT
212 namespace ns {
213 // Check that pragma float_control can appear in namespace.
214 #pragma float_control(except, on, push)
215 float exc_on(double x, float zero) {
216 // CHECK-NS: define {{.*}}exc_on{{.*}}
217 {} try {
218 x = 1.0 / zero; /* division by zero, the result unused */
219 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
220 } catch (...) {}
221 return zero;
225 // Check pragma is still effective after namespace closes
226 float exc_still_on(double x, float zero) {
227 // CHECK-NS: define {{.*}}exc_still_on{{.*}}
228 {} try {
229 x = 1.0 / zero; /* division by zero, the result unused */
230 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
231 } catch (...) {}
232 return zero;
235 #pragma float_control(pop)
236 float exc_off(double x, float zero) {
237 // CHECK-NS: define {{.*}}exc_off{{.*}}
238 {} try {
239 x = 1.0 / zero; /* division by zero, the result unused */
240 //CHECK-NS: fdiv double
241 } catch (...) {}
242 return zero;
245 namespace fc_template_namespace {
246 #pragma float_control(except, on, push)
247 template <class T>
248 T exc_on(double x, T zero) {
249 // CHECK-NS: define {{.*}}fc_template_namespace{{.*}}
250 {} try {
251 x = 1.0 / zero; /* division by zero, the result unused */
252 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
253 } catch (...) {}
254 return zero;
258 #pragma float_control(pop)
259 float xx(double x, float z) {
260 return fc_template_namespace::exc_on<float>(x, z);
262 #endif // EXCEPT
264 float try_lam(float x, unsigned n) {
265 // CHECK: define {{.*}}try_lam{{.*}}class.anon{{.*}}
266 float result;
267 auto t =
268 // Lambda expression begins
269 [](float a, float b) {
270 #pragma float_control( except, on)
271 return a * b;
272 //CHECK: llvm.experimental.constrained.fmul{{.*}}fpexcept.strict
273 } // end of lambda expression
274 (1.0f,2.0f);
275 result = x + t;
276 return result;
279 float mySub(float x, float y) {
280 // CHECK: define {{.*}}float {{.*}}mySub{{.*}}
281 // CHECK-NS: fsub float
282 // CHECK-SOURCE: fsub float
283 // CHECK-DOUBLE: fpext float
284 // CHECK-DOUBLE: fpext float
285 // CHECK-DOUBLE: fsub double
286 // CHECK-DOUBLE: fptrunc double {{.*}} to float
287 // CHECK-EXTENDED: fpext float
288 // CHECK-EXTENDED: fpext float
289 // CHECK-EXTENDED: fsub double
290 // CHECK-EXTENDED: fptrunc double {{.*}} to float
291 return x - y;
294 float mySubSource(float x, float y) {
295 // CHECK: define {{.*}}float {{.*}}mySubSource{{.*}}
296 #pragma clang fp eval_method(source)
297 return x - y;
298 // CHECK: fsub float
301 float mySubExtended(float x, float y) {
302 // CHECK: define {{.*}}float {{.*}}mySubExtended{{.*}}
303 #pragma clang fp eval_method(extended)
304 return x - y;
305 // CHECK: fpext float
306 // CHECK: fpext float
307 // CHECK: fsub x86_fp80
308 // CHECK: fptrunc x86_fp80 {{.*}} to float
309 // CHECK-AIX: fsub double
310 // CHECK-AIX: fptrunc double
313 float mySubDouble(float x, float y) {
314 // CHECK: define {{.*}}float {{.*}}mySubDouble{{.*}}
315 #pragma clang fp eval_method(double)
316 return x - y;
317 // CHECK: fpext float
318 // CHECK: fpext float
319 // CHECK: fsub double
320 // CHECK: fptrunc double {{.*}} to float
323 #ifndef NF128
324 __float128 mySub128(__float128 x, __float128 y) {
325 // CHECK: define {{.*}}mySub128{{.*}}
326 // Expect no fpext since fp128 is already widest
327 // CHECK: load fp128
328 // CHECK-NEXT: load fp128
329 // CHECK-NEXT: fsub fp128
330 // CHECK-NEXT: ret fp128
331 return x - y;
333 #endif
335 void mySubfp16(__fp16 *res, __fp16 *x, __fp16 *y) {
336 // CHECK: define {{.*}}mySubfp16{{.*}}
337 *res = *x - *y;
338 // CHECK: load half
339 // CHECK-NEXT: load half
340 // CHECK-NEXT: fpext half{{.*}}
341 // CHECK-NEXT: load half
342 // CHECK-NEXT: load half
343 // CHECK-NS: fpext half{{.*}} to float
344 // CHECK-DEFAULT: fpext half{{.*}} to float
345 // CHECK-DOUBLE: fpext half{{.*}} to float
346 // CHECK-EXTENDED: fpext half{{.*}} to float
347 // CHECK-NEXT: fsub
348 // CHECK-NEXT: fptrunc {{.*}}to half
349 // CHECK-NS: fptrunc float {{.*}} to half
350 // CHECK-DOUBLE: fptrunc float {{.*}} to half
351 // CHECK-EXTENDED: fptrunc float {{.*}} to half
354 float Div(float x, float y, float z) {
355 // CHECK: define{{.*}}float {{.*}}Div{{.*}}
356 // CHECK-CONST-ARGS: fdiv float
357 return x / (y / z);
360 float DivExtended(float x, float y, float z) {
361 // CHECK: define{{.*}}float {{.*}}DivExtended{{.*}}
362 #pragma clang fp eval_method(extended)
363 // CHECK-CONST-ARGS: fdiv x86_fp80
364 // CHECK-CONST-ARGS: fptrunc x86_fp80
365 return x / (y / z);
368 float DivDouble(float x, float y, float z) {
369 // CHECK: define{{.*}}float {{.*}}DivDouble{{.*}}
370 #pragma clang fp eval_method(double)
371 // CHECK-CONST-ARGS: fdiv double
372 // CHECK-CONST-ARGS: fptrunc double
373 return x / (y / z);
376 float DivSource(float x, float y, float z) {
377 // CHECK: define{{.*}}float {{.*}}DivSource{{.*}}
378 #pragma clang fp eval_method(source)
379 // CHECK-CONST-ARGS: fdiv float
380 return x / (y / z);
383 int main() {
384 float f = Div(4.2f, 1.0f, 3.0f);
385 float fextended = DivExtended(4.2f, 1.0f, 3.0f);
386 float fdouble = DivDouble(4.2f, 1.0f, 3.0f);
387 float fsource = DivSource(4.2f, 1.0f, 3.0f);
388 // CHECK: store float