1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2 ; RUN: opt -attributor -enable-new-pm=0 -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=14 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_NPM,NOT_CGSCC_OPM,NOT_TUNIT_NPM,IS__TUNIT____,IS________OPM,IS__TUNIT_OPM
3 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal -attributor-max-iterations-verify -attributor-annotate-decl-cs -attributor-max-iterations=14 -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CGSCC_OPM,NOT_CGSCC_NPM,NOT_TUNIT_OPM,IS__TUNIT____,IS________NPM,IS__TUNIT_NPM
4 ; RUN: opt -attributor-cgscc -enable-new-pm=0 -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_NPM,IS__CGSCC____,IS________OPM,IS__CGSCC_OPM
5 ; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_TUNIT_NPM,NOT_TUNIT_OPM,NOT_CGSCC_OPM,IS__CGSCC____,IS________NPM,IS__CGSCC_NPM
7 target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
9 declare i1* @geti1Ptr()
11 ; Make sure we do *not* return true.
13 ; CHECK: @[[G1:[a-zA-Z0-9_$"\\.-]+]] = private global i1* undef
14 ; CHECK: @[[G2:[a-zA-Z0-9_$"\\.-]+]] = private global i1* undef
15 ; CHECK: @[[G3:[a-zA-Z0-9_$"\\.-]+]] = private global i1 undef
17 define internal i1 @recursive_inst_comparator(i1* %a, i1* %b) {
18 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone willreturn
19 ; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_inst_comparator
20 ; IS__TUNIT____-SAME: (i1* noalias nofree readnone [[A:%.*]], i1* noalias nofree readnone [[B:%.*]]) #[[ATTR0:[0-9]+]] {
21 ; IS__TUNIT____-NEXT: [[CMP:%.*]] = icmp eq i1* [[A]], [[B]]
22 ; IS__TUNIT____-NEXT: ret i1 [[CMP]]
24 ; IS__CGSCC____: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
25 ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_inst_comparator
26 ; IS__CGSCC____-SAME: (i1* noalias nofree readnone [[A:%.*]], i1* noalias nofree readnone [[B:%.*]]) #[[ATTR0:[0-9]+]] {
27 ; IS__CGSCC____-NEXT: [[CMP:%.*]] = icmp eq i1* [[A]], [[B]]
28 ; IS__CGSCC____-NEXT: ret i1 [[CMP]]
30 %cmp = icmp eq i1* %a, %b
34 define internal i1 @recursive_inst_generator(i1 %c, i1* %p) {
35 ; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_inst_generator
36 ; IS__TUNIT____-SAME: (i1 [[C:%.*]], i1* nofree [[P:%.*]]) {
37 ; IS__TUNIT____-NEXT: [[A:%.*]] = call i1* @geti1Ptr()
38 ; IS__TUNIT____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
40 ; IS__TUNIT____-NEXT: [[R1:%.*]] = call i1 @recursive_inst_comparator(i1* noalias nofree readnone [[A]], i1* noalias nofree readnone [[P]]) #[[ATTR4:[0-9]+]]
41 ; IS__TUNIT____-NEXT: ret i1 [[R1]]
43 ; IS__TUNIT____-NEXT: [[R2:%.*]] = call i1 @recursive_inst_generator(i1 noundef true, i1* nofree [[A]])
44 ; IS__TUNIT____-NEXT: ret i1 [[R2]]
46 ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_inst_generator
47 ; IS__CGSCC____-SAME: (i1 [[C:%.*]], i1* nofree [[P:%.*]]) {
48 ; IS__CGSCC____-NEXT: [[A:%.*]] = call i1* @geti1Ptr()
49 ; IS__CGSCC____-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
51 ; IS__CGSCC____-NEXT: [[R1:%.*]] = call i1 @recursive_inst_comparator(i1* noalias nofree readnone [[A]], i1* noalias nofree readnone [[P]])
52 ; IS__CGSCC____-NEXT: ret i1 [[R1]]
54 ; IS__CGSCC____-NEXT: [[R2:%.*]] = call i1 @recursive_inst_generator(i1 noundef true, i1* nofree [[A]])
55 ; IS__CGSCC____-NEXT: ret i1 [[R2]]
57 %a = call i1* @geti1Ptr()
58 br i1 %c, label %t, label %f
60 %r1 = call i1 @recursive_inst_comparator(i1* %a, i1* %p)
63 %r2 = call i1 @recursive_inst_generator(i1 true, i1* %a)
67 ; FIXME: This should *not* return true.
68 define i1 @recursive_inst_generator_caller(i1 %c) {
69 ; CHECK-LABEL: define {{[^@]+}}@recursive_inst_generator_caller
70 ; CHECK-SAME: (i1 [[C:%.*]]) {
71 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_generator(i1 [[C]], i1* undef)
72 ; CHECK-NEXT: ret i1 [[CALL]]
74 %call = call i1 @recursive_inst_generator(i1 %c, i1* undef)
78 ; Make sure we do *not* return true.
79 define internal i1 @recursive_inst_compare(i1 %c, i1* %p) {
80 ; CHECK-LABEL: define {{[^@]+}}@recursive_inst_compare
81 ; CHECK-SAME: (i1 [[C:%.*]], i1* [[P:%.*]]) {
82 ; CHECK-NEXT: [[A:%.*]] = call i1* @geti1Ptr()
83 ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
85 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
86 ; CHECK-NEXT: ret i1 [[CMP]]
88 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare(i1 noundef true, i1* [[A]])
89 ; CHECK-NEXT: ret i1 [[CALL]]
91 %a = call i1* @geti1Ptr()
92 br i1 %c, label %t, label %f
94 %cmp = icmp eq i1* %a, %p
97 %call = call i1 @recursive_inst_compare(i1 true, i1* %a)
101 ; FIXME: This should *not* return true.
102 define i1 @recursive_inst_compare_caller(i1 %c) {
103 ; CHECK-LABEL: define {{[^@]+}}@recursive_inst_compare_caller
104 ; CHECK-SAME: (i1 [[C:%.*]]) {
105 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare(i1 [[C]], i1* undef)
106 ; CHECK-NEXT: ret i1 [[CALL]]
108 %call = call i1 @recursive_inst_compare(i1 %c, i1* undef)
112 ; Make sure we do *not* return true.
113 define internal i1 @recursive_alloca_compare(i1 %c, i1* %p) {
114 ; CHECK: Function Attrs: nofree nosync nounwind readnone
115 ; CHECK-LABEL: define {{[^@]+}}@recursive_alloca_compare
116 ; CHECK-SAME: (i1 [[C:%.*]], i1* noalias nofree nonnull readnone [[P:%.*]]) #[[ATTR1:[0-9]+]] {
117 ; CHECK-NEXT: [[A:%.*]] = alloca i1, align 1
118 ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
120 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
121 ; CHECK-NEXT: ret i1 [[CMP]]
123 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare(i1 noundef true, i1* noalias nofree noundef nonnull readnone dereferenceable(1) [[A]]) #[[ATTR1]]
124 ; CHECK-NEXT: ret i1 [[CALL]]
127 br i1 %c, label %t, label %f
129 %cmp = icmp eq i1* %a, %p
132 %call = call i1 @recursive_alloca_compare(i1 true, i1* %a)
136 ; FIXME: This should *not* return true.
137 define i1 @recursive_alloca_compare_caller(i1 %c) {
138 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone
139 ; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller
140 ; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
141 ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare(i1 [[C]], i1* undef) #[[ATTR1]]
142 ; IS__TUNIT____-NEXT: ret i1 [[CALL]]
144 ; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone
145 ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller
146 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
147 ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare(i1 [[C]], i1* undef) #[[ATTR4:[0-9]+]]
148 ; IS__CGSCC____-NEXT: ret i1 [[CALL]]
150 %call = call i1 @recursive_alloca_compare(i1 %c, i1* undef)
154 ; Make sure we do *not* simplify this to return 0 or 1, return 42 is ok though.
155 define internal i8 @recursive_alloca_load_return(i1 %c, i8* %p, i8 %v) {
156 ; CHECK: Function Attrs: argmemonly nofree nosync nounwind
157 ; CHECK-LABEL: define {{[^@]+}}@recursive_alloca_load_return
158 ; CHECK-SAME: (i1 [[C:%.*]], i8* nocapture nofree nonnull readonly [[P:%.*]], i8 noundef [[V:%.*]]) #[[ATTR2:[0-9]+]] {
159 ; CHECK-NEXT: [[A:%.*]] = alloca i8, align 1
160 ; CHECK-NEXT: store i8 [[V]], i8* [[A]], align 1
161 ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
163 ; CHECK-NEXT: store i8 0, i8* [[A]], align 1
164 ; CHECK-NEXT: [[L:%.*]] = load i8, i8* [[P]], align 1
165 ; CHECK-NEXT: ret i8 [[L]]
167 ; CHECK-NEXT: [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 noundef true, i8* noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[A]], i8 noundef 1) #[[ATTR3:[0-9]+]]
168 ; CHECK-NEXT: ret i8 [[CALL]]
172 br i1 %c, label %t, label %f
178 %call = call i8 @recursive_alloca_load_return(i1 true, i8* %a, i8 1)
182 define i8 @recursive_alloca_load_return_caller(i1 %c) {
183 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind readnone
184 ; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_load_return_caller
185 ; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
186 ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 [[C]], i8* undef, i8 noundef 42) #[[ATTR3]]
187 ; IS__TUNIT____-NEXT: ret i8 [[CALL]]
189 ; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone
190 ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_load_return_caller
191 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
192 ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 [[C]], i8* undef, i8 noundef 42) #[[ATTR5:[0-9]+]]
193 ; IS__CGSCC____-NEXT: ret i8 [[CALL]]
195 %call = call i8 @recursive_alloca_load_return(i1 %c, i8* undef, i8 42)
199 @G1 = private global i1* undef
200 @G2 = private global i1* undef
201 @G3 = private global i1 undef
203 ; Make sure we do *not* return true.
204 define internal i1 @recursive_alloca_compare_global1(i1 %c) {
205 ; CHECK: Function Attrs: nofree nosync nounwind
206 ; CHECK-LABEL: define {{[^@]+}}@recursive_alloca_compare_global1
207 ; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
208 ; CHECK-NEXT: [[A:%.*]] = alloca i1, align 1
209 ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
211 ; CHECK-NEXT: [[P:%.*]] = load i1*, i1** @G1, align 8
212 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
213 ; CHECK-NEXT: ret i1 [[CMP]]
215 ; CHECK-NEXT: store i1* [[A]], i1** @G1, align 8
216 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 noundef true) #[[ATTR3]]
217 ; CHECK-NEXT: ret i1 [[CALL]]
220 br i1 %c, label %t, label %f
222 %p = load i1*, i1** @G1
223 %cmp = icmp eq i1* %a, %p
226 store i1* %a, i1** @G1
227 %call = call i1 @recursive_alloca_compare_global1(i1 true)
231 ; FIXME: This should *not* return true.
232 define i1 @recursive_alloca_compare_caller_global1(i1 %c) {
233 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind
234 ; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global1
235 ; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
236 ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 [[C]]) #[[ATTR3]]
237 ; IS__TUNIT____-NEXT: ret i1 [[CALL]]
239 ; IS__CGSCC____: Function Attrs: nofree nosync nounwind
240 ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global1
241 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
242 ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 [[C]]) #[[ATTR5]]
243 ; IS__CGSCC____-NEXT: ret i1 [[CALL]]
245 %call = call i1 @recursive_alloca_compare_global1(i1 %c)
249 define internal i1 @recursive_alloca_compare_global2(i1 %c) {
250 ; CHECK: Function Attrs: nofree nosync nounwind
251 ; CHECK-LABEL: define {{[^@]+}}@recursive_alloca_compare_global2
252 ; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
253 ; CHECK-NEXT: [[A:%.*]] = alloca i1, align 1
254 ; CHECK-NEXT: [[P:%.*]] = load i1*, i1** @G2, align 8
255 ; CHECK-NEXT: store i1* [[A]], i1** @G2, align 8
256 ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
258 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
259 ; CHECK-NEXT: ret i1 [[CMP]]
261 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 noundef true) #[[ATTR3]]
262 ; CHECK-NEXT: ret i1 [[CALL]]
265 %p = load i1*, i1** @G2
266 store i1* %a, i1** @G2
267 br i1 %c, label %t, label %f
269 %cmp = icmp eq i1* %a, %p
272 %call = call i1 @recursive_alloca_compare_global2(i1 true)
276 ; FIXME: This should *not* return true.
277 define i1 @recursive_alloca_compare_caller_global2(i1 %c) {
278 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind
279 ; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global2
280 ; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
281 ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 [[C]]) #[[ATTR3]]
282 ; IS__TUNIT____-NEXT: ret i1 [[CALL]]
284 ; IS__CGSCC____: Function Attrs: nofree nosync nounwind
285 ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global2
286 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
287 ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 [[C]]) #[[ATTR5]]
288 ; IS__CGSCC____-NEXT: ret i1 [[CALL]]
290 %call = call i1 @recursive_alloca_compare_global2(i1 %c)
293 define internal i1 @recursive_inst_compare_global3(i1 %c) {
295 ; CHECK: Function Attrs: nofree nosync nounwind
296 ; CHECK-LABEL: define {{[^@]+}}@recursive_inst_compare_global3
297 ; CHECK-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
298 ; CHECK-NEXT: [[P:%.*]] = load i1, i1* @G3, align 1
299 ; CHECK-NEXT: store i1 [[C]], i1* @G3, align 1
300 ; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
302 ; CHECK-NEXT: [[CMP:%.*]] = icmp eq i1 [[C]], [[P]]
303 ; CHECK-NEXT: ret i1 [[CMP]]
305 ; CHECK-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 noundef true) #[[ATTR3]]
306 ; CHECK-NEXT: ret i1 [[CALL]]
308 %p = load i1, i1* @G3
310 br i1 %c, label %t, label %f
312 %cmp = icmp eq i1 %c, %p
315 %call = call i1 @recursive_inst_compare_global3(i1 true)
319 ; FIXME: This should *not* return true.
320 define i1 @recursive_inst_compare_caller_global3(i1 %c) {
321 ; IS__TUNIT____: Function Attrs: nofree nosync nounwind
322 ; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_inst_compare_caller_global3
323 ; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
324 ; IS__TUNIT____-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 [[C]]) #[[ATTR3]]
325 ; IS__TUNIT____-NEXT: ret i1 [[CALL]]
327 ; IS__CGSCC____: Function Attrs: nofree nosync nounwind
328 ; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_inst_compare_caller_global3
329 ; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
330 ; IS__CGSCC____-NEXT: [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 [[C]]) #[[ATTR5]]
331 ; IS__CGSCC____-NEXT: ret i1 [[CALL]]
333 %call = call i1 @recursive_inst_compare_global3(i1 %c)
337 ; IS__TUNIT____: attributes #[[ATTR0]] = { nofree nosync nounwind readnone willreturn }
338 ; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone }
339 ; IS__TUNIT____: attributes #[[ATTR2]] = { argmemonly nofree nosync nounwind }
340 ; IS__TUNIT____: attributes #[[ATTR3]] = { nofree nosync nounwind }
341 ; IS__TUNIT____: attributes #[[ATTR4]] = { nounwind readnone }
343 ; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
344 ; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone }
345 ; IS__CGSCC____: attributes #[[ATTR2]] = { argmemonly nofree nosync nounwind }
346 ; IS__CGSCC____: attributes #[[ATTR3]] = { nofree nosync nounwind }
347 ; IS__CGSCC____: attributes #[[ATTR4]] = { nounwind readnone }
348 ; IS__CGSCC____: attributes #[[ATTR5]] = { nounwind }