]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - test/Transforms/FunctionAttrs/convergent.ll
Vendor import of llvm trunk r351319 (just before the release_80 branch
[FreeBSD/FreeBSD.git] / test / Transforms / FunctionAttrs / convergent.ll
1 ; FIXME: convert CHECK-INDIRECT into CHECK (and remove -check-prefixes) as soon
2 ; FIXME: as new-pass-manager's handling of indirect_non_convergent_call is fixed
3 ;
4 ; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-INDIRECT
5 ; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
6
7 ; CHECK: Function Attrs
8 ; CHECK-NOT: convergent
9 ; CHECK-NEXT: define i32 @nonleaf()
10 define i32 @nonleaf() convergent {
11   %a = call i32 @leaf()
12   ret i32 %a
13 }
14
15 ; CHECK: Function Attrs
16 ; CHECK-NOT: convergent
17 ; CHECK-NEXT: define i32 @leaf()
18 define i32 @leaf() convergent {
19   ret i32 0
20 }
21
22 ; CHECK: Function Attrs
23 ; CHECK-SAME: convergent
24 ; CHECK-NEXT: declare i32 @k()
25 declare i32 @k() convergent
26
27 ; CHECK: Function Attrs
28 ; CHECK-SAME: convergent
29 ; CHECK-NEXT: define i32 @extern()
30 define i32 @extern() convergent {
31   %a = call i32 @k() convergent
32   ret i32 %a
33 }
34
35 ; Convergent should not be removed on the function here.  Although the call is
36 ; not explicitly convergent, it picks up the convergent attr from the callee.
37 ;
38 ; CHECK: Function Attrs
39 ; CHECK-SAME: convergent
40 ; CHECK-NEXT: define i32 @extern_non_convergent_call()
41 define i32 @extern_non_convergent_call() convergent {
42   %a = call i32 @k()
43   ret i32 %a
44 }
45
46 ; CHECK: Function Attrs
47 ; CHECK-SAME: convergent
48 ; CHECK-NEXT: define i32 @indirect_convergent_call(
49 define i32 @indirect_convergent_call(i32 ()* %f) convergent {
50    %a = call i32 %f() convergent
51    ret i32 %a
52 }
53 ; Give indirect_non_convergent_call the norecurse attribute so we get a
54 ; "Function Attrs" comment in the output.
55 ;
56 ; CHECK: Function Attrs
57 ; CHECK-INDIRECT-NOT: convergent
58 ; CHECK-INDIRECT-NEXT: define i32 @indirect_non_convergent_call(
59 define i32 @indirect_non_convergent_call(i32 ()* %f) convergent norecurse {
60    %a = call i32 %f()
61    ret i32 %a
62 }
63
64 ; CHECK: Function Attrs
65 ; CHECK-SAME: convergent
66 ; CHECK-NEXT: declare void @llvm.nvvm.barrier0()
67 declare void @llvm.nvvm.barrier0() convergent
68
69 ; CHECK: Function Attrs
70 ; CHECK-SAME: convergent
71 ; CHECK-NEXT: define i32 @intrinsic()
72 define i32 @intrinsic() convergent {
73   ; Implicitly convergent, because the intrinsic is convergent.
74   call void @llvm.nvvm.barrier0()
75   ret i32 0
76 }
77
78 ; CHECK: Function Attrs
79 ; CHECK-NOT: convergent
80 ; CHECK-NEXT: define i32 @recursive1()
81 define i32 @recursive1() convergent {
82   %a = call i32 @recursive2() convergent
83   ret i32 %a
84 }
85
86 ; CHECK: Function Attrs
87 ; CHECK-NOT: convergent
88 ; CHECK-NEXT: define i32 @recursive2()
89 define i32 @recursive2() convergent {
90   %a = call i32 @recursive1() convergent
91   ret i32 %a
92 }
93
94 ; CHECK: Function Attrs
95 ; CHECK-SAME: convergent
96 ; CHECK-NEXT: define i32 @noopt()
97 define i32 @noopt() convergent optnone noinline {
98   %a = call i32 @noopt_friend() convergent
99   ret i32 0
100 }
101
102 ; A function which is mutually-recursive with a convergent, optnone function
103 ; shouldn't have its convergent attribute stripped.
104 ; CHECK: Function Attrs
105 ; CHECK-SAME: convergent
106 ; CHECK-NEXT: define i32 @noopt_friend()
107 define i32 @noopt_friend() convergent {
108   %a = call i32 @noopt()
109   ret i32 0
110 }