xref: /llvm-project/llvm/test/Transforms/Inline/attributes.ll (revision e5369823bc0655806469724335d0ca5a4c17d8c7)
1; RUN: opt < %s -passes=inline -S | FileCheck %s
2; RUN: opt < %s -passes='cgscc(inline)' -S | FileCheck %s
3target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
4
5define i32 @noattr_callee(i32 %i) {
6  ret i32 %i
7}
8
9define i32 @sanitize_address_callee(i32 %i) sanitize_address {
10  ret i32 %i
11}
12
13define i32 @sanitize_hwaddress_callee(i32 %i) sanitize_hwaddress {
14  ret i32 %i
15}
16
17define i32 @sanitize_thread_callee(i32 %i) sanitize_thread {
18  ret i32 %i
19}
20
21define i32 @sanitize_memory_callee(i32 %i) sanitize_memory {
22  ret i32 %i
23}
24
25define i32 @sanitize_memtag_callee(i32 %i) sanitize_memtag {
26  ret i32 %i
27}
28
29define i32 @safestack_callee(i32 %i) safestack {
30  ret i32 %i
31}
32
33define i32 @slh_callee(i32 %i) speculative_load_hardening {
34  ret i32 %i
35}
36
37define i32 @alwaysinline_callee(i32 %i) alwaysinline {
38  ret i32 %i
39}
40
41define i32 @alwaysinline_sanitize_address_callee(i32 %i) alwaysinline sanitize_address {
42  ret i32 %i
43}
44
45define i32 @alwaysinline_sanitize_hwaddress_callee(i32 %i) alwaysinline sanitize_hwaddress {
46  ret i32 %i
47}
48
49define i32 @alwaysinline_sanitize_thread_callee(i32 %i) alwaysinline sanitize_thread {
50  ret i32 %i
51}
52
53define i32 @alwaysinline_sanitize_memory_callee(i32 %i) alwaysinline sanitize_memory {
54  ret i32 %i
55}
56
57define i32 @alwaysinline_sanitize_memtag_callee(i32 %i) alwaysinline sanitize_memtag {
58  ret i32 %i
59}
60
61define i32 @alwaysinline_safestack_callee(i32 %i) alwaysinline safestack {
62  ret i32 %i
63}
64
65
66; Check that:
67;  * noattr callee is inlined into noattr caller,
68;  * sanitize_(address|memory|thread) callee is not inlined into noattr caller,
69;  * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.
70
71define i32 @test_no_sanitize_address(i32 %arg) {
72  %x1 = call i32 @noattr_callee(i32 %arg)
73  %x2 = call i32 @sanitize_address_callee(i32 %x1)
74  %x3 = call i32 @alwaysinline_callee(i32 %x2)
75  %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)
76  ret i32 %x4
77; CHECK-LABEL: @test_no_sanitize_address(
78; CHECK-NEXT: @sanitize_address_callee
79; CHECK-NEXT: ret i32
80}
81
82define i32 @test_no_sanitize_hwaddress(i32 %arg) {
83  %x1 = call i32 @noattr_callee(i32 %arg)
84  %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
85  %x3 = call i32 @alwaysinline_callee(i32 %x2)
86  %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
87  ret i32 %x4
88; CHECK-LABEL: @test_no_sanitize_hwaddress(
89; CHECK-NEXT: @sanitize_hwaddress_callee
90; CHECK-NEXT: ret i32
91}
92
93define i32 @test_no_sanitize_memory(i32 %arg) {
94  %x1 = call i32 @noattr_callee(i32 %arg)
95  %x2 = call i32 @sanitize_memory_callee(i32 %x1)
96  %x3 = call i32 @alwaysinline_callee(i32 %x2)
97  %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)
98  ret i32 %x4
99; CHECK-LABEL: @test_no_sanitize_memory(
100; CHECK-NEXT: @sanitize_memory_callee
101; CHECK-NEXT: ret i32
102}
103
104define i32 @test_no_sanitize_thread(i32 %arg) {
105  %x1 = call i32 @noattr_callee(i32 %arg)
106  %x2 = call i32 @sanitize_thread_callee(i32 %x1)
107  %x3 = call i32 @alwaysinline_callee(i32 %x2)
108  %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)
109  ret i32 %x4
110; CHECK-LABEL: @test_no_sanitize_thread(
111; CHECK-NEXT: @sanitize_thread_callee
112; CHECK-NEXT: ret i32
113}
114
115define i32 @test_no_sanitize_memtag(i32 %arg) {
116  %x1 = call i32 @noattr_callee(i32 %arg)
117  %x2 = call i32 @sanitize_memtag_callee(i32 %x1)
118  %x3 = call i32 @alwaysinline_callee(i32 %x2)
119  %x4 = call i32 @alwaysinline_sanitize_memtag_callee(i32 %x3)
120  ret i32 %x4
121; CHECK-LABEL: @test_no_sanitize_memtag(
122; CHECK-NEXT: @sanitize_memtag_callee
123; CHECK-NEXT: ret i32
124}
125
126
127; Check that:
128;  * noattr callee is not inlined into sanitize_(address|memory|thread) caller,
129;  * sanitize_(address|memory|thread) callee is inlined into the caller with the same attribute,
130;  * alwaysinline callee is always inlined no matter what sanitize_* attributes are present.
131
132define i32 @test_sanitize_address(i32 %arg) sanitize_address {
133  %x1 = call i32 @noattr_callee(i32 %arg)
134  %x2 = call i32 @sanitize_address_callee(i32 %x1)
135  %x3 = call i32 @alwaysinline_callee(i32 %x2)
136  %x4 = call i32 @alwaysinline_sanitize_address_callee(i32 %x3)
137  ret i32 %x4
138; CHECK-LABEL: @test_sanitize_address(
139; CHECK-NEXT: @noattr_callee
140; CHECK-NEXT: ret i32
141}
142
143define i32 @test_sanitize_hwaddress(i32 %arg) sanitize_hwaddress {
144  %x1 = call i32 @noattr_callee(i32 %arg)
145  %x2 = call i32 @sanitize_hwaddress_callee(i32 %x1)
146  %x3 = call i32 @alwaysinline_callee(i32 %x2)
147  %x4 = call i32 @alwaysinline_sanitize_hwaddress_callee(i32 %x3)
148  ret i32 %x4
149; CHECK-LABEL: @test_sanitize_hwaddress(
150; CHECK-NEXT: @noattr_callee
151; CHECK-NEXT: ret i32
152}
153
154define i32 @test_sanitize_memory(i32 %arg) sanitize_memory {
155  %x1 = call i32 @noattr_callee(i32 %arg)
156  %x2 = call i32 @sanitize_memory_callee(i32 %x1)
157  %x3 = call i32 @alwaysinline_callee(i32 %x2)
158  %x4 = call i32 @alwaysinline_sanitize_memory_callee(i32 %x3)
159  ret i32 %x4
160; CHECK-LABEL: @test_sanitize_memory(
161; CHECK-NEXT: @noattr_callee
162; CHECK-NEXT: ret i32
163}
164
165define i32 @test_sanitize_thread(i32 %arg) sanitize_thread {
166  %x1 = call i32 @noattr_callee(i32 %arg)
167  %x2 = call i32 @sanitize_thread_callee(i32 %x1)
168  %x3 = call i32 @alwaysinline_callee(i32 %x2)
169  %x4 = call i32 @alwaysinline_sanitize_thread_callee(i32 %x3)
170  ret i32 %x4
171; CHECK-LABEL: @test_sanitize_thread(
172; CHECK-NEXT: @noattr_callee
173; CHECK-NEXT: ret i32
174}
175
176define i32 @test_sanitize_memtag(i32 %arg) sanitize_memtag {
177  %x1 = call i32 @noattr_callee(i32 %arg)
178  %x2 = call i32 @sanitize_memtag_callee(i32 %x1)
179  %x3 = call i32 @alwaysinline_callee(i32 %x2)
180  %x4 = call i32 @alwaysinline_sanitize_memtag_callee(i32 %x3)
181  ret i32 %x4
182; CHECK-LABEL: @test_sanitize_memtag(
183; CHECK-NEXT: @noattr_callee
184; CHECK-NEXT: ret i32
185}
186
187define i32 @test_safestack(i32 %arg) safestack {
188  %x1 = call i32 @noattr_callee(i32 %arg)
189  %x2 = call i32 @safestack_callee(i32 %x1)
190  %x3 = call i32 @alwaysinline_callee(i32 %x2)
191  %x4 = call i32 @alwaysinline_safestack_callee(i32 %x3)
192  ret i32 %x4
193; CHECK-LABEL: @test_safestack(
194; CHECK-NEXT: @noattr_callee
195; CHECK-NEXT: ret i32
196}
197
198; Can inline a normal function into an SLH'ed function.
199define i32 @test_caller_slh(i32 %i) speculative_load_hardening {
200; CHECK-LABEL: @test_caller_slh(
201; CHECK-SAME: ) [[SLH:.*]] {
202; CHECK-NOT: call
203; CHECK: ret i32
204entry:
205  %callee = call i32 @noattr_callee(i32 %i)
206  ret i32 %callee
207}
208
209; Can inline a SLH'ed function into a normal one, propagating SLH.
210define i32 @test_callee_slh(i32 %i) {
211; CHECK-LABEL: @test_callee_slh(
212; CHECK-SAME: ) [[SLH:.*]] {
213; CHECK-NOT: call
214; CHECK: ret i32
215entry:
216  %callee = call i32 @slh_callee(i32 %i)
217  ret i32 %callee
218}
219
220; Check that a function doesn't get inlined if target-cpu strings don't match
221; exactly.
222define i32 @test_target_cpu_callee0(i32 %i) "target-cpu"="corei7" {
223  ret i32 %i
224}
225
226define i32 @test_target_cpu0(i32 %i) "target-cpu"="corei7" {
227  %1 = call i32 @test_target_cpu_callee0(i32 %i)
228  ret i32 %1
229; CHECK-LABEL: @test_target_cpu0(
230; CHECK-NOT: @test_target_cpu_callee0
231}
232
233define i32 @test_target_cpu_callee1(i32 %i) "target-cpu"="x86-64" {
234  ret i32 %i
235}
236
237define i32 @test_target_cpu1(i32 %i) "target-cpu"="corei7" {
238  %1 = call i32 @test_target_cpu_callee1(i32 %i)
239  ret i32 %1
240; CHECK-LABEL: @test_target_cpu1(
241; CHECK-NEXT: @test_target_cpu_callee1
242; CHECK-NEXT: ret i32
243}
244
245; Check that a function doesn't get inlined if target-features strings don't
246; match exactly.
247define i32 @test_target_features_callee0(i32 %i)  "target-features"="+sse4.2" {
248  ret i32 %i
249}
250
251define i32 @test_target_features0(i32 %i) "target-features"="+sse4.2" {
252  %1 = call i32 @test_target_features_callee0(i32 %i)
253  ret i32 %1
254; CHECK-LABEL: @test_target_features0(
255; CHECK-NOT: @test_target_features_callee0
256}
257
258define i32 @test_target_features_callee1(i32 %i) "target-features"="+avx2" {
259  ret i32 %i
260}
261
262define i32 @test_target_features1(i32 %i) "target-features"="+sse4.2" {
263  %1 = call i32 @test_target_features_callee1(i32 %i)
264  ret i32 %1
265; CHECK-LABEL: @test_target_features1(
266; CHECK-NEXT: @test_target_features_callee1
267; CHECK-NEXT: ret i32
268}
269
270define i32 @less-precise-fpmad_callee0(i32 %i) "less-precise-fpmad"="false" {
271  ret i32 %i
272; CHECK: @less-precise-fpmad_callee0(i32 %i) [[FPMAD_FALSE:#[0-9]+]] {
273; CHECK-NEXT: ret i32
274}
275
276define i32 @less-precise-fpmad_callee1(i32 %i) "less-precise-fpmad"="true" {
277  ret i32 %i
278; CHECK: @less-precise-fpmad_callee1(i32 %i) [[FPMAD_TRUE:#[0-9]+]] {
279; CHECK-NEXT: ret i32
280}
281
282define i32 @test_less-precise-fpmad0(i32 %i) "less-precise-fpmad"="false" {
283  %1 = call i32 @less-precise-fpmad_callee0(i32 %i)
284  ret i32 %1
285; CHECK: @test_less-precise-fpmad0(i32 %i) [[FPMAD_FALSE]] {
286; CHECK-NEXT: ret i32
287}
288
289define i32 @test_less-precise-fpmad1(i32 %i) "less-precise-fpmad"="false" {
290  %1 = call i32 @less-precise-fpmad_callee1(i32 %i)
291  ret i32 %1
292; CHECK: @test_less-precise-fpmad1(i32 %i) [[FPMAD_FALSE]] {
293; CHECK-NEXT: ret i32
294}
295
296define i32 @test_less-precise-fpmad2(i32 %i) "less-precise-fpmad"="true" {
297  %1 = call i32 @less-precise-fpmad_callee0(i32 %i)
298  ret i32 %1
299; CHECK: @test_less-precise-fpmad2(i32 %i) [[FPMAD_FALSE]] {
300; CHECK-NEXT: ret i32
301}
302
303define i32 @test_less-precise-fpmad3(i32 %i) "less-precise-fpmad"="true" {
304  %1 = call i32 @less-precise-fpmad_callee1(i32 %i)
305  ret i32 %1
306; CHECK: @test_less-precise-fpmad3(i32 %i) [[FPMAD_TRUE]] {
307; CHECK-NEXT: ret i32
308}
309
310define i32 @no-implicit-float_callee0(i32 %i) {
311  ret i32 %i
312; CHECK: @no-implicit-float_callee0(i32 %i) {
313; CHECK-NEXT: ret i32
314}
315
316define i32 @no-implicit-float_callee1(i32 %i) noimplicitfloat {
317  ret i32 %i
318; CHECK: @no-implicit-float_callee1(i32 %i) [[NOIMPLICITFLOAT:#[0-9]+]] {
319; CHECK-NEXT: ret i32
320}
321
322define i32 @test_no-implicit-float0(i32 %i) {
323  %1 = call i32 @no-implicit-float_callee0(i32 %i)
324  ret i32 %1
325; CHECK: @test_no-implicit-float0(i32 %i) {
326; CHECK-NEXT: ret i32
327}
328
329define i32 @test_no-implicit-float1(i32 %i) {
330  %1 = call i32 @no-implicit-float_callee1(i32 %i)
331  ret i32 %1
332; CHECK: @test_no-implicit-float1(i32 %i) [[NOIMPLICITFLOAT]] {
333; CHECK-NEXT: ret i32
334}
335
336define i32 @test_no-implicit-float2(i32 %i) noimplicitfloat {
337  %1 = call i32 @no-implicit-float_callee0(i32 %i)
338  ret i32 %1
339; CHECK: @test_no-implicit-float2(i32 %i) [[NOIMPLICITFLOAT]] {
340; CHECK-NEXT: ret i32
341}
342
343define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat {
344  %1 = call i32 @no-implicit-float_callee1(i32 %i)
345  ret i32 %1
346; CHECK: @test_no-implicit-float3(i32 %i) [[NOIMPLICITFLOAT]] {
347; CHECK-NEXT: ret i32
348}
349
350; Check that no-jump-tables flag propagates from inlined callee to caller
351
352define i32 @no-use-jump-tables_callee0(i32 %i) {
353  ret i32 %i
354; CHECK: @no-use-jump-tables_callee0(i32 %i) {
355; CHECK-NEXT: ret i32
356}
357
358define i32 @no-use-jump-tables_callee1(i32 %i) "no-jump-tables"="true" {
359  ret i32 %i
360; CHECK: @no-use-jump-tables_callee1(i32 %i) [[NOUSEJUMPTABLES:#[0-9]+]] {
361; CHECK-NEXT: ret i32
362}
363
364define i32 @test_no-use-jump-tables0(i32 %i) {
365  %1 = call i32 @no-use-jump-tables_callee0(i32 %i)
366  ret i32 %1
367; CHECK: @test_no-use-jump-tables0(i32 %i) {
368; CHECK-NEXT: ret i32
369}
370
371define i32 @test_no-use-jump-tables1(i32 %i) {
372  %1 = call i32 @no-use-jump-tables_callee1(i32 %i)
373  ret i32 %1
374; CHECK: @test_no-use-jump-tables1(i32 %i) [[NOUSEJUMPTABLES]] {
375; CHECK-NEXT: ret i32
376}
377
378define i32 @test_no-use-jump-tables2(i32 %i) "no-jump-tables"="true" {
379  %1 = call i32 @no-use-jump-tables_callee0(i32 %i)
380  ret i32 %1
381; CHECK: @test_no-use-jump-tables2(i32 %i) [[NOUSEJUMPTABLES]] {
382; CHECK-NEXT: ret i32
383}
384
385define i32 @test_no-use-jump-tables3(i32 %i) "no-jump-tables"="true" {
386  %1 = call i32 @no-use-jump-tables_callee1(i32 %i)
387  ret i32 %1
388; CHECK: @test_no-use-jump-tables3(i32 %i) [[NOUSEJUMPTABLES]] {
389; CHECK-NEXT: ret i32
390}
391
392; Callee with null_pointer_is_valid attribute should not be inlined
393; into a caller without this attribute.
394; Exception: alwaysinline callee can still be inlined but
395; null_pointer_is_valid should get copied to caller.
396
397define i32 @null-pointer-is-valid_callee0(i32 %i) null_pointer_is_valid {
398  ret i32 %i
399; CHECK: @null-pointer-is-valid_callee0(i32 %i)
400; CHECK-NEXT: ret i32
401}
402
403define i32 @null-pointer-is-valid_callee1(i32 %i) alwaysinline null_pointer_is_valid {
404  ret i32 %i
405; CHECK: @null-pointer-is-valid_callee1(i32 %i)
406; CHECK-NEXT: ret i32
407}
408
409define i32 @null-pointer-is-valid_callee2(i32 %i)  {
410  ret i32 %i
411; CHECK: @null-pointer-is-valid_callee2(i32 %i)
412; CHECK-NEXT: ret i32
413}
414
415; No inlining since caller does not have null_pointer_is_valid attribute.
416define i32 @test_null-pointer-is-valid0(i32 %i) {
417  %1 = call i32 @null-pointer-is-valid_callee0(i32 %i)
418  ret i32 %1
419; CHECK: @test_null-pointer-is-valid0(
420; CHECK: call i32 @null-pointer-is-valid_callee0
421; CHECK-NEXT: ret i32
422}
423
424; alwaysinline should force inlining even when caller does not have
425; null_pointer_is_valid attribute. However, the attribute should be
426; copied to caller.
427define i32 @test_null-pointer-is-valid1(i32 %i) {
428  %1 = call i32 @null-pointer-is-valid_callee1(i32 %i)
429  ret i32 %1
430; CHECK: @test_null-pointer-is-valid1(i32 %i) [[NULLPOINTERISVALID:#[0-9]+]] {
431; CHECK-NEXT: ret i32
432}
433
434; Can inline since both caller and callee have null_pointer_is_valid
435; attribute.
436define i32 @test_null-pointer-is-valid2(i32 %i) null_pointer_is_valid {
437  %1 = call i32 @null-pointer-is-valid_callee2(i32 %i)
438  ret i32 %1
439; CHECK: @test_null-pointer-is-valid2(i32 %i) [[NULLPOINTERISVALID]] {
440; CHECK-NEXT: ret i32
441}
442
443define i32 @no-infs-fp-math_callee0(i32 %i) "no-infs-fp-math"="false" {
444  ret i32 %i
445; CHECK: @no-infs-fp-math_callee0(i32 %i) [[NO_INFS_FPMATH_FALSE:#[0-9]+]] {
446; CHECK-NEXT: ret i32
447}
448
449define i32 @no-infs-fp-math_callee1(i32 %i) "no-infs-fp-math"="true" {
450  ret i32 %i
451; CHECK: @no-infs-fp-math_callee1(i32 %i) [[NO_INFS_FPMATH_TRUE:#[0-9]+]] {
452; CHECK-NEXT: ret i32
453}
454
455define i32 @test_no-infs-fp-math0(i32 %i) "no-infs-fp-math"="false" {
456  %1 = call i32 @no-infs-fp-math_callee0(i32 %i)
457  ret i32 %1
458; CHECK: @test_no-infs-fp-math0(i32 %i) [[NO_INFS_FPMATH_FALSE]] {
459; CHECK-NEXT: ret i32
460}
461
462define i32 @test_no-infs-fp-math1(i32 %i) "no-infs-fp-math"="false" {
463  %1 = call i32 @no-infs-fp-math_callee1(i32 %i)
464  ret i32 %1
465; CHECK: @test_no-infs-fp-math1(i32 %i) [[NO_INFS_FPMATH_FALSE]] {
466; CHECK-NEXT: ret i32
467}
468
469define i32 @test_no-infs-fp-math2(i32 %i) "no-infs-fp-math"="true" {
470  %1 = call i32 @no-infs-fp-math_callee0(i32 %i)
471  ret i32 %1
472; CHECK: @test_no-infs-fp-math2(i32 %i) [[NO_INFS_FPMATH_FALSE]] {
473; CHECK-NEXT: ret i32
474}
475
476define i32 @test_no-infs-fp-math3(i32 %i) "no-infs-fp-math"="true" {
477  %1 = call i32 @no-infs-fp-math_callee1(i32 %i)
478  ret i32 %1
479; CHECK: @test_no-infs-fp-math3(i32 %i) [[NO_INFS_FPMATH_TRUE]] {
480; CHECK-NEXT: ret i32
481}
482
483define i32 @no-nans-fp-math_callee0(i32 %i) "no-nans-fp-math"="false" {
484  ret i32 %i
485; CHECK: @no-nans-fp-math_callee0(i32 %i) [[NO_NANS_FPMATH_FALSE:#[0-9]+]] {
486; CHECK-NEXT: ret i32
487}
488
489define i32 @no-nans-fp-math_callee1(i32 %i) "no-nans-fp-math"="true" {
490  ret i32 %i
491; CHECK: @no-nans-fp-math_callee1(i32 %i) [[NO_NANS_FPMATH_TRUE:#[0-9]+]] {
492; CHECK-NEXT: ret i32
493}
494
495define i32 @test_no-nans-fp-math0(i32 %i) "no-nans-fp-math"="false" {
496  %1 = call i32 @no-nans-fp-math_callee0(i32 %i)
497  ret i32 %1
498; CHECK: @test_no-nans-fp-math0(i32 %i) [[NO_NANS_FPMATH_FALSE]] {
499; CHECK-NEXT: ret i32
500}
501
502define i32 @test_no-nans-fp-math1(i32 %i) "no-nans-fp-math"="false" {
503  %1 = call i32 @no-nans-fp-math_callee1(i32 %i)
504  ret i32 %1
505; CHECK: @test_no-nans-fp-math1(i32 %i) [[NO_NANS_FPMATH_FALSE]] {
506; CHECK-NEXT: ret i32
507}
508
509define i32 @test_no-nans-fp-math2(i32 %i) "no-nans-fp-math"="true" {
510  %1 = call i32 @no-nans-fp-math_callee0(i32 %i)
511  ret i32 %1
512; CHECK: @test_no-nans-fp-math2(i32 %i) [[NO_NANS_FPMATH_FALSE]] {
513; CHECK-NEXT: ret i32
514}
515
516define i32 @test_no-nans-fp-math3(i32 %i) "no-nans-fp-math"="true" {
517  %1 = call i32 @no-nans-fp-math_callee1(i32 %i)
518  ret i32 %1
519; CHECK: @test_no-nans-fp-math3(i32 %i) [[NO_NANS_FPMATH_TRUE]] {
520; CHECK-NEXT: ret i32
521}
522
523define i32 @no-signed-zeros-fp-math_callee0(i32 %i) "no-signed-zeros-fp-math"="false" {
524  ret i32 %i
525; CHECK: @no-signed-zeros-fp-math_callee0(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_FALSE:#[0-9]+]] {
526; CHECK-NEXT: ret i32
527}
528
529define i32 @no-signed-zeros-fp-math_callee1(i32 %i) "no-signed-zeros-fp-math"="true" {
530  ret i32 %i
531; CHECK: @no-signed-zeros-fp-math_callee1(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_TRUE:#[0-9]+]] {
532; CHECK-NEXT: ret i32
533}
534
535define i32 @test_no-signed-zeros-fp-math0(i32 %i) "no-signed-zeros-fp-math"="false" {
536  %1 = call i32 @no-signed-zeros-fp-math_callee0(i32 %i)
537  ret i32 %1
538; CHECK: @test_no-signed-zeros-fp-math0(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_FALSE]] {
539; CHECK-NEXT: ret i32
540}
541
542define i32 @test_no-signed-zeros-fp-math1(i32 %i) "no-signed-zeros-fp-math"="false" {
543  %1 = call i32 @no-signed-zeros-fp-math_callee1(i32 %i)
544  ret i32 %1
545; CHECK: @test_no-signed-zeros-fp-math1(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_FALSE]] {
546; CHECK-NEXT: ret i32
547}
548
549define i32 @test_no-signed-zeros-fp-math2(i32 %i) "no-signed-zeros-fp-math"="true" {
550  %1 = call i32 @no-signed-zeros-fp-math_callee0(i32 %i)
551  ret i32 %1
552; CHECK: @test_no-signed-zeros-fp-math2(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_FALSE]] {
553; CHECK-NEXT: ret i32
554}
555
556define i32 @test_no-signed-zeros-fp-math3(i32 %i) "no-signed-zeros-fp-math"="true" {
557  %1 = call i32 @no-signed-zeros-fp-math_callee1(i32 %i)
558  ret i32 %1
559; CHECK: @test_no-signed-zeros-fp-math3(i32 %i) [[NO_SIGNED_ZEROS_FPMATH_TRUE]] {
560; CHECK-NEXT: ret i32
561}
562
563define i32 @unsafe-fp-math_callee0(i32 %i) "unsafe-fp-math"="false" {
564  ret i32 %i
565; CHECK: @unsafe-fp-math_callee0(i32 %i) [[UNSAFE_FPMATH_FALSE:#[0-9]+]] {
566; CHECK-NEXT: ret i32
567}
568
569define i32 @unsafe-fp-math_callee1(i32 %i) "unsafe-fp-math"="true" {
570  ret i32 %i
571; CHECK: @unsafe-fp-math_callee1(i32 %i) [[UNSAFE_FPMATH_TRUE:#[0-9]+]] {
572; CHECK-NEXT: ret i32
573}
574
575define i32 @test_unsafe-fp-math0(i32 %i) "unsafe-fp-math"="false" {
576  %1 = call i32 @unsafe-fp-math_callee0(i32 %i)
577  ret i32 %1
578; CHECK: @test_unsafe-fp-math0(i32 %i) [[UNSAFE_FPMATH_FALSE]] {
579; CHECK-NEXT: ret i32
580}
581
582define i32 @test_unsafe-fp-math1(i32 %i) "unsafe-fp-math"="false" {
583  %1 = call i32 @unsafe-fp-math_callee1(i32 %i)
584  ret i32 %1
585; CHECK: @test_unsafe-fp-math1(i32 %i) [[UNSAFE_FPMATH_FALSE]] {
586; CHECK-NEXT: ret i32
587}
588
589define i32 @test_unsafe-fp-math2(i32 %i) "unsafe-fp-math"="true" {
590  %1 = call i32 @unsafe-fp-math_callee0(i32 %i)
591  ret i32 %1
592; CHECK: @test_unsafe-fp-math2(i32 %i) [[UNSAFE_FPMATH_FALSE]] {
593; CHECK-NEXT: ret i32
594}
595
596define i32 @test_unsafe-fp-math3(i32 %i) "unsafe-fp-math"="true" {
597  %1 = call i32 @unsafe-fp-math_callee1(i32 %i)
598  ret i32 %1
599; CHECK: @test_unsafe-fp-math3(i32 %i) [[UNSAFE_FPMATH_TRUE]] {
600; CHECK-NEXT: ret i32
601}
602
603; Test that fn_ret_thunk_extern has no CompatRule; inlining is permitted.
604; Test that fn_ret_thunk_extern has no MergeRule; fn_ret_thunk_extern is not
605; propagated or dropped on the caller after inlining.
606define i32 @thunk_extern_callee() fn_ret_thunk_extern {
607; CHECK: @thunk_extern_callee() [[FNRETTHUNK_EXTERN:#[0-9]+]]
608  ret i32 42
609}
610
611define i32 @thunk_keep_caller() {
612; CHECK: @thunk_keep_caller() {
613; CHECK-NEXT: ret i32 42
614  %1 = call i32 @thunk_extern_callee()
615  ret i32 %1
616}
617
618define i32 @thunk_keep_callee() {
619; CHECK: @thunk_keep_callee() {
620  ret i32 42
621}
622
623define i32 @thunk_extern_caller() fn_ret_thunk_extern {
624; CHECK: @thunk_extern_caller() [[FNRETTHUNK_EXTERN]]
625; CHECK-NEXT: ret i32 42
626  %1 = call i32 @thunk_keep_callee()
627  ret i32 %1
628}
629
630; CHECK: attributes [[SLH]] = { speculative_load_hardening }
631; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" }
632; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" }
633; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat }
634; CHECK: attributes [[NOUSEJUMPTABLES]] = { "no-jump-tables"="true" }
635; CHECK: attributes [[NULLPOINTERISVALID]] = { null_pointer_is_valid }
636; CHECK: attributes [[NO_INFS_FPMATH_FALSE]] = { "no-infs-fp-math"="false" }
637; CHECK: attributes [[NO_INFS_FPMATH_TRUE]] = { "no-infs-fp-math"="true" }
638; CHECK: attributes [[NO_NANS_FPMATH_FALSE]] = { "no-nans-fp-math"="false" }
639; CHECK: attributes [[NO_NANS_FPMATH_TRUE]] = { "no-nans-fp-math"="true" }
640; CHECK: attributes [[NO_SIGNED_ZEROS_FPMATH_FALSE]] = { "no-signed-zeros-fp-math"="false" }
641; CHECK: attributes [[NO_SIGNED_ZEROS_FPMATH_TRUE]] = { "no-signed-zeros-fp-math"="true" }
642; CHECK: attributes [[UNSAFE_FPMATH_FALSE]] = { "unsafe-fp-math"="false" }
643; CHECK: attributes [[UNSAFE_FPMATH_TRUE]] = { "unsafe-fp-math"="true" }
644; CHECK: attributes [[FNRETTHUNK_EXTERN]] = { fn_ret_thunk_extern }
645