xref: /llvm-project/llvm/test/Transforms/Attributor/returned.ll (revision 29441e4f5fa5f5c7709f7cf180815ba97f611297)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --check-attributes --check-globals
2; RUN: opt -aa-pipeline=basic-aa -passes=attributor -attributor-manifest-internal  -attributor-annotate-decl-cs  -S < %s | FileCheck %s --check-prefixes=CHECK,TUNIT
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CHECK,CGSCC
4;
5; Test cases specifically designed for the "returned" argument attribute.
6; We use FIXME's to indicate problems and missing attributes.
7;
8
9; TEST SCC test returning an integer value argument
10;
11; int scc_r1(int a, int b, int r);
12; int scc_r2(int a, int b, int r);
13;
14; __attribute__((noinline)) int sink_r0(int r) {
15;   return r;
16; }
17;
18; __attribute__((noinline)) int scc_r1(int a, int r, int b) {
19;   return scc_r2(r, a, sink_r0(r));
20; }
21;
22; __attribute__((noinline)) int scc_r2(int a, int b, int r) {
23;   if (a > b)
24;     return scc_r2(b, a, sink_r0(r));
25;   if (a < b)
26;     return scc_r1(sink_r0(b), scc_r2(scc_r1(a, b, r), scc_r1(a, scc_r2(r, r, r), r), scc_r2(a, b, r)), scc_r1(a, b, r));
27;   return a == b ? r : scc_r2(a, b, r);
28; }
29; __attribute__((noinline)) int scc_rX(int a, int b, int r) {
30;   if (a > b)
31;     return scc_r2(b, a, sink_r0(r));
32;   if (a < b)                                                                         // V Diff to scc_r2
33;     return scc_r1(sink_r0(b), scc_r2(scc_r1(a, b, r), scc_r1(a, scc_r2(r, r, r), r), scc_r1(a, b, r)), scc_r1(a, b, r));
34;   return a == b ? r : scc_r2(a, b, r);
35; }
36target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
37
38;.
39; CHECK: @G = external global i8
40; CHECK: @_ZTI1X = external dso_local constant { ptr, ptr }, align 8
41; CHECK: @_ZTI1Y = external dso_local constant { ptr, ptr, ptr }, align 8
42;.
43define i32 @sink_r0(i32 %r) #0 {
44; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
45; CHECK-LABEL: define {{[^@]+}}@sink_r0
46; CHECK-SAME: (i32 returned [[R:%.*]]) #[[ATTR0:[0-9]+]] {
47; CHECK-NEXT:  entry:
48; CHECK-NEXT:    ret i32 [[R]]
49;
50entry:
51  ret i32 %r
52}
53
54define i32 @scc_r1(i32 %a, i32 %r, i32 %b) #0 {
55; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
56; TUNIT-LABEL: define {{[^@]+}}@scc_r1
57; TUNIT-SAME: (i32 [[A:%.*]], i32 returned [[R:%.*]], i32 [[B:%.*]]) #[[ATTR1:[0-9]+]] {
58; TUNIT-NEXT:  entry:
59; TUNIT-NEXT:    [[CALL1:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[A]], i32 [[R]]) #[[ATTR8:[0-9]+]]
60; TUNIT-NEXT:    ret i32 [[R]]
61;
62; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
63; CGSCC-LABEL: define {{[^@]+}}@scc_r1
64; CGSCC-SAME: (i32 [[A:%.*]], i32 returned [[R:%.*]], i32 [[B:%.*]]) #[[ATTR1:[0-9]+]] {
65; CGSCC-NEXT:  entry:
66; CGSCC-NEXT:    [[CALL1:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[A]], i32 [[R]]) #[[ATTR7:[0-9]+]]
67; CGSCC-NEXT:    ret i32 [[R]]
68;
69entry:
70  %call = call i32 @sink_r0(i32 %r)
71  %call1 = call i32 @scc_r2(i32 %r, i32 %a, i32 %call)
72  ret i32 %call1
73}
74
75define i32 @scc_r2(i32 %a, i32 %b, i32 %r) #0 {
76; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
77; TUNIT-LABEL: define {{[^@]+}}@scc_r2
78; TUNIT-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 returned [[R:%.*]]) #[[ATTR1]] {
79; TUNIT-NEXT:  entry:
80; TUNIT-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]]
81; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
82; TUNIT:       if.then:
83; TUNIT-NEXT:    [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR8]]
84; TUNIT-NEXT:    br label [[RETURN:%.*]]
85; TUNIT:       if.end:
86; TUNIT-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]]
87; TUNIT-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]]
88; TUNIT:       if.then3:
89; TUNIT-NEXT:    [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR8]]
90; TUNIT-NEXT:    [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR8]]
91; TUNIT-NEXT:    [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 undef) #[[ATTR8]]
92; TUNIT-NEXT:    [[CALL8:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR8]]
93; TUNIT-NEXT:    [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[R]]) #[[ATTR8]]
94; TUNIT-NEXT:    [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[R]], i32 undef) #[[ATTR8]]
95; TUNIT-NEXT:    br label [[RETURN]]
96; TUNIT:       if.end12:
97; TUNIT-NEXT:    [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]]
98; TUNIT-NEXT:    br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
99; TUNIT:       cond.true:
100; TUNIT-NEXT:    br label [[COND_END:%.*]]
101; TUNIT:       cond.false:
102; TUNIT-NEXT:    [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR8]]
103; TUNIT-NEXT:    br label [[COND_END]]
104; TUNIT:       cond.end:
105; TUNIT-NEXT:    [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ]
106; TUNIT-NEXT:    br label [[RETURN]]
107; TUNIT:       return:
108; TUNIT-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[R]], [[COND_END]] ]
109; TUNIT-NEXT:    ret i32 [[R]]
110;
111; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
112; CGSCC-LABEL: define {{[^@]+}}@scc_r2
113; CGSCC-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 returned [[R:%.*]]) #[[ATTR1]] {
114; CGSCC-NEXT:  entry:
115; CGSCC-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]]
116; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
117; CGSCC:       if.then:
118; CGSCC-NEXT:    [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR7]]
119; CGSCC-NEXT:    br label [[RETURN:%.*]]
120; CGSCC:       if.end:
121; CGSCC-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]]
122; CGSCC-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]]
123; CGSCC:       if.then3:
124; CGSCC-NEXT:    [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR7]]
125; CGSCC-NEXT:    [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR7]]
126; CGSCC-NEXT:    [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 undef) #[[ATTR7]]
127; CGSCC-NEXT:    [[CALL8:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]]
128; CGSCC-NEXT:    [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[R]]) #[[ATTR7]]
129; CGSCC-NEXT:    [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[R]], i32 undef) #[[ATTR7]]
130; CGSCC-NEXT:    br label [[RETURN]]
131; CGSCC:       if.end12:
132; CGSCC-NEXT:    [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]]
133; CGSCC-NEXT:    br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
134; CGSCC:       cond.true:
135; CGSCC-NEXT:    br label [[COND_END:%.*]]
136; CGSCC:       cond.false:
137; CGSCC-NEXT:    [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]]
138; CGSCC-NEXT:    br label [[COND_END]]
139; CGSCC:       cond.end:
140; CGSCC-NEXT:    [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ]
141; CGSCC-NEXT:    br label [[RETURN]]
142; CGSCC:       return:
143; CGSCC-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[R]], [[COND_END]] ]
144; CGSCC-NEXT:    ret i32 [[R]]
145;
146entry:
147  %cmp = icmp sgt i32 %a, %b
148  br i1 %cmp, label %if.then, label %if.end
149
150if.then:                                          ; preds = %entry
151  %call = call i32 @sink_r0(i32 %r)
152  %call1 = call i32 @scc_r2(i32 %b, i32 %a, i32 %call)
153  br label %return
154
155if.end:                                           ; preds = %entry
156  %cmp2 = icmp slt i32 %a, %b
157  br i1 %cmp2, label %if.then3, label %if.end12
158
159if.then3:                                         ; preds = %if.end
160  %call4 = call i32 @sink_r0(i32 %b)
161  %call5 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
162  %call6 = call i32 @scc_r2(i32 %r, i32 %r, i32 %r)
163  %call7 = call i32 @scc_r1(i32 %a, i32 %call6, i32 %r)
164  %call8 = call i32 @scc_r2(i32 %a, i32 %b, i32 %r)
165  %call9 = call i32 @scc_r2(i32 %call5, i32 %call7, i32 %call8)
166  %call10 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
167  %call11 = call i32 @scc_r1(i32 %call4, i32 %call9, i32 %call10)
168  br label %return
169
170if.end12:                                         ; preds = %if.end
171  %cmp13 = icmp eq i32 %a, %b
172  br i1 %cmp13, label %cond.true, label %cond.false
173
174cond.true:                                        ; preds = %if.end12
175  br label %cond.end
176
177cond.false:                                       ; preds = %if.end12
178  %call14 = call i32 @scc_r2(i32 %a, i32 %b, i32 %r)
179  br label %cond.end
180
181cond.end:                                         ; preds = %cond.false, %cond.true
182  %cond = phi i32 [ %r, %cond.true ], [ %call14, %cond.false ]
183  br label %return
184
185return:                                           ; preds = %cond.end, %if.then3, %if.then
186  %retval.0 = phi i32 [ %call1, %if.then ], [ %call11, %if.then3 ], [ %cond, %cond.end ]
187  ret i32 %retval.0
188}
189
190define i32 @scc_rX(i32 %a, i32 %b, i32 %r) #0 {
191; TUNIT: Function Attrs: nofree noinline norecurse nosync nounwind memory(none) uwtable
192; TUNIT-LABEL: define {{[^@]+}}@scc_rX
193; TUNIT-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[R:%.*]]) #[[ATTR2:[0-9]+]] {
194; TUNIT-NEXT:  entry:
195; TUNIT-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]]
196; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
197; TUNIT:       if.then:
198; TUNIT-NEXT:    [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR8]]
199; TUNIT-NEXT:    br label [[RETURN:%.*]]
200; TUNIT:       if.end:
201; TUNIT-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]]
202; TUNIT-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]]
203; TUNIT:       if.then3:
204; TUNIT-NEXT:    [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR8]]
205; TUNIT-NEXT:    [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR8]]
206; TUNIT-NEXT:    [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 undef) #[[ATTR8]]
207; TUNIT-NEXT:    [[CALL8:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 undef) #[[ATTR8]]
208; TUNIT-NEXT:    [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[B]]) #[[ATTR8]]
209; TUNIT-NEXT:    [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[B]], i32 undef) #[[ATTR8]]
210; TUNIT-NEXT:    br label [[RETURN]]
211; TUNIT:       if.end12:
212; TUNIT-NEXT:    [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]]
213; TUNIT-NEXT:    br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
214; TUNIT:       cond.true:
215; TUNIT-NEXT:    br label [[COND_END:%.*]]
216; TUNIT:       cond.false:
217; TUNIT-NEXT:    [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR8]]
218; TUNIT-NEXT:    br label [[COND_END]]
219; TUNIT:       cond.end:
220; TUNIT-NEXT:    [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ]
221; TUNIT-NEXT:    br label [[RETURN]]
222; TUNIT:       return:
223; TUNIT-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[R]], [[IF_THEN]] ], [ [[B]], [[IF_THEN3]] ], [ [[R]], [[COND_END]] ]
224; TUNIT-NEXT:    ret i32 [[RETVAL_0]]
225;
226; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
227; CGSCC-LABEL: define {{[^@]+}}@scc_rX
228; CGSCC-SAME: (i32 [[A:%.*]], i32 [[B:%.*]], i32 [[R:%.*]]) #[[ATTR1]] {
229; CGSCC-NEXT:  entry:
230; CGSCC-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], [[B]]
231; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
232; CGSCC:       if.then:
233; CGSCC-NEXT:    [[CALL1:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[A]], i32 [[R]]) #[[ATTR7]]
234; CGSCC-NEXT:    br label [[RETURN:%.*]]
235; CGSCC:       if.end:
236; CGSCC-NEXT:    [[CMP2:%.*]] = icmp slt i32 [[A]], [[B]]
237; CGSCC-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]]
238; CGSCC:       if.then3:
239; CGSCC-NEXT:    [[CALL5:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]]
240; CGSCC-NEXT:    [[CALL6:%.*]] = call i32 @scc_r2(i32 [[R]], i32 [[R]], i32 [[R]]) #[[ATTR7]]
241; CGSCC-NEXT:    [[CALL7:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[R]], i32 [[R]]) #[[ATTR7]]
242; CGSCC-NEXT:    [[CALL8:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]]
243; CGSCC-NEXT:    [[CALL9:%.*]] = call i32 @scc_r2(i32 [[B]], i32 [[R]], i32 [[B]]) #[[ATTR7]]
244; CGSCC-NEXT:    [[CALL10:%.*]] = call i32 @scc_r1(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]]
245; CGSCC-NEXT:    [[CALL11:%.*]] = call i32 @scc_r1(i32 [[B]], i32 [[B]], i32 [[B]]) #[[ATTR7]]
246; CGSCC-NEXT:    br label [[RETURN]]
247; CGSCC:       if.end12:
248; CGSCC-NEXT:    [[CMP13:%.*]] = icmp eq i32 [[A]], [[B]]
249; CGSCC-NEXT:    br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
250; CGSCC:       cond.true:
251; CGSCC-NEXT:    br label [[COND_END:%.*]]
252; CGSCC:       cond.false:
253; CGSCC-NEXT:    [[CALL14:%.*]] = call i32 @scc_r2(i32 [[A]], i32 [[B]], i32 [[R]]) #[[ATTR7]]
254; CGSCC-NEXT:    br label [[COND_END]]
255; CGSCC:       cond.end:
256; CGSCC-NEXT:    [[COND:%.*]] = phi i32 [ [[R]], [[COND_TRUE]] ], [ [[CALL14]], [[COND_FALSE]] ]
257; CGSCC-NEXT:    br label [[RETURN]]
258; CGSCC:       return:
259; CGSCC-NEXT:    [[RETVAL_0:%.*]] = phi i32 [ [[CALL1]], [[IF_THEN]] ], [ [[CALL11]], [[IF_THEN3]] ], [ [[R]], [[COND_END]] ]
260; CGSCC-NEXT:    ret i32 [[RETVAL_0]]
261;
262entry:
263  %cmp = icmp sgt i32 %a, %b
264  br i1 %cmp, label %if.then, label %if.end
265
266if.then:                                          ; preds = %entry
267  %call = call i32 @sink_r0(i32 %r)
268  %call1 = call i32 @scc_r2(i32 %b, i32 %a, i32 %call)
269  br label %return
270
271if.end:                                           ; preds = %entry
272  %cmp2 = icmp slt i32 %a, %b
273  br i1 %cmp2, label %if.then3, label %if.end12
274
275if.then3:                                         ; preds = %if.end
276  %call4 = call i32 @sink_r0(i32 %b)
277  %call5 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
278  %call6 = call i32 @scc_r2(i32 %r, i32 %r, i32 %r)
279  %call7 = call i32 @scc_r1(i32 %a, i32 %call6, i32 %r)
280  %call8 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
281  %call9 = call i32 @scc_r2(i32 %call5, i32 %call7, i32 %call8)
282  %call10 = call i32 @scc_r1(i32 %a, i32 %b, i32 %r)
283  %call11 = call i32 @scc_r1(i32 %call4, i32 %call9, i32 %call10)
284  br label %return
285
286if.end12:                                         ; preds = %if.end
287  %cmp13 = icmp eq i32 %a, %b
288  br i1 %cmp13, label %cond.true, label %cond.false
289
290cond.true:                                        ; preds = %if.end12
291  br label %cond.end
292
293cond.false:                                       ; preds = %if.end12
294  %call14 = call i32 @scc_r2(i32 %a, i32 %b, i32 %r)
295  br label %cond.end
296
297cond.end:                                         ; preds = %cond.false, %cond.true
298  %cond = phi i32 [ %r, %cond.true ], [ %call14, %cond.false ]
299  br label %return
300
301return:                                           ; preds = %cond.end, %if.then3, %if.then
302  %retval.0 = phi i32 [ %call1, %if.then ], [ %call11, %if.then3 ], [ %cond, %cond.end ]
303  ret i32 %retval.0
304}
305
306
307; TEST SCC test returning a pointer value argument
308;
309; double* ptr_scc_r1(double* a, double* b, double* r);
310; double* ptr_scc_r2(double* a, double* b, double* r);
311;
312; __attribute__((noinline)) double* ptr_sink_r0(double* r) {
313;   return r;
314; }
315;
316; __attribute__((noinline)) double* ptr_scc_r1(double* a, double* r, double* b) {
317;   return ptr_scc_r2(r, a, ptr_sink_r0(r));
318; }
319;
320; __attribute__((noinline)) double* ptr_scc_r2(double* a, double* b, double* r) {
321;   if (a > b)
322;     return ptr_scc_r2(b, a, ptr_sink_r0(r));
323;   if (a < b)
324;     return ptr_scc_r1(ptr_sink_r0(b), ptr_scc_r2(ptr_scc_r1(a, b, r), ptr_scc_r1(a, ptr_scc_r2(r, r, r), r), ptr_scc_r2(a, b, r)), ptr_scc_r1(a, b, r));
325;   return a == b ? r : ptr_scc_r2(a, b, r);
326; }
327define ptr @ptr_sink_r0(ptr %r) #0 {
328; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
329; CHECK-LABEL: define {{[^@]+}}@ptr_sink_r0
330; CHECK-SAME: (ptr nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR0]] {
331; CHECK-NEXT:  entry:
332; CHECK-NEXT:    ret ptr [[R]]
333;
334entry:
335  ret ptr %r
336}
337
338define ptr @ptr_scc_r1(ptr %a, ptr %r, ptr %b) #0 {
339; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
340; TUNIT-LABEL: define {{[^@]+}}@ptr_scc_r1
341; TUNIT-SAME: (ptr nofree readnone captures(none) [[A:%.*]], ptr nofree readnone returned "no-capture-maybe-returned" [[R:%.*]], ptr nofree readnone captures(none) [[B:%.*]]) #[[ATTR1]] {
342; TUNIT-NEXT:  entry:
343; TUNIT-NEXT:    [[CALL1:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[R]], ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR8]]
344; TUNIT-NEXT:    ret ptr [[R]]
345;
346; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
347; CGSCC-LABEL: define {{[^@]+}}@ptr_scc_r1
348; CGSCC-SAME: (ptr nofree readnone captures(none) [[A:%.*]], ptr nofree readnone returned [[R:%.*]], ptr nofree readnone captures(none) [[B:%.*]]) #[[ATTR1]] {
349; CGSCC-NEXT:  entry:
350; CGSCC-NEXT:    [[CALL1:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[R]], ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone [[R]]) #[[ATTR7]]
351; CGSCC-NEXT:    ret ptr [[R]]
352;
353entry:
354  %call = call ptr @ptr_sink_r0(ptr %r)
355  %call1 = call ptr @ptr_scc_r2(ptr %r, ptr %a, ptr %call)
356  ret ptr %call1
357}
358
359define ptr @ptr_scc_r2(ptr %a, ptr %b, ptr %r) #0 {
360; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
361; TUNIT-LABEL: define {{[^@]+}}@ptr_scc_r2
362; TUNIT-SAME: (ptr nofree readnone captures(none) [[A:%.*]], ptr nofree readnone captures(none) [[B:%.*]], ptr nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR1]] {
363; TUNIT-NEXT:  entry:
364; TUNIT-NEXT:    [[CMP:%.*]] = icmp ugt ptr [[A]], [[B]]
365; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
366; TUNIT:       if.then:
367; TUNIT-NEXT:    [[CALL1:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[B]], ptr noalias nofree nonnull readnone captures(none) [[A]], ptr noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR8]]
368; TUNIT-NEXT:    br label [[RETURN:%.*]]
369; TUNIT:       if.end:
370; TUNIT-NEXT:    [[CMP2:%.*]] = icmp ult ptr [[A]], [[B]]
371; TUNIT-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]]
372; TUNIT:       if.then3:
373; TUNIT-NEXT:    [[CALL5:%.*]] = call ptr @ptr_scc_r1(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree nonnull readnone "no-capture-maybe-returned" [[B]], ptr noalias nofree readnone captures(none) undef) #[[ATTR8]]
374; TUNIT-NEXT:    [[CALL6:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[R]], ptr noalias nofree readnone captures(none) [[R]], ptr noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR8]]
375; TUNIT-NEXT:    [[CALL7:%.*]] = call ptr @ptr_scc_r1(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone "no-capture-maybe-returned" [[R]], ptr noalias nofree readnone captures(none) undef) #[[ATTR8]]
376; TUNIT-NEXT:    [[CALL8:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree nonnull readnone captures(none) [[B]], ptr noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR8]]
377; TUNIT-NEXT:    [[CALL9:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[B]], ptr noalias nofree readnone captures(none) [[R]], ptr noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR8]]
378; TUNIT-NEXT:    [[CALL11:%.*]] = call ptr @ptr_scc_r1(ptr noalias nofree readnone captures(none) [[B]], ptr noalias nofree readnone "no-capture-maybe-returned" [[R]], ptr noalias nofree readnone captures(none) undef) #[[ATTR8]]
379; TUNIT-NEXT:    br label [[RETURN]]
380; TUNIT:       if.end12:
381; TUNIT-NEXT:    [[CMP13:%.*]] = icmp eq ptr [[A]], [[B]]
382; TUNIT-NEXT:    br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
383; TUNIT:       cond.true:
384; TUNIT-NEXT:    br label [[COND_END:%.*]]
385; TUNIT:       cond.false:
386; TUNIT-NEXT:    [[CALL14:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone captures(none) [[B]], ptr noalias nofree readnone "no-capture-maybe-returned" [[R]]) #[[ATTR8]]
387; TUNIT-NEXT:    br label [[COND_END]]
388; TUNIT:       cond.end:
389; TUNIT-NEXT:    [[COND:%.*]] = phi ptr [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ]
390; TUNIT-NEXT:    br label [[RETURN]]
391; TUNIT:       return:
392; TUNIT-NEXT:    [[RETVAL_0:%.*]] = phi ptr [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[R]], [[COND_END]] ]
393; TUNIT-NEXT:    ret ptr [[R]]
394;
395; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
396; CGSCC-LABEL: define {{[^@]+}}@ptr_scc_r2
397; CGSCC-SAME: (ptr nofree readnone captures(none) [[A:%.*]], ptr nofree readnone captures(none) [[B:%.*]], ptr nofree readnone returned [[R:%.*]]) #[[ATTR1]] {
398; CGSCC-NEXT:  entry:
399; CGSCC-NEXT:    [[CMP:%.*]] = icmp ugt ptr [[A]], [[B]]
400; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
401; CGSCC:       if.then:
402; CGSCC-NEXT:    [[CALL1:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[B]], ptr noalias nofree nonnull readnone captures(none) [[A]], ptr noalias nofree readnone [[R]]) #[[ATTR7]]
403; CGSCC-NEXT:    br label [[RETURN:%.*]]
404; CGSCC:       if.end:
405; CGSCC-NEXT:    [[CMP2:%.*]] = icmp ult ptr [[A]], [[B]]
406; CGSCC-NEXT:    br i1 [[CMP2]], label [[IF_THEN3:%.*]], label [[IF_END12:%.*]]
407; CGSCC:       if.then3:
408; CGSCC-NEXT:    [[CALL5:%.*]] = call ptr @ptr_scc_r1(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree nonnull readnone [[B]], ptr noalias nofree readnone captures(none) undef) #[[ATTR7]]
409; CGSCC-NEXT:    [[CALL6:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[R]], ptr noalias nofree readnone captures(none) [[R]], ptr noalias nofree readnone [[R]]) #[[ATTR7]]
410; CGSCC-NEXT:    [[CALL7:%.*]] = call ptr @ptr_scc_r1(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone [[R]], ptr noalias nofree readnone captures(none) undef) #[[ATTR7]]
411; CGSCC-NEXT:    [[CALL8:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree nonnull readnone captures(none) [[B]], ptr noalias nofree readnone [[R]]) #[[ATTR7]]
412; CGSCC-NEXT:    [[CALL9:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[B]], ptr noalias nofree readnone captures(none) [[R]], ptr noalias nofree readnone [[R]]) #[[ATTR7]]
413; CGSCC-NEXT:    [[CALL11:%.*]] = call ptr @ptr_scc_r1(ptr noalias nofree nonnull readnone captures(none) [[B]], ptr noalias nofree readnone [[R]], ptr noalias nofree readnone captures(none) undef) #[[ATTR7]]
414; CGSCC-NEXT:    br label [[RETURN]]
415; CGSCC:       if.end12:
416; CGSCC-NEXT:    [[CMP13:%.*]] = icmp eq ptr [[A]], [[B]]
417; CGSCC-NEXT:    br i1 [[CMP13]], label [[COND_TRUE:%.*]], label [[COND_FALSE:%.*]]
418; CGSCC:       cond.true:
419; CGSCC-NEXT:    br label [[COND_END:%.*]]
420; CGSCC:       cond.false:
421; CGSCC-NEXT:    [[CALL14:%.*]] = call ptr @ptr_scc_r2(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone captures(none) [[B]], ptr noalias nofree readnone [[R]]) #[[ATTR7]]
422; CGSCC-NEXT:    br label [[COND_END]]
423; CGSCC:       cond.end:
424; CGSCC-NEXT:    [[COND:%.*]] = phi ptr [ [[R]], [[COND_TRUE]] ], [ [[R]], [[COND_FALSE]] ]
425; CGSCC-NEXT:    br label [[RETURN]]
426; CGSCC:       return:
427; CGSCC-NEXT:    [[RETVAL_0:%.*]] = phi ptr [ [[R]], [[IF_THEN]] ], [ [[R]], [[IF_THEN3]] ], [ [[R]], [[COND_END]] ]
428; CGSCC-NEXT:    ret ptr [[R]]
429;
430entry:
431  %cmp = icmp ugt ptr %a, %b
432  br i1 %cmp, label %if.then, label %if.end
433
434if.then:                                          ; preds = %entry
435  %call = call ptr @ptr_sink_r0(ptr %r)
436  %call1 = call ptr @ptr_scc_r2(ptr %b, ptr %a, ptr %call)
437  br label %return
438
439if.end:                                           ; preds = %entry
440  %cmp2 = icmp ult ptr %a, %b
441  br i1 %cmp2, label %if.then3, label %if.end12
442
443if.then3:                                         ; preds = %if.end
444  %call4 = call ptr @ptr_sink_r0(ptr %b)
445  %call5 = call ptr @ptr_scc_r1(ptr %a, ptr %b, ptr %r)
446  %call6 = call ptr @ptr_scc_r2(ptr %r, ptr %r, ptr %r)
447  %call7 = call ptr @ptr_scc_r1(ptr %a, ptr %call6, ptr %r)
448  %call8 = call ptr @ptr_scc_r2(ptr %a, ptr %b, ptr %r)
449  %call9 = call ptr @ptr_scc_r2(ptr %call5, ptr %call7, ptr %call8)
450  %call10 = call ptr @ptr_scc_r1(ptr %a, ptr %b, ptr %r)
451  %call11 = call ptr @ptr_scc_r1(ptr %call4, ptr %call9, ptr %call10)
452  br label %return
453
454if.end12:                                         ; preds = %if.end
455  %cmp13 = icmp eq ptr %a, %b
456  br i1 %cmp13, label %cond.true, label %cond.false
457
458cond.true:                                        ; preds = %if.end12
459  br label %cond.end
460
461cond.false:                                       ; preds = %if.end12
462  %call14 = call ptr @ptr_scc_r2(ptr %a, ptr %b, ptr %r)
463  br label %cond.end
464
465cond.end:                                         ; preds = %cond.false, %cond.true
466  %cond = phi ptr [ %r, %cond.true ], [ %call14, %cond.false ]
467  br label %return
468
469return:                                           ; preds = %cond.end, %if.then3, %if.then
470  %retval.0 = phi ptr [ %call1, %if.then ], [ %call11, %if.then3 ], [ %cond, %cond.end ]
471  ret ptr %retval.0
472}
473
474
475; TEST a no-return singleton SCC
476;
477; int* rt0(int *a) {
478;   return *a ? a : rt0(a);
479; }
480;
481define ptr @rt0(ptr %a) #0 {
482; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(argmem: read) uwtable
483; TUNIT-LABEL: define {{[^@]+}}@rt0
484; TUNIT-SAME: (ptr nofree noundef nonnull readonly returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR3:[0-9]+]] {
485; TUNIT-NEXT:  entry:
486; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @rt0(ptr nofree noundef nonnull readonly align 4 dereferenceable(4) "no-capture-maybe-returned" [[A]]) #[[ATTR10:[0-9]+]]
487; TUNIT-NEXT:    ret ptr [[A]]
488;
489; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(argmem: read) uwtable
490; CGSCC-LABEL: define {{[^@]+}}@rt0
491; CGSCC-SAME: (ptr nofree noundef nonnull readonly returned align 4 dereferenceable(4) "no-capture-maybe-returned" [[A:%.*]]) #[[ATTR2:[0-9]+]] {
492; CGSCC-NEXT:  entry:
493; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @rt0(ptr nofree noundef nonnull readonly align 4 dereferenceable(4) "no-capture-maybe-returned" [[A]]) #[[ATTR8:[0-9]+]]
494; CGSCC-NEXT:    ret ptr [[A]]
495;
496entry:
497  %v = load i32, ptr %a, align 4
498  %tobool = icmp ne i32 %v, 0
499  %call = call ptr @rt0(ptr %a)
500  %sel = select i1 %tobool, ptr %a, ptr %call
501  ret ptr %sel
502}
503
504; TEST a no-return singleton SCC
505;
506; int* rt1(int *a) {
507;   return *a ? undef : rt1(a);
508; }
509;
510define ptr @rt1(ptr %a) #0 {
511; TUNIT: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
512; TUNIT-LABEL: define {{[^@]+}}@rt1
513; TUNIT-SAME: (ptr nofree nonnull readnone align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR4:[0-9]+]] {
514; TUNIT-NEXT:  entry:
515; TUNIT-NEXT:    ret ptr undef
516;
517; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
518; CGSCC-LABEL: define {{[^@]+}}@rt1
519; CGSCC-SAME: (ptr nofree nonnull readnone align 4 captures(none) dereferenceable(4) [[A:%.*]]) #[[ATTR3:[0-9]+]] {
520; CGSCC-NEXT:  entry:
521; CGSCC-NEXT:    ret ptr undef
522;
523entry:
524  %v = load i32, ptr %a, align 4
525  %tobool = icmp ne i32 %v, 0
526  %call = call ptr @rt1(ptr %a)
527  %sel = select i1 %tobool, ptr undef, ptr %call
528  ret ptr %sel
529}
530
531; TEST another SCC test
532;
533define ptr @rt2_helper(ptr %a) #0 {
534; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
535; TUNIT-LABEL: define {{[^@]+}}@rt2_helper
536; TUNIT-SAME: (ptr nofree readnone returned [[A:%.*]]) #[[ATTR1]] {
537; TUNIT-NEXT:  entry:
538; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @rt2(ptr noalias nofree readnone [[A]], ptr noalias nofree readnone "no-capture-maybe-returned" [[A]]) #[[ATTR8]]
539; TUNIT-NEXT:    ret ptr [[A]]
540;
541; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
542; CGSCC-LABEL: define {{[^@]+}}@rt2_helper
543; CGSCC-SAME: (ptr nofree readnone returned [[A:%.*]]) #[[ATTR1]] {
544; CGSCC-NEXT:  entry:
545; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @rt2(ptr noalias nofree readnone [[A]], ptr noalias nofree readnone "no-capture-maybe-returned" [[A]]) #[[ATTR7]]
546; CGSCC-NEXT:    ret ptr [[A]]
547;
548entry:
549  %call = call ptr @rt2(ptr %a, ptr %a)
550  ret ptr %call
551}
552
553define ptr @rt2(ptr %a, ptr %b) #0 {
554; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
555; TUNIT-LABEL: define {{[^@]+}}@rt2
556; TUNIT-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] {
557; TUNIT-NEXT:  entry:
558; TUNIT-NEXT:    [[CMP:%.*]] = icmp eq ptr [[A]], null
559; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
560; TUNIT:       if.then:
561; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @rt2_helper(ptr noalias nofree readnone [[A]]) #[[ATTR8]]
562; TUNIT-NEXT:    br label [[IF_END]]
563; TUNIT:       if.end:
564; TUNIT-NEXT:    [[SEL:%.*]] = phi ptr [ [[B]], [[ENTRY:%.*]] ], [ [[A]], [[IF_THEN]] ]
565; TUNIT-NEXT:    ret ptr [[SEL]]
566;
567; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
568; CGSCC-LABEL: define {{[^@]+}}@rt2
569; CGSCC-SAME: (ptr nofree readnone [[A:%.*]], ptr nofree readnone "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] {
570; CGSCC-NEXT:  entry:
571; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq ptr [[A]], null
572; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
573; CGSCC:       if.then:
574; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @rt2_helper(ptr noalias nofree readnone [[A]]) #[[ATTR7]]
575; CGSCC-NEXT:    br label [[IF_END]]
576; CGSCC:       if.end:
577; CGSCC-NEXT:    [[SEL:%.*]] = phi ptr [ [[B]], [[ENTRY:%.*]] ], [ [[A]], [[IF_THEN]] ]
578; CGSCC-NEXT:    ret ptr [[SEL]]
579;
580entry:
581  %cmp = icmp eq ptr %a, null
582  br i1 %cmp, label %if.then, label %if.end
583
584if.then:
585  %call = call ptr @rt2_helper(ptr %a)
586  br label %if.end
587
588if.end:
589  %sel = phi ptr [ %b, %entry], [%call, %if.then]
590  ret ptr %sel
591}
592
593; TEST another SCC test
594;
595define ptr @rt3_helper(ptr %a, ptr %b) #0 {
596; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
597; TUNIT-LABEL: define {{[^@]+}}@rt3_helper
598; TUNIT-SAME: (ptr nofree readnone captures(none) [[A:%.*]], ptr nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] {
599; TUNIT-NEXT:  entry:
600; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @rt3(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR8]]
601; TUNIT-NEXT:    ret ptr [[B]]
602;
603; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
604; CGSCC-LABEL: define {{[^@]+}}@rt3_helper
605; CGSCC-SAME: (ptr nofree readnone captures(none) [[A:%.*]], ptr nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] {
606; CGSCC-NEXT:  entry:
607; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @rt3(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR7]]
608; CGSCC-NEXT:    ret ptr [[B]]
609;
610entry:
611  %call = call ptr @rt3(ptr %a, ptr %b)
612  ret ptr %call
613}
614
615define ptr @rt3(ptr %a, ptr %b) #0 {
616; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
617; TUNIT-LABEL: define {{[^@]+}}@rt3
618; TUNIT-SAME: (ptr nofree readnone captures(none) [[A:%.*]], ptr nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] {
619; TUNIT-NEXT:  entry:
620; TUNIT-NEXT:    [[CMP:%.*]] = icmp eq ptr [[A]], null
621; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
622; TUNIT:       if.then:
623; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @rt3_helper(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR8]]
624; TUNIT-NEXT:    br label [[IF_END]]
625; TUNIT:       if.end:
626; TUNIT-NEXT:    [[SEL:%.*]] = phi ptr [ [[B]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ]
627; TUNIT-NEXT:    ret ptr [[B]]
628;
629; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
630; CGSCC-LABEL: define {{[^@]+}}@rt3
631; CGSCC-SAME: (ptr nofree readnone captures(none) [[A:%.*]], ptr nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR1]] {
632; CGSCC-NEXT:  entry:
633; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq ptr [[A]], null
634; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
635; CGSCC:       if.then:
636; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @rt3_helper(ptr noalias nofree readnone captures(none) [[A]], ptr noalias nofree readnone "no-capture-maybe-returned" [[B]]) #[[ATTR7]]
637; CGSCC-NEXT:    br label [[IF_END]]
638; CGSCC:       if.end:
639; CGSCC-NEXT:    [[SEL:%.*]] = phi ptr [ [[B]], [[ENTRY:%.*]] ], [ [[B]], [[IF_THEN]] ]
640; CGSCC-NEXT:    ret ptr [[B]]
641;
642entry:
643  %cmp = icmp eq ptr %a, null
644  br i1 %cmp, label %if.then, label %if.end
645
646if.then:
647  %call = call ptr @rt3_helper(ptr %a, ptr %b)
648  br label %if.end
649
650if.end:
651  %sel = phi ptr [ %b, %entry], [%call, %if.then]
652  ret ptr %sel
653}
654
655; TEST address taken function with call to an external functions
656;
657;  void unknown_fn(void *);
658;
659;  int* calls_unknown_fn(int *r) {
660;    unknown_fn(&calls_unknown_fn);
661;    return r;
662;  }
663;
664declare void @unknown_fn(ptr) #0
665
666define ptr @calls_unknown_fn(ptr %r) #0 {
667; TUNIT: Function Attrs: noinline nounwind uwtable
668; TUNIT-LABEL: define {{[^@]+}}@calls_unknown_fn
669; TUNIT-SAME: (ptr nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR5:[0-9]+]] {
670; TUNIT-NEXT:    tail call void @unknown_fn(ptr noundef nonnull @calls_unknown_fn) #[[ATTR11:[0-9]+]]
671; TUNIT-NEXT:    ret ptr [[R]]
672;
673; CGSCC: Function Attrs: noinline nounwind uwtable
674; CGSCC-LABEL: define {{[^@]+}}@calls_unknown_fn
675; CGSCC-SAME: (ptr nofree readnone returned "no-capture-maybe-returned" [[R:%.*]]) #[[ATTR4:[0-9]+]] {
676; CGSCC-NEXT:    tail call void @unknown_fn(ptr noundef nonnull @calls_unknown_fn) #[[ATTR9:[0-9]+]]
677; CGSCC-NEXT:    ret ptr [[R]]
678;
679  tail call void @unknown_fn(ptr nonnull @calls_unknown_fn)
680  ret ptr %r
681}
682
683
684; TEST call to a function that might be redifined at link time
685;
686;  int *maybe_redefined_fn(int *r) {
687;    return r;
688;  }
689;
690;  int *calls_maybe_redefined_fn(int *r) {
691;    maybe_redefined_fn(r);
692;    return r;
693;  }
694;
695; Verify the maybe-redefined function is not annotated:
696;
697define linkonce_odr ptr @maybe_redefined_fn(ptr %r) #0 {
698; TUNIT: Function Attrs: noinline nounwind uwtable
699; TUNIT-LABEL: define {{[^@]+}}@maybe_redefined_fn
700; TUNIT-SAME: (ptr [[R:%.*]]) #[[ATTR5]] {
701; TUNIT-NEXT:  entry:
702; TUNIT-NEXT:    ret ptr [[R]]
703;
704; CGSCC: Function Attrs: noinline nounwind uwtable
705; CGSCC-LABEL: define {{[^@]+}}@maybe_redefined_fn
706; CGSCC-SAME: (ptr [[R:%.*]]) #[[ATTR4]] {
707; CGSCC-NEXT:  entry:
708; CGSCC-NEXT:    ret ptr [[R]]
709;
710entry:
711  ret ptr %r
712}
713
714define ptr @calls_maybe_redefined_fn(ptr %r) #0 {
715; TUNIT: Function Attrs: noinline nounwind uwtable
716; TUNIT-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn
717; TUNIT-SAME: (ptr returned [[R:%.*]]) #[[ATTR5]] {
718; TUNIT-NEXT:  entry:
719; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @maybe_redefined_fn(ptr [[R]]) #[[ATTR11]]
720; TUNIT-NEXT:    ret ptr [[R]]
721;
722; CGSCC: Function Attrs: noinline nounwind uwtable
723; CGSCC-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn
724; CGSCC-SAME: (ptr returned [[R:%.*]]) #[[ATTR4]] {
725; CGSCC-NEXT:  entry:
726; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @maybe_redefined_fn(ptr [[R]]) #[[ATTR9]]
727; CGSCC-NEXT:    ret ptr [[R]]
728;
729entry:
730  %call = call ptr @maybe_redefined_fn(ptr %r)
731  ret ptr %r
732}
733
734; TEST return call to a function that might be redifined at link time
735;
736;  int *maybe_redefined_fn2(int *r) {
737;    return r;
738;  }
739;
740;  int *calls_maybe_redefined_fn2(int *r) {
741;    return maybe_redefined_fn2(r);
742;  }
743;
744; Verify the maybe-redefined function is not annotated:
745;
746define linkonce_odr ptr @maybe_redefined_fn2(ptr %r) #0 {
747; TUNIT: Function Attrs: noinline nounwind uwtable
748; TUNIT-LABEL: define {{[^@]+}}@maybe_redefined_fn2
749; TUNIT-SAME: (ptr [[R:%.*]]) #[[ATTR5]] {
750; TUNIT-NEXT:  entry:
751; TUNIT-NEXT:    ret ptr [[R]]
752;
753; CGSCC: Function Attrs: noinline nounwind uwtable
754; CGSCC-LABEL: define {{[^@]+}}@maybe_redefined_fn2
755; CGSCC-SAME: (ptr [[R:%.*]]) #[[ATTR4]] {
756; CGSCC-NEXT:  entry:
757; CGSCC-NEXT:    ret ptr [[R]]
758;
759entry:
760  ret ptr %r
761}
762
763define ptr @calls_maybe_redefined_fn2(ptr %r) #0 {
764; TUNIT: Function Attrs: noinline nounwind uwtable
765; TUNIT-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn2
766; TUNIT-SAME: (ptr [[R:%.*]]) #[[ATTR5]] {
767; TUNIT-NEXT:  entry:
768; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @maybe_redefined_fn2(ptr [[R]]) #[[ATTR11]]
769; TUNIT-NEXT:    ret ptr [[CALL]]
770;
771; CGSCC: Function Attrs: noinline nounwind uwtable
772; CGSCC-LABEL: define {{[^@]+}}@calls_maybe_redefined_fn2
773; CGSCC-SAME: (ptr [[R:%.*]]) #[[ATTR4]] {
774; CGSCC-NEXT:  entry:
775; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @maybe_redefined_fn2(ptr [[R]]) #[[ATTR9]]
776; CGSCC-NEXT:    ret ptr [[CALL]]
777;
778entry:
779  %call = call ptr @maybe_redefined_fn2(ptr %r)
780  ret ptr %call
781}
782
783
784; TEST returned argument goes through select and phi
785;
786; double select_and_phi(double b) {
787;   double x = b;
788;   if (b > 0)
789;     x = b;
790;   return b == 0? b : x;
791; }
792;
793define double @select_and_phi(double %b) #0 {
794; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
795; CHECK-LABEL: define {{[^@]+}}@select_and_phi
796; CHECK-SAME: (double returned [[B:%.*]]) #[[ATTR0]] {
797; CHECK-NEXT:  entry:
798; CHECK-NEXT:    [[CMP:%.*]] = fcmp ogt double [[B]], 0.000000e+00
799; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
800; CHECK:       if.then:
801; CHECK-NEXT:    br label [[IF_END]]
802; CHECK:       if.end:
803; CHECK-NEXT:    [[PHI:%.*]] = phi double [ [[B]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ]
804; CHECK-NEXT:    ret double [[B]]
805;
806entry:
807  %cmp = fcmp ogt double %b, 0.000000e+00
808  br i1 %cmp, label %if.then, label %if.end
809
810if.then:                                          ; preds = %entry
811  br label %if.end
812
813if.end:                                           ; preds = %if.then, %entry
814  %phi = phi double [ %b, %if.then ], [ %b, %entry ]
815  %cmp1 = fcmp oeq double %b, 0.000000e+00
816  %sel = select i1 %cmp1, double %b, double %phi
817  ret double %sel
818}
819
820
821; TEST returned argument goes through recursion, select, and phi
822;
823; double recursion_select_and_phi(int a, double b) {
824;   double x = b;
825;   if (a-- > 0)
826;     x = recursion_select_and_phi(a, b);
827;   return b == 0? b : x;
828; }
829;
830define double @recursion_select_and_phi(i32 %a, double %b) #0 {
831; TUNIT: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
832; TUNIT-LABEL: define {{[^@]+}}@recursion_select_and_phi
833; TUNIT-SAME: (i32 [[A:%.*]], double returned [[B:%.*]]) #[[ATTR1]] {
834; TUNIT-NEXT:  entry:
835; TUNIT-NEXT:    [[DEC:%.*]] = add nsw i32 [[A]], -1
836; TUNIT-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], 0
837; TUNIT-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
838; TUNIT:       if.then:
839; TUNIT-NEXT:    [[CALL:%.*]] = call double @recursion_select_and_phi(i32 [[DEC]], double [[B]]) #[[ATTR8]]
840; TUNIT-NEXT:    br label [[IF_END]]
841; TUNIT:       if.end:
842; TUNIT-NEXT:    [[PHI:%.*]] = phi double [ [[B]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ]
843; TUNIT-NEXT:    ret double [[B]]
844;
845; CGSCC: Function Attrs: nofree noinline nosync nounwind memory(none) uwtable
846; CGSCC-LABEL: define {{[^@]+}}@recursion_select_and_phi
847; CGSCC-SAME: (i32 [[A:%.*]], double returned [[B:%.*]]) #[[ATTR1]] {
848; CGSCC-NEXT:  entry:
849; CGSCC-NEXT:    [[DEC:%.*]] = add nsw i32 [[A]], -1
850; CGSCC-NEXT:    [[CMP:%.*]] = icmp sgt i32 [[A]], 0
851; CGSCC-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
852; CGSCC:       if.then:
853; CGSCC-NEXT:    [[CALL:%.*]] = call double @recursion_select_and_phi(i32 [[DEC]], double [[B]]) #[[ATTR7]]
854; CGSCC-NEXT:    br label [[IF_END]]
855; CGSCC:       if.end:
856; CGSCC-NEXT:    [[PHI:%.*]] = phi double [ [[B]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ]
857; CGSCC-NEXT:    ret double [[B]]
858;
859entry:
860  %dec = add nsw i32 %a, -1
861  %cmp = icmp sgt i32 %a, 0
862  br i1 %cmp, label %if.then, label %if.end
863
864if.then:                                          ; preds = %entry
865  %call = call double @recursion_select_and_phi(i32 %dec, double %b)
866  br label %if.end
867
868if.end:                                           ; preds = %if.then, %entry
869  %phi = phi double [ %call, %if.then ], [ %b, %entry ]
870  %cmp1 = fcmp oeq double %b, 0.000000e+00
871  %sel = select i1 %cmp1, double %b, double %phi
872  ret double %sel
873}
874
875
876; TEST returned argument goes through bitcasts
877;
878; double* bitcast(int* b) {
879;   return (double*)b;
880; }
881;
882define ptr @bitcast(ptr %b) #0 {
883; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
884; CHECK-LABEL: define {{[^@]+}}@bitcast
885; CHECK-SAME: (ptr nofree readnone returned "no-capture-maybe-returned" [[B:%.*]]) #[[ATTR0]] {
886; CHECK-NEXT:  entry:
887; CHECK-NEXT:    ret ptr [[B]]
888;
889entry:
890  ret ptr %b
891}
892
893
894; TEST returned argument goes through select and phi interleaved with bitcasts
895;
896; double* bitcasts_select_and_phi(int* b) {
897;   double* x = b;
898;   if (b == 0)
899;     x = b;
900;   return b != 0 ? b : x;
901; }
902;
903define ptr @bitcasts_select_and_phi(ptr %b) #0 {
904; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
905; CHECK-LABEL: define {{[^@]+}}@bitcasts_select_and_phi
906; CHECK-SAME: (ptr nofree readnone returned [[B:%.*]]) #[[ATTR0]] {
907; CHECK-NEXT:  entry:
908; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B]], null
909; CHECK-NEXT:    br i1 [[CMP]], label [[IF_THEN:%.*]], label [[IF_END:%.*]]
910; CHECK:       if.then:
911; CHECK-NEXT:    br label [[IF_END]]
912; CHECK:       if.end:
913; CHECK-NEXT:    [[PHI:%.*]] = phi ptr [ [[B]], [[IF_THEN]] ], [ [[B]], [[ENTRY:%.*]] ]
914; CHECK-NEXT:    ret ptr [[B]]
915;
916entry:
917  %cmp = icmp eq ptr %b, null
918  br i1 %cmp, label %if.then, label %if.end
919
920if.then:                                          ; preds = %entry
921  br label %if.end
922
923if.end:                                           ; preds = %if.then, %entry
924  %phi = phi ptr [ %b, %if.then ], [ %b, %entry ]
925  %cmp2 = icmp ne ptr %b, null
926  %sel = select i1 %cmp2, ptr %phi, ptr %b
927  ret ptr %sel
928}
929
930
931; TEST return argument or argument or undef
932;
933; double* ret_arg_arg_undef(int* b) {
934;   if (b == 0)
935;     return (double*)b;
936;   if (b == 0)
937;     return (double*)b;
938;   /* return undef */
939; }
940;
941define ptr @ret_arg_arg_undef(ptr %b) #0 {
942; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
943; CHECK-LABEL: define {{[^@]+}}@ret_arg_arg_undef
944; CHECK-SAME: (ptr nofree readnone returned [[B:%.*]]) #[[ATTR0]] {
945; CHECK-NEXT:  entry:
946; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B]], null
947; CHECK-NEXT:    br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[IF_END:%.*]]
948; CHECK:       ret_arg0:
949; CHECK-NEXT:    ret ptr [[B]]
950; CHECK:       if.end:
951; CHECK-NEXT:    br i1 [[CMP]], label [[RET_ARG1:%.*]], label [[RET_UNDEF:%.*]]
952; CHECK:       ret_arg1:
953; CHECK-NEXT:    ret ptr [[B]]
954; CHECK:       ret_undef:
955; CHECK-NEXT:    ret ptr undef
956;
957entry:
958  %cmp = icmp eq ptr %b, null
959  br i1 %cmp, label %ret_arg0, label %if.end
960
961ret_arg0:
962  ret ptr %b
963
964if.end:
965  br i1 %cmp, label %ret_arg1, label %ret_undef
966
967ret_arg1:
968  ret ptr %b
969
970ret_undef:
971  ret ptr undef
972}
973
974
975; TEST return undef or argument or argument
976;
977; double* ret_undef_arg_arg(int* b) {
978;   if (b == 0)
979;     return (double*)b;
980;   if (b == 0)
981;     return (double*)b;
982;   /* return undef */
983; }
984;
985define ptr @ret_undef_arg_arg(ptr %b) #0 {
986; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
987; CHECK-LABEL: define {{[^@]+}}@ret_undef_arg_arg
988; CHECK-SAME: (ptr nofree readnone returned [[B:%.*]]) #[[ATTR0]] {
989; CHECK-NEXT:  entry:
990; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B]], null
991; CHECK-NEXT:    br i1 [[CMP]], label [[RET_UNDEF:%.*]], label [[IF_END:%.*]]
992; CHECK:       ret_undef:
993; CHECK-NEXT:    ret ptr undef
994; CHECK:       if.end:
995; CHECK-NEXT:    br i1 [[CMP]], label [[RET_ARG0:%.*]], label [[RET_ARG1:%.*]]
996; CHECK:       ret_arg0:
997; CHECK-NEXT:    ret ptr [[B]]
998; CHECK:       ret_arg1:
999; CHECK-NEXT:    ret ptr [[B]]
1000;
1001entry:
1002  %cmp = icmp eq ptr %b, null
1003  br i1 %cmp, label %ret_undef, label %if.end
1004
1005ret_undef:
1006  ret ptr undef
1007
1008if.end:
1009  br i1 %cmp, label %ret_arg0, label %ret_arg1
1010
1011ret_arg0:
1012  ret ptr %b
1013
1014ret_arg1:
1015  ret ptr %b
1016}
1017
1018
1019; TEST return undef or argument or undef
1020;
1021; double* ret_undef_arg_undef(int* b) {
1022;   if (b == 0)
1023;     /* return undef */
1024;   if (b == 0)
1025;     return (double*)b;
1026;   /* return undef */
1027; }
1028;
1029define ptr @ret_undef_arg_undef(ptr %b) #0 {
1030; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
1031; CHECK-LABEL: define {{[^@]+}}@ret_undef_arg_undef
1032; CHECK-SAME: (ptr nofree readnone returned [[B:%.*]]) #[[ATTR0]] {
1033; CHECK-NEXT:  entry:
1034; CHECK-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B]], null
1035; CHECK-NEXT:    br i1 [[CMP]], label [[RET_UNDEF0:%.*]], label [[IF_END:%.*]]
1036; CHECK:       ret_undef0:
1037; CHECK-NEXT:    ret ptr undef
1038; CHECK:       if.end:
1039; CHECK-NEXT:    br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNDEF1:%.*]]
1040; CHECK:       ret_arg:
1041; CHECK-NEXT:    ret ptr [[B]]
1042; CHECK:       ret_undef1:
1043; CHECK-NEXT:    ret ptr undef
1044;
1045entry:
1046  %cmp = icmp eq ptr %b, null
1047  br i1 %cmp, label %ret_undef0, label %if.end
1048
1049ret_undef0:
1050  ret ptr undef
1051
1052if.end:
1053  br i1 %cmp, label %ret_arg, label %ret_undef1
1054
1055ret_arg:
1056  ret ptr %b
1057
1058ret_undef1:
1059  ret ptr undef
1060}
1061
1062; TEST return argument or unknown call result
1063;
1064; int* ret_arg_or_unknown(int* b) {
1065;   if (b == 0)
1066;     return b;
1067;   return unknown();
1068; }
1069;
1070; Verify we do not assume b is returned
1071;
1072declare ptr @unknown(ptr)
1073
1074define ptr @ret_arg_or_unknown(ptr %b) #0 {
1075; TUNIT: Function Attrs: noinline nounwind uwtable
1076; TUNIT-LABEL: define {{[^@]+}}@ret_arg_or_unknown
1077; TUNIT-SAME: (ptr [[B:%.*]]) #[[ATTR5]] {
1078; TUNIT-NEXT:  entry:
1079; TUNIT-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B]], null
1080; TUNIT-NEXT:    br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]]
1081; TUNIT:       ret_arg:
1082; TUNIT-NEXT:    ret ptr [[B]]
1083; TUNIT:       ret_unknown:
1084; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @unknown(ptr nonnull [[B]])
1085; TUNIT-NEXT:    ret ptr [[CALL]]
1086;
1087; CGSCC: Function Attrs: noinline nounwind uwtable
1088; CGSCC-LABEL: define {{[^@]+}}@ret_arg_or_unknown
1089; CGSCC-SAME: (ptr [[B:%.*]]) #[[ATTR4]] {
1090; CGSCC-NEXT:  entry:
1091; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B]], null
1092; CGSCC-NEXT:    br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]]
1093; CGSCC:       ret_arg:
1094; CGSCC-NEXT:    ret ptr [[B]]
1095; CGSCC:       ret_unknown:
1096; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @unknown(ptr nonnull [[B]])
1097; CGSCC-NEXT:    ret ptr [[CALL]]
1098;
1099entry:
1100  %cmp = icmp eq ptr %b, null
1101  br i1 %cmp, label %ret_arg, label %ret_unknown
1102
1103ret_arg:
1104  ret ptr %b
1105
1106ret_unknown:
1107  %call = call ptr @unknown(ptr %b)
1108  ret ptr %call
1109}
1110
1111define ptr @ret_arg_or_unknown_through_phi(ptr %b) #0 {
1112; TUNIT: Function Attrs: noinline nounwind uwtable
1113; TUNIT-LABEL: define {{[^@]+}}@ret_arg_or_unknown_through_phi
1114; TUNIT-SAME: (ptr [[B:%.*]]) #[[ATTR5]] {
1115; TUNIT-NEXT:  entry:
1116; TUNIT-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B]], null
1117; TUNIT-NEXT:    br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]]
1118; TUNIT:       ret_arg:
1119; TUNIT-NEXT:    br label [[R:%.*]]
1120; TUNIT:       ret_unknown:
1121; TUNIT-NEXT:    [[CALL:%.*]] = call ptr @unknown(ptr nonnull [[B]])
1122; TUNIT-NEXT:    br label [[R]]
1123; TUNIT:       r:
1124; TUNIT-NEXT:    [[PHI:%.*]] = phi ptr [ [[B]], [[RET_ARG]] ], [ [[CALL]], [[RET_UNKNOWN]] ]
1125; TUNIT-NEXT:    ret ptr [[PHI]]
1126;
1127; CGSCC: Function Attrs: noinline nounwind uwtable
1128; CGSCC-LABEL: define {{[^@]+}}@ret_arg_or_unknown_through_phi
1129; CGSCC-SAME: (ptr [[B:%.*]]) #[[ATTR4]] {
1130; CGSCC-NEXT:  entry:
1131; CGSCC-NEXT:    [[CMP:%.*]] = icmp eq ptr [[B]], null
1132; CGSCC-NEXT:    br i1 [[CMP]], label [[RET_ARG:%.*]], label [[RET_UNKNOWN:%.*]]
1133; CGSCC:       ret_arg:
1134; CGSCC-NEXT:    br label [[R:%.*]]
1135; CGSCC:       ret_unknown:
1136; CGSCC-NEXT:    [[CALL:%.*]] = call ptr @unknown(ptr nonnull [[B]])
1137; CGSCC-NEXT:    br label [[R]]
1138; CGSCC:       r:
1139; CGSCC-NEXT:    [[PHI:%.*]] = phi ptr [ [[B]], [[RET_ARG]] ], [ [[CALL]], [[RET_UNKNOWN]] ]
1140; CGSCC-NEXT:    ret ptr [[PHI]]
1141;
1142entry:
1143  %cmp = icmp eq ptr %b, null
1144  br i1 %cmp, label %ret_arg, label %ret_unknown
1145
1146ret_arg:
1147  br label %r
1148
1149ret_unknown:
1150  %call = call ptr @unknown(ptr %b)
1151  br label %r
1152
1153r:
1154  %phi = phi ptr [ %b, %ret_arg ], [ %call, %ret_unknown ]
1155  ret ptr %phi
1156}
1157
1158; TEST inconsistent IR in dead code.
1159;
1160define i32 @deadblockcall1(i32 %A) #0 {
1161; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
1162; CHECK-LABEL: define {{[^@]+}}@deadblockcall1
1163; CHECK-SAME: (i32 returned [[A:%.*]]) #[[ATTR0]] {
1164; CHECK-NEXT:  entry:
1165; CHECK-NEXT:    ret i32 [[A]]
1166; CHECK:       unreachableblock:
1167; CHECK-NEXT:    unreachable
1168;
1169entry:
1170  ret i32 %A
1171unreachableblock:
1172  %B = call i32 @deadblockcall1(i32 %B)
1173  ret i32 %B
1174}
1175
1176declare i32 @deadblockcall_helper(i32 returned %A);
1177
1178define i32 @deadblockcall2(i32 %A) #0 {
1179; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
1180; CHECK-LABEL: define {{[^@]+}}@deadblockcall2
1181; CHECK-SAME: (i32 returned [[A:%.*]]) #[[ATTR0]] {
1182; CHECK-NEXT:  entry:
1183; CHECK-NEXT:    ret i32 [[A]]
1184; CHECK:       unreachableblock1:
1185; CHECK-NEXT:    unreachable
1186; CHECK:       unreachableblock2:
1187; CHECK-NEXT:    unreachable
1188;
1189entry:
1190  ret i32 %A
1191unreachableblock1:
1192  %B = call i32 @deadblockcall_helper(i32 %B)
1193  ret i32 %B
1194unreachableblock2:
1195  %C = call i32 @deadblockcall1(i32 %C)
1196  ret i32 %C
1197}
1198
1199define i32 @deadblockphi1(i32 %A) #0 {
1200; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
1201; CHECK-LABEL: define {{[^@]+}}@deadblockphi1
1202; CHECK-SAME: (i32 returned [[A:%.*]]) #[[ATTR0]] {
1203; CHECK-NEXT:  entry:
1204; CHECK-NEXT:    br label [[R:%.*]]
1205; CHECK:       unreachableblock1:
1206; CHECK-NEXT:    unreachable
1207; CHECK:       unreachableblock2:
1208; CHECK-NEXT:    unreachable
1209; CHECK:       r:
1210; CHECK-NEXT:    ret i32 [[A]]
1211;
1212entry:
1213  br label %r
1214unreachableblock1:
1215  %B = call i32 @deadblockcall_helper(i32 %B)
1216  ret i32 %B
1217unreachableblock2:
1218  %C = call i32 @deadblockcall1(i32 %C)
1219  br label %r
1220r:
1221  %PHI = phi i32 [%A, %entry], [%C, %unreachableblock2]
1222  ret i32 %PHI
1223}
1224
1225define i32 @deadblockphi2(i32 %A) #0 {
1226; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
1227; CHECK-LABEL: define {{[^@]+}}@deadblockphi2
1228; CHECK-SAME: (i32 returned [[A:%.*]]) #[[ATTR0]] {
1229; CHECK-NEXT:  entry:
1230; CHECK-NEXT:    br label [[R:%.*]]
1231; CHECK:       unreachableblock1:
1232; CHECK-NEXT:    unreachable
1233; CHECK:       unreachableblock2:
1234; CHECK-NEXT:    unreachable
1235; CHECK:       unreachableblock3:
1236; CHECK-NEXT:    unreachable
1237; CHECK:       r:
1238; CHECK-NEXT:    ret i32 [[A]]
1239;
1240entry:
1241  br label %r
1242unreachableblock1:
1243  %B = call i32 @deadblockcall_helper(i32 %B)
1244  br label %unreachableblock3
1245unreachableblock2:
1246  %C = call i32 @deadblockcall1(i32 %C)
1247  br label %unreachableblock3
1248unreachableblock3:
1249  %PHI1 = phi i32 [%B, %unreachableblock1], [%C, %unreachableblock2]
1250  br label %r
1251r:
1252  %PHI2 = phi i32 [%A, %entry], [%PHI1, %unreachableblock3]
1253  ret i32 %PHI2
1254}
1255
1256declare void @noreturn() noreturn;
1257
1258define i32 @deadblockphi3(i32 %A, i1 %c) #0 {
1259; TUNIT: Function Attrs: noinline nounwind uwtable
1260; TUNIT-LABEL: define {{[^@]+}}@deadblockphi3
1261; TUNIT-SAME: (i32 returned [[A:%.*]], i1 noundef [[C:%.*]]) #[[ATTR5]] {
1262; TUNIT-NEXT:  entry:
1263; TUNIT-NEXT:    br i1 [[C]], label [[R:%.*]], label [[UNREACHABLECALL:%.*]]
1264; TUNIT:       unreachablecall:
1265; TUNIT-NEXT:    call void @noreturn() #[[ATTR6:[0-9]+]]
1266; TUNIT-NEXT:    unreachable
1267; TUNIT:       unreachableblock2:
1268; TUNIT-NEXT:    unreachable
1269; TUNIT:       unreachableblock3:
1270; TUNIT-NEXT:    unreachable
1271; TUNIT:       r:
1272; TUNIT-NEXT:    ret i32 [[A]]
1273;
1274; CGSCC: Function Attrs: noinline nounwind uwtable
1275; CGSCC-LABEL: define {{[^@]+}}@deadblockphi3
1276; CGSCC-SAME: (i32 returned [[A:%.*]], i1 noundef [[C:%.*]]) #[[ATTR4]] {
1277; CGSCC-NEXT:  entry:
1278; CGSCC-NEXT:    br i1 [[C]], label [[R:%.*]], label [[UNREACHABLECALL:%.*]]
1279; CGSCC:       unreachablecall:
1280; CGSCC-NEXT:    call void @noreturn() #[[ATTR5:[0-9]+]]
1281; CGSCC-NEXT:    unreachable
1282; CGSCC:       unreachableblock2:
1283; CGSCC-NEXT:    unreachable
1284; CGSCC:       unreachableblock3:
1285; CGSCC-NEXT:    unreachable
1286; CGSCC:       r:
1287; CGSCC-NEXT:    ret i32 [[A]]
1288;
1289entry:
1290  br i1 %c, label %r, label %unreachablecall
1291unreachablecall:
1292  call void @noreturn();
1293  %B = call i32 @deadblockcall_helper(i32 0)
1294  br label %unreachableblock3
1295unreachableblock2:
1296  %C = call i32 @deadblockcall1(i32 %C)
1297  br label %unreachableblock3
1298unreachableblock3:
1299  %PHI1 = phi i32 [%B, %unreachablecall], [%C, %unreachableblock2]
1300  br label %r
1301r:
1302  %PHI2 = phi i32 [%A, %entry], [%PHI1, %unreachableblock3]
1303  ret i32 %PHI2
1304}
1305
1306define weak_odr i32 @non_exact_0() {
1307; CHECK-LABEL: define {{[^@]+}}@non_exact_0() {
1308; CHECK-NEXT:    ret i32 0
1309;
1310  ret i32 0
1311}
1312define weak_odr i32 @non_exact_1(i32 %a) {
1313; CHECK-LABEL: define {{[^@]+}}@non_exact_1
1314; CHECK-SAME: (i32 [[A:%.*]]) {
1315; CHECK-NEXT:    ret i32 [[A]]
1316;
1317  ret i32 %a
1318}
1319define weak_odr i32 @non_exact_2(i32 returned %a) {
1320; CHECK-LABEL: define {{[^@]+}}@non_exact_2
1321; CHECK-SAME: (i32 returned [[A:%.*]]) {
1322; CHECK-NEXT:    ret i32 [[A]]
1323;
1324  ret i32 %a
1325}
1326define weak_odr align 16 ptr @non_exact_3(ptr align 32 returned %a) {
1327; CHECK-LABEL: define {{[^@]+}}@non_exact_3
1328; CHECK-SAME: (ptr returned align 32 [[A:%.*]]) {
1329; CHECK-NEXT:    ret ptr [[A]]
1330;
1331  ret ptr %a
1332}
1333define weak_odr align 16 ptr @non_exact_4(ptr align 32 %a) {
1334; CHECK-LABEL: define {{[^@]+}}@non_exact_4
1335; CHECK-SAME: (ptr align 32 [[A:%.*]]) {
1336; CHECK-NEXT:    ret ptr [[A]]
1337;
1338  ret ptr %a
1339}
1340; We can use the alignment information of the weak function non_exact_3 argument
1341; because it was given to us and not derived.
1342; We can use the return information of the weak function non_exact_4.
1343; %c2 and %c3 should be replaced but not %c0 or %c1!
1344define i32 @exact(ptr align 8 %a, ptr align 8 %b) {
1345; CHECK-LABEL: define {{[^@]+}}@exact
1346; CHECK-SAME: (ptr align 8 [[A:%.*]], ptr align 8 [[B:%.*]]) {
1347; CHECK-NEXT:    [[C0:%.*]] = call i32 @non_exact_0()
1348; CHECK-NEXT:    [[C1:%.*]] = call i32 @non_exact_1(i32 noundef 1)
1349; CHECK-NEXT:    [[C2:%.*]] = call i32 @non_exact_2(i32 noundef 2)
1350; CHECK-NEXT:    [[C3:%.*]] = call align 32 ptr @non_exact_3(ptr align 32 [[A]])
1351; CHECK-NEXT:    [[C4:%.*]] = call align 16 ptr @non_exact_4(ptr align 32 [[B]])
1352; CHECK-NEXT:    [[C3L:%.*]] = load i32, ptr [[A]], align 32
1353; CHECK-NEXT:    [[C4L:%.*]] = load i32, ptr [[C4]], align 16
1354; CHECK-NEXT:    [[ADD1:%.*]] = add i32 [[C0]], [[C1]]
1355; CHECK-NEXT:    [[ADD2:%.*]] = add i32 [[ADD1]], 2
1356; CHECK-NEXT:    [[ADD3:%.*]] = add i32 [[ADD2]], [[C3L]]
1357; CHECK-NEXT:    [[ADD4:%.*]] = add i32 [[ADD3]], [[C4L]]
1358; CHECK-NEXT:    ret i32 [[ADD4]]
1359;
1360  %c0 = call i32 @non_exact_0()
1361  %c1 = call i32 @non_exact_1(i32 1)
1362  %c2 = call i32 @non_exact_2(i32 2)
1363  %c3 = call ptr @non_exact_3(ptr %a)
1364  %c4 = call ptr @non_exact_4(ptr %b)
1365  %c3l = load i32, ptr %c3
1366  %c4l = load i32, ptr %c4
1367  %add1 = add i32 %c0, %c1
1368  %add2 = add i32 %add1, %c2
1369  %add3 = add i32 %add2, %c3l
1370  %add4 = add i32 %add3, %c4l
1371  ret i32 %add4
1372}
1373
1374@G = external global i8
1375define ptr @ret_const() #0 {
1376; CHECK: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
1377; CHECK-LABEL: define {{[^@]+}}@ret_const
1378; CHECK-SAME: () #[[ATTR0]] {
1379; CHECK-NEXT:    ret ptr @G
1380;
1381  ret ptr @G
1382}
1383define ptr @use_const() #0 {
1384; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
1385; TUNIT-LABEL: define {{[^@]+}}@use_const
1386; TUNIT-SAME: () #[[ATTR0]] {
1387; TUNIT-NEXT:    ret ptr @G
1388;
1389; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
1390; CGSCC-LABEL: define {{[^@]+}}@use_const
1391; CGSCC-SAME: () #[[ATTR3]] {
1392; CGSCC-NEXT:    [[C:%.*]] = call noundef nonnull dereferenceable(1) ptr @ret_const() #[[ATTR10:[0-9]+]]
1393; CGSCC-NEXT:    ret ptr [[C]]
1394;
1395  %c = call ptr @ret_const()
1396  ret ptr %c
1397}
1398define ptr @dont_use_const() #0 {
1399; TUNIT: Function Attrs: mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable
1400; TUNIT-LABEL: define {{[^@]+}}@dont_use_const
1401; TUNIT-SAME: () #[[ATTR0]] {
1402; TUNIT-NEXT:    ret ptr @G
1403;
1404; CGSCC: Function Attrs: mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable
1405; CGSCC-LABEL: define {{[^@]+}}@dont_use_const
1406; CGSCC-SAME: () #[[ATTR3]] {
1407; CGSCC-NEXT:    [[C:%.*]] = musttail call noundef nonnull dereferenceable(1) ptr @ret_const() #[[ATTR10]]
1408; CGSCC-NEXT:    ret ptr [[C]]
1409;
1410  %c = musttail call ptr @ret_const()
1411  ret ptr %c
1412}
1413
1414; UTC_ARGS: --disable
1415;
1416; Verify we do not derive constraints for @_Z3fooP1X as if it was returning `null`.
1417;
1418; CHEKC-NOT: noalias
1419; CHECK-NOT: align 536870912
1420
1421%struct.Y = type { %struct.X }
1422%struct.X = type { ptr }
1423
1424@_ZTI1X = external dso_local constant { ptr, ptr }, align 8
1425@_ZTI1Y = external dso_local constant { ptr, ptr, ptr }, align 8
1426
1427define internal ptr @_ZN1Y3barEv(ptr %this) align 2 {
1428entry:
1429  ret ptr %this
1430}
1431
1432define dso_local ptr @_Z3fooP1X(ptr %x) {
1433entry:
1434  %0 = icmp eq ptr %x, null
1435  br i1 %0, label %dynamic_cast.null, label %dynamic_cast.notnull
1436
1437dynamic_cast.notnull:                             ; preds = %entry
1438  %1 = call ptr @__dynamic_cast(ptr %x, ptr @_ZTI1X, ptr @_ZTI1Y, i64 0) #2
1439  br label %dynamic_cast.end
1440
1441dynamic_cast.null:                                ; preds = %entry
1442  br label %dynamic_cast.end
1443
1444dynamic_cast.end:                                 ; preds = %dynamic_cast.null, %dynamic_cast.notnull
1445  %QQ5 = phi ptr [ %1, %dynamic_cast.notnull ], [ null, %dynamic_cast.null ]
1446  %call = call ptr @_ZN1Y3barEv(ptr %QQ5)
1447  ret ptr %call
1448}
1449
1450declare dso_local ptr @__dynamic_cast(ptr, ptr, ptr, i64)
1451
1452; UTC_ARGS: --enable
1453
1454; This does not return %arg, @recGood does.
1455
1456define internal i32 @recBad(i1 %c, i32 %arg) {
1457; TUNIT: Function Attrs: nofree nosync nounwind memory(none)
1458; TUNIT-LABEL: define {{[^@]+}}@recBad
1459; TUNIT-SAME: (i1 noundef [[C:%.*]], i32 [[ARG:%.*]]) #[[ATTR8]] {
1460; TUNIT-NEXT:    [[ADD:%.*]] = add i32 [[ARG]], 1
1461; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
1462; TUNIT:       t:
1463; TUNIT-NEXT:    [[R:%.*]] = call i32 @recBad(i1 noundef false, i32 [[ADD]]) #[[ATTR8]]
1464; TUNIT-NEXT:    ret i32 [[ADD]]
1465; TUNIT:       f:
1466; TUNIT-NEXT:    ret i32 [[ARG]]
1467;
1468; CGSCC: Function Attrs: nofree nosync nounwind memory(none)
1469; CGSCC-LABEL: define {{[^@]+}}@recBad
1470; CGSCC-SAME: (i1 noundef [[C:%.*]], i32 [[ARG:%.*]]) #[[ATTR7]] {
1471; CGSCC-NEXT:    [[ADD:%.*]] = add i32 [[ARG]], 1
1472; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
1473; CGSCC:       t:
1474; CGSCC-NEXT:    [[R:%.*]] = call i32 @recBad(i1 noundef false, i32 [[ADD]]) #[[ATTR7]]
1475; CGSCC-NEXT:    ret i32 [[ADD]]
1476; CGSCC:       f:
1477; CGSCC-NEXT:    ret i32 [[ARG]]
1478;
1479  %add = add i32 %arg, 1
1480  br i1 %c, label %t, label %f
1481t:
1482  %r = call i32 @recBad(i1 false, i32 %add)
1483  ret i32 %r
1484f:
1485  ret i32 %arg
1486}
1487
1488define i32 @recBadCaller(i1 %cQ, i32 %argQ) {
1489; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none)
1490; TUNIT-LABEL: define {{[^@]+}}@recBadCaller
1491; TUNIT-SAME: (i1 [[CQ:%.*]], i32 [[ARGQ:%.*]]) #[[ATTR9:[0-9]+]] {
1492; TUNIT-NEXT:    [[RQ:%.*]] = call i32 @recBad(i1 noundef [[CQ]], i32 [[ARGQ]]) #[[ATTR8]]
1493; TUNIT-NEXT:    ret i32 [[RQ]]
1494;
1495; CGSCC: Function Attrs: nofree nosync nounwind memory(none)
1496; CGSCC-LABEL: define {{[^@]+}}@recBadCaller
1497; CGSCC-SAME: (i1 noundef [[CQ:%.*]], i32 [[ARGQ:%.*]]) #[[ATTR7]] {
1498; CGSCC-NEXT:    [[RQ:%.*]] = call i32 @recBad(i1 noundef [[CQ]], i32 [[ARGQ]]) #[[ATTR7]]
1499; CGSCC-NEXT:    ret i32 [[RQ]]
1500;
1501  %rQ = call i32 @recBad(i1 %cQ, i32 %argQ)
1502  ret i32 %rQ
1503}
1504
1505define internal i32 @recGood(i1 %c, i32 %arg) {
1506; TUNIT: Function Attrs: nofree nosync nounwind memory(none)
1507; TUNIT-LABEL: define {{[^@]+}}@recGood
1508; TUNIT-SAME: (i1 noundef [[C:%.*]], i32 returned [[ARG:%.*]]) #[[ATTR8]] {
1509; TUNIT-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
1510; TUNIT:       t:
1511; TUNIT-NEXT:    [[R:%.*]] = call i32 @recGood(i1 noundef false, i32 [[ARG]]) #[[ATTR8]]
1512; TUNIT-NEXT:    ret i32 [[ARG]]
1513; TUNIT:       f:
1514; TUNIT-NEXT:    ret i32 [[ARG]]
1515;
1516; CGSCC: Function Attrs: nofree nosync nounwind memory(none)
1517; CGSCC-LABEL: define {{[^@]+}}@recGood
1518; CGSCC-SAME: (i1 noundef [[C:%.*]], i32 returned [[ARG:%.*]]) #[[ATTR7]] {
1519; CGSCC-NEXT:    br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
1520; CGSCC:       t:
1521; CGSCC-NEXT:    [[R:%.*]] = call i32 @recGood(i1 noundef false, i32 [[ARG]]) #[[ATTR7]]
1522; CGSCC-NEXT:    ret i32 [[ARG]]
1523; CGSCC:       f:
1524; CGSCC-NEXT:    ret i32 [[ARG]]
1525;
1526  br i1 %c, label %t, label %f
1527t:
1528  %r = call i32 @recGood(i1 false, i32 %arg)
1529  ret i32 %r
1530f:
1531  ret i32 %arg
1532}
1533
1534define i32 @recGoodCaller(i1 %cQ, i32 %argQ) {
1535; TUNIT: Function Attrs: nofree norecurse nosync nounwind memory(none)
1536; TUNIT-LABEL: define {{[^@]+}}@recGoodCaller
1537; TUNIT-SAME: (i1 [[CQ:%.*]], i32 returned [[ARGQ:%.*]]) #[[ATTR9]] {
1538; TUNIT-NEXT:    [[RQ:%.*]] = call i32 @recGood(i1 noundef [[CQ]], i32 [[ARGQ]]) #[[ATTR8]]
1539; TUNIT-NEXT:    ret i32 [[ARGQ]]
1540;
1541; CGSCC: Function Attrs: nofree nosync nounwind memory(none)
1542; CGSCC-LABEL: define {{[^@]+}}@recGoodCaller
1543; CGSCC-SAME: (i1 noundef [[CQ:%.*]], i32 [[ARGQ:%.*]]) #[[ATTR7]] {
1544; CGSCC-NEXT:    [[RQ:%.*]] = call i32 @recGood(i1 noundef [[CQ]], i32 [[ARGQ]]) #[[ATTR7]]
1545; CGSCC-NEXT:    ret i32 [[RQ]]
1546;
1547  %rQ = call i32 @recGood(i1 %cQ, i32 %argQ)
1548  ret i32 %rQ
1549}
1550
1551attributes #0 = { noinline nounwind uwtable }
1552;.
1553; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable }
1554; TUNIT: attributes #[[ATTR1]] = { nofree noinline nosync nounwind memory(none) uwtable }
1555; TUNIT: attributes #[[ATTR2]] = { nofree noinline norecurse nosync nounwind memory(none) uwtable }
1556; TUNIT: attributes #[[ATTR3]] = { nofree noinline nosync nounwind memory(argmem: read) uwtable }
1557; TUNIT: attributes #[[ATTR4]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable }
1558; TUNIT: attributes #[[ATTR5]] = { noinline nounwind uwtable }
1559; TUNIT: attributes #[[ATTR6]] = { noreturn }
1560; TUNIT: attributes #[[ATTR7:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
1561; TUNIT: attributes #[[ATTR8]] = { nofree nosync nounwind memory(none) }
1562; TUNIT: attributes #[[ATTR9]] = { nofree norecurse nosync nounwind memory(none) }
1563; TUNIT: attributes #[[ATTR10]] = { nofree nosync nounwind memory(read) }
1564; TUNIT: attributes #[[ATTR11]] = { nounwind }
1565; TUNIT: attributes #[[ATTR12:[0-9]+]] = { nounwind memory(none) }
1566;.
1567; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree noinline norecurse nosync nounwind willreturn memory(none) uwtable }
1568; CGSCC: attributes #[[ATTR1]] = { nofree noinline nosync nounwind memory(none) uwtable }
1569; CGSCC: attributes #[[ATTR2]] = { nofree noinline nosync nounwind memory(argmem: read) uwtable }
1570; CGSCC: attributes #[[ATTR3]] = { mustprogress nofree noinline nosync nounwind willreturn memory(none) uwtable }
1571; CGSCC: attributes #[[ATTR4]] = { noinline nounwind uwtable }
1572; CGSCC: attributes #[[ATTR5]] = { noreturn }
1573; CGSCC: attributes #[[ATTR6:[0-9]+]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
1574; CGSCC: attributes #[[ATTR7]] = { nofree nosync nounwind memory(none) }
1575; CGSCC: attributes #[[ATTR8]] = { nofree nosync nounwind memory(read) }
1576; CGSCC: attributes #[[ATTR9]] = { nounwind }
1577; CGSCC: attributes #[[ATTR10]] = { nofree nosync willreturn }
1578;.
1579