blob: 7d8843220f44dc23f41bb69c91e1c8655b85421d [file] [log] [blame]
Melanie Blower7f2db992020-05-08 08:05:34 -07001// RUN: %clang_cc1 -DEXCEPT=1 -fcxx-exceptions -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck -check-prefix=CHECK-NS %s
Melanie Blowerf5360d42020-05-01 10:32:06 -07002// RUN: %clang_cc1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
Melanie Blowere5578012020-05-06 11:45:55 -07003// RUN: %clang_cc1 -verify -DFENV_ON=1 -triple x86_64-linux-gnu -emit-llvm -o - %s | FileCheck %s
Melanie Blower7b8e3062020-05-14 05:56:35 -07004// 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.
7float 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?
16float 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?
27class Foo {};
28Foo operator+(Foo, Foo);
29
30template <typename T>
31T template_muladd(T a, T b, T c) {
32#pragma float_control(precise, off)
33 return a * b + c;
34}
35
36float 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
43template <typename T>
44class 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
51template 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)
59float 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)
Melanie Blowerf5360d42020-05-01 10:32:06 -070066
67float 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}
89float 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}
Melanie Blowere5578012020-05-06 11:45:55 -0700105
Melanie Blower7b8e3062020-05-14 05:56:35 -0700106float 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
Melanie Blowerf5360d42020-05-01 10:32:06 -0700114float 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}
Melanie Blowere5578012020-05-06 11:45:55 -0700121
122#if FENV_ON
123// expected-warning@+1{{pragma STDC FENV_ACCESS ON is not supported, ignoring pragma}}
124#pragma STDC FENV_ACCESS ON
125#endif
126// CHECK-LABEL: define {{.*}}callt{{.*}}
127
128void callt() {
129 volatile float z;
130 z = z * z;
131//CHECK: = fmul float
132}
Melanie Blower7f2db992020-05-08 08:05:34 -0700133
134#if EXCEPT
135namespace ns {
136// Check that pragma float_control can appear in namespace.
137#pragma float_control(except, on, push)
138float exc_on(double x, float zero) {
139// CHECK-NS: define {{.*}}exc_on{{.*}}
140 {} try {
141 x = 1.0 / zero; /* division by zero, the result unused */
142//CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
143 } catch (...) {}
144 return zero;
145}
146}
147
148// Check pragma is still effective after namespace closes
149float exc_still_on(double x, float zero) {
150// CHECK-NS: define {{.*}}exc_still_on{{.*}}
151 {} try {
152 x = 1.0 / zero; /* division by zero, the result unused */
153//CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
154 } catch (...) {}
155 return zero;
156}
157
158#pragma float_control(pop)
159float exc_off(double x, float zero) {
160// CHECK-NS: define {{.*}}exc_off{{.*}}
161 {} try {
162 x = 1.0 / zero; /* division by zero, the result unused */
Melanie Blower827be692020-05-15 07:30:49 -0700163//CHECK-NS: fdiv double
Melanie Blower7f2db992020-05-08 08:05:34 -0700164 } catch (...) {}
165 return zero;
166}
167
168namespace fc_template_namespace {
169#pragma float_control(except, on, push)
170template <class T>
171T exc_on(double x, T zero) {
172// CHECK-NS: define {{.*}}fc_template_namespace{{.*}}
173 {} try {
174 x = 1.0 / zero; /* division by zero, the result unused */
175//CHECK-NS: llvm.experimental.constrained.fdiv{{.*}}
176 } catch (...) {}
177 return zero;
178}
179}
180
181#pragma float_control(pop)
182float xx(double x, float z) {
183 return fc_template_namespace::exc_on<float>(x, z);
184}
185#endif // EXCEPT