• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1; RUN: opt -functionattrs -S < %s | FileCheck %s
2
3; CHECK: Function Attrs
4; CHECK-NOT: convergent
5; CHECK-NEXT: define i32 @nonleaf()
6define i32 @nonleaf() convergent {
7  %a = call i32 @leaf()
8  ret i32 %a
9}
10
11; CHECK: Function Attrs
12; CHECK-NOT: convergent
13; CHECK-NEXT: define i32 @leaf()
14define i32 @leaf() convergent {
15  ret i32 0
16}
17
18; CHECK: Function Attrs
19; CHECK-SAME: convergent
20; CHECK-NEXT: declare i32 @k()
21declare i32 @k() convergent
22
23; CHECK: Function Attrs
24; CHECK-SAME: convergent
25; CHECK-NEXT: define i32 @extern()
26define i32 @extern() convergent {
27  %a = call i32 @k() convergent
28  ret i32 %a
29}
30
31; Convergent should not be removed on the function here.  Although the call is
32; not explicitly convergent, it picks up the convergent attr from the callee.
33;
34; CHECK: Function Attrs
35; CHECK-SAME: convergent
36; CHECK-NEXT: define i32 @extern_non_convergent_call()
37define i32 @extern_non_convergent_call() convergent {
38  %a = call i32 @k()
39  ret i32 %a
40}
41
42; CHECK: Function Attrs
43; CHECK-SAME: convergent
44; CHECK-NEXT: define i32 @indirect_convergent_call(
45define i32 @indirect_convergent_call(i32 ()* %f) convergent {
46   %a = call i32 %f() convergent
47   ret i32 %a
48}
49; Give indirect_non_convergent_call the norecurse attribute so we get a
50; "Function Attrs" comment in the output.
51;
52; CHECK: Function Attrs
53; CHECK-NOT: convergent
54; CHECK-NEXT: define i32 @indirect_non_convergent_call(
55define i32 @indirect_non_convergent_call(i32 ()* %f) convergent norecurse {
56   %a = call i32 %f()
57   ret i32 %a
58}
59
60; CHECK: Function Attrs
61; CHECK-SAME: convergent
62; CHECK-NEXT: declare void @llvm.nvvm.barrier0()
63declare void @llvm.nvvm.barrier0() convergent
64
65; CHECK: Function Attrs
66; CHECK-SAME: convergent
67; CHECK-NEXT: define i32 @intrinsic()
68define i32 @intrinsic() convergent {
69  ; Implicitly convergent, because the intrinsic is convergent.
70  call void @llvm.nvvm.barrier0()
71  ret i32 0
72}
73
74; CHECK: Function Attrs
75; CHECK-NOT: convergent
76; CHECK-NEXT: define i32 @recursive1()
77define i32 @recursive1() convergent {
78  %a = call i32 @recursive2() convergent
79  ret i32 %a
80}
81
82; CHECK: Function Attrs
83; CHECK-NOT: convergent
84; CHECK-NEXT: define i32 @recursive2()
85define i32 @recursive2() convergent {
86  %a = call i32 @recursive1() convergent
87  ret i32 %a
88}
89
90; CHECK: Function Attrs
91; CHECK-SAME: convergent
92; CHECK-NEXT: define i32 @noopt()
93define i32 @noopt() convergent optnone noinline {
94  %a = call i32 @noopt_friend() convergent
95  ret i32 0
96}
97
98; A function which is mutually-recursive with a convergent, optnone function
99; shouldn't have its convergent attribute stripped.
100; CHECK: Function Attrs
101; CHECK-SAME: convergent
102; CHECK-NEXT: define i32 @noopt_friend()
103define i32 @noopt_friend() convergent {
104  %a = call i32 @noopt()
105  ret i32 0
106}
107