xref: /llvm-project/llvm/test/Transforms/InstCombine/strlen-6.ll (revision 10f315dc9c96ec2413881ab55a285e35d80def88)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that strlen calls with members of constant structs are folded.
3;
4; RUN: opt < %s -passes=instcombine -S | FileCheck %s
5
6; struct A_a4 { char a[4]; };
7%struct.A_a4 = type { [4 x i8] }
8
9; struct A_a4_a5 { char a[4], b[5]; };
10%struct.A_a4_a5 = type { [4 x i8], [5 x i8] }
11
12; struct A_a4_i32_a5 { char a[4]; int32_t i; char b[5]; };
13%struct.A_a4_i32_a5 = type { [4 x i8], i32, [5 x i8] }
14
15@a_s3 = constant %struct.A_a4 { [4 x i8 ] c"123\00" }
16@a_s3_s4 = constant %struct.A_a4_a5 { [4 x i8 ] c"123\00", [5 x i8] c"1234\00" }
17@a_s3_i32_s4 = constant %struct.A_a4_i32_a5 { [4 x i8 ] c"123\00", i32 -1, [5 x i8] c"1234\00" }
18
19; Structs with flexible array members.
20@ax_s3 = constant { i8, [4 x i8] } { i8 3, [4 x i8] c"123\00" }
21@ax_s5 = constant { i16, [6 x i8] } { i16 5, [6 x i8] c"12345\00" }
22@ax_s7 = constant { i32, i32, [8 x i8] } { i32 7, i32 0, [8 x i8] c"1234567\00" }
23
24@ax = external global [0 x i64]
25
26
27declare i64 @strlen(ptr)
28
29
30; Fold strlen(a_s3.a) to 3.
31
32define i64 @fold_strlen_a_S3_to_3() {
33; CHECK-LABEL: @fold_strlen_a_S3_to_3(
34; CHECK-NEXT:    ret i64 3
35;
36  %len = call i64 @strlen(ptr @a_s3)
37  ret i64 %len
38}
39
40
41; Fold strlen(&a_s3.a[1]) to 2.
42
43define i64 @fold_strlen_a_S3_p1_to_2() {
44; CHECK-LABEL: @fold_strlen_a_S3_p1_to_2(
45; CHECK-NEXT:    ret i64 2
46;
47  %ptr = getelementptr %struct.A_a4, ptr @a_s3, i32 0, i32 0, i32 1
48  %len = call i64 @strlen(ptr %ptr)
49  ret i64 %len
50}
51
52
53; Fold strlen(&a_s3.a[2]) to 1.
54
55define i64 @fold_strlen_a_S3_p2_to_1() {
56; CHECK-LABEL: @fold_strlen_a_S3_p2_to_1(
57; CHECK-NEXT:    ret i64 1
58;
59  %ptr = getelementptr %struct.A_a4, ptr @a_s3, i32 0, i32 0, i32 2
60  %len = call i64 @strlen(ptr %ptr)
61  ret i64 %len
62}
63
64
65; Fold strlen(&a_s3.a[3]) to 0.
66
67define i64 @fold_strlen_a_S3_p3_to_0() {
68; CHECK-LABEL: @fold_strlen_a_S3_p3_to_0(
69; CHECK-NEXT:    ret i64 0
70;
71  %ptr = getelementptr %struct.A_a4, ptr @a_s3, i32 0, i32 0, i32 3
72  %len = call i64 @strlen(ptr %ptr)
73  ret i64 %len
74}
75
76
77; Fold strlen(a_s3_s4.a) to 3.
78
79define i64 @fold_strlen_a_S3_s4_to_3() {
80; CHECK-LABEL: @fold_strlen_a_S3_s4_to_3(
81; CHECK-NEXT:    ret i64 3
82;
83  %len = call i64 @strlen(ptr @a_s3_s4)
84  ret i64 %len
85}
86
87
88; Fold strlen(&a_s3_s4.a[2]) to 1.
89
90define i64 @fold_strlen_a_S3_p2_s4_to_1() {
91; CHECK-LABEL: @fold_strlen_a_S3_p2_s4_to_1(
92; CHECK-NEXT:    ret i64 1
93;
94  %ptr = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 0, i32 2
95  %len = call i64 @strlen(ptr %ptr)
96  ret i64 %len
97}
98
99
100; Fold strlen(a_s3_s4.b) to 4.
101; Exercise both variants of the GEP index.
102
103define void @fold_strlen_a_s3_S4_to_4() {
104; CHECK-LABEL: @fold_strlen_a_s3_S4_to_4(
105; CHECK-NEXT:    store i64 4, ptr @ax, align 4
106; CHECK-NEXT:    store i64 4, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4
107; CHECK-NEXT:    ret void
108;
109  %p1 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 0, i32 4
110  %len1 = call i64 @strlen(ptr %p1)
111  store i64 %len1, ptr @ax
112
113  %p2 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 1, i32 0
114  %len2 = call i64 @strlen(ptr %p2)
115  %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1
116  store i64 %len1, ptr %pax1
117
118  ret void
119}
120
121
122; Fold strlen(&a_s3_s4.b[1]) to 3.
123; Exercise both variants of the GEP index.
124
125define void @fold_strlen_a_s3_S4_p1_to_3() {
126; CHECK-LABEL: @fold_strlen_a_s3_S4_p1_to_3(
127; CHECK-NEXT:    store i64 3, ptr @ax, align 4
128; CHECK-NEXT:    store i64 3, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4
129; CHECK-NEXT:    ret void
130;
131  %p1 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 0, i32 5
132  %len1 = call i64 @strlen(ptr %p1)
133  store i64 %len1, ptr @ax
134
135  %p2 = getelementptr %struct.A_a4_a5, ptr @a_s3_s4, i32 0, i32 1, i32 1
136  %len2 = call i64 @strlen(ptr %p2)
137  %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1
138  store i64 %len1, ptr %pax1
139
140  ret void
141}
142
143
144; Fold strlen(a_s3_i32_s4.b) to 4.
145; Exercise both variants of the GEP index.
146
147define void @fold_strlen_a_s3_i32_S4_to_4() {
148; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_to_4(
149; CHECK-NEXT:    store i64 4, ptr @ax, align 4
150; CHECK-NEXT:    store i64 4, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4
151; CHECK-NEXT:    ret void
152;
153  %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 8
154  %len1 = call i64 @strlen(ptr %p1)
155  store i64 %len1, ptr @ax
156
157  %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 0
158  %len2 = call i64 @strlen(ptr %p2)
159  %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1
160  store i64 %len1, ptr %pax1
161
162  ret void
163}
164
165
166; Fold strlen(&a_s3_i32_s4.b[1]) to 3.
167; Exercise both variants of the GEP index.
168
169define void @fold_strlen_a_s3_i32_S4_p1_to_3() {
170; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p1_to_3(
171; CHECK-NEXT:    store i64 3, ptr @ax, align 4
172; CHECK-NEXT:    store i64 3, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4
173; CHECK-NEXT:    ret void
174;
175  %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 9
176  %len1 = call i64 @strlen(ptr %p1)
177  store i64 %len1, ptr @ax
178
179  %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 0
180  %len2 = call i64 @strlen(ptr %p2)
181  %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1
182  store i64 %len1, ptr %pax1
183
184  ret void
185}
186
187
188; Fold strlen(&a_s3_i32_s4.b[2]) to 2.
189; Exercise both variants of the GEP index.
190
191define void @fold_strlen_a_s3_i32_S4_p2_to_2() {
192; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p2_to_2(
193; CHECK-NEXT:    store i64 2, ptr @ax, align 4
194; CHECK-NEXT:    store i64 2, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4
195; CHECK-NEXT:    ret void
196;
197  %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 10
198  %len1 = call i64 @strlen(ptr %p1)
199  store i64 %len1, ptr @ax
200
201  %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 2
202  %len2 = call i64 @strlen(ptr %p2)
203  %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1
204  store i64 %len1, ptr %pax1
205
206  ret void
207}
208
209
210; Fold strlen(&a_s3_i32_s4.b[3]) to 1.
211; Exercise both variants of the GEP index.
212
213define void @fold_strlen_a_s3_i32_S4_p3_to_1() {
214; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p3_to_1(
215; CHECK-NEXT:    store i64 1, ptr @ax, align 4
216; CHECK-NEXT:    store i64 1, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4
217; CHECK-NEXT:    ret void
218;
219  %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 11
220  %len1 = call i64 @strlen(ptr %p1)
221  store i64 %len1, ptr @ax
222
223  %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 3
224  %len2 = call i64 @strlen(ptr %p2)
225  %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1
226  store i64 %len1, ptr %pax1
227
228  ret void
229}
230
231
232; Fold strlen(&a_s3_i32_s4.b[4]) to 0.
233; Exercise both variants of the GEP index.
234
235define void @fold_strlen_a_s3_i32_S4_p4_to_0() {
236; CHECK-LABEL: @fold_strlen_a_s3_i32_S4_p4_to_0(
237; CHECK-NEXT:    store i64 0, ptr @ax, align 4
238; CHECK-NEXT:    store i64 0, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4
239; CHECK-NEXT:    ret void
240;
241  %p1 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 0, i32 12
242  %len1 = call i64 @strlen(ptr %p1)
243  store i64 %len1, ptr @ax
244
245  %p2 = getelementptr %struct.A_a4_i32_a5, ptr @a_s3_i32_s4, i32 0, i32 2, i32 4
246  %len2 = call i64 @strlen(ptr %p2)
247  %pax1 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1
248  store i64 %len1, ptr %pax1
249
250  ret void
251}
252
253
254; Fold strlen(ax_sN.a) of an constant initialized flexible array member
255; to N for N in { 3, 5, 7 }.
256
257define void @fold_strlen_ax_s() {
258; CHECK-LABEL: @fold_strlen_ax_s(
259; CHECK-NEXT:    store i64 3, ptr @ax, align 4
260; CHECK-NEXT:    store i64 5, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 8), align 4
261; CHECK-NEXT:    store i64 7, ptr getelementptr inbounds nuw (i8, ptr @ax, i64 16), align 4
262; CHECK-NEXT:    ret void
263;
264  %pax_s3 = getelementptr { i8, [4 x i8] }, ptr @ax_s3, i64 0, i32 1, i64 0
265  %len3 = call i64 @strlen(ptr %pax_s3)
266  store i64 %len3, ptr @ax
267
268  %pax_s5 = getelementptr { i16, [6 x i8] }, ptr @ax_s5, i64 0, i32 1, i64 0
269  %len5 = call i64 @strlen(ptr %pax_s5)
270  %pax2 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 1
271  store i64 %len5, ptr %pax2
272
273  %pax_s7 = getelementptr { i32, i32, [8 x i8] }, ptr @ax_s7, i64 0, i32 2, i64 0
274  %len7 = call i64 @strlen(ptr %pax_s7)
275  %pax3 = getelementptr inbounds [0 x i64], ptr @ax, i64 0, i64 2
276  store i64 %len7, ptr %pax3
277
278  ret void
279}
280