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=17 -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=17 -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
6
7target datalayout = "e-m:o-i64:64-f80:128-n8:16:32:64-S128"
8
9declare i1* @geti1Ptr()
10
11; Make sure we do *not* return true.
12;.
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
16;.
17define internal i1 @recursive_inst_comparator(i1* %a, i1* %b) {
18; CHECK: Function Attrs: nofree norecurse nosync nounwind readnone willreturn
19; CHECK-LABEL: define {{[^@]+}}@recursive_inst_comparator
20; CHECK-SAME: (i1* noalias nofree readnone [[A:%.*]], i1* noalias nofree readnone [[B:%.*]]) #[[ATTR0:[0-9]+]] {
21; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i1* [[A]], [[B]]
22; CHECK-NEXT:    ret i1 [[CMP]]
23;
24  %cmp = icmp eq i1* %a, %b
25  ret i1 %cmp
26}
27
28define internal i1 @recursive_inst_generator(i1 %c, i1* %p) {
29; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_inst_generator
30; IS__TUNIT____-SAME: (i1 [[C:%.*]], i1* nofree [[P:%.*]]) {
31; IS__TUNIT____-NEXT:    [[A:%.*]] = call i1* @geti1Ptr()
32; IS__TUNIT____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
33; IS__TUNIT____:       t:
34; IS__TUNIT____-NEXT:    [[R1:%.*]] = call i1 @recursive_inst_comparator(i1* noalias nofree readnone [[A]], i1* noalias nofree readnone [[P]]) #[[ATTR6:[0-9]+]]
35; IS__TUNIT____-NEXT:    ret i1 [[R1]]
36; IS__TUNIT____:       f:
37; IS__TUNIT____-NEXT:    [[R2:%.*]] = call i1 @recursive_inst_generator(i1 noundef true, i1* nofree [[A]])
38; IS__TUNIT____-NEXT:    ret i1 [[R2]]
39;
40; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_inst_generator
41; IS__CGSCC____-SAME: (i1 [[C:%.*]], i1* nofree [[P:%.*]]) {
42; IS__CGSCC____-NEXT:    [[A:%.*]] = call i1* @geti1Ptr()
43; IS__CGSCC____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
44; IS__CGSCC____:       t:
45; IS__CGSCC____-NEXT:    [[R1:%.*]] = call i1 @recursive_inst_comparator(i1* noalias nofree readnone [[A]], i1* noalias nofree readnone [[P]])
46; IS__CGSCC____-NEXT:    ret i1 [[R1]]
47; IS__CGSCC____:       f:
48; IS__CGSCC____-NEXT:    [[R2:%.*]] = call i1 @recursive_inst_generator(i1 noundef true, i1* nofree [[A]])
49; IS__CGSCC____-NEXT:    ret i1 [[R2]]
50;
51  %a = call i1* @geti1Ptr()
52  br i1 %c, label %t, label %f
53t:
54  %r1 = call i1 @recursive_inst_comparator(i1* %a, i1* %p)
55  ret i1 %r1
56f:
57  %r2 = call i1 @recursive_inst_generator(i1 true, i1* %a)
58  ret i1 %r2
59}
60
61; FIXME: This should *not* return true.
62define i1 @recursive_inst_generator_caller(i1 %c) {
63; CHECK-LABEL: define {{[^@]+}}@recursive_inst_generator_caller
64; CHECK-SAME: (i1 [[C:%.*]]) {
65; CHECK-NEXT:    [[CALL:%.*]] = call i1 @recursive_inst_generator(i1 [[C]], i1* undef)
66; CHECK-NEXT:    ret i1 [[CALL]]
67;
68  %call = call i1 @recursive_inst_generator(i1 %c, i1* undef)
69  ret i1 %call
70}
71
72; Make sure we do *not* return true.
73define internal i1 @recursive_inst_compare(i1 %c, i1* %p) {
74; CHECK-LABEL: define {{[^@]+}}@recursive_inst_compare
75; CHECK-SAME: (i1 [[C:%.*]], i1* [[P:%.*]]) {
76; CHECK-NEXT:    [[A:%.*]] = call i1* @geti1Ptr()
77; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
78; CHECK:       t:
79; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
80; CHECK-NEXT:    ret i1 [[CMP]]
81; CHECK:       f:
82; CHECK-NEXT:    [[CALL:%.*]] = call i1 @recursive_inst_compare(i1 noundef true, i1* [[A]])
83; CHECK-NEXT:    ret i1 [[CALL]]
84;
85  %a = call i1* @geti1Ptr()
86  br i1 %c, label %t, label %f
87t:
88  %cmp = icmp eq i1* %a, %p
89  ret i1 %cmp
90f:
91  %call = call i1 @recursive_inst_compare(i1 true, i1* %a)
92  ret i1 %call
93}
94
95; FIXME: This should *not* return true.
96define i1 @recursive_inst_compare_caller(i1 %c) {
97; CHECK-LABEL: define {{[^@]+}}@recursive_inst_compare_caller
98; CHECK-SAME: (i1 [[C:%.*]]) {
99; CHECK-NEXT:    [[CALL:%.*]] = call i1 @recursive_inst_compare(i1 [[C]], i1* undef)
100; CHECK-NEXT:    ret i1 [[CALL]]
101;
102  %call = call i1 @recursive_inst_compare(i1 %c, i1* undef)
103  ret i1 %call
104}
105
106; Make sure we do *not* return true.
107define internal i1 @recursive_alloca_compare(i1 %c, i1* %p) {
108; CHECK: Function Attrs: nofree nosync nounwind readnone
109; CHECK-LABEL: define {{[^@]+}}@recursive_alloca_compare
110; CHECK-SAME: (i1 [[C:%.*]], i1* noalias nofree nonnull readnone [[P:%.*]]) #[[ATTR1:[0-9]+]] {
111; CHECK-NEXT:    [[A:%.*]] = alloca i1, align 1
112; CHECK-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
113; CHECK:       t:
114; CHECK-NEXT:    [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
115; CHECK-NEXT:    ret i1 [[CMP]]
116; CHECK:       f:
117; CHECK-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare(i1 noundef true, i1* noalias nofree noundef nonnull readnone dereferenceable(1) [[A]]) #[[ATTR1]]
118; CHECK-NEXT:    ret i1 [[CALL]]
119;
120  %a = alloca i1
121  br i1 %c, label %t, label %f
122t:
123  %cmp = icmp eq i1* %a, %p
124  ret i1 %cmp
125f:
126  %call = call i1 @recursive_alloca_compare(i1 true, i1* %a)
127  ret i1 %call
128}
129
130; FIXME: This should *not* return true.
131define i1 @recursive_alloca_compare_caller(i1 %c) {
132; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone
133; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller
134; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR2:[0-9]+]] {
135; IS__TUNIT____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare(i1 [[C]], i1* undef) #[[ATTR1]]
136; IS__TUNIT____-NEXT:    ret i1 [[CALL]]
137;
138; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone
139; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller
140; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
141; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare(i1 [[C]], i1* undef) #[[ATTR4:[0-9]+]]
142; IS__CGSCC____-NEXT:    ret i1 [[CALL]]
143;
144  %call = call i1 @recursive_alloca_compare(i1 %c, i1* undef)
145  ret i1 %call
146}
147
148; Make sure we do *not* simplify this to return 0 or 1, return 42 is ok though.
149define internal i8 @recursive_alloca_load_return(i1 %c, i8* %p, i8 %v) {
150; IS__TUNIT____: Function Attrs: argmemonly nofree nosync nounwind
151; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_load_return
152; IS__TUNIT____-SAME: (i1 [[C:%.*]], i8* nocapture nofree nonnull readonly [[P:%.*]], i8 noundef [[V:%.*]]) #[[ATTR3:[0-9]+]] {
153; IS__TUNIT____-NEXT:    [[A:%.*]] = alloca i8, align 1
154; IS__TUNIT____-NEXT:    store i8 [[V]], i8* [[A]], align 1
155; IS__TUNIT____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
156; IS__TUNIT____:       t:
157; IS__TUNIT____-NEXT:    store i8 0, i8* [[A]], align 1
158; IS__TUNIT____-NEXT:    [[L:%.*]] = load i8, i8* [[P]], align 1
159; IS__TUNIT____-NEXT:    ret i8 [[L]]
160; IS__TUNIT____:       f:
161; IS__TUNIT____-NEXT:    [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 noundef true, i8* noalias nocapture nofree noundef nonnull readonly dereferenceable(1) [[A]], i8 noundef 1) #[[ATTR4:[0-9]+]]
162; IS__TUNIT____-NEXT:    ret i8 [[CALL]]
163;
164; IS__CGSCC____: Function Attrs: argmemonly nofree nosync nounwind
165; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_load_return
166; IS__CGSCC____-SAME: (i1 [[C:%.*]], i8* nocapture nofree nonnull readonly [[P:%.*]], i8 noundef [[V:%.*]]) #[[ATTR2:[0-9]+]] {
167; IS__CGSCC____-NEXT:    [[A:%.*]] = alloca i8, align 1
168; IS__CGSCC____-NEXT:    store i8 [[V]], i8* [[A]], align 1
169; IS__CGSCC____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
170; IS__CGSCC____:       t:
171; IS__CGSCC____-NEXT:    store i8 0, i8* [[A]], align 1
172; IS__CGSCC____-NEXT:    [[L:%.*]] = load i8, i8* [[P]], align 1
173; IS__CGSCC____-NEXT:    ret i8 [[L]]
174; IS__CGSCC____:       f:
175; IS__CGSCC____-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]+]]
176; IS__CGSCC____-NEXT:    ret i8 [[CALL]]
177;
178  %a = alloca i8
179  store i8 %v, i8* %a
180  br i1 %c, label %t, label %f
181t:
182  store i8 0, i8* %a
183  %l = load i8, i8* %p
184  ret i8 %l
185f:
186  %call = call i8 @recursive_alloca_load_return(i1 true, i8* %a, i8 1)
187  ret i8 %call
188}
189
190define i8 @recursive_alloca_load_return_caller(i1 %c) {
191; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind readnone
192; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_load_return_caller
193; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR2]] {
194; IS__TUNIT____-NEXT:    [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 [[C]], i8* undef, i8 noundef 42) #[[ATTR4]]
195; IS__TUNIT____-NEXT:    ret i8 [[CALL]]
196;
197; IS__CGSCC____: Function Attrs: nofree nosync nounwind readnone
198; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_load_return_caller
199; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR1]] {
200; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i8 @recursive_alloca_load_return(i1 [[C]], i8* undef, i8 noundef 42) #[[ATTR5:[0-9]+]]
201; IS__CGSCC____-NEXT:    ret i8 [[CALL]]
202;
203  %call = call i8 @recursive_alloca_load_return(i1 %c, i8* undef, i8 42)
204  ret i8 %call
205}
206
207@G1 = private global i1* undef
208@G2 = private global i1* undef
209@G3 = private global i1 undef
210
211; Make sure we do *not* return true.
212define internal i1 @recursive_alloca_compare_global1(i1 %c) {
213; IS__TUNIT____: Function Attrs: nofree nosync nounwind
214; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_compare_global1
215; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR4]] {
216; IS__TUNIT____-NEXT:    [[A:%.*]] = alloca i1, align 1
217; IS__TUNIT____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
218; IS__TUNIT____:       t:
219; IS__TUNIT____-NEXT:    [[P:%.*]] = load i1*, i1** @G1, align 8
220; IS__TUNIT____-NEXT:    [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
221; IS__TUNIT____-NEXT:    ret i1 [[CMP]]
222; IS__TUNIT____:       f:
223; IS__TUNIT____-NEXT:    store i1* [[A]], i1** @G1, align 8
224; IS__TUNIT____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 noundef true) #[[ATTR4]]
225; IS__TUNIT____-NEXT:    ret i1 [[CALL]]
226;
227; IS__CGSCC____: Function Attrs: nofree nosync nounwind
228; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_compare_global1
229; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
230; IS__CGSCC____-NEXT:    [[A:%.*]] = alloca i1, align 1
231; IS__CGSCC____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
232; IS__CGSCC____:       t:
233; IS__CGSCC____-NEXT:    [[P:%.*]] = load i1*, i1** @G1, align 8
234; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
235; IS__CGSCC____-NEXT:    ret i1 [[CMP]]
236; IS__CGSCC____:       f:
237; IS__CGSCC____-NEXT:    store i1* [[A]], i1** @G1, align 8
238; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 noundef true) #[[ATTR3]]
239; IS__CGSCC____-NEXT:    ret i1 [[CALL]]
240;
241  %a = alloca i1
242  br i1 %c, label %t, label %f
243t:
244  %p = load i1*, i1** @G1
245  %cmp = icmp eq i1* %a, %p
246  ret i1 %cmp
247f:
248  store i1* %a, i1** @G1
249  %call = call i1 @recursive_alloca_compare_global1(i1 true)
250  ret i1 %call
251}
252
253; FIXME: This should *not* return true.
254define i1 @recursive_alloca_compare_caller_global1(i1 %c) {
255; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind
256; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global1
257; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR5:[0-9]+]] {
258; IS__TUNIT____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 [[C]]) #[[ATTR4]]
259; IS__TUNIT____-NEXT:    ret i1 [[CALL]]
260;
261; IS__CGSCC____: Function Attrs: nofree nosync nounwind
262; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global1
263; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
264; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare_global1(i1 [[C]]) #[[ATTR5]]
265; IS__CGSCC____-NEXT:    ret i1 [[CALL]]
266;
267  %call = call i1 @recursive_alloca_compare_global1(i1 %c)
268  ret i1 %call
269}
270
271define internal i1 @recursive_alloca_compare_global2(i1 %c) {
272; IS__TUNIT____: Function Attrs: nofree nosync nounwind
273; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_compare_global2
274; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR4]] {
275; IS__TUNIT____-NEXT:    [[A:%.*]] = alloca i1, align 1
276; IS__TUNIT____-NEXT:    [[P:%.*]] = load i1*, i1** @G2, align 8
277; IS__TUNIT____-NEXT:    store i1* [[A]], i1** @G2, align 8
278; IS__TUNIT____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
279; IS__TUNIT____:       t:
280; IS__TUNIT____-NEXT:    [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
281; IS__TUNIT____-NEXT:    ret i1 [[CMP]]
282; IS__TUNIT____:       f:
283; IS__TUNIT____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 noundef true) #[[ATTR4]]
284; IS__TUNIT____-NEXT:    ret i1 [[CALL]]
285;
286; IS__CGSCC____: Function Attrs: nofree nosync nounwind
287; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_compare_global2
288; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
289; IS__CGSCC____-NEXT:    [[A:%.*]] = alloca i1, align 1
290; IS__CGSCC____-NEXT:    [[P:%.*]] = load i1*, i1** @G2, align 8
291; IS__CGSCC____-NEXT:    store i1* [[A]], i1** @G2, align 8
292; IS__CGSCC____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
293; IS__CGSCC____:       t:
294; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp eq i1* [[A]], [[P]]
295; IS__CGSCC____-NEXT:    ret i1 [[CMP]]
296; IS__CGSCC____:       f:
297; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 noundef true) #[[ATTR3]]
298; IS__CGSCC____-NEXT:    ret i1 [[CALL]]
299;
300  %a = alloca i1
301  %p = load i1*, i1** @G2
302  store i1* %a, i1** @G2
303  br i1 %c, label %t, label %f
304t:
305  %cmp = icmp eq i1* %a, %p
306  ret i1 %cmp
307f:
308  %call = call i1 @recursive_alloca_compare_global2(i1 true)
309  ret i1 %call
310}
311
312; FIXME: This should *not* return true.
313define i1 @recursive_alloca_compare_caller_global2(i1 %c) {
314; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind
315; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global2
316; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR5]] {
317; IS__TUNIT____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 [[C]]) #[[ATTR4]]
318; IS__TUNIT____-NEXT:    ret i1 [[CALL]]
319;
320; IS__CGSCC____: Function Attrs: nofree nosync nounwind
321; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_alloca_compare_caller_global2
322; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
323; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i1 @recursive_alloca_compare_global2(i1 [[C]]) #[[ATTR5]]
324; IS__CGSCC____-NEXT:    ret i1 [[CALL]]
325;
326  %call = call i1 @recursive_alloca_compare_global2(i1 %c)
327  ret i1 %call
328}
329define internal i1 @recursive_inst_compare_global3(i1 %c) {
330;
331; IS__TUNIT____: Function Attrs: nofree nosync nounwind
332; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_inst_compare_global3
333; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR4]] {
334; IS__TUNIT____-NEXT:    [[P:%.*]] = load i1, i1* @G3, align 1
335; IS__TUNIT____-NEXT:    store i1 [[C]], i1* @G3, align 1
336; IS__TUNIT____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
337; IS__TUNIT____:       t:
338; IS__TUNIT____-NEXT:    [[CMP:%.*]] = icmp eq i1 [[C]], [[P]]
339; IS__TUNIT____-NEXT:    ret i1 [[CMP]]
340; IS__TUNIT____:       f:
341; IS__TUNIT____-NEXT:    [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 noundef true) #[[ATTR4]]
342; IS__TUNIT____-NEXT:    ret i1 [[CALL]]
343;
344; IS__CGSCC____: Function Attrs: nofree nosync nounwind
345; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_inst_compare_global3
346; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
347; IS__CGSCC____-NEXT:    [[P:%.*]] = load i1, i1* @G3, align 1
348; IS__CGSCC____-NEXT:    store i1 [[C]], i1* @G3, align 1
349; IS__CGSCC____-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
350; IS__CGSCC____:       t:
351; IS__CGSCC____-NEXT:    [[CMP:%.*]] = icmp eq i1 [[C]], [[P]]
352; IS__CGSCC____-NEXT:    ret i1 [[CMP]]
353; IS__CGSCC____:       f:
354; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 noundef true) #[[ATTR3]]
355; IS__CGSCC____-NEXT:    ret i1 [[CALL]]
356;
357  %p = load i1, i1* @G3
358  store i1 %c, i1* @G3
359  br i1 %c, label %t, label %f
360t:
361  %cmp = icmp eq i1 %c, %p
362  ret i1 %cmp
363f:
364  %call = call i1 @recursive_inst_compare_global3(i1 true)
365  ret i1 %call
366}
367
368; FIXME: This should *not* return true.
369define i1 @recursive_inst_compare_caller_global3(i1 %c) {
370; IS__TUNIT____: Function Attrs: nofree norecurse nosync nounwind
371; IS__TUNIT____-LABEL: define {{[^@]+}}@recursive_inst_compare_caller_global3
372; IS__TUNIT____-SAME: (i1 [[C:%.*]]) #[[ATTR5]] {
373; IS__TUNIT____-NEXT:    [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 [[C]]) #[[ATTR4]]
374; IS__TUNIT____-NEXT:    ret i1 [[CALL]]
375;
376; IS__CGSCC____: Function Attrs: nofree nosync nounwind
377; IS__CGSCC____-LABEL: define {{[^@]+}}@recursive_inst_compare_caller_global3
378; IS__CGSCC____-SAME: (i1 [[C:%.*]]) #[[ATTR3]] {
379; IS__CGSCC____-NEXT:    [[CALL:%.*]] = call i1 @recursive_inst_compare_global3(i1 [[C]]) #[[ATTR5]]
380; IS__CGSCC____-NEXT:    ret i1 [[CALL]]
381;
382  %call = call i1 @recursive_inst_compare_global3(i1 %c)
383  ret i1 %call
384}
385;.
386; IS__TUNIT____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
387; IS__TUNIT____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone }
388; IS__TUNIT____: attributes #[[ATTR2]] = { nofree norecurse nosync nounwind readnone }
389; IS__TUNIT____: attributes #[[ATTR3]] = { argmemonly nofree nosync nounwind }
390; IS__TUNIT____: attributes #[[ATTR4]] = { nofree nosync nounwind }
391; IS__TUNIT____: attributes #[[ATTR5]] = { nofree norecurse nosync nounwind }
392; IS__TUNIT____: attributes #[[ATTR6]] = { nounwind readnone }
393;.
394; IS__CGSCC____: attributes #[[ATTR0]] = { nofree norecurse nosync nounwind readnone willreturn }
395; IS__CGSCC____: attributes #[[ATTR1]] = { nofree nosync nounwind readnone }
396; IS__CGSCC____: attributes #[[ATTR2]] = { argmemonly nofree nosync nounwind }
397; IS__CGSCC____: attributes #[[ATTR3]] = { nofree nosync nounwind }
398; IS__CGSCC____: attributes #[[ATTR4]] = { nounwind readnone }
399; IS__CGSCC____: attributes #[[ATTR5]] = { nounwind }
400;.
401