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
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)
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)
72 // Does float_control survive template instantiation?
74 Foo
operator+(Foo
, Foo
);
77 T
template_muladd(T a
, T b
, T c
) {
78 #pragma float_control(precise, off)
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
);
91 float method(float a
, float b
, float c
) {
92 #pragma float_control(precise, off)
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
111 #pragma float_control(pop)
113 float fff(float x
, float y
) {
114 // CHECK-LABEL: define{{.*}} float @_Z3fffff{{.*}}
116 #pragma float_control(except, on)
119 //CHECK: llvm.experimental.constrained.fmul{{.*}}
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)
129 //CHECK: llvm.experimental.constrained.fmul{{.*}}
132 //CHECK: llvm.experimental.constrained.fmul{{.*}}
135 float check_precise(float x
, float y
) {
136 // CHECK-LABEL: define{{.*}} float @_Z13check_preciseff{{.*}}
139 #pragma float_control(precise, on)
141 //CHECK: llvm.fmuladd{{.*}}
144 #pragma float_control(precise, off)
146 //CHECK: fmul fast float
147 //CHECK: fadd fast float
152 float fma_test2(float a
, float b
, float c
) {
153 // CHECK-LABEL define{{.*}} float @_Z9fma_test2fff{{.*}}
154 #pragma float_control(precise, off)
160 float fma_test1(float a
, float b
, float c
) {
161 // CHECK-LABEL define{{.*}} float @_Z9fma_test1fff{{.*}}
162 #pragma float_control(precise, on)
168 #pragma float_control(push)
169 #pragma float_control(precise, on)
171 Distance
operator+(Distance
, Distance
);
174 T
add(T lhs
, T rhs
) {
175 #pragma float_control(except, on)
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{{.*}}
187 #pragma STDC FENV_ACCESS ON
189 // CHECK-LABEL: define {{.*}}callt{{.*}}
194 //CHECK-FENV: llvm.experimental.constrained.fmul{{.*}}
197 // CHECK-LABEL: define {{.*}}myAdd{{.*}}
198 float myAdd(int i
, float f
) {
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{{.*}}
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{{.*}}
218 x
= 1.0 / zero
; /* division by zero, the result unused */
219 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
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{{.*}}
229 x
= 1.0 / zero
; /* division by zero, the result unused */
230 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
235 #pragma float_control(pop)
236 float exc_off(double x
, float zero
) {
237 // CHECK-NS: define {{.*}}exc_off{{.*}}
239 x
= 1.0 / zero
; /* division by zero, the result unused */
240 //CHECK-NS: fdiv double
245 namespace fc_template_namespace
{
246 #pragma float_control(except, on, push)
248 T
exc_on(double x
, T zero
) {
249 // CHECK-NS: define {{.*}}fc_template_namespace{{.*}}
251 x
= 1.0 / zero
; /* division by zero, the result unused */
252 //CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
258 #pragma float_control(pop)
259 float xx(double x
, float z
) {
260 return fc_template_namespace::exc_on
<float>(x
, z
);
264 float try_lam(float x
, unsigned n
) {
265 // CHECK: define {{.*}}try_lam{{.*}}class.anon{{.*}}
268 // Lambda expression begins
269 [](float a
, float b
) {
270 #pragma float_control( except, on)
272 //CHECK: llvm.experimental.constrained.fmul{{.*}}fpexcept.strict
273 } // end of lambda expression
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
294 float mySubSource(float x
, float y
) {
295 // CHECK: define {{.*}}float {{.*}}mySubSource{{.*}}
296 #pragma clang fp eval_method(source)
301 float mySubExtended(float x
, float y
) {
302 // CHECK: define {{.*}}float {{.*}}mySubExtended{{.*}}
303 #pragma clang fp eval_method(extended)
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)
317 // CHECK: fpext float
318 // CHECK: fpext float
319 // CHECK: fsub double
320 // CHECK: fptrunc double {{.*}} to float
324 __float128
mySub128(__float128 x
, __float128 y
) {
325 // CHECK: define {{.*}}mySub128{{.*}}
326 // Expect no fpext since fp128 is already widest
328 // CHECK-NEXT: load fp128
329 // CHECK-NEXT: fsub fp128
330 // CHECK-NEXT: ret fp128
335 void mySubfp16(__fp16
*res
, __fp16
*x
, __fp16
*y
) {
336 // CHECK: define {{.*}}mySubfp16{{.*}}
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
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
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
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
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
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