Re-land [openmp] Fix warnings when building on Windows with latest MSVC or Clang...
[llvm-project.git] / llvm / test / Transforms / InstCombine / str-int-3.ll
blob7d46297b5d143b759518ec65f112eac2c315ce3c
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
6 declare i32 @atoi(ptr)
7 declare i64 @atol(ptr)
8 declare i64 @atoll(ptr)
10 declare i64 @strtol(ptr, ptr, i32)
11 declare i64 @strtoll(ptr, ptr, i32)
13 %struct.A = type { [4 x i8], [5 x i8], [7 x i8] }
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" }]
18 ; Fold atoi(a[I].M) for constant I in [0, 1] and member M in [a, b]
19 ; to a constant.
21 define void @fold_atoi_member(ptr %pi) {
22 ; CHECK-LABEL: @fold_atoi_member(
23 ; CHECK-NEXT:    store i32 1, ptr [[PI:%.*]], align 4
24 ; CHECK-NEXT:    [[PIA0B:%.*]] = getelementptr i32, ptr [[PI]], i64 1
25 ; CHECK-NEXT:    store i32 12, ptr [[PIA0B]], align 4
26 ; CHECK-NEXT:    [[PIA1A:%.*]] = getelementptr i32, ptr [[PI]], i64 2
27 ; CHECK-NEXT:    store i32 123, ptr [[PIA1A]], align 4
28 ; CHECK-NEXT:    [[PIA1B:%.*]] = getelementptr i32, ptr [[PI]], i64 3
29 ; CHECK-NEXT:    store i32 1234, ptr [[PIA1B]], align 4
30 ; CHECK-NEXT:    ret void
32 ; Fold atoi(a[0].a) to 1.
33   %ia0a = call i32 @atoi(ptr @a)
34   store i32 %ia0a, ptr %pi
36 ; Fold atoi(a[0].b) to 12.
37   %pa0b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 0
38   %ia0b = call i32 @atoi(ptr %pa0b)
39   %pia0b = getelementptr i32, ptr %pi, i32 1
40   store i32 %ia0b, ptr %pia0b
42 ; Fold atoi(a[1].a) to 123.
43   %pa1a = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 0
44   %ia1a = call i32 @atoi(ptr %pa1a)
45   %pia1a = getelementptr i32, ptr %pi, i32 2
46   store i32 %ia1a, ptr %pia1a
48 ; Fold atoi(a[1].b) to 1234.
49   %pa1b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 0
50   %ia1b = call i32 @atoi(ptr %pa1b)
51   %pia1b = getelementptr i32, ptr %pi, i32 3
52   store i32 %ia1b, ptr %pia1b
54   ret void
58 ; TODO: Fold atoi with an excessive offset.  It's undefined so folding it
59 ; to zero is valid and might prevent crashes or returning a bogus value,
60 ; even though it prevents detecting the bug by sanitizers.
61 ; This is not fully implemented because the out-of-bounds offset results
62 ; in the empty string which atoi (via strtol) is required to interpret as
63 ; a zero but for which it may set errno to EINVAL.  To fold only
64 ; the undefined calls the folder would have to differentiate between
65 ; the empty string an out-of-bounds pointer.
67 define void @fold_atoi_offset_out_of_bounds(ptr %pi) {
68 ; CHECK-LABEL: @fold_atoi_offset_out_of_bounds(
69 ; CHECK-NEXT:    [[IA_0_0_32:%.*]] = call i32 @atoi(ptr nocapture nonnull getelementptr inbounds ([2 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 0))
70 ; CHECK-NEXT:    store i32 [[IA_0_0_32]], ptr [[PI:%.*]], align 4
71 ; CHECK-NEXT:    [[IA_0_0_33:%.*]] = call i32 @atoi(ptr nocapture getelementptr ([2 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 1))
72 ; CHECK-NEXT:    store i32 [[IA_0_0_33]], ptr [[PI]], align 4
73 ; CHECK-NEXT:    ret void
75 ; TODO: Check folding.
76 ; Fold atoi((const char*)a + sizeof a) to zero.
77   %ia_0_0_32 = call i32 @atoi(ptr getelementptr inbounds ([2 x %struct.A], ptr @a, i64 1, i64 0, i32 0, i64 0))
78   store i32 %ia_0_0_32, ptr %pi
80 ; Likewise, fold atoi((const char*)a + sizeof a + 1) to zero.
81   %pa_0_0_33 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 0, i64 33
82   %ia_0_0_33 = call i32 @atoi(ptr %pa_0_0_33)
83   store i32 %ia_0_0_33, ptr %pi
85   ret void
89 ; Fold atol(a[I].M) for constant I in [0, 1] and member M in [a, b, c]
90 ; to a constant.
92 define void @fold_atol_member(ptr %pi) {
93 ; CHECK-LABEL: @fold_atol_member(
94 ; CHECK-NEXT:    store i64 1, ptr [[PI:%.*]], align 4
95 ; CHECK-NEXT:    [[PIA0B:%.*]] = getelementptr i64, ptr [[PI]], i64 1
96 ; CHECK-NEXT:    store i64 12, ptr [[PIA0B]], align 4
97 ; CHECK-NEXT:    [[PIA0C:%.*]] = getelementptr i64, ptr [[PI]], i64 2
98 ; CHECK-NEXT:    store i64 56789, ptr [[PIA0C]], align 4
99 ; CHECK-NEXT:    [[PIA1A:%.*]] = getelementptr i64, ptr [[PI]], i64 3
100 ; CHECK-NEXT:    store i64 123, ptr [[PIA1A]], align 4
101 ; CHECK-NEXT:    [[PIA1B:%.*]] = getelementptr i64, ptr [[PI]], i64 4
102 ; CHECK-NEXT:    store i64 1234, ptr [[PIA1B]], align 4
103 ; CHECK-NEXT:    [[PIA1C:%.*]] = getelementptr i64, ptr [[PI]], i64 5
104 ; CHECK-NEXT:    store i64 67890, ptr [[PIA1C]], align 4
105 ; CHECK-NEXT:    ret void
107 ; Fold atol(a[0].a) to 1.
108   %ia0a = call i64 @atol(ptr @a)
109   store i64 %ia0a, ptr %pi
111 ; Fold atol(a[0].b) to 12.
112   %pa0b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 0
113   %ia0b = call i64 @atol(ptr %pa0b)
114   %pia0b = getelementptr i64, ptr %pi, i32 1
115   store i64 %ia0b, ptr %pia0b
117 ; Fold atol(a[0].c) to 56789.
118   %pa0c = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 2, i64 0
119   %ia0c = call i64 @atol(ptr %pa0c)
120   %pia0c = getelementptr i64, ptr %pi, i32 2
121   store i64 %ia0c, ptr %pia0c
123 ; Fold atol(a[1].a) to 123.
124   %pa1a = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 0
125   %ia1a = call i64 @atol(ptr %pa1a)
126   %pia1a = getelementptr i64, ptr %pi, i32 3
127   store i64 %ia1a, ptr %pia1a
129 ; Fold atol(a[1].b) to 1234.
130   %pa1b = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 0
131   %ia1b = call i64 @atol(ptr %pa1b)
132   %pia1b = getelementptr i64, ptr %pi, i32 4
133   store i64 %ia1b, ptr %pia1b
135 ; Fold atol(a[1].c) to 67890.
136   %pa1c = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 2, i64 0
137   %ia1c = call i64 @atol(ptr %pa1c)
138   %pia1c = getelementptr i64, ptr %pi, i32 5
139   store i64 %ia1c, ptr %pia1c
141   ret void
145 ; Fold atoll(a[I].M + C) for constant I in [0, 1], member M in [a, b, c],
146 ; and C in a valid range to a constant.
148 define void @fold_atoll_member_pC(ptr %pi) {
149 ; CHECK-LABEL: @fold_atoll_member_pC(
150 ; CHECK-NEXT:    store i64 1, ptr [[PI:%.*]], align 4
151 ; CHECK-NEXT:    [[PIA0BP1:%.*]] = getelementptr i64, ptr [[PI]], i64 1
152 ; CHECK-NEXT:    store i64 2, ptr [[PIA0BP1]], align 4
153 ; CHECK-NEXT:    [[PIA0CP3:%.*]] = getelementptr i64, ptr [[PI]], i64 2
154 ; CHECK-NEXT:    store i64 89, ptr [[PIA0CP3]], align 4
155 ; CHECK-NEXT:    [[PIA1AP2:%.*]] = getelementptr i64, ptr [[PI]], i64 3
156 ; CHECK-NEXT:    store i64 3, ptr [[PIA1AP2]], align 4
157 ; CHECK-NEXT:    [[PIA1BP3:%.*]] = getelementptr i64, ptr [[PI]], i64 4
158 ; CHECK-NEXT:    store i64 4, ptr [[PIA1BP3]], align 4
159 ; CHECK-NEXT:    [[PIA1CP4:%.*]] = getelementptr i64, ptr [[PI]], i64 5
160 ; CHECK-NEXT:    store i64 0, ptr [[PIA1CP4]], align 4
161 ; CHECK-NEXT:    ret void
163 ; Fold atoll(a[0].a) to 1.
164   %ia0a = call i64 @atol(ptr @a)
165   store i64 %ia0a, ptr %pi
167 ; Fold atoll(a[0].b + 1) to 2.
168   %pa0bp1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1
169   %ia0bp1 = call i64 @atol(ptr %pa0bp1)
170   %pia0bp1 = getelementptr i64, ptr %pi, i32 1
171   store i64 %ia0bp1, ptr %pia0bp1
173 ; Fold atoll(a[0].c + 3) to 89.
174   %pa0cp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 2, i64 3
175   %ia0cp3 = call i64 @atol(ptr %pa0cp3)
176   %pia0cp3 = getelementptr i64, ptr %pi, i32 2
177   store i64 %ia0cp3, ptr %pia0cp3
179 ; Fold atoll(a[1].a + 2) to 3.
180   %pa1ap2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 2
181   %ia1ap2 = call i64 @atol(ptr %pa1ap2)
182   %pia1ap2 = getelementptr i64, ptr %pi, i32 3
183   store i64 %ia1ap2, ptr %pia1ap2
185 ; Fold atoll(a[1].b + 3) to 4.
186   %pa1bp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 3
187   %ia1bp3 = call i64 @atol(ptr %pa1bp3)
188   %pia1bp3 = getelementptr i64, ptr %pi, i32 4
189   store i64 %ia1bp3, ptr %pia1bp3
191 ; Fold atoll(a[1].c + 4) to 0.
192   %pa1cp4 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 2, i64 4
193   %ia1cp4 = call i64 @atol(ptr %pa1cp4)
194   %pia1cp4 = getelementptr i64, ptr %pi, i32 5
195   store i64 %ia1cp4, ptr %pia1cp4
197   ret void
201 ; Fold strtol(a[I].M + C, 0, 0) for constant I in [0, 1], member M in [a, b, c],
202 ; and C in a valid range to a constant.
204 define void @fold_strtol_member_pC(ptr %pi) {
205 ; CHECK-LABEL: @fold_strtol_member_pC(
206 ; CHECK-NEXT:    store i64 1, ptr [[PI:%.*]], align 4
207 ; CHECK-NEXT:    [[PIA0BP1:%.*]] = getelementptr i64, ptr [[PI]], i64 1
208 ; CHECK-NEXT:    store i64 2, ptr [[PIA0BP1]], align 4
209 ; CHECK-NEXT:    [[PIA0CP3:%.*]] = getelementptr i64, ptr [[PI]], i64 2
210 ; CHECK-NEXT:    store i64 89, ptr [[PIA0CP3]], align 4
211 ; CHECK-NEXT:    [[PIA1AP2:%.*]] = getelementptr i64, ptr [[PI]], i64 3
212 ; CHECK-NEXT:    store i64 3, ptr [[PIA1AP2]], align 4
213 ; CHECK-NEXT:    [[PIA1BP3:%.*]] = getelementptr i64, ptr [[PI]], i64 4
214 ; CHECK-NEXT:    store i64 4, ptr [[PIA1BP3]], align 4
215 ; CHECK-NEXT:    [[PIA1CP4:%.*]] = getelementptr i64, ptr [[PI]], i64 5
216 ; CHECK-NEXT:    store i64 0, ptr [[PIA1CP4]], align 4
217 ; CHECK-NEXT:    ret void
219 ; Fold strtol(a[0].a, 0, 0) to 1.
220   %ia0a = call i64 @strtol(ptr @a, ptr null, i32 0)
221   store i64 %ia0a, ptr %pi
223 ; Fold strtol(a[0].b + 1, 0, 0, ptr null, i32 0) to 2.
224   %pa0bp1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1
225   %ia0bp1 = call i64 @strtol(ptr %pa0bp1, ptr null, i32 0)
226   %pia0bp1 = getelementptr i64, ptr %pi, i32 1
227   store i64 %ia0bp1, ptr %pia0bp1
229 ; Fold strtol(a[0].c + 3, 0, 0, ptr null, i32 0) to 89.
230   %pa0cp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 2, i64 3
231   %ia0cp3 = call i64 @strtol(ptr %pa0cp3, ptr null, i32 0)
232   %pia0cp3 = getelementptr i64, ptr %pi, i32 2
233   store i64 %ia0cp3, ptr %pia0cp3
235 ; Fold strtol(a[1].a + 2, 0, 0, ptr null, i32 0) to 3.
236   %pa1ap2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 2
237   %ia1ap2 = call i64 @strtol(ptr %pa1ap2, ptr null, i32 0)
238   %pia1ap2 = getelementptr i64, ptr %pi, i32 3
239   store i64 %ia1ap2, ptr %pia1ap2
241 ; Fold strtol(a[1].b + 3, 0, 0, ptr null, i32 0) to 4.
242   %pa1bp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 3
243   %ia1bp3 = call i64 @strtol(ptr %pa1bp3, ptr null, i32 0)
244   %pia1bp3 = getelementptr i64, ptr %pi, i32 4
245   store i64 %ia1bp3, ptr %pia1bp3
247 ; Fold strtol(a[1].c + 4, 0, 0, ptr null, i32 0) to 0.
248   %pa1cp4 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 2, i64 4
249   %ia1cp4 = call i64 @strtol(ptr %pa1cp4, ptr null, i32 0)
250   %pia1cp4 = getelementptr i64, ptr %pi, i32 5
251   store i64 %ia1cp4, ptr %pia1cp4
253   ret void
257 ; Fold strtoll(a[I].M + C, 0, 0) for constant I in [0, 1], member M
258 ; in [a, b, c], and C in a valid range to a constant.
260 define void @fold_strtoll_member_pC(ptr %pi) {
261 ; CHECK-LABEL: @fold_strtoll_member_pC(
262 ; CHECK-NEXT:    store i64 1, ptr [[PI:%.*]], align 4
263 ; CHECK-NEXT:    [[PIA0BP1:%.*]] = getelementptr i64, ptr [[PI]], i64 1
264 ; CHECK-NEXT:    store i64 2, ptr [[PIA0BP1]], align 4
265 ; CHECK-NEXT:    [[PIA0CP3:%.*]] = getelementptr i64, ptr [[PI]], i64 2
266 ; CHECK-NEXT:    store i64 89, ptr [[PIA0CP3]], align 4
267 ; CHECK-NEXT:    [[PIA1AP2:%.*]] = getelementptr i64, ptr [[PI]], i64 3
268 ; CHECK-NEXT:    store i64 3, ptr [[PIA1AP2]], align 4
269 ; CHECK-NEXT:    [[PIA1BP3:%.*]] = getelementptr i64, ptr [[PI]], i64 4
270 ; CHECK-NEXT:    store i64 4, ptr [[PIA1BP3]], align 4
271 ; CHECK-NEXT:    [[PIA1CP4:%.*]] = getelementptr i64, ptr [[PI]], i64 5
272 ; CHECK-NEXT:    store i64 0, ptr [[PIA1CP4]], align 4
273 ; CHECK-NEXT:    ret void
275 ; Fold strtoll(a[0].a, 0, 0) to 1.
276   %ia0a = call i64 @strtoll(ptr @a, ptr null, i32 0)
277   store i64 %ia0a, ptr %pi
279 ; Fold strtoll(a[0].b + 1, 0, 0, ptr null, i32 0) to 2.
280   %pa0bp1 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 1, i64 1
281   %ia0bp1 = call i64 @strtoll(ptr %pa0bp1, ptr null, i32 0)
282   %pia0bp1 = getelementptr i64, ptr %pi, i32 1
283   store i64 %ia0bp1, ptr %pia0bp1
285 ; Fold strtoll(a[0].c + 3, 0, 0, ptr null, i32 0) to 89.
286   %pa0cp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 0, i32 2, i64 3
287   %ia0cp3 = call i64 @strtoll(ptr %pa0cp3, ptr null, i32 0)
288   %pia0cp3 = getelementptr i64, ptr %pi, i32 2
289   store i64 %ia0cp3, ptr %pia0cp3
291 ; Fold strtoll(a[1].a + 2, 0, 0, ptr null, i32 0) to 3.
292   %pa1ap2 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 0, i64 2
293   %ia1ap2 = call i64 @strtoll(ptr %pa1ap2, ptr null, i32 0)
294   %pia1ap2 = getelementptr i64, ptr %pi, i32 3
295   store i64 %ia1ap2, ptr %pia1ap2
297 ; Fold strtoll(a[1].b + 3, 0, 0, ptr null, i32 0) to 4.
298   %pa1bp3 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 1, i64 3
299   %ia1bp3 = call i64 @strtoll(ptr %pa1bp3, ptr null, i32 0)
300   %pia1bp3 = getelementptr i64, ptr %pi, i32 4
301   store i64 %ia1bp3, ptr %pia1bp3
303 ; Fold strtoll(a[1].c + 4, 0, 0, ptr null, i32 0) to 0.
304   %pa1cp4 = getelementptr [2 x %struct.A], ptr @a, i64 0, i64 1, i32 2, i64 4
305   %ia1cp4 = call i64 @strtoll(ptr %pa1cp4, ptr null, i32 0)
306   %pia1cp4 = getelementptr i64, ptr %pi, i32 5
307   store i64 %ia1cp4, ptr %pia1cp4
309   ret void