Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / FunctionAttrs / willreturn.ll
blob70926345ce274efa491923f79454274a6b995179
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --check-attributes
2 ; RUN: opt -passes=function-attrs -S %s | FileCheck --check-prefixes=COMMON,FNATTRS %s
3 ; RUN: opt -passes=attributor-light -S %s | FileCheck --check-prefixes=COMMON,ATTRIBUTOR %s
5 define void @mustprogress_readnone() mustprogress {
6 ; FNATTRS: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(none)
7 ; FNATTRS-LABEL: @mustprogress_readnone(
8 ; FNATTRS-NEXT:  entry:
9 ; FNATTRS-NEXT:    br label [[WHILE_BODY:%.*]]
10 ; FNATTRS:       while.body:
11 ; FNATTRS-NEXT:    br label [[WHILE_BODY]]
13 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind memory(none)
14 ; ATTRIBUTOR-LABEL: @mustprogress_readnone(
15 ; ATTRIBUTOR-NEXT:  entry:
16 ; ATTRIBUTOR-NEXT:    br label [[WHILE_BODY:%.*]]
17 ; ATTRIBUTOR:       while.body:
18 ; ATTRIBUTOR-NEXT:    br label [[WHILE_BODY]]
20 entry:
21   br label %while.body
23 while.body:
24   br label %while.body
27 define i32 @mustprogress_load(ptr %ptr) mustprogress {
28 ; FNATTRS: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(argmem: read)
29 ; FNATTRS-LABEL: @mustprogress_load(
30 ; FNATTRS-NEXT:  entry:
31 ; FNATTRS-NEXT:    br label [[WHILE_BODY:%.*]]
32 ; FNATTRS:       while.body:
33 ; FNATTRS-NEXT:    [[R:%.*]] = load i32, ptr [[PTR:%.*]], align 4
34 ; FNATTRS-NEXT:    br label [[WHILE_BODY]]
36 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind memory(argmem: read)
37 ; ATTRIBUTOR-LABEL: @mustprogress_load(
38 ; ATTRIBUTOR-NEXT:  entry:
39 ; ATTRIBUTOR-NEXT:    br label [[WHILE_BODY:%.*]]
40 ; ATTRIBUTOR:       while.body:
41 ; ATTRIBUTOR-NEXT:    [[R:%.*]] = load i32, ptr [[PTR:%.*]], align 4
42 ; ATTRIBUTOR-NEXT:    br label [[WHILE_BODY]]
44 entry:
45   br label %while.body
47 while.body:
48   %r = load i32, ptr %ptr
49   br label %while.body
52 define void @mustprogress_store(ptr %ptr) mustprogress {
53 ; COMMON: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind memory(argmem: write)
54 ; COMMON-LABEL: @mustprogress_store(
55 ; COMMON-NEXT:  entry:
56 ; COMMON-NEXT:    br label [[WHILE_BODY:%.*]]
57 ; COMMON:       while.body:
58 ; COMMON-NEXT:    store i32 0, ptr [[PTR:%.*]], align 4
59 ; COMMON-NEXT:    br label [[WHILE_BODY]]
61 entry:
62   br label %while.body
64 while.body:
65   store i32 0, ptr %ptr
66   br label %while.body
69 declare void @unknown_fn()
71 define void @mustprogress_call_unknown_fn() mustprogress {
72 ; COMMON: Function Attrs: mustprogress
73 ; COMMON-LABEL: @mustprogress_call_unknown_fn(
74 ; COMMON-NEXT:    call void @unknown_fn()
75 ; COMMON-NEXT:    ret void
77   call void @unknown_fn()
78   ret void
81 define i32 @mustprogress_call_known_functions(ptr %ptr) mustprogress {
82 ; FNATTRS: Function Attrs: mustprogress nofree norecurse noreturn nosync nounwind willreturn memory(argmem: read)
83 ; FNATTRS-LABEL: @mustprogress_call_known_functions(
84 ; FNATTRS-NEXT:    call void @mustprogress_readnone()
85 ; FNATTRS-NEXT:    [[R:%.*]] = call i32 @mustprogress_load(ptr [[PTR:%.*]])
86 ; FNATTRS-NEXT:    ret i32 [[R]]
88 ; ATTRIBUTOR: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
89 ; ATTRIBUTOR-LABEL: @mustprogress_call_known_functions(
90 ; ATTRIBUTOR-NEXT:    call void @mustprogress_readnone() #[[ATTR9:[0-9]+]]
91 ; ATTRIBUTOR-NEXT:    [[R:%.*]] = call i32 @mustprogress_load(ptr nocapture nofree readonly [[PTR:%.*]]) #[[ATTR12:[0-9]+]]
92 ; ATTRIBUTOR-NEXT:    ret i32 [[R]]
94   call void @mustprogress_readnone()
95   %r = call i32 @mustprogress_load(ptr %ptr)
96   ret i32 %r
99 declare i32 @__gxx_personality_v0(...)
101 define i64 @mustprogress_mayunwind() mustprogress personality ptr @__gxx_personality_v0 {
102 ; FNATTRS: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
103 ; FNATTRS-LABEL: @mustprogress_mayunwind(
104 ; FNATTRS-NEXT:    [[A:%.*]] = invoke i64 @fn_noread()
105 ; FNATTRS-NEXT:            to label [[A:%.*]] unwind label [[B:%.*]]
106 ; FNATTRS:       A:
107 ; FNATTRS-NEXT:    ret i64 10
108 ; FNATTRS:       B:
109 ; FNATTRS-NEXT:    [[VAL:%.*]] = landingpad { ptr, i32 }
110 ; FNATTRS-NEXT:            catch ptr null
111 ; FNATTRS-NEXT:    ret i64 0
113 ; ATTRIBUTOR: Function Attrs: mustprogress nosync nounwind willreturn memory(none)
114 ; ATTRIBUTOR-LABEL: @mustprogress_mayunwind(
115 ; ATTRIBUTOR-NEXT:    [[A:%.*]] = invoke i64 @fn_noread() #[[ATTR13:[0-9]+]]
116 ; ATTRIBUTOR-NEXT:            to label [[A:%.*]] unwind label [[B:%.*]]
117 ; ATTRIBUTOR:       A:
118 ; ATTRIBUTOR-NEXT:    ret i64 10
119 ; ATTRIBUTOR:       B:
120 ; ATTRIBUTOR-NEXT:    [[VAL:%.*]] = landingpad { ptr, i32 }
121 ; ATTRIBUTOR-NEXT:            catch ptr null
122 ; ATTRIBUTOR-NEXT:    ret i64 0
124   %a = invoke i64 @fn_noread()
125   to label %A unwind label %B
127   ret i64 10
130   %val = landingpad { ptr, i32 }
131   catch ptr null
132   ret i64 0
135 ; Function without loops or non-willreturn calls will return.
136 define void @willreturn_no_loop(i1 %c, ptr %p) {
137 ; FNATTRS: Function Attrs: mustprogress willreturn
138 ; FNATTRS-LABEL: @willreturn_no_loop(
139 ; FNATTRS-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
140 ; FNATTRS:       if:
141 ; FNATTRS-NEXT:    [[TMP1:%.*]] = load atomic i32, ptr [[P:%.*]] seq_cst, align 4
142 ; FNATTRS-NEXT:    call void @fn_willreturn()
143 ; FNATTRS-NEXT:    br label [[END:%.*]]
144 ; FNATTRS:       else:
145 ; FNATTRS-NEXT:    store atomic i32 0, ptr [[P]] seq_cst, align 4
146 ; FNATTRS-NEXT:    br label [[END]]
147 ; FNATTRS:       end:
148 ; FNATTRS-NEXT:    ret void
150 ; ATTRIBUTOR: Function Attrs: mustprogress willreturn
151 ; ATTRIBUTOR-LABEL: @willreturn_no_loop(
152 ; ATTRIBUTOR-NEXT:    br i1 [[C:%.*]], label [[IF:%.*]], label [[ELSE:%.*]]
153 ; ATTRIBUTOR:       if:
154 ; ATTRIBUTOR-NEXT:    [[TMP1:%.*]] = load atomic i32, ptr [[P:%.*]] seq_cst, align 4
155 ; ATTRIBUTOR-NEXT:    call void @fn_willreturn() #[[ATTR11:[0-9]+]]
156 ; ATTRIBUTOR-NEXT:    br label [[END:%.*]]
157 ; ATTRIBUTOR:       else:
158 ; ATTRIBUTOR-NEXT:    store atomic i32 0, ptr [[P]] seq_cst, align 4
159 ; ATTRIBUTOR-NEXT:    br label [[END]]
160 ; ATTRIBUTOR:       end:
161 ; ATTRIBUTOR-NEXT:    ret void
163   br i1 %c, label %if, label %else
166   load atomic i32, ptr %p seq_cst, align 4
167   call void @fn_willreturn()
168   br label %end
170 else:
171   store atomic i32 0, ptr %p seq_cst, align 4
172   br label %end
174 end:
175   ret void
178 ; Calls a function that is not guaranteed to return, not willreturn.
179 define void @willreturn_non_returning_function(i1 %c, ptr %p) {
180 ; COMMON-LABEL: @willreturn_non_returning_function(
181 ; COMMON-NEXT:    call void @unknown_fn()
182 ; COMMON-NEXT:    ret void
184   call void @unknown_fn()
185   ret void
188 ; Infinite loop without mustprogress, will not return.
189 define void @willreturn_loop() {
190 ; COMMON: Function Attrs: nofree norecurse noreturn nosync nounwind memory(none)
191 ; COMMON-LABEL: @willreturn_loop(
192 ; COMMON-NEXT:    br label [[LOOP:%.*]]
193 ; COMMON:       loop:
194 ; COMMON-NEXT:    br label [[LOOP]]
196   br label %loop
198 loop:
199   br label %loop
202 ; Finite loop. Could be willreturn but not detected.
203 ; FIXME
204 define void @willreturn_finite_loop() {
205 ; COMMON: Function Attrs: nofree norecurse nosync nounwind memory(none)
206 ; COMMON-LABEL: @willreturn_finite_loop(
207 ; COMMON-NEXT:  entry:
208 ; COMMON-NEXT:    br label [[LOOP:%.*]]
209 ; COMMON:       loop:
210 ; COMMON-NEXT:    [[I:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[I_INC:%.*]], [[LOOP]] ]
211 ; COMMON-NEXT:    [[I_INC]] = add nuw i32 [[I]], 1
212 ; COMMON-NEXT:    [[C:%.*]] = icmp ne i32 [[I_INC]], 100
213 ; COMMON-NEXT:    br i1 [[C]], label [[LOOP]], label [[END:%.*]]
214 ; COMMON:       end:
215 ; COMMON-NEXT:    ret void
217 entry:
218   br label %loop
220 loop:
221   %i = phi i32 [ 0, %entry], [ %i.inc, %loop ]
222   %i.inc = add nuw i32 %i, 1
223   %c = icmp ne i32 %i.inc, 100
224   br i1 %c, label %loop, label %end
226 end:
227   ret void
230 ; Infinite recursion without mustprogress, will not return.
231 define void @willreturn_recursion() {
232 ; FNATTRS: Function Attrs: nofree nosync nounwind memory(none)
233 ; FNATTRS-LABEL: @willreturn_recursion(
234 ; FNATTRS-NEXT:    tail call void @willreturn_recursion()
235 ; FNATTRS-NEXT:    ret void
237 ; ATTRIBUTOR: Function Attrs: nofree nosync nounwind memory(none)
238 ; ATTRIBUTOR-LABEL: @willreturn_recursion(
239 ; ATTRIBUTOR-NEXT:    tail call void @willreturn_recursion() #[[ATTR9]]
240 ; ATTRIBUTOR-NEXT:    ret void
242   tail call void @willreturn_recursion()
243   ret void
246 ; Irreducible infinite loop, will not return.
247 define void @willreturn_irreducible(i1 %c) {
248 ; COMMON: Function Attrs: nofree norecurse noreturn nosync nounwind memory(none)
249 ; COMMON-LABEL: @willreturn_irreducible(
250 ; COMMON-NEXT:    br i1 [[C:%.*]], label [[BB1:%.*]], label [[BB2:%.*]]
251 ; COMMON:       bb1:
252 ; COMMON-NEXT:    br label [[BB2]]
253 ; COMMON:       bb2:
254 ; COMMON-NEXT:    br label [[BB1]]
256   br i1 %c, label %bb1, label %bb2
258 bb1:
259   br label %bb2
261 bb2:
262   br label %bb1
265 define linkonce i32 @square(i32) {
266 ; COMMON-LABEL: @square(
267 ; COMMON-NEXT:    [[TMP2:%.*]] = mul nsw i32 [[TMP0:%.*]], [[TMP0]]
268 ; COMMON-NEXT:    ret i32 [[TMP2]]
270   %2 = mul nsw i32 %0, %0
271   ret i32 %2
274 declare i64 @fn_noread() readnone
275 declare void @fn_willreturn() willreturn