xref: /llvm-project/llvm/test/Transforms/Attributor/denormal-fp-math.ll (revision 850ec7bbb18f36535d60b5201b0d7f368408ec23)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes --check-globals --version 2
2; RUN: opt -S -passes=attributor < %s | FileCheck %s
3
4; Keep the attribute checks clean by disabling inference of anything else.
5declare void @call_of_mystery()
6
7; Should infer to ieee,ieee/default
8define internal void @leaf_dynamic_dynamic_from_ieee_ieee() #0 {
9; CHECK-LABEL: define internal void @leaf_dynamic_dynamic_from_ieee_ieee() {
10; CHECK-NEXT:    call void @call_of_mystery()
11; CHECK-NEXT:    ret void
12;
13  call void @call_of_mystery()
14  ret void
15}
16
17; Should infer to ieee,ieee/default
18define internal void @leaf_recursive_dynamic_dynamic_from_ieee_ieee() #0 {
19; CHECK-LABEL: define internal void @leaf_recursive_dynamic_dynamic_from_ieee_ieee() {
20; CHECK-NEXT:    call void @call_of_mystery()
21; CHECK-NEXT:    call void @leaf_recursive_dynamic_dynamic_from_ieee_ieee()
22; CHECK-NEXT:    ret void
23;
24  call void @call_of_mystery()
25  call void @leaf_recursive_dynamic_dynamic_from_ieee_ieee()
26  ret void
27}
28
29; Should strip denormal-fp-math for default ieee
30define internal void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_ieee_ieee() #1 {
31; CHECK-LABEL: define internal void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_ieee_ieee() {
32; CHECK-NEXT:    call void @call_of_mystery()
33; CHECK-NEXT:    ret void
34;
35  call void @call_of_mystery()
36  ret void
37}
38
39; Should infer to preserve-sign,preserve-sign
40define internal void @leaf_dynamic_dynamic_from_daz_daz() #0 {
41; CHECK-LABEL: define internal void @leaf_dynamic_dynamic_from_daz_daz
42; CHECK-SAME: () #[[ATTR0:[0-9]+]] {
43; CHECK-NEXT:    call void @call_of_mystery()
44; CHECK-NEXT:    ret void
45;
46  call void @call_of_mystery()
47  ret void
48}
49
50; This goes to invalid because of the mismatch in the main mode. We
51; could theoretically refine to denormal-fp-math-f32=preserve-sign,preserve-sign
52define internal void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz() #1 {
53; CHECK-LABEL: define internal void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz
54; CHECK-SAME: () #[[ATTR1:[0-9]+]] {
55; CHECK-NEXT:    call void @call_of_mystery()
56; CHECK-NEXT:    ret void
57;
58  call void @call_of_mystery()
59  ret void
60}
61
62; Leave this alone, must stay dynamic,dynamic
63define internal void @leaf_dynamic_dynamic_from_daz_daz_and_ieee_ieee() #0 {
64; CHECK-LABEL: define internal void @leaf_dynamic_dynamic_from_daz_daz_and_ieee_ieee
65; CHECK-SAME: () #[[ATTR2:[0-9]+]] {
66; CHECK-NEXT:    call void @call_of_mystery()
67; CHECK-NEXT:    ret void
68;
69  call void @call_of_mystery()
70  ret void
71}
72
73; Leave this alone, should only have denormal-fp-math-f32=ieee,ieee
74define internal void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz_and_ieee_ieee() #1 {
75; CHECK-LABEL: define internal void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz_and_ieee_ieee
76; CHECK-SAME: () #[[ATTR1]] {
77; CHECK-NEXT:    call void @call_of_mystery()
78; CHECK-NEXT:    ret void
79;
80  call void @call_of_mystery()
81  ret void
82}
83
84; Leave as dynamic,dynamic
85define void @externally_visible_dynamic_dynamic_from_ieee_ieee() #0 {
86; CHECK-LABEL: define void @externally_visible_dynamic_dynamic_from_ieee_ieee
87; CHECK-SAME: () #[[ATTR2]] {
88; CHECK-NEXT:    call void @call_of_mystery()
89; CHECK-NEXT:    ret void
90;
91  call void @call_of_mystery()
92  ret void
93}
94
95; Should infer to positive-zero,positive-zero
96define internal void @leaf_dynamic_dynamic_from_dapz_dapz() #0 {
97; CHECK-LABEL: define internal void @leaf_dynamic_dynamic_from_dapz_dapz
98; CHECK-SAME: () #[[ATTR3:[0-9]+]] {
99; CHECK-NEXT:    call void @call_of_mystery()
100; CHECK-NEXT:    ret void
101;
102  call void @call_of_mystery()
103  ret void
104}
105
106; ieee,ieee entry point
107define void @func_ieee_ieee() #2 {
108; CHECK-LABEL: define void @func_ieee_ieee() {
109; CHECK-NEXT:    call void @leaf_dynamic_dynamic_from_ieee_ieee()
110; CHECK-NEXT:    call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_ieee_ieee()
111; CHECK-NEXT:    call void @leaf_dynamic_dynamic_from_daz_daz_and_ieee_ieee()
112; CHECK-NEXT:    call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz_and_ieee_ieee()
113; CHECK-NEXT:    call void @externally_visible_dynamic_dynamic_from_ieee_ieee()
114; CHECK-NEXT:    call void @leaf_dynamic_ieee_from_ieee_ieee()
115; CHECK-NEXT:    call void @leaf_ieee_dynamic_from_ieee_ieee()
116; CHECK-NEXT:    call void @leaf_recursive_dynamic_dynamic_from_ieee_ieee()
117; CHECK-NEXT:    ret void
118;
119  call void @leaf_dynamic_dynamic_from_ieee_ieee()
120  call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_ieee_ieee()
121  call void @leaf_dynamic_dynamic_from_daz_daz_and_ieee_ieee()
122  call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz_and_ieee_ieee()
123  call void @externally_visible_dynamic_dynamic_from_ieee_ieee()
124  call void @leaf_dynamic_ieee_from_ieee_ieee()
125  call void @leaf_ieee_dynamic_from_ieee_ieee()
126  call void @leaf_recursive_dynamic_dynamic_from_ieee_ieee()
127  ret void
128}
129
130; ieee,ieee entry point
131define void @func_default_is_ieee_ieee() {
132; CHECK-LABEL: define void @func_default_is_ieee_ieee() {
133; CHECK-NEXT:    call void @leaf_dynamic_dynamic_from_ieee_ieee()
134; CHECK-NEXT:    call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_ieee_ieee()
135; CHECK-NEXT:    call void @leaf_dynamic_dynamic_from_daz_daz_and_ieee_ieee()
136; CHECK-NEXT:    call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz_and_ieee_ieee()
137; CHECK-NEXT:    call void @externally_visible_dynamic_dynamic_from_ieee_ieee()
138; CHECK-NEXT:    call void @leaf_dynamic_ieee_from_ieee_ieee()
139; CHECK-NEXT:    call void @leaf_ieee_dynamic_from_ieee_ieee()
140; CHECK-NEXT:    call void @leaf_recursive_dynamic_dynamic_from_ieee_ieee()
141; CHECK-NEXT:    ret void
142;
143  call void @leaf_dynamic_dynamic_from_ieee_ieee()
144  call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_ieee_ieee()
145  call void @leaf_dynamic_dynamic_from_daz_daz_and_ieee_ieee()
146  call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz_and_ieee_ieee()
147  call void @externally_visible_dynamic_dynamic_from_ieee_ieee()
148  call void @leaf_dynamic_ieee_from_ieee_ieee()
149  call void @leaf_ieee_dynamic_from_ieee_ieee()
150  call void @leaf_recursive_dynamic_dynamic_from_ieee_ieee()
151  ret void
152}
153
154; preserve-sign,preserve-sign entry point
155define void @func_daz_daz() #3 {
156; CHECK-LABEL: define void @func_daz_daz
157; CHECK-SAME: () #[[ATTR0]] {
158; CHECK-NEXT:    call void @leaf_dynamic_dynamic_from_daz_daz()
159; CHECK-NEXT:    call void @leaf_dynamic_dynamic_from_daz_daz_and_ieee_ieee()
160; CHECK-NEXT:    call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz_and_ieee_ieee()
161; CHECK-NEXT:    call void @leaf_f64_dynamic_f64_dynamic__f32_daz_f32_daz_from__daz_daz()
162; CHECK-NEXT:    call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz()
163; CHECK-NEXT:    ret void
164;
165  call void @leaf_dynamic_dynamic_from_daz_daz()
166  call void @leaf_dynamic_dynamic_from_daz_daz_and_ieee_ieee()
167  call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz_and_ieee_ieee()
168  call void @leaf_f64_dynamic_f64_dynamic__f32_daz_f32_daz_from__daz_daz()
169  call void @leaf_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic__dynamic_dynamic_from_daz_daz()
170  ret void
171}
172
173; positive-zero,positive-zero entry point
174define void @func_dapz_dapz() #4 {
175; CHECK-LABEL: define void @func_dapz_dapz
176; CHECK-SAME: () #[[ATTR3]] {
177; CHECK-NEXT:    call void @leaf_dynamic_dynamic_from_dapz_dapz()
178; CHECK-NEXT:    ret void
179;
180  call void @leaf_dynamic_dynamic_from_dapz_dapz()
181  ret void
182}
183
184; Could be fully preserve-sign,preserve-sign, but this isn't a
185; realistic case and we don't bother trying to handle it.
186define internal void @leaf_f64_dynamic_f64_dynamic__f32_daz_f32_daz_from__daz_daz() #5 {
187; CHECK-LABEL: define internal void @leaf_f64_dynamic_f64_dynamic__f32_daz_f32_daz_from__daz_daz
188; CHECK-SAME: () #[[ATTR4:[0-9]+]] {
189; CHECK-NEXT:    call void @call_of_mystery()
190; CHECK-NEXT:    ret void
191;
192  call void @call_of_mystery()
193  ret void
194}
195
196; -> ieee,ieee
197define internal void @leaf_dynamic_ieee_from_ieee_ieee() #6 {
198; CHECK-LABEL: define internal void @leaf_dynamic_ieee_from_ieee_ieee() {
199; CHECK-NEXT:    call void @call_of_mystery()
200; CHECK-NEXT:    ret void
201;
202  call void @call_of_mystery()
203  ret void
204}
205
206; -> ieee,ieee
207define internal void @leaf_ieee_dynamic_from_ieee_ieee() #7 {
208; CHECK-LABEL: define internal void @leaf_ieee_dynamic_from_ieee_ieee() {
209; CHECK-NEXT:    call void @call_of_mystery()
210; CHECK-NEXT:    ret void
211;
212  call void @call_of_mystery()
213  ret void
214}
215
216; Specialize the f64 mode to ieee,ieee but leave f32 as dynamic,dynamic
217define internal void @leaf_dynamic_dynamic_from_f64_ieee_f32_dynamic() #0 {
218; CHECK-LABEL: define internal void @leaf_dynamic_dynamic_from_f64_ieee_f32_dynamic
219; CHECK-SAME: () #[[ATTR1]] {
220; CHECK-NEXT:    call void @call_of_mystery()
221; CHECK-NEXT:    ret void
222;
223  call void @call_of_mystery()
224  ret void
225}
226
227define void @func_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic() #1 {
228; CHECK-LABEL: define void @func_f64_ieee_f64_ieee__f32_dynamic_f32_dynamic
229; CHECK-SAME: () #[[ATTR1]] {
230; CHECK-NEXT:    call void @leaf_dynamic_dynamic_from_f64_ieee_f32_dynamic()
231; CHECK-NEXT:    ret void
232;
233  call void @leaf_dynamic_dynamic_from_f64_ieee_f32_dynamic()
234  ret void
235}
236
237; -> preserve-sign,ieee.
238define internal void @leaf_daz_dynamic_from_dynamic_ieee() #8 {
239; CHECK-LABEL: define internal void @leaf_daz_dynamic_from_dynamic_ieee
240; CHECK-SAME: () #[[ATTR5:[0-9]+]] {
241; CHECK-NEXT:    call void @call_of_mystery()
242; CHECK-NEXT:    ret void
243;
244  call void @call_of_mystery()
245  ret void
246}
247
248define void @dynamic_ieee() #6 {
249; CHECK-LABEL: define void @dynamic_ieee
250; CHECK-SAME: () #[[ATTR6:[0-9]+]] {
251; CHECK-NEXT:    call void @leaf_daz_dynamic_from_dynamic_ieee()
252; CHECK-NEXT:    ret void
253;
254  call void @leaf_daz_dynamic_from_dynamic_ieee()
255  ret void
256}
257
258; Leave unchanged as ieee,ieeee
259define internal void @leaf_ieee_ieee_from_dynamic() {
260; CHECK-LABEL: define internal void @leaf_ieee_ieee_from_dynamic() {
261; CHECK-NEXT:    call void @call_of_mystery()
262; CHECK-NEXT:    ret void
263;
264  call void @call_of_mystery()
265  ret void
266}
267
268; Leave unchanged as dynamic,dynamic
269define internal void @leaf_dynamic_from_dynamic() {
270; CHECK-LABEL: define internal void @leaf_dynamic_from_dynamic() {
271; CHECK-NEXT:    call void @call_of_mystery()
272; CHECK-NEXT:    ret void
273;
274  call void @call_of_mystery()
275  ret void
276}
277
278; Leave unchanged as preserve-sign,preserve-sign
279define internal void @leaf_daz_daz_from_dynamic() #3 {
280; CHECK-LABEL: define internal void @leaf_daz_daz_from_dynamic
281; CHECK-SAME: () #[[ATTR0]] {
282; CHECK-NEXT:    call void @call_of_mystery()
283; CHECK-NEXT:    ret void
284;
285  call void @call_of_mystery()
286  ret void
287}
288
289define void @dynamic_dynamic() #0 {
290; CHECK-LABEL: define void @dynamic_dynamic
291; CHECK-SAME: () #[[ATTR2]] {
292; CHECK-NEXT:    call void @leaf_ieee_ieee_from_dynamic()
293; CHECK-NEXT:    call void @leaf_daz_daz_from_dynamic()
294; CHECK-NEXT:    call void @leaf_dynamic_from_dynamic()
295; CHECK-NEXT:    ret void
296;
297  call void @leaf_ieee_ieee_from_dynamic()
298  call void @leaf_daz_daz_from_dynamic()
299  call void @leaf_dynamic_from_dynamic()
300  ret void
301}
302
303define internal void @leaf_ieee_f64_daz_f32() #9 {
304; CHECK-LABEL: define internal void @leaf_ieee_f64_daz_f32
305; CHECK-SAME: () #[[ATTR7:[0-9]+]] {
306; CHECK-NEXT:    call void @call_of_mystery()
307; CHECK-NEXT:    ret void
308;
309  call void @call_of_mystery()
310  ret void
311}
312
313define internal void @leaf_ieee_f64_daz_f32_from_ieee_f64_dynamic_f32() #10 {
314; CHECK-LABEL: define internal void @leaf_ieee_f64_daz_f32_from_ieee_f64_dynamic_f32
315; CHECK-SAME: () #[[ATTR8:[0-9]+]] {
316; CHECK-NEXT:    call void @call_of_mystery()
317; CHECK-NEXT:    ret void
318;
319  call void @call_of_mystery()
320  ret void
321}
322
323define void @ieee_f64_dynamic_f32() #1 {
324; CHECK-LABEL: define void @ieee_f64_dynamic_f32
325; CHECK-SAME: () #[[ATTR1]] {
326; CHECK-NEXT:    call void @leaf_ieee_f64_daz_f32()
327; CHECK-NEXT:    call void @leaf_ieee_f64_daz_f32_from_ieee_f64_dynamic_f32()
328; CHECK-NEXT:    ret void
329;
330  call void @leaf_ieee_f64_daz_f32()
331  call void @leaf_ieee_f64_daz_f32_from_ieee_f64_dynamic_f32()
332  ret void
333}
334
335; => "preserve-sign,positive-zero" + "denormal-fp-math-f32"="ieee,positive-zero"
336define internal void @leaf_daz_dynamic_dynamic_dapz_from_daz_dapz_ieee_dapz() #11 {
337; CHECK-LABEL: define internal void @leaf_daz_dynamic_dynamic_dapz_from_daz_dapz_ieee_dapz
338; CHECK-SAME: () #[[ATTR9:[0-9]+]] {
339; CHECK-NEXT:    call void @call_of_mystery()
340; CHECK-NEXT:    ret void
341;
342  call void @call_of_mystery()
343  ret void
344}
345
346define void @daz_dapz_ieee_dapz() #12 {
347; CHECK-LABEL: define void @daz_dapz_ieee_dapz
348; CHECK-SAME: () #[[ATTR9]] {
349; CHECK-NEXT:    call void @leaf_daz_dynamic_dynamic_dapz_from_daz_dapz_ieee_dapz()
350; CHECK-NEXT:    ret void
351;
352  call void @leaf_daz_dynamic_dynamic_dapz_from_daz_dapz_ieee_dapz()
353  ret void
354}
355
356attributes #0 = { "denormal-fp-math"="dynamic,dynamic" }
357attributes #1 = { "denormal-fp-math-f32"="dynamic,dynamic" }
358attributes #2 = { "denormal-fp-math"="ieee,ieee" }
359attributes #3 = { "denormal-fp-math"="preserve-sign,preserve-sign" }
360attributes #4 = { "denormal-fp-math"="positive-zero,positive-zero" }
361attributes #5 = { "denormal-fp-math"="dynamic,dynamic" "denormal-fp-math-f32"="preserve-sign,preserve-sign" }
362attributes #6 = { "denormal-fp-math"="dynamic,ieee" }
363attributes #7 = { "denormal-fp-math"="ieee,dynamic" }
364attributes #8 = { "denormal-fp-math"="preserve-sign,dynamic" }
365attributes #9 = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" }
366attributes #10 = { "denormal-fp-math"="preserve-sign,preserve-sign" "denormal-fp-math-f32"="ieee,ieee" }
367attributes #11 = { "denormal-fp-math"="preserve-sign,dynamic" "denormal-fp-math-f32"="dynamic,positive-zero" }
368attributes #12 = { "denormal-fp-math"="preserve-sign,positive-zero" "denormal-fp-math-f32"="ieee,positive-zero" }
369;.
370; CHECK: attributes #[[ATTR0]] = { "denormal-fp-math"="preserve-sign,preserve-sign" }
371; CHECK: attributes #[[ATTR1]] = { "denormal-fp-math-f32"="dynamic,dynamic" }
372; CHECK: attributes #[[ATTR2]] = { "denormal-fp-math"="dynamic,dynamic" }
373; CHECK: attributes #[[ATTR3]] = { "denormal-fp-math"="positive-zero,positive-zero" }
374; CHECK: attributes #[[ATTR4]] = { "denormal-fp-math"="dynamic,dynamic" "denormal-fp-math-f32"="preserve-sign,preserve-sign" }
375; CHECK: attributes #[[ATTR5]] = { "denormal-fp-math"="preserve-sign,ieee" }
376; CHECK: attributes #[[ATTR6]] = { "denormal-fp-math"="dynamic,ieee" }
377; CHECK: attributes #[[ATTR7]] = { "denormal-fp-math-f32"="preserve-sign,preserve-sign" }
378; CHECK: attributes #[[ATTR8]] = { "denormal-fp-math"="preserve-sign,preserve-sign" "denormal-fp-math-f32"="ieee,ieee" }
379; CHECK: attributes #[[ATTR9]] = { "denormal-fp-math"="preserve-sign,positive-zero" "denormal-fp-math-f32"="ieee,positive-zero" }
380;.
381