1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; Verify that strlen calls with members of constant structs are folded.
4 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
6 declare i64 @strlen(ptr)
8 %struct.A = type { [4 x i8], [5 x i8] }
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
13 ; Fold strlen(a[I].a + J) and strlen(a[I].b + J) with constant I and J
16 define 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
55 ; Fold strlen(a[0].a) to 1.
56 %lena0a = call i64 @strlen(ptr @a)
57 store i64 %lena0a, ptr %plen
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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.
168 define 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
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
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
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
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