[InstCombine] Signed saturation tests. NFC
[llvm-complete.git] / test / Transforms / FunctionAttrs / convergent.ll
blob0e4b7515d0187048973839197440bdeadec13985
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
4 ; RUN: opt -functionattrs -S < %s | FileCheck %s --check-prefixes=CHECK,CHECK-INDIRECT
5 ; RUN: opt -passes=function-attrs -S < %s | FileCheck %s
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
15 ; CHECK: Function Attrs
16 ; CHECK-NOT: convergent
17 ; CHECK-NEXT: define i32 @leaf()
18 define i32 @leaf() convergent {
19   ret i32 0
22 ; CHECK: Function Attrs
23 ; CHECK-SAME: convergent
24 ; CHECK-NEXT: declare i32 @k()
25 declare i32 @k() convergent
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
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.
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
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
53 ; Give indirect_non_convergent_call the norecurse attribute so we get a
54 ; "Function Attrs" comment in the output.
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
64 ; CHECK: Function Attrs
65 ; CHECK-SAME: convergent
66 ; CHECK-NEXT: declare void @llvm.nvvm.barrier0()
67 declare void @llvm.nvvm.barrier0() convergent
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
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
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
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
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