xref: /llvm-project/llvm/test/Transforms/Attributor/call-simplify-pointer-info.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=TUNIT
3; RUN: opt -aa-pipeline=basic-aa -passes=attributor-cgscc -attributor-manifest-internal  -attributor-annotate-decl-cs -S < %s | FileCheck %s --check-prefixes=CGSCC
4;
5
6define internal i8 @read_arg(ptr %p) {
7; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
8; CGSCC-LABEL: define {{[^@]+}}@read_arg
9; CGSCC-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(1022) [[P:%.*]]) #[[ATTR0:[0-9]+]] {
10; CGSCC-NEXT:  entry:
11; CGSCC-NEXT:    [[L:%.*]] = load i8, ptr [[P]], align 1
12; CGSCC-NEXT:    ret i8 [[L]]
13;
14entry:
15  %l = load i8, ptr %p, align 1
16  ret i8 %l
17}
18
19define internal i8 @read_arg_index(ptr %p, i64 %index) {
20; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
21; CGSCC-LABEL: define {{[^@]+}}@read_arg_index
22; CGSCC-SAME: (ptr nofree noundef nonnull readonly align 16 captures(none) dereferenceable(1024) [[P:%.*]]) #[[ATTR0]] {
23; CGSCC-NEXT:  entry:
24; CGSCC-NEXT:    [[G:%.*]] = getelementptr inbounds i8, ptr [[P]], i64 2
25; CGSCC-NEXT:    [[L:%.*]] = load i8, ptr [[G]], align 1
26; CGSCC-NEXT:    ret i8 [[L]]
27;
28entry:
29  %g = getelementptr inbounds i8, ptr %p, i64 %index
30  %l = load i8, ptr %g, align 1
31  ret i8 %l
32}
33
34define i8 @call_simplifiable_1() {
35; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
36; TUNIT-LABEL: define {{[^@]+}}@call_simplifiable_1
37; TUNIT-SAME: () #[[ATTR0:[0-9]+]] {
38; TUNIT-NEXT:  entry:
39; TUNIT-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
40; TUNIT-NEXT:    [[I0:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 2
41; TUNIT-NEXT:    ret i8 2
42;
43; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
44; CGSCC-LABEL: define {{[^@]+}}@call_simplifiable_1
45; CGSCC-SAME: () #[[ATTR1:[0-9]+]] {
46; CGSCC-NEXT:  entry:
47; CGSCC-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
48; CGSCC-NEXT:    [[I0:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 2
49; CGSCC-NEXT:    store i8 2, ptr [[I0]], align 2
50; CGSCC-NEXT:    [[R:%.*]] = call i8 @read_arg(ptr nofree noundef nonnull readonly align 2 captures(none) dereferenceable(1022) [[I0]]) #[[ATTR3:[0-9]+]]
51; CGSCC-NEXT:    ret i8 [[R]]
52;
53entry:
54  %Bytes = alloca [1024 x i8], align 16
55  %i0 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 2
56  store i8 2, ptr %i0, align 1
57  %r = call i8 @read_arg(ptr %i0)
58  ret i8 %r
59}
60
61;;; Same as read_arg, but we need a copy to form distinct leaves in the callgraph.
62
63define internal i8 @read_arg_1(ptr %p) {
64; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
65; CGSCC-LABEL: define {{[^@]+}}@read_arg_1
66; CGSCC-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(1) [[P:%.*]]) #[[ATTR0]] {
67; CGSCC-NEXT:  entry:
68; CGSCC-NEXT:    [[L:%.*]] = load i8, ptr [[P]], align 1
69; CGSCC-NEXT:    ret i8 [[L]]
70;
71entry:
72  %l = load i8, ptr %p, align 1
73  ret i8 %l
74}
75
76define internal i8 @sum_two_same_loads(ptr %p) {
77; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)
78; CGSCC-LABEL: define {{[^@]+}}@sum_two_same_loads
79; CGSCC-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(1022) [[P:%.*]]) #[[ATTR2:[0-9]+]] {
80; CGSCC-NEXT:    [[X:%.*]] = call i8 @read_arg_1(ptr nofree noundef nonnull readonly captures(none) dereferenceable(1022) [[P]]) #[[ATTR3]]
81; CGSCC-NEXT:    [[Y:%.*]] = call i8 @read_arg_1(ptr nofree noundef nonnull readonly captures(none) dereferenceable(1022) [[P]]) #[[ATTR3]]
82; CGSCC-NEXT:    [[Z:%.*]] = add nsw i8 [[X]], [[Y]]
83; CGSCC-NEXT:    ret i8 [[Z]]
84;
85  %x = call i8 @read_arg_1(ptr %p)
86  %y = call i8 @read_arg_1(ptr %p)
87  %z = add nsw i8 %x, %y
88  ret i8 %z
89}
90
91define i8 @call_simplifiable_2() {
92; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
93; TUNIT-LABEL: define {{[^@]+}}@call_simplifiable_2
94; TUNIT-SAME: () #[[ATTR0]] {
95; TUNIT-NEXT:  entry:
96; TUNIT-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
97; TUNIT-NEXT:    [[I0:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 2
98; TUNIT-NEXT:    [[I1:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 3
99; TUNIT-NEXT:    ret i8 4
100;
101; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
102; CGSCC-LABEL: define {{[^@]+}}@call_simplifiable_2
103; CGSCC-SAME: () #[[ATTR1]] {
104; CGSCC-NEXT:  entry:
105; CGSCC-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
106; CGSCC-NEXT:    [[I0:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 2
107; CGSCC-NEXT:    store i8 2, ptr [[I0]], align 2
108; CGSCC-NEXT:    [[I1:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 3
109; CGSCC-NEXT:    store i8 3, ptr [[I1]], align 1
110; CGSCC-NEXT:    [[R:%.*]] = call i8 @sum_two_same_loads(ptr nofree noundef nonnull readonly align 2 captures(none) dereferenceable(1022) [[I0]]) #[[ATTR3]]
111; CGSCC-NEXT:    ret i8 [[R]]
112;
113entry:
114  %Bytes = alloca [1024 x i8], align 16
115  %i0 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 2
116  store i8 2, ptr %i0
117  %i1 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 3
118  store i8 3, ptr %i1
119  %r = call i8 @sum_two_same_loads(ptr %i0)
120  ret i8 %r
121}
122
123define i8 @call_simplifiable_3() {
124; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
125; TUNIT-LABEL: define {{[^@]+}}@call_simplifiable_3
126; TUNIT-SAME: () #[[ATTR0]] {
127; TUNIT-NEXT:  entry:
128; TUNIT-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
129; TUNIT-NEXT:    [[I2:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 2
130; TUNIT-NEXT:    ret i8 2
131;
132; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
133; CGSCC-LABEL: define {{[^@]+}}@call_simplifiable_3
134; CGSCC-SAME: () #[[ATTR1]] {
135; CGSCC-NEXT:  entry:
136; CGSCC-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
137; CGSCC-NEXT:    [[I2:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 2
138; CGSCC-NEXT:    store i8 2, ptr [[I2]], align 2
139; CGSCC-NEXT:    [[R:%.*]] = call i8 @read_arg_index(ptr nofree noundef nonnull readonly align 16 captures(none) dereferenceable(1024) [[BYTES]]) #[[ATTR3]]
140; CGSCC-NEXT:    ret i8 [[R]]
141;
142entry:
143  %Bytes = alloca [1024 x i8], align 16
144  %i0 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 0
145  %i2 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 2
146  store i8 2, ptr %i2, align 1
147  %r = call i8 @read_arg_index(ptr %i0, i64 2)
148  ret i8 %r
149}
150
151;;; Same as read_arg, but we need a copy to form distinct leaves in the callgraph.
152
153define internal i8 @read_arg_2(ptr %p) {
154; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
155; TUNIT-LABEL: define {{[^@]+}}@read_arg_2
156; TUNIT-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(971) [[P:%.*]]) #[[ATTR1:[0-9]+]] {
157; TUNIT-NEXT:  entry:
158; TUNIT-NEXT:    [[L:%.*]] = load i8, ptr [[P]], align 1
159; TUNIT-NEXT:    ret i8 [[L]]
160;
161; CGSCC: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
162; CGSCC-LABEL: define {{[^@]+}}@read_arg_2
163; CGSCC-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(1) [[P:%.*]]) #[[ATTR0]] {
164; CGSCC-NEXT:  entry:
165; CGSCC-NEXT:    [[L:%.*]] = load i8, ptr [[P]], align 1
166; CGSCC-NEXT:    ret i8 [[L]]
167;
168entry:
169  %l = load i8, ptr %p, align 1
170  ret i8 %l
171}
172
173define internal i8 @sum_two_different_loads(ptr %p, ptr %q) {
174; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read)
175; TUNIT-LABEL: define {{[^@]+}}@sum_two_different_loads
176; TUNIT-SAME: (ptr nofree nonnull readonly captures(none) dereferenceable(972) [[P:%.*]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(971) [[Q:%.*]]) #[[ATTR1]] {
177; TUNIT-NEXT:    [[X:%.*]] = call i8 @read_arg_2(ptr nofree noundef nonnull readonly captures(none) dereferenceable(972) [[P]]) #[[ATTR2:[0-9]+]]
178; TUNIT-NEXT:    [[Y:%.*]] = call i8 @read_arg_2(ptr nofree noundef nonnull readonly captures(none) dereferenceable(971) [[Q]]) #[[ATTR2]]
179; TUNIT-NEXT:    [[Z:%.*]] = add nsw i8 [[X]], [[Y]]
180; TUNIT-NEXT:    ret i8 [[Z]]
181;
182; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(argmem: read)
183; CGSCC-LABEL: define {{[^@]+}}@sum_two_different_loads
184; CGSCC-SAME: (ptr nofree noundef nonnull readonly captures(none) dereferenceable(972) [[P:%.*]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(971) [[Q:%.*]]) #[[ATTR2]] {
185; CGSCC-NEXT:    [[X:%.*]] = call i8 @read_arg_2(ptr nofree noundef nonnull readonly captures(none) dereferenceable(972) [[P]]) #[[ATTR3]]
186; CGSCC-NEXT:    [[Y:%.*]] = call i8 @read_arg_2(ptr nofree noundef nonnull readonly captures(none) dereferenceable(971) [[Q]]) #[[ATTR3]]
187; CGSCC-NEXT:    [[Z:%.*]] = add nsw i8 [[X]], [[Y]]
188; CGSCC-NEXT:    ret i8 [[Z]]
189;
190  %x = call i8 @read_arg_2(ptr %p)
191  %y = call i8 @read_arg_2(ptr %q)
192  %z = add nsw i8 %x, %y
193  ret i8 %z
194}
195
196define i8 @call_partially_simplifiable_1() {
197; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
198; TUNIT-LABEL: define {{[^@]+}}@call_partially_simplifiable_1
199; TUNIT-SAME: () #[[ATTR0]] {
200; TUNIT-NEXT:  entry:
201; TUNIT-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
202; TUNIT-NEXT:    [[I2:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 2
203; TUNIT-NEXT:    store i8 2, ptr [[I2]], align 2
204; TUNIT-NEXT:    [[I3:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 3
205; TUNIT-NEXT:    store i8 3, ptr [[I3]], align 1
206; TUNIT-NEXT:    [[I4:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 4
207; TUNIT-NEXT:    [[R:%.*]] = call i8 @sum_two_different_loads(ptr nofree noundef nonnull readonly align 2 captures(none) dereferenceable(1022) [[I2]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(1021) [[I3]]) #[[ATTR3:[0-9]+]]
208; TUNIT-NEXT:    ret i8 [[R]]
209;
210; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
211; CGSCC-LABEL: define {{[^@]+}}@call_partially_simplifiable_1
212; CGSCC-SAME: () #[[ATTR1]] {
213; CGSCC-NEXT:  entry:
214; CGSCC-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
215; CGSCC-NEXT:    [[I2:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 2
216; CGSCC-NEXT:    store i8 2, ptr [[I2]], align 2
217; CGSCC-NEXT:    [[I3:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 3
218; CGSCC-NEXT:    store i8 3, ptr [[I3]], align 1
219; CGSCC-NEXT:    [[I4:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 4
220; CGSCC-NEXT:    store i8 4, ptr [[I4]], align 4
221; CGSCC-NEXT:    [[R:%.*]] = call i8 @sum_two_different_loads(ptr nofree noundef nonnull readonly align 2 captures(none) dereferenceable(1022) [[I2]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(1021) [[I3]]) #[[ATTR3]]
222; CGSCC-NEXT:    ret i8 [[R]]
223;
224entry:
225  %Bytes = alloca [1024 x i8], align 16
226  %i2 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 2
227  store i8 2, ptr %i2
228  %i3 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 3
229  store i8 3, ptr %i3
230  %i4 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 4
231  ;;; This store is redundant, hence removed.
232  store i8 4, ptr %i4
233  %r = call i8 @sum_two_different_loads(ptr %i2, ptr %i3)
234  ret i8 %r
235}
236
237define i8 @call_partially_simplifiable_2(i1 %cond) {
238; TUNIT: Function Attrs: mustprogress nofree norecurse nosync nounwind willreturn memory(none)
239; TUNIT-LABEL: define {{[^@]+}}@call_partially_simplifiable_2
240; TUNIT-SAME: (i1 [[COND:%.*]]) #[[ATTR0]] {
241; TUNIT-NEXT:  entry:
242; TUNIT-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
243; TUNIT-NEXT:    [[I51:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 51
244; TUNIT-NEXT:    [[I52:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 52
245; TUNIT-NEXT:    store i8 2, ptr [[I52]], align 4
246; TUNIT-NEXT:    [[I53:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 53
247; TUNIT-NEXT:    store i8 3, ptr [[I53]], align 1
248; TUNIT-NEXT:    [[I54:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 54
249; TUNIT-NEXT:    [[SEL:%.*]] = select i1 [[COND]], ptr [[I51]], ptr [[I52]]
250; TUNIT-NEXT:    [[R:%.*]] = call i8 @sum_two_different_loads(ptr nofree nonnull readonly captures(none) dereferenceable(972) [[SEL]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(971) [[I53]]) #[[ATTR3]]
251; TUNIT-NEXT:    ret i8 [[R]]
252;
253; CGSCC: Function Attrs: mustprogress nofree nosync nounwind willreturn memory(none)
254; CGSCC-LABEL: define {{[^@]+}}@call_partially_simplifiable_2
255; CGSCC-SAME: (i1 [[COND:%.*]]) #[[ATTR1]] {
256; CGSCC-NEXT:  entry:
257; CGSCC-NEXT:    [[BYTES:%.*]] = alloca [1024 x i8], align 16
258; CGSCC-NEXT:    [[I51:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 51
259; CGSCC-NEXT:    [[I52:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 52
260; CGSCC-NEXT:    store i8 2, ptr [[I52]], align 4
261; CGSCC-NEXT:    [[I53:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 53
262; CGSCC-NEXT:    store i8 3, ptr [[I53]], align 1
263; CGSCC-NEXT:    [[I54:%.*]] = getelementptr inbounds [1024 x i8], ptr [[BYTES]], i64 0, i64 54
264; CGSCC-NEXT:    store i8 4, ptr [[I54]], align 2
265; CGSCC-NEXT:    [[SEL:%.*]] = select i1 [[COND]], ptr [[I51]], ptr [[I52]]
266; CGSCC-NEXT:    [[R:%.*]] = call i8 @sum_two_different_loads(ptr nofree noundef nonnull readonly captures(none) dereferenceable(972) [[SEL]], ptr nofree noundef nonnull readonly captures(none) dereferenceable(971) [[I53]]) #[[ATTR3]]
267; CGSCC-NEXT:    ret i8 [[R]]
268;
269entry:
270  %Bytes = alloca [1024 x i8], align 16
271  %i51 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 51
272  %i52 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 52
273  store i8 2, ptr %i52
274  %i53 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 53
275  store i8 3, ptr %i53
276  %i54 = getelementptr inbounds [1024 x i8], ptr %Bytes, i64 0, i64 54
277  ;;; This store is redundant, hence removed. Not affected by the select.
278  store i8 4, ptr %i54
279  %sel = select i1 %cond, ptr %i51, ptr %i52
280  %r = call i8 @sum_two_different_loads(ptr %sel, ptr %i53)
281  ret i8 %r
282}
283
284;.
285; TUNIT: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(none) }
286; TUNIT: attributes #[[ATTR1]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
287; TUNIT: attributes #[[ATTR2]] = { nofree nosync nounwind willreturn memory(read) }
288; TUNIT: attributes #[[ATTR3]] = { nofree norecurse nosync nounwind willreturn memory(read) }
289;.
290; CGSCC: attributes #[[ATTR0]] = { mustprogress nofree norecurse nosync nounwind willreturn memory(argmem: read) }
291; CGSCC: attributes #[[ATTR1]] = { mustprogress nofree nosync nounwind willreturn memory(none) }
292; CGSCC: attributes #[[ATTR2]] = { mustprogress nofree nosync nounwind willreturn memory(argmem: read) }
293; CGSCC: attributes #[[ATTR3]] = { nofree willreturn memory(read) }
294;.
295