1 // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DDEFAULT=1 -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-DDEFAULT %s
2 // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DEBSTRICT=1 -ffp-exception-behavior=strict -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-DEBSTRICT %s
3 // RUN: %clang_cc1 -triple x86_64-linux-gnu -DFAST=1 -ffast-math -ffp-contract=fast -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-FAST %s
4 // RUN: %clang_cc1 -triple x86_64-linux-gnu -ffp-contract=on -DNOHONOR=1 -menable-no-infs -menable-no-nans -emit-llvm -o - %s | FileCheck --check-prefix=CHECK-NOHONOR %s
5 
6 #define FUN(n) \
7   (float z) { return n * z + n; }
8 
9 float fun_default FUN(1)
10 //CHECK-LABEL: define {{.*}} @_Z11fun_defaultf{{.*}}
11 #if DEFAULT
12 //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}}
13 #endif
14 #if EBSTRICT
15 // Note that backend wants constrained intrinsics used
16 // throughout the function if they are needed anywhere in the function.
17 // In that case, operations are built with constrained intrinsics operator
18 // but using default settings for exception behavior and rounding mode.
19 //CHECK-DEBSTRICT: llvm.experimental.constrained.fmul{{.*}}tonearest{{.*}}strict
20 #endif
21 #if FAST
22 //CHECK-FAST: fmul fast float
23 //CHECK-FAST: fadd fast float
24 #endif
25 
26 #pragma float_control(push)
27 #ifndef FAST
28 // Rule: precise must be enabled
29 #pragma float_control(except, on)
30 #endif
31     float exc_on FUN(2)
32 //CHECK-LABEL: define {{.*}} @_Z6exc_onf{{.*}}
33 #if DEFAULT
34 //CHECK-DDEFAULT: llvm.experimental.constrained.fmul{{.*}}
35 #endif
36 #if EBSTRICT
37 //CHECK-DEBSTRICT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict
38 #endif
39 #if NOHONOR
40 //CHECK-NOHONOR: nnan ninf float {{.*}}llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict
41 #endif
42 #if FAST
43 //Not possible to enable float_control(except) in FAST mode.
44 //CHECK-FAST: fmul fast float
45 //CHECK-FAST: fadd fast float
46 #endif
47 
48 #pragma float_control(pop)
49         float exc_pop FUN(5)
50 //CHECK-LABEL: define {{.*}} @_Z7exc_popf{{.*}}
51 #if DEFAULT
52 //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}}
53 #endif
54 #if EBSTRICT
55 //CHECK-DEBSTRICT: llvm.experimental.constrained.fmuladd{{.*}}tonearest{{.*}}strict
56 #endif
57 #if NOHONOR
58 //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}}
59 #endif
60 #if FAST
61 //CHECK-FAST: fmul fast float
62 //CHECK-FAST: fadd fast float
63 #endif
64 
65 #pragma float_control(except, off)
66             float exc_off FUN(5)
67 //CHECK-LABEL: define {{.*}} @_Z7exc_offf{{.*}}
68 #if DEFAULT
69 //CHECK-DDEFAULT: call float @llvm.fmuladd{{.*}}
70 #endif
71 #if EBSTRICT
72 //CHECK-DEBSTRICT: call float @llvm.fmuladd{{.*}}
73 #endif
74 #if NOHONOR
75 //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}}
76 #endif
77 #if FAST
78 //CHECK-FAST: fmul fast float
79 //CHECK-FAST: fadd fast float
80 #endif
81 
82 #pragma float_control(precise, on, push)
83                 float precise_on FUN(3)
84 //CHECK-LABEL: define {{.*}} @_Z10precise_onf{{.*}}
85 #if DEFAULT
86 //CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}}
87 #endif
88 #if EBSTRICT
89 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}}
90 #endif
91 #if NOHONOR
92 // If precise is pushed then all fast-math should be off!
93 //CHECK-NOHONOR: call float {{.*}}llvm.fmuladd{{.*}}
94 #endif
95 #if FAST
96 //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}}
97 #endif
98 
99 #pragma float_control(pop)
100                     float precise_pop FUN(3)
101 //CHECK-LABEL: define {{.*}} @_Z11precise_popf{{.*}}
102 #if DEFAULT
103 //CHECK-DDEFAULT: float {{.*}}llvm.fmuladd{{.*}}
104 #endif
105 #if EBSTRICT
106 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}}
107 #endif
108 #if NOHONOR
109 //CHECK-NOHONOR: call nnan ninf float @llvm.fmuladd{{.*}}
110 #endif
111 #if FAST
112 //CHECK-FAST: fmul fast float
113 //CHECK-FAST: fadd fast float
114 #endif
115 #pragma float_control(precise, off)
116                         float precise_off FUN(4)
117 //CHECK-LABEL: define {{.*}} @_Z11precise_offf{{.*}}
118 #if DEFAULT
119 // Note: precise_off enables fp_contract=fast and the instructions
120 // generated do not include the contract flag, although it was enabled
121 // in IRBuilder.
122 //CHECK-DDEFAULT: fmul fast float
123 //CHECK-DDEFAULT: fadd fast float
124 #endif
125 #if EBSTRICT
126 //CHECK-DEBSTRICT: fmul fast float
127 //CHECK-DEBSTRICT: fadd fast float
128 #endif
129 #if NOHONOR
130 // fast math should be enabled, and contract should be fast
131 //CHECK-NOHONOR: fmul fast float
132 //CHECK-NOHONOR: fadd fast float
133 #endif
134 #if FAST
135 //CHECK-FAST: fmul fast float
136 //CHECK-FAST: fadd fast float
137 #endif
138 
139 #pragma float_control(precise, on)
140                             float precise_on2 FUN(3)
141 //CHECK-LABEL: define {{.*}} @_Z11precise_on2f{{.*}}
142 #if DEFAULT
143 //CHECK-DDEFAULT: llvm.fmuladd{{.*}}
144 #endif
145 #if EBSTRICT
146 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}}
147 #endif
148 #if NOHONOR
149 // fast math should be off, and contract should be on
150 //CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}}
151 #endif
152 #if FAST
153 //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}}
154 #endif
155 
156 #pragma float_control(push)
157                                 float precise_push FUN(3)
158 //CHECK-LABEL: define {{.*}} @_Z12precise_pushf{{.*}}
159 #if DEFAULT
160 //CHECK-DDEFAULT: llvm.fmuladd{{.*}}
161 #endif
162 #if EBSTRICT
163 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}}
164 #endif
165 #if NOHONOR
166 //CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}}
167 #endif
168 #if FAST
169 //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}}
170 #endif
171 
172 #pragma float_control(precise, off)
173                                     float precise_off2 FUN(4)
174 //CHECK-LABEL: define {{.*}} @_Z12precise_off2f{{.*}}
175 #if DEFAULT
176 //CHECK-DDEFAULT: fmul fast float
177 //CHECK-DDEFAULT: fadd fast float
178 #endif
179 #if EBSTRICT
180 //CHECK-DEBSTRICT: fmul fast float
181 //CHECK-DEBSTRICT: fadd fast float
182 #endif
183 #if NOHONOR
184 // fast math settings since precise is off
185 //CHECK-NOHONOR: fmul fast float
186 //CHECK-NOHONOR: fadd fast float
187 #endif
188 #if FAST
189 //CHECK-FAST: fmul fast float
190 //CHECK-FAST: fadd fast float
191 #endif
192 
193 #pragma float_control(pop)
194                                         float precise_pop2 FUN(3)
195 //CHECK-LABEL: define {{.*}} @_Z12precise_pop2f{{.*}}
196 #if DEFAULT
197 //CHECK-DDEFAULT: llvm.fmuladd{{.*}}
198 #endif
199 #if EBSTRICT
200 //CHECK-DEBSTRICT: float {{.*}}llvm.fmuladd{{.*}}
201 #endif
202 #if NOHONOR
203 //CHECK-NOHONOR: float {{.*}}llvm.fmuladd{{.*}}
204 #endif
205 #if FAST
206 //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}}
207 #endif
208 
209 #ifndef FAST
210 // Rule: precise must be enabled
211 #pragma float_control(except, on)
212 #endif
213                                             float y();
214 class ON {
215   // Settings for top level class initializer use program source setting.
216   float z = 2 + y() * 7;
217 //CHECK-LABEL: define {{.*}} void @_ZN2ONC2Ev{{.*}}
218 #if DEFAULT
219 //CHECK-DDEFAULT: call float {{.*}}llvm.fmuladd
220 #endif
221 #if EBSTRICT
222 //Currently, same as default [command line options not considered]
223 //CHECK-DEBSTRICT: call float {{.*}}llvm.fmuladd
224 #endif
225 #if NOHONOR
226 //CHECK-NOHONOR: call float {{.*}}llvm.fmuladd
227 #endif
228 #if FAST
229 //CHECK-FAST: float {{.*}}llvm.fmuladd{{.*}}
230 #endif
231 };
232 ON on;
233 #pragma float_control(except, off)
234 class OFF {
235   float w = 2 + y() * 7;
236 //CHECK-LABEL: define {{.*}} void @_ZN3OFFC2Ev{{.*}}
237 //CHECK: call float {{.*}}llvm.fmuladd
238 };
239 OFF off;
240 
241 #pragma clang fp reassociate(on)
242 struct MyComplex {
243   float xx;
244   float yy;
245   MyComplex(float x, float y) {
246     xx = x;
247     yy = y;
248   }
249   MyComplex() {}
250   const MyComplex operator+(const MyComplex other) const {
251 //CHECK-LABEL: define {{.*}} @_ZNK9MyComplexplES_
252 //CHECK: fadd reassoc float
253 //CHECK: fadd reassoc float
254     return MyComplex(xx + other.xx, yy + other.yy);
255   }
256 };
257 MyComplex useAdd() {
258   MyComplex a (1, 3);
259   MyComplex b (2, 4);
260    return a + b;
261 }
262