1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; Verify that calls to atoi and related conversion functions with members
3; of constant structs as arguments are folded to constants as expected.
4; RUN: opt < %s -passes=instcombine -S | FileCheck %s
5
6declare i32 @atoi(i8*)
7declare i64 @atol(i8*)
8declare i64 @atoll(i8*)
9
10declare i64 @strtol(i8*, i8**, i32)
11declare i64 @strtoll(i8*, i8**, i32)
12
13%struct.A = type { [4 x i8], [5 x i8], [7 x i8] }
14
15@a = constant [2 x %struct.A] [%struct.A { [4 x i8] c"1\00\00\00", [5 x i8] c"12\00\00\00", [7 x i8] c"56789\00\00" }, %struct.A { [4 x i8] c"123\00", [5 x i8] c"1234\00", [7 x i8] c"67890\00\00" }]
16
17
18; Fold atoi(a[I].M) for constant I in [0, 1] and member M in [a, b]
19; to a constant.
20
21define void @fold_atoi_member(i32* %pi) {
22; CHECK-LABEL: @fold_atoi_member(
23; CHECK-NEXT:    [[IA0A:%.*]] = call i32 @atoi(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0))
24; CHECK-NEXT:    store i32 [[IA0A]], i32* [[PI:%.*]], align 4
25; CHECK-NEXT:    [[IA0B:%.*]] = call i32 @atoi(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0))
26; CHECK-NEXT:    [[PIA0B:%.*]] = getelementptr i32, i32* [[PI]], i64 1
27; CHECK-NEXT:    store i32 [[IA0B]], i32* [[PIA0B]], align 4
28; CHECK-NEXT:    [[IA1A:%.*]] = call i32 @atoi(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0))
29; CHECK-NEXT:    [[PIA1A:%.*]] = getelementptr i32, i32* [[PI]], i64 2
30; CHECK-NEXT:    store i32 [[IA1A]], i32* [[PIA1A]], align 4
31; CHECK-NEXT:    [[IA1B:%.*]] = call i32 @atoi(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0))
32; CHECK-NEXT:    [[PIA1B:%.*]] = getelementptr i32, i32* [[PI]], i64 3
33; CHECK-NEXT:    store i32 [[IA1B]], i32* [[PIA1B]], align 4
34; CHECK-NEXT:    ret void
35;
36; Fold atoi(a[0].a) to 1.
37  %pa0a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0
38  %ia0a = call i32 @atoi(i8* %pa0a)
39  %pia0a = getelementptr i32, i32* %pi, i32 0
40  store i32 %ia0a, i32* %pia0a
41
42; Fold atoi(a[0].b) to 12.
43  %pa0b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0
44  %ia0b = call i32 @atoi(i8* %pa0b)
45  %pia0b = getelementptr i32, i32* %pi, i32 1
46  store i32 %ia0b, i32* %pia0b
47
48; Fold atoi(a[1].a) to 123.
49  %pa1a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0
50  %ia1a = call i32 @atoi(i8* %pa1a)
51  %pia1a = getelementptr i32, i32* %pi, i32 2
52  store i32 %ia1a, i32* %pia1a
53
54; Fold atoi(a[1].b) to 1234.
55  %pa1b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0
56  %ia1b = call i32 @atoi(i8* %pa1b)
57  %pia1b = getelementptr i32, i32* %pi, i32 3
58  store i32 %ia1b, i32* %pia1b
59
60  ret void
61}
62
63
64; Do not fold atoi with an excessive offset.  It's undefined so folding
65; it (e.g., to zero) would be valid and might prevent crashes or returning
66; a bogus value but could also prevent detecting the bug by sanitizers.
67
68define void @call_atoi_offset_out_of_bounds(i32* %pi) {
69; CHECK-LABEL: @call_atoi_offset_out_of_bounds(
70; CHECK-NEXT:    [[IA_0_0_32:%.*]] = call i32 @atoi(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 1, i64 0, i32 0, i64 0))
71; CHECK-NEXT:    store i32 [[IA_0_0_32]], i32* [[PI:%.*]], align 4
72; CHECK-NEXT:    [[IA_0_0_33:%.*]] = call i32 @atoi(i8* getelementptr ([2 x %struct.A], [2 x %struct.A]* @a, i64 1, i64 0, i32 0, i64 1))
73; CHECK-NEXT:    store i32 [[IA_0_0_33]], i32* [[PI]], align 4
74; CHECK-NEXT:    ret void
75;
76; Do not fold atoi((const char*)a + sizeof a).
77  %pa_0_0_32 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 32
78  %ia_0_0_32 = call i32 @atoi(i8* %pa_0_0_32)
79  %pia_0_0_32 = getelementptr i32, i32* %pi, i32 0
80  store i32 %ia_0_0_32, i32* %pia_0_0_32
81
82; Likewise, do not fold atoi((const char*)a + sizeof a + 1).
83  %pa_0_0_33 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 33
84  %ia_0_0_33 = call i32 @atoi(i8* %pa_0_0_33)
85  %pia_0_0_33 = getelementptr i32, i32* %pi, i32 0
86  store i32 %ia_0_0_33, i32* %pia_0_0_33
87
88  ret void
89}
90
91
92; Fold atol(a[I].M) for constant I in [0, 1] and member M in [a, b, c]
93; to a constant.
94
95define void @fold_atol_member(i64* %pi) {
96; CHECK-LABEL: @fold_atol_member(
97; CHECK-NEXT:    [[IA0A:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0))
98; CHECK-NEXT:    store i64 [[IA0A]], i64* [[PI:%.*]], align 4
99; CHECK-NEXT:    [[IA0B:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0))
100; CHECK-NEXT:    [[PIA0B:%.*]] = getelementptr i64, i64* [[PI]], i64 1
101; CHECK-NEXT:    store i64 [[IA0B]], i64* [[PIA0B]], align 4
102; CHECK-NEXT:    [[IA0C:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 0))
103; CHECK-NEXT:    [[PIA0C:%.*]] = getelementptr i64, i64* [[PI]], i64 2
104; CHECK-NEXT:    store i64 [[IA0C]], i64* [[PIA0C]], align 4
105; CHECK-NEXT:    [[IA1A:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0))
106; CHECK-NEXT:    [[PIA1A:%.*]] = getelementptr i64, i64* [[PI]], i64 3
107; CHECK-NEXT:    store i64 [[IA1A]], i64* [[PIA1A]], align 4
108; CHECK-NEXT:    [[IA1B:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0))
109; CHECK-NEXT:    [[PIA1B:%.*]] = getelementptr i64, i64* [[PI]], i64 4
110; CHECK-NEXT:    store i64 [[IA1B]], i64* [[PIA1B]], align 4
111; CHECK-NEXT:    [[IA1C:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 0))
112; CHECK-NEXT:    [[PIA1C:%.*]] = getelementptr i64, i64* [[PI]], i64 5
113; CHECK-NEXT:    store i64 [[IA1C]], i64* [[PIA1C]], align 4
114; CHECK-NEXT:    ret void
115;
116; Fold atol(a[0].a) to 1.
117  %pa0a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0
118  %ia0a = call i64 @atol(i8* %pa0a)
119  %pia0a = getelementptr i64, i64* %pi, i32 0
120  store i64 %ia0a, i64* %pia0a
121
122; Fold atol(a[0].b) to 12.
123  %pa0b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 0
124  %ia0b = call i64 @atol(i8* %pa0b)
125  %pia0b = getelementptr i64, i64* %pi, i32 1
126  store i64 %ia0b, i64* %pia0b
127
128; Fold atol(a[0].c) to 56789.
129  %pa0c = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 0
130  %ia0c = call i64 @atol(i8* %pa0c)
131  %pia0c = getelementptr i64, i64* %pi, i32 2
132  store i64 %ia0c, i64* %pia0c
133
134; Fold atol(a[1].a) to 123.
135  %pa1a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 0
136  %ia1a = call i64 @atol(i8* %pa1a)
137  %pia1a = getelementptr i64, i64* %pi, i32 3
138  store i64 %ia1a, i64* %pia1a
139
140; Fold atol(a[1].b) to 1234.
141  %pa1b = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 0
142  %ia1b = call i64 @atol(i8* %pa1b)
143  %pia1b = getelementptr i64, i64* %pi, i32 4
144  store i64 %ia1b, i64* %pia1b
145
146; Fold atol(a[1].c) to 67890.
147  %pa1c = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 0
148  %ia1c = call i64 @atol(i8* %pa1c)
149  %pia1c = getelementptr i64, i64* %pi, i32 5
150  store i64 %ia1c, i64* %pia1c
151
152  ret void
153}
154
155
156; Fold atoll(a[I].M + C) for constant I in [0, 1], member M in [a, b, c],
157; and C in a valid range to a constant.
158
159define void @fold_atoll_member_pC(i64* %pi) {
160; CHECK-LABEL: @fold_atoll_member_pC(
161; CHECK-NEXT:    [[IA0A:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0))
162; CHECK-NEXT:    store i64 [[IA0A]], i64* [[PI:%.*]], align 4
163; CHECK-NEXT:    [[IA0BP1:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1))
164; CHECK-NEXT:    [[PIA0BP1:%.*]] = getelementptr i64, i64* [[PI]], i64 1
165; CHECK-NEXT:    store i64 [[IA0BP1]], i64* [[PIA0BP1]], align 4
166; CHECK-NEXT:    [[IA0CP3:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 3))
167; CHECK-NEXT:    [[PIA0CP3:%.*]] = getelementptr i64, i64* [[PI]], i64 2
168; CHECK-NEXT:    store i64 [[IA0CP3]], i64* [[PIA0CP3]], align 4
169; CHECK-NEXT:    [[IA1AP2:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 2))
170; CHECK-NEXT:    [[PIA1AP2:%.*]] = getelementptr i64, i64* [[PI]], i64 3
171; CHECK-NEXT:    store i64 [[IA1AP2]], i64* [[PIA1AP2]], align 4
172; CHECK-NEXT:    [[IA1BP3:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 3))
173; CHECK-NEXT:    [[PIA1BP3:%.*]] = getelementptr i64, i64* [[PI]], i64 4
174; CHECK-NEXT:    store i64 [[IA1BP3]], i64* [[PIA1BP3]], align 4
175; CHECK-NEXT:    [[IA1CP4:%.*]] = call i64 @atol(i8* getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 4))
176; CHECK-NEXT:    [[PIA1CP4:%.*]] = getelementptr i64, i64* [[PI]], i64 5
177; CHECK-NEXT:    store i64 [[IA1CP4]], i64* [[PIA1CP4]], align 4
178; CHECK-NEXT:    ret void
179;
180; Fold atoll(a[0].a) to 1.
181  %pa0a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0
182  %ia0a = call i64 @atol(i8* %pa0a)
183  %pia0a = getelementptr i64, i64* %pi, i32 0
184  store i64 %ia0a, i64* %pia0a
185
186; Fold atoll(a[0].b + 1) to 2.
187  %pa0bp1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1
188  %ia0bp1 = call i64 @atol(i8* %pa0bp1)
189  %pia0bp1 = getelementptr i64, i64* %pi, i32 1
190  store i64 %ia0bp1, i64* %pia0bp1
191
192; Fold atoll(a[0].c + 3) to 89.
193  %pa0cp3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 3
194  %ia0cp3 = call i64 @atol(i8* %pa0cp3)
195  %pia0cp3 = getelementptr i64, i64* %pi, i32 2
196  store i64 %ia0cp3, i64* %pia0cp3
197
198; Fold atoll(a[1].a + 2) to 3.
199  %pa1ap2 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 2
200  %ia1ap2 = call i64 @atol(i8* %pa1ap2)
201  %pia1ap2 = getelementptr i64, i64* %pi, i32 3
202  store i64 %ia1ap2, i64* %pia1ap2
203
204; Fold atoll(a[1].b + 3) to 4.
205  %pa1bp3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 3
206  %ia1bp3 = call i64 @atol(i8* %pa1bp3)
207  %pia1bp3 = getelementptr i64, i64* %pi, i32 4
208  store i64 %ia1bp3, i64* %pia1bp3
209
210; Fold atoll(a[1].c + 4) to 0.
211  %pa1cp4 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 4
212  %ia1cp4 = call i64 @atol(i8* %pa1cp4)
213  %pia1cp4 = getelementptr i64, i64* %pi, i32 5
214  store i64 %ia1cp4, i64* %pia1cp4
215
216  ret void
217}
218
219
220; Fold strtol(a[I].M + C, 0, 0) for constant I in [0, 1], member M in [a, b, c],
221; and C in a valid range to a constant.
222
223define void @fold_strtol_member_pC(i64* %pi) {
224; CHECK-LABEL: @fold_strtol_member_pC(
225; CHECK-NEXT:    [[IA0A:%.*]] = call i64 @strtol(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0), i8** null, i32 0)
226; CHECK-NEXT:    store i64 [[IA0A]], i64* [[PI:%.*]], align 4
227; CHECK-NEXT:    [[IA0BP1:%.*]] = call i64 @strtol(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1), i8** null, i32 0)
228; CHECK-NEXT:    [[PIA0BP1:%.*]] = getelementptr i64, i64* [[PI]], i64 1
229; CHECK-NEXT:    store i64 [[IA0BP1]], i64* [[PIA0BP1]], align 4
230; CHECK-NEXT:    [[IA0CP3:%.*]] = call i64 @strtol(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 3), i8** null, i32 0)
231; CHECK-NEXT:    [[PIA0CP3:%.*]] = getelementptr i64, i64* [[PI]], i64 2
232; CHECK-NEXT:    store i64 [[IA0CP3]], i64* [[PIA0CP3]], align 4
233; CHECK-NEXT:    [[IA1AP2:%.*]] = call i64 @strtol(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 2), i8** null, i32 0)
234; CHECK-NEXT:    [[PIA1AP2:%.*]] = getelementptr i64, i64* [[PI]], i64 3
235; CHECK-NEXT:    store i64 [[IA1AP2]], i64* [[PIA1AP2]], align 4
236; CHECK-NEXT:    [[IA1BP3:%.*]] = call i64 @strtol(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 3), i8** null, i32 0)
237; CHECK-NEXT:    [[PIA1BP3:%.*]] = getelementptr i64, i64* [[PI]], i64 4
238; CHECK-NEXT:    store i64 [[IA1BP3]], i64* [[PIA1BP3]], align 4
239; CHECK-NEXT:    [[IA1CP4:%.*]] = call i64 @strtol(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 4), i8** null, i32 0)
240; CHECK-NEXT:    [[PIA1CP4:%.*]] = getelementptr i64, i64* [[PI]], i64 5
241; CHECK-NEXT:    store i64 [[IA1CP4]], i64* [[PIA1CP4]], align 4
242; CHECK-NEXT:    ret void
243;
244; Fold strtol(a[0].a, 0, 0) to 1.
245  %pa0a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0
246  %ia0a = call i64 @strtol(i8* %pa0a, i8** null, i32 0)
247  %pia0a = getelementptr i64, i64* %pi, i32 0
248  store i64 %ia0a, i64* %pia0a
249
250; Fold strtol(a[0].b + 1, 0, 0, i8** null, i32 0) to 2.
251  %pa0bp1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1
252  %ia0bp1 = call i64 @strtol(i8* %pa0bp1, i8** null, i32 0)
253  %pia0bp1 = getelementptr i64, i64* %pi, i32 1
254  store i64 %ia0bp1, i64* %pia0bp1
255
256; Fold strtol(a[0].c + 3, 0, 0, i8** null, i32 0) to 89.
257  %pa0cp3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 3
258  %ia0cp3 = call i64 @strtol(i8* %pa0cp3, i8** null, i32 0)
259  %pia0cp3 = getelementptr i64, i64* %pi, i32 2
260  store i64 %ia0cp3, i64* %pia0cp3
261
262; Fold strtol(a[1].a + 2, 0, 0, i8** null, i32 0) to 3.
263  %pa1ap2 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 2
264  %ia1ap2 = call i64 @strtol(i8* %pa1ap2, i8** null, i32 0)
265  %pia1ap2 = getelementptr i64, i64* %pi, i32 3
266  store i64 %ia1ap2, i64* %pia1ap2
267
268; Fold strtol(a[1].b + 3, 0, 0, i8** null, i32 0) to 4.
269  %pa1bp3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 3
270  %ia1bp3 = call i64 @strtol(i8* %pa1bp3, i8** null, i32 0)
271  %pia1bp3 = getelementptr i64, i64* %pi, i32 4
272  store i64 %ia1bp3, i64* %pia1bp3
273
274; Fold strtol(a[1].c + 4, 0, 0, i8** null, i32 0) to 0.
275  %pa1cp4 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 4
276  %ia1cp4 = call i64 @strtol(i8* %pa1cp4, i8** null, i32 0)
277  %pia1cp4 = getelementptr i64, i64* %pi, i32 5
278  store i64 %ia1cp4, i64* %pia1cp4
279
280  ret void
281}
282
283
284; Fold strtoll(a[I].M + C, 0, 0) for constant I in [0, 1], member M
285; in [a, b, c], and C in a valid range to a constant.
286
287define void @fold_strtoll_member_pC(i64* %pi) {
288; CHECK-LABEL: @fold_strtoll_member_pC(
289; CHECK-NEXT:    [[IA0A:%.*]] = call i64 @strtoll(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0), i8** null, i32 0)
290; CHECK-NEXT:    store i64 [[IA0A]], i64* [[PI:%.*]], align 4
291; CHECK-NEXT:    [[IA0BP1:%.*]] = call i64 @strtoll(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1), i8** null, i32 0)
292; CHECK-NEXT:    [[PIA0BP1:%.*]] = getelementptr i64, i64* [[PI]], i64 1
293; CHECK-NEXT:    store i64 [[IA0BP1]], i64* [[PIA0BP1]], align 4
294; CHECK-NEXT:    [[IA0CP3:%.*]] = call i64 @strtoll(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 3), i8** null, i32 0)
295; CHECK-NEXT:    [[PIA0CP3:%.*]] = getelementptr i64, i64* [[PI]], i64 2
296; CHECK-NEXT:    store i64 [[IA0CP3]], i64* [[PIA0CP3]], align 4
297; CHECK-NEXT:    [[IA1AP2:%.*]] = call i64 @strtoll(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 2), i8** null, i32 0)
298; CHECK-NEXT:    [[PIA1AP2:%.*]] = getelementptr i64, i64* [[PI]], i64 3
299; CHECK-NEXT:    store i64 [[IA1AP2]], i64* [[PIA1AP2]], align 4
300; CHECK-NEXT:    [[IA1BP3:%.*]] = call i64 @strtoll(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 3), i8** null, i32 0)
301; CHECK-NEXT:    [[PIA1BP3:%.*]] = getelementptr i64, i64* [[PI]], i64 4
302; CHECK-NEXT:    store i64 [[IA1BP3]], i64* [[PIA1BP3]], align 4
303; CHECK-NEXT:    [[IA1CP4:%.*]] = call i64 @strtoll(i8* nocapture getelementptr inbounds ([2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 4), i8** null, i32 0)
304; CHECK-NEXT:    [[PIA1CP4:%.*]] = getelementptr i64, i64* [[PI]], i64 5
305; CHECK-NEXT:    store i64 [[IA1CP4]], i64* [[PIA1CP4]], align 4
306; CHECK-NEXT:    ret void
307;
308; Fold strtoll(a[0].a, 0, 0) to 1.
309  %pa0a = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 0, i64 0
310  %ia0a = call i64 @strtoll(i8* %pa0a, i8** null, i32 0)
311  %pia0a = getelementptr i64, i64* %pi, i32 0
312  store i64 %ia0a, i64* %pia0a
313
314; Fold strtoll(a[0].b + 1, 0, 0, i8** null, i32 0) to 2.
315  %pa0bp1 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 1, i64 1
316  %ia0bp1 = call i64 @strtoll(i8* %pa0bp1, i8** null, i32 0)
317  %pia0bp1 = getelementptr i64, i64* %pi, i32 1
318  store i64 %ia0bp1, i64* %pia0bp1
319
320; Fold strtoll(a[0].c + 3, 0, 0, i8** null, i32 0) to 89.
321  %pa0cp3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 0, i32 2, i64 3
322  %ia0cp3 = call i64 @strtoll(i8* %pa0cp3, i8** null, i32 0)
323  %pia0cp3 = getelementptr i64, i64* %pi, i32 2
324  store i64 %ia0cp3, i64* %pia0cp3
325
326; Fold strtoll(a[1].a + 2, 0, 0, i8** null, i32 0) to 3.
327  %pa1ap2 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 0, i64 2
328  %ia1ap2 = call i64 @strtoll(i8* %pa1ap2, i8** null, i32 0)
329  %pia1ap2 = getelementptr i64, i64* %pi, i32 3
330  store i64 %ia1ap2, i64* %pia1ap2
331
332; Fold strtoll(a[1].b + 3, 0, 0, i8** null, i32 0) to 4.
333  %pa1bp3 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 1, i64 3
334  %ia1bp3 = call i64 @strtoll(i8* %pa1bp3, i8** null, i32 0)
335  %pia1bp3 = getelementptr i64, i64* %pi, i32 4
336  store i64 %ia1bp3, i64* %pia1bp3
337
338; Fold strtoll(a[1].c + 4, 0, 0, i8** null, i32 0) to 0.
339  %pa1cp4 = getelementptr [2 x %struct.A], [2 x %struct.A]* @a, i64 0, i64 1, i32 2, i64 4
340  %ia1cp4 = call i64 @strtoll(i8* %pa1cp4, i8** null, i32 0)
341  %pia1cp4 = getelementptr i64, i64* %pi, i32 5
342  store i64 %ia1cp4, i64* %pia1cp4
343
344  ret void
345}
346