blob: 0e4b7515d0187048973839197440bdeadec13985 [file] [log] [blame]
Fedor Sergeev6660fd02018-03-23 21:46:16 +00001; 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
Justin Lebar260854b2016-02-09 23:03:22 +00006
7; CHECK: Function Attrs
8; CHECK-NOT: convergent
9; CHECK-NEXT: define i32 @nonleaf()
10define 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()
18define i32 @leaf() convergent {
19 ret i32 0
20}
21
22; CHECK: Function Attrs
23; CHECK-SAME: convergent
24; CHECK-NEXT: declare i32 @k()
25declare i32 @k() convergent
26
27; CHECK: Function Attrs
28; CHECK-SAME: convergent
29; CHECK-NEXT: define i32 @extern()
30define i32 @extern() convergent {
Justin Lebar9d943972016-03-14 20:18:54 +000031 %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()
41define i32 @extern_non_convergent_call() convergent {
Justin Lebar260854b2016-02-09 23:03:22 +000042 %a = call i32 @k()
43 ret i32 %a
44}
45
46; CHECK: Function Attrs
47; CHECK-SAME: convergent
Justin Lebar9d943972016-03-14 20:18:54 +000048; CHECK-NEXT: define i32 @indirect_convergent_call(
49define 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
Fedor Sergeev6660fd02018-03-23 21:46:16 +000057; CHECK-INDIRECT-NOT: convergent
58; CHECK-INDIRECT-NEXT: define i32 @indirect_non_convergent_call(
Justin Lebar9d943972016-03-14 20:18:54 +000059define i32 @indirect_non_convergent_call(i32 ()* %f) convergent norecurse {
60 %a = call i32 %f()
61 ret i32 %a
Justin Lebar260854b2016-02-09 23:03:22 +000062}
63
64; CHECK: Function Attrs
65; CHECK-SAME: convergent
Justin Bognera4635372016-07-06 20:02:45 +000066; CHECK-NEXT: declare void @llvm.nvvm.barrier0()
67declare void @llvm.nvvm.barrier0() convergent
Justin Lebar260854b2016-02-09 23:03:22 +000068
69; CHECK: Function Attrs
70; CHECK-SAME: convergent
71; CHECK-NEXT: define i32 @intrinsic()
72define i32 @intrinsic() convergent {
Justin Lebar9d943972016-03-14 20:18:54 +000073 ; Implicitly convergent, because the intrinsic is convergent.
Justin Bognera4635372016-07-06 20:02:45 +000074 call void @llvm.nvvm.barrier0()
Justin Lebar260854b2016-02-09 23:03:22 +000075 ret i32 0
76}
77
Justin Lebar260854b2016-02-09 23:03:22 +000078; CHECK: Function Attrs
79; CHECK-NOT: convergent
80; CHECK-NEXT: define i32 @recursive1()
81define i32 @recursive1() convergent {
Justin Lebar9d943972016-03-14 20:18:54 +000082 %a = call i32 @recursive2() convergent
Justin Lebar260854b2016-02-09 23:03:22 +000083 ret i32 %a
84}
85
86; CHECK: Function Attrs
87; CHECK-NOT: convergent
88; CHECK-NEXT: define i32 @recursive2()
89define i32 @recursive2() convergent {
Justin Lebar9d943972016-03-14 20:18:54 +000090 %a = call i32 @recursive1() convergent
Justin Lebar260854b2016-02-09 23:03:22 +000091 ret i32 %a
92}
93
94; CHECK: Function Attrs
95; CHECK-SAME: convergent
96; CHECK-NEXT: define i32 @noopt()
97define i32 @noopt() convergent optnone noinline {
Justin Lebar9d943972016-03-14 20:18:54 +000098 %a = call i32 @noopt_friend() convergent
Justin Lebar260854b2016-02-09 23:03:22 +000099 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()
107define i32 @noopt_friend() convergent {
108 %a = call i32 @noopt()
109 ret i32 0
110}