xref: /llvm-project/llvm/test/Transforms/InstCombine/strlen-7.ll (revision 90ba33099cbb17e7c159e9ebc5a512037db99d6d)
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
6declare i64 @strlen(ptr)
7
8%struct.A = type { [4 x i8], [5 x i8] }
9
10@a = constant [2 x %struct.A] [%struct.A { [4 x i8] c"1\00\00\00", [5 x i8] c"12\00\00\00" }, %struct.A { [4 x i8] c"123\00", [5 x i8] c"1234\00" }], align 16
11
12
13; Fold strlen(a[I].a + J) and strlen(a[I].b + J) with constant I and J
14; to constants.
15
16define void @fold_strlen_A(ptr %plen) {
17; CHECK-LABEL: @fold_strlen_A(
18; CHECK-NEXT:    store i64 1, ptr [[PLEN:%.*]], align 4
19; CHECK-NEXT:    [[PLEN1:%.*]] = getelementptr i8, ptr [[PLEN]], i64 8
20; CHECK-NEXT:    store i64 0, ptr [[PLEN1]], align 4
21; CHECK-NEXT:    [[PLEN2:%.*]] = getelementptr i8, ptr [[PLEN]], i64 16
22; CHECK-NEXT:    store i64 0, ptr [[PLEN2]], align 4
23; CHECK-NEXT:    [[PLEN3:%.*]] = getelementptr i8, ptr [[PLEN]], i64 24
24; CHECK-NEXT:    store i64 0, ptr [[PLEN3]], align 4
25; CHECK-NEXT:    [[PLEN4:%.*]] = getelementptr i8, ptr [[PLEN]], i64 32
26; CHECK-NEXT:    store i64 2, ptr [[PLEN4]], align 4
27; CHECK-NEXT:    [[PLEN5:%.*]] = getelementptr i8, ptr [[PLEN]], i64 40
28; CHECK-NEXT:    store i64 1, ptr [[PLEN5]], align 4
29; CHECK-NEXT:    [[PLEN6:%.*]] = getelementptr i8, ptr [[PLEN]], i64 48
30; CHECK-NEXT:    store i64 0, ptr [[PLEN6]], align 4
31; CHECK-NEXT:    [[PLEN7:%.*]] = getelementptr i8, ptr [[PLEN]], i64 56
32; CHECK-NEXT:    store i64 0, ptr [[PLEN7]], align 4
33; CHECK-NEXT:    [[PLEN8:%.*]] = getelementptr i8, ptr [[PLEN]], i64 64
34; CHECK-NEXT:    store i64 0, ptr [[PLEN8]], align 4
35; CHECK-NEXT:    [[PLEN9:%.*]] = getelementptr i8, ptr [[PLEN]], i64 72
36; CHECK-NEXT:    store i64 3, ptr [[PLEN9]], align 4
37; CHECK-NEXT:    [[PLEN10:%.*]] = getelementptr i8, ptr [[PLEN]], i64 80
38; CHECK-NEXT:    store i64 2, ptr [[PLEN10]], align 4
39; CHECK-NEXT:    [[PLEN11:%.*]] = getelementptr i8, ptr [[PLEN]], i64 88
40; CHECK-NEXT:    store i64 1, ptr [[PLEN11]], align 4
41; CHECK-NEXT:    [[PLEN12:%.*]] = getelementptr i8, ptr [[PLEN]], i64 96
42; CHECK-NEXT:    store i64 0, ptr [[PLEN12]], align 4
43; CHECK-NEXT:    [[PLEN14:%.*]] = getelementptr i8, ptr [[PLEN]], i64 112
44; CHECK-NEXT:    store i64 4, ptr [[PLEN14]], align 4
45; CHECK-NEXT:    [[PLEN15:%.*]] = getelementptr i8, ptr [[PLEN]], i64 120
46; CHECK-NEXT:    store i64 3, ptr [[PLEN15]], align 4
47; CHECK-NEXT:    [[PLEN16:%.*]] = getelementptr i8, ptr [[PLEN]], i64 128
48; CHECK-NEXT:    store i64 2, ptr [[PLEN16]], align 4
49; CHECK-NEXT:    [[PLEN17:%.*]] = getelementptr i8, ptr [[PLEN]], i64 136
50; CHECK-NEXT:    store i64 1, ptr [[PLEN17]], align 4
51; CHECK-NEXT:    [[PLEN18:%.*]] = getelementptr i8, ptr [[PLEN]], i64 144
52; CHECK-NEXT:    store i64 0, ptr [[PLEN18]], align 4
53; CHECK-NEXT:    ret void
54;
55; Fold strlen(a[0].a) to 1.
56  %lena0a = call i64 @strlen(ptr @a)
57  store i64 %lena0a, ptr %plen
58
59; Fold strlen(a[0].a + 1) to 0.
60  %pa0ap1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 1
61  %lena0ap1 = call i64 @strlen(ptr %pa0ap1)
62  %plen1 = getelementptr i64, ptr %plen, i32 1
63  store i64 %lena0ap1, ptr %plen1
64
65; Fold strlen(a[0].a + 2) to 0.
66  %pa0ap2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 2
67  %lena0ap2 = call i64 @strlen(ptr %pa0ap2)
68  %plen2 = getelementptr i64, ptr %plen, i32 2
69  store i64 %lena0ap2, ptr %plen2
70
71; Fold strlen(a[0].a + 3) to 0.
72  %pa0ap3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 3
73  %lena0ap3 = call i64 @strlen(ptr %pa0ap3)
74  %plen3 = getelementptr i64, ptr %plen, i32 3
75  store i64 %lena0ap3, ptr %plen3
76
77; Fold strlen(a[0].b) to 2.
78  %pa0b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 0
79  %lena0b = call i64 @strlen(ptr %pa0b)
80  %plen4 = getelementptr i64, ptr %plen, i32 4
81  store i64 %lena0b, ptr %plen4
82
83; Fold strlen(a[0].b + 1) to 1.
84  %pa0bp1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1
85  %lena0bp1 = call i64 @strlen(ptr %pa0bp1)
86  %plen5 = getelementptr i64, ptr %plen, i32 5
87  store i64 %lena0bp1, ptr %plen5
88
89; Fold strlen(a[0].b + 2) to 0.
90  %pa0bp2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 2
91  %lena0bp2 = call i64 @strlen(ptr %pa0bp2)
92  %plen6 = getelementptr i64, ptr %plen, i32 6
93  store i64 %lena0bp2, ptr %plen6
94
95; Fold strlen(a[0].b + 3) to 0.
96  %pa0bp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 3
97  %lena0bp3 = call i64 @strlen(ptr %pa0bp3)
98  %plen7 = getelementptr i64, ptr %plen, i32 7
99  store i64 %lena0bp3, ptr %plen7
100
101; Fold strlen(a[0].b + 4) to 0.
102  %pa0bp4 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 4
103  %lena0bp4 = call i64 @strlen(ptr %pa0bp4)
104  %plen8 = getelementptr i64, ptr %plen, i32 8
105  store i64 %lena0bp4, ptr %plen8
106
107; Fold strlen(a[1].a) to 3.
108  %pa1a = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 0
109  %lena1a = call i64 @strlen(ptr %pa1a)
110  %plen9 = getelementptr i64, ptr %plen, i32 9
111  store i64 %lena1a, ptr %plen9
112
113; Fold strlen(a[1].a + 1) to 2.
114  %pa1ap1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 1
115  %lena1ap1 = call i64 @strlen(ptr %pa1ap1)
116  %plen10 = getelementptr i64, ptr %plen, i32 10
117  store i64 %lena1ap1, ptr %plen10
118
119; Fold strlen(a[1].a + 2) to 1.
120  %pa1ap2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 2
121  %lena1ap2 = call i64 @strlen(ptr %pa1ap2)
122  %plen11 = getelementptr i64, ptr %plen, i32 11
123  store i64 %lena1ap2, ptr %plen11
124
125; Fold strlen(a[1].a + 3) to 0.
126  %pa1ap3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 3
127  %lena1ap3 = call i64 @strlen(ptr %pa1ap3)
128  %plen12 = getelementptr i64, ptr %plen, i32 12
129  store i64 %lena1ap3, ptr %plen12
130
131; Fold strlen(a[1].b) to 4.
132  %pa1b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 0
133  %lena1b = call i64 @strlen(ptr %pa1b)
134  %plen14 = getelementptr i64, ptr %plen, i32 14
135  store i64 %lena1b, ptr %plen14
136
137; Fold strlen(a[1].b + 1) to 3.
138  %pa1bp1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 1
139  %lena1bp1 = call i64 @strlen(ptr %pa1bp1)
140  %plen15 = getelementptr i64, ptr %plen, i32 15
141  store i64 %lena1bp1, ptr %plen15
142
143; Fold strlen(a[1].b + 2) to 2.
144  %pa1bp2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 2
145  %lena1bp2 = call i64 @strlen(ptr %pa1bp2)
146  %plen16 = getelementptr i64, ptr %plen, i32 16
147  store i64 %lena1bp2, ptr %plen16
148
149; Fold strlen(a[1].b + 3) to 1.
150  %pa1bp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 3
151  %lena1bp3 = call i64 @strlen(ptr %pa1bp3)
152  %plen17 = getelementptr i64, ptr %plen, i32 17
153  store i64 %lena1bp3, ptr %plen17
154
155; Fold strlen(a[1].b + 4) to 0.
156  %pa1bp4 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 4
157  %lena1bp4 = call i64 @strlen(ptr %pa1bp4)
158  %plen18 = getelementptr i64, ptr %plen, i32 18
159  store i64 %lena1bp4, ptr %plen18
160
161  ret void
162}
163
164
165; TODO: Fold strlen(a[I].a + X) and strlen(a[I].b + X) with constant I and
166; variable X to (X - strlen(a[I].a)) and (X - strlen(a[I].b)) respectively.
167
168define void @fold_strlen_A_pI(ptr %plen, i64 %I) {
169; CHECK-LABEL: @fold_strlen_A_pI(
170; CHECK-NEXT:    [[PA0A:%.*]] = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 [[I:%.*]]
171; CHECK-NEXT:    [[LENA0A:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[PA0A]])
172; CHECK-NEXT:    store i64 [[LENA0A]], ptr [[PLEN:%.*]], align 4
173; CHECK-NEXT:    [[PA0B:%.*]] = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 [[I]]
174; CHECK-NEXT:    [[LENA0B:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[PA0B]])
175; CHECK-NEXT:    [[PLEN1:%.*]] = getelementptr i8, ptr [[PLEN]], i64 8
176; CHECK-NEXT:    store i64 [[LENA0B]], ptr [[PLEN1]], align 4
177; CHECK-NEXT:    [[PA1A:%.*]] = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 [[I]]
178; CHECK-NEXT:    [[LENA1A:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[PA1A]])
179; CHECK-NEXT:    [[PLEN2:%.*]] = getelementptr i8, ptr [[PLEN]], i64 16
180; CHECK-NEXT:    store i64 [[LENA1A]], ptr [[PLEN2]], align 4
181; CHECK-NEXT:    [[PA1B:%.*]] = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 [[I]]
182; CHECK-NEXT:    [[LENA1B:%.*]] = call i64 @strlen(ptr noundef nonnull dereferenceable(1) [[PA1B]])
183; CHECK-NEXT:    [[PLEN3:%.*]] = getelementptr i8, ptr [[PLEN]], i64 24
184; CHECK-NEXT:    store i64 [[LENA1B]], ptr [[PLEN3]], align 4
185; CHECK-NEXT:    ret void
186;
187  %pa0a = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 %I
188  %lena0a = call i64 @strlen(ptr %pa0a)
189  store i64 %lena0a, ptr %plen
190
191  %pa0b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 %I
192  %lena0b = call i64 @strlen(ptr %pa0b)
193  %plen1 = getelementptr i64, ptr %plen, i32 1
194  store i64 %lena0b, ptr %plen1
195
196  %pa1a = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 %I
197  %lena1a = call i64 @strlen(ptr %pa1a)
198  %plen2 = getelementptr i64, ptr %plen, i32 2
199  store i64 %lena1a, ptr %plen2
200
201  %pa1b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 %I
202  %lena1b = call i64 @strlen(ptr %pa1b)
203  %plen3 = getelementptr i64, ptr %plen, i32 3
204  store i64 %lena1b, ptr %plen3
205
206  ret void
207}
208