Bump version to 19.1.0-rc3
[llvm-project.git] / llvm / test / Transforms / InstCombine / str-int-5.ll
blob4ccf7ea6407c249d88ec74573045a65ea7b5eae5
1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; Verify that calls to strtoul and strtoull are interpreted correctly even
3 ; in corner cases (or not folded).
5 ; RUN: opt < %s -passes=instcombine -S | FileCheck %s
7 declare i32 @strtoul(ptr, ptr, i32)
8 declare i64 @strtoull(ptr, ptr, i32)
11 ; All POSIX whitespace characters.
12 @ws = constant [7 x i8] c"\09\0d\0a\0b\0c \00"
14 ; A negative and positive number preceded by all POSIX whitespace.
15 @ws_im123 = constant [11 x i8] c"\09\0d\0a\0b\0c -123\00"
16 @ws_ip234 = constant [11 x i8] c"\09\0d\0a\0b\0c +234\00"
18 @i32min = constant [13 x i8] c" -2147483648\00"
19 @i32min_m1 = constant [13 x i8] c" -2147483649\00"
20 @o32min = constant [15 x i8] c" +020000000000\00"
21 @mo32min = constant [15 x i8] c" -020000000000\00"
22 @x32min = constant [13 x i8] c" +0x80000000\00"
23 @mx32min = constant [13 x i8] c" +0x80000000\00"
25 @i32max = constant [12 x i8] c" 2147483647\00"
26 @i32max_p1 = constant [12 x i8] c" 2147483648\00"
27 @mX01 = constant [6 x i8] c" -0X1\00"
29 @ui32max = constant [12 x i8] c" 4294967295\00"
30 @ui32max_p1 = constant [12 x i8] c" 4294967296\00"
32 @i64min = constant [22 x i8] c" -9223372036854775808\00"
33 @i64min_m1 = constant [22 x i8] c" -9223372036854775809\00"
35 @i64max = constant [21 x i8] c" 9223372036854775807\00"
36 @i64max_p1 = constant [21 x i8] c" 9223372036854775808\00"
38 @ui64max = constant [22 x i8] c" 18446744073709551615\00"
39 @x64max = constant [20 x i8] c" 0xffffffffffffffff\00"
40 @ui64max_p1 = constant [22 x i8] c" 18446744073709551616\00"
42 @endptr = external global ptr
45 ; Exercise folding calls to 32-bit strtoul.
47 define void @fold_strtoul(ptr %ps) {
48 ; CHECK-LABEL: @fold_strtoul(
49 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @ws_im123, i64 10), ptr @endptr, align 8
50 ; CHECK-NEXT:    store i32 -123, ptr [[PS:%.*]], align 4
51 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @ws_ip234, i64 10), ptr @endptr, align 8
52 ; CHECK-NEXT:    [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 4
53 ; CHECK-NEXT:    store i32 234, ptr [[PS1]], align 4
54 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @i32min_m1, i64 12), ptr @endptr, align 8
55 ; CHECK-NEXT:    [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 8
56 ; CHECK-NEXT:    store i32 2147483647, ptr [[PS2]], align 4
57 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @i32min, i64 12), ptr @endptr, align 8
58 ; CHECK-NEXT:    [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 12
59 ; CHECK-NEXT:    store i32 -2147483648, ptr [[PS3]], align 4
60 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @o32min, i64 14), ptr @endptr, align 8
61 ; CHECK-NEXT:    [[PS4:%.*]] = getelementptr i8, ptr [[PS]], i64 16
62 ; CHECK-NEXT:    store i32 -2147483648, ptr [[PS4]], align 4
63 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @mo32min, i64 14), ptr @endptr, align 8
64 ; CHECK-NEXT:    [[PS5:%.*]] = getelementptr i8, ptr [[PS]], i64 20
65 ; CHECK-NEXT:    store i32 -2147483648, ptr [[PS5]], align 4
66 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @x32min, i64 12), ptr @endptr, align 8
67 ; CHECK-NEXT:    [[PS6:%.*]] = getelementptr i8, ptr [[PS]], i64 24
68 ; CHECK-NEXT:    store i32 -2147483648, ptr [[PS6]], align 4
69 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @mx32min, i64 12), ptr @endptr, align 8
70 ; CHECK-NEXT:    [[PS7:%.*]] = getelementptr i8, ptr [[PS]], i64 28
71 ; CHECK-NEXT:    store i32 -2147483648, ptr [[PS7]], align 4
72 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @i32max, i64 11), ptr @endptr, align 8
73 ; CHECK-NEXT:    [[PS8:%.*]] = getelementptr i8, ptr [[PS]], i64 32
74 ; CHECK-NEXT:    store i32 2147483647, ptr [[PS8]], align 4
75 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @mX01, i64 5), ptr @endptr, align 8
76 ; CHECK-NEXT:    [[PS9:%.*]] = getelementptr i8, ptr [[PS]], i64 36
77 ; CHECK-NEXT:    store i32 -1, ptr [[PS9]], align 4
78 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @i32max_p1, i64 11), ptr @endptr, align 8
79 ; CHECK-NEXT:    [[PS10:%.*]] = getelementptr i8, ptr [[PS]], i64 40
80 ; CHECK-NEXT:    store i32 -2147483648, ptr [[PS10]], align 4
81 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @ui32max, i64 11), ptr @endptr, align 8
82 ; CHECK-NEXT:    [[PS11:%.*]] = getelementptr i8, ptr [[PS]], i64 44
83 ; CHECK-NEXT:    store i32 -1, ptr [[PS11]], align 4
84 ; CHECK-NEXT:    ret void
86 ; Fold a valid sequence with leading POSIX whitespace and a minus to
87 ; (uint32_t)-123.
88   %im123 = call i32 @strtoul(ptr @ws_im123, ptr @endptr, i32 10)
89   store i32 %im123, ptr %ps
91 ; Fold a valid sequence with leading POSIX whitespace and a plus to +234.
92   %ip234 = call i32 @strtoul(ptr @ws_ip234, ptr @endptr, i32 10)
93   %ps1 = getelementptr i32, ptr %ps, i32 1
94   store i32 %ip234, ptr %ps1
96 ; Fold the result of conversion that's equal to INT32_MIN - 1.
97   %i32min32m1 = call i32 @strtoul(ptr @i32min_m1, ptr @endptr, i32 10)
98   %ps2 = getelementptr i32, ptr %ps, i32 2
99   store i32 %i32min32m1, ptr %ps2
101 ; Fold INT32_MIN.
102   %i32min = call i32 @strtoul(ptr @i32min, ptr @endptr, i32 10)
103   %ps3 = getelementptr i32, ptr %ps, i32 3
104   store i32 %i32min, ptr %ps3
106 ; Fold INT32_MIN in octal.
107   %o32min = call i32 @strtoul(ptr @o32min, ptr @endptr, i32 0)
108   %ps4 = getelementptr i32, ptr %ps, i32 4
109   store i32 %o32min, ptr %ps4
111 ; Fold -INT32_MIN in octal.
112   %mo32min = call i32 @strtoul(ptr @mo32min, ptr @endptr, i32 0)
113   %ps5 = getelementptr i32, ptr %ps, i32 5
114   store i32 %mo32min, ptr %ps5
116 ; Fold INT32_MIN in hex.
117   %x32min = call i32 @strtoul(ptr @x32min, ptr @endptr, i32 0)
118   %ps6 = getelementptr i32, ptr %ps, i32 6
119   store i32 %x32min, ptr %ps6
121 ; Fold -INT32_MIN in hex.
122   %mx32min = call i32 @strtoul(ptr @mx32min, ptr @endptr, i32 0)
123   %ps7 = getelementptr i32, ptr %ps, i32 7
124   store i32 %x32min, ptr %ps7
126 ; Fold INT32_MAX.
127   %i32max = call i32 @strtoul(ptr @i32max, ptr @endptr, i32 10)
128   %ps8 = getelementptr i32, ptr %ps, i32 8
129   store i32 %i32max, ptr %ps8
131 ; Fold -0x01.
132   %mX01 = call i32 @strtoul(ptr @mX01, ptr @endptr, i32 0)
133   %ps9 = getelementptr i32, ptr %ps, i32 9
134   store i32 %mX01, ptr %ps9
136 ; Fold the result of conversion that's equal to INT32_MAX + 1.
137   %i32max32p1 = call i32 @strtoul(ptr @i32max_p1, ptr @endptr, i32 10)
138   %ps10 = getelementptr i32, ptr %ps, i32 10
139   store i32 %i32max32p1, ptr %ps10
141 ; Fold UINT32_MAX.
142   %ui32max = call i32 @strtoul(ptr @ui32max, ptr @endptr, i32 10)
143   %ps11 = getelementptr i32, ptr %ps, i32 11
144   store i32 %ui32max, ptr %ps11
146   ret void
150 ; Exercise not folding calls to 32-bit strtoul.
152 define void @call_strtoul(ptr %ps) {
153 ; CHECK-LABEL: @call_strtoul(
154 ; CHECK-NEXT:    [[MINM1:%.*]] = call i32 @strtoul(ptr nonnull @i64min_m1, ptr nonnull @endptr, i32 10)
155 ; CHECK-NEXT:    store i32 [[MINM1]], ptr [[PS:%.*]], align 4
156 ; CHECK-NEXT:    [[MAXP1:%.*]] = call i32 @strtoul(ptr nonnull @ui32max_p1, ptr nonnull @endptr, i32 10)
157 ; CHECK-NEXT:    [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 4
158 ; CHECK-NEXT:    store i32 [[MAXP1]], ptr [[PS1]], align 4
159 ; CHECK-NEXT:    [[NWS:%.*]] = call i32 @strtoul(ptr nonnull @ws, ptr nonnull @endptr, i32 10)
160 ; CHECK-NEXT:    [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 8
161 ; CHECK-NEXT:    store i32 [[NWS]], ptr [[PS2]], align 4
162 ; CHECK-NEXT:    [[NWSP6:%.*]] = call i32 @strtoul(ptr nonnull getelementptr inbounds (i8, ptr @ws, i64 6), ptr nonnull @endptr, i32 10)
163 ; CHECK-NEXT:    [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 12
164 ; CHECK-NEXT:    store i32 [[NWSP6]], ptr [[PS3]], align 4
165 ; CHECK-NEXT:    ret void
167 ; Do not fold the result of conversion that overflows uint32_t.  This
168 ; could be folded into a constant provided errnor were set to ERANGE.
169   %minm1 = call i32 @strtoul(ptr @i64min_m1, ptr @endptr, i32 10)
170   store i32 %minm1, ptr %ps
172 ; Do not fold the result of conversion that's greater than UINT32_MAX
173 ; (same logic as above applies here).
174   %maxp1 = call i32 @strtoul(ptr @ui32max_p1, ptr @endptr, i32 10)
175   %ps1 = getelementptr i32, ptr %ps, i32 1
176   store i32 %maxp1, ptr %ps1
178 ; Do not fold a sequence consisting of just whitespace characters.
179   %nws = call i32 @strtoul(ptr @ws, ptr @endptr, i32 10)
180   %ps2 = getelementptr i32, ptr %ps, i32 2
181   store i32 %nws, ptr %ps2
183 ; Do not fold an empty sequence.  The library call may or may not end up
184 ; storing EINVAL in errno.
185   %pswsp6 = getelementptr [7 x i8], ptr @ws, i32 0, i32 6
186   %nwsp6 = call i32 @strtoul(ptr %pswsp6, ptr @endptr, i32 10)
187   %ps3 = getelementptr i32, ptr %ps, i32 3
188   store i32 %nwsp6, ptr %ps3
190   ret void
194 ; Exercise folding calls to 64-bit strtoull.
196 define void @fold_strtoull(ptr %ps) {
197 ; CHECK-LABEL: @fold_strtoull(
198 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @ws_im123, i64 10), ptr @endptr, align 8
199 ; CHECK-NEXT:    store i64 -123, ptr [[PS:%.*]], align 4
200 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @ws_ip234, i64 10), ptr @endptr, align 8
201 ; CHECK-NEXT:    [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 8
202 ; CHECK-NEXT:    store i64 234, ptr [[PS1]], align 4
203 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @i64min_m1, i64 21), ptr @endptr, align 8
204 ; CHECK-NEXT:    [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 16
205 ; CHECK-NEXT:    store i64 9223372036854775807, ptr [[PS2]], align 4
206 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @i32min, i64 12), ptr @endptr, align 8
207 ; CHECK-NEXT:    [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 24
208 ; CHECK-NEXT:    store i64 -2147483648, ptr [[PS3]], align 4
209 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @o32min, i64 14), ptr @endptr, align 8
210 ; CHECK-NEXT:    [[PS4:%.*]] = getelementptr i8, ptr [[PS]], i64 32
211 ; CHECK-NEXT:    store i64 2147483648, ptr [[PS4]], align 4
212 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @x32min, i64 12), ptr @endptr, align 8
213 ; CHECK-NEXT:    [[PS5:%.*]] = getelementptr i8, ptr [[PS]], i64 40
214 ; CHECK-NEXT:    store i64 2147483648, ptr [[PS5]], align 4
215 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @i64min, i64 21), ptr @endptr, align 8
216 ; CHECK-NEXT:    [[PS6:%.*]] = getelementptr i8, ptr [[PS]], i64 48
217 ; CHECK-NEXT:    store i64 -9223372036854775808, ptr [[PS6]], align 4
218 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @i64max, i64 20), ptr @endptr, align 8
219 ; CHECK-NEXT:    [[PS7:%.*]] = getelementptr i8, ptr [[PS]], i64 56
220 ; CHECK-NEXT:    store i64 9223372036854775807, ptr [[PS7]], align 4
221 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @i64max_p1, i64 20), ptr @endptr, align 8
222 ; CHECK-NEXT:    [[PS8:%.*]] = getelementptr i8, ptr [[PS]], i64 64
223 ; CHECK-NEXT:    store i64 -9223372036854775808, ptr [[PS8]], align 4
224 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @ui64max, i64 21), ptr @endptr, align 8
225 ; CHECK-NEXT:    [[PS9:%.*]] = getelementptr i8, ptr [[PS]], i64 72
226 ; CHECK-NEXT:    store i64 -1, ptr [[PS9]], align 4
227 ; CHECK-NEXT:    store ptr getelementptr inbounds (i8, ptr @x64max, i64 19), ptr @endptr, align 8
228 ; CHECK-NEXT:    [[PS10:%.*]] = getelementptr i8, ptr [[PS]], i64 80
229 ; CHECK-NEXT:    store i64 -1, ptr [[PS10]], align 4
230 ; CHECK-NEXT:    ret void
232 ; Fold a valid sequence with leading POSIX whitespace and a minus to
233 ; (uint64_t)-123.
234   %im123 = call i64 @strtoull(ptr @ws_im123, ptr @endptr, i32 10)
235   store i64 %im123, ptr %ps
237 ; Fold a valid sequence with leading POSIX whitespace and a plus to +234.
238   %ip234 = call i64 @strtoull(ptr @ws_ip234, ptr @endptr, i32 10)
239   %ps1 = getelementptr i64, ptr %ps, i32 1
240   store i64 %ip234, ptr %ps1
242 ; Fold the result of conversion that's equal to INT64_MIN - 1.
243   %i64min32m1 = call i64 @strtoull(ptr @i64min_m1, ptr @endptr, i32 10)
244   %ps2 = getelementptr i64, ptr %ps, i32 2
245   store i64 %i64min32m1, ptr %ps2
247 ; Fold INT32_MIN.
248   %i32min = call i64 @strtoull(ptr @i32min, ptr @endptr, i32 10)
249   %ps3 = getelementptr i64, ptr %ps, i32 3
250   store i64 %i32min, ptr %ps3
252 ; Fold INT32_MIN in octal.
253   %o32min = call i64 @strtoull(ptr @o32min, ptr @endptr, i32 0)
254   %ps4 = getelementptr i64, ptr %ps, i32 4
255   store i64 %o32min, ptr %ps4
257 ; Fold INT32_MIN in hex.
258   %x32min = call i64 @strtoull(ptr @x32min, ptr @endptr, i32 0)
259   %ps5 = getelementptr i64, ptr %ps, i32 5
260   store i64 %x32min, ptr %ps5
262 ; Fold INT64_MIN.
263   %i64min = call i64 @strtoull(ptr @i64min, ptr @endptr, i32 10)
264   %ps6 = getelementptr i64, ptr %ps, i32 6
265   store i64 %i64min, ptr %ps6
267 ; Fold INT64_MAX.
268   %i64max = call i64 @strtoull(ptr @i64max, ptr @endptr, i32 10)
269   %ps7 = getelementptr i64, ptr %ps, i32 7
270   store i64 %i64max, ptr %ps7
272 ; Fold the result of conversion that's equal to INT64_MAX + 1 to INT64_MIN.
273   %i64max32p1 = call i64 @strtoull(ptr @i64max_p1, ptr @endptr, i32 10)
274   %ps8 = getelementptr i64, ptr %ps, i32 8
275   store i64 %i64max32p1, ptr %ps8
277 ; Fold UINT64_MAX.
278   %ui64max = call i64 @strtoull(ptr @ui64max, ptr @endptr, i32 10)
279   %ps9 = getelementptr i64, ptr %ps, i32 9
280   store i64 %ui64max, ptr %ps9
282 ; Fold UINT64_MAX in hex.
283   %x64max = call i64 @strtoull(ptr @x64max, ptr @endptr, i32 0)
284   %ps10 = getelementptr i64, ptr %ps, i32 10
285   store i64 %x64max, ptr %ps10
287   ret void
291 ; Exercise not folding calls to 64-bit strtoull.
293 define void @call_strtoull(ptr %ps) {
294 ; CHECK-LABEL: @call_strtoull(
295 ; CHECK-NEXT:    [[MAXP1:%.*]] = call i64 @strtoull(ptr nonnull @ui64max_p1, ptr nonnull @endptr, i32 10)
296 ; CHECK-NEXT:    [[PS1:%.*]] = getelementptr i8, ptr [[PS:%.*]], i64 8
297 ; CHECK-NEXT:    store i64 [[MAXP1]], ptr [[PS1]], align 4
298 ; CHECK-NEXT:    [[NWS:%.*]] = call i64 @strtoull(ptr nonnull @ws, ptr nonnull @endptr, i32 10)
299 ; CHECK-NEXT:    [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 16
300 ; CHECK-NEXT:    store i64 [[NWS]], ptr [[PS2]], align 4
301 ; CHECK-NEXT:    [[NWSP6:%.*]] = call i64 @strtoull(ptr nonnull getelementptr inbounds (i8, ptr @ws, i64 6), ptr nonnull @endptr, i32 10)
302 ; CHECK-NEXT:    [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 24
303 ; CHECK-NEXT:    store i64 [[NWSP6]], ptr [[PS3]], align 4
304 ; CHECK-NEXT:    ret void
306 ; Do not fold the result of conversion that overflows uint64_t.  This
307 ; could be folded into a constant provided errnor were set to ERANGE.
308   %maxp1 = call i64 @strtoull(ptr @ui64max_p1, ptr @endptr, i32 10)
309   %ps1 = getelementptr i64, ptr %ps, i32 1
310   store i64 %maxp1, ptr %ps1
312 ; Do not fold a sequence consisting of just whitespace characters.
313   %nws = call i64 @strtoull(ptr @ws, ptr @endptr, i32 10)
314   %ps2 = getelementptr i64, ptr %ps, i32 2
315   store i64 %nws, ptr %ps2
317 ; Do not fold an empty sequence.  The library call may or may not end up
318 ; storing EINVAL in errno.
319   %pswsp6 = getelementptr [7 x i8], ptr @ws, i32 0, i32 6
320   %nwsp6 = call i64 @strtoull(ptr %pswsp6, ptr @endptr, i32 10)
321   %ps3 = getelementptr i64, ptr %ps, i32 3
322   store i64 %nwsp6, ptr %ps3
324   ret void