326 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; Verify that calls to strtoul and strtoull are interpreted correctly even3; in corner cases (or not folded).4;5; RUN: opt < %s -passes=instcombine -S | FileCheck %s6 7declare i32 @strtoul(ptr, ptr, i32)8declare i64 @strtoull(ptr, ptr, i32)9 10 11; All POSIX whitespace characters.12@ws = constant [7 x i8] c"\09\0d\0a\0b\0c \00"13 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"17 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"24 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"28 29@ui32max = constant [12 x i8] c" 4294967295\00"30@ui32max_p1 = constant [12 x i8] c" 4294967296\00"31 32@i64min = constant [22 x i8] c" -9223372036854775808\00"33@i64min_m1 = constant [22 x i8] c" -9223372036854775809\00"34 35@i64max = constant [21 x i8] c" 9223372036854775807\00"36@i64max_p1 = constant [21 x i8] c" 9223372036854775808\00"37 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"41 42@endptr = external global ptr43 44 45; Exercise folding calls to 32-bit strtoul.46 47define void @fold_strtoul(ptr %ps) {48; CHECK-LABEL: @fold_strtoul(49; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @ws_im123, i64 10), ptr @endptr, align 850; CHECK-NEXT: store i32 -123, ptr [[PS:%.*]], align 451; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @ws_ip234, i64 10), ptr @endptr, align 852; CHECK-NEXT: [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 453; CHECK-NEXT: store i32 234, ptr [[PS1]], align 454; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @i32min_m1, i64 12), ptr @endptr, align 855; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 856; CHECK-NEXT: store i32 2147483647, ptr [[PS2]], align 457; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @i32min, i64 12), ptr @endptr, align 858; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 1259; CHECK-NEXT: store i32 -2147483648, ptr [[PS3]], align 460; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @o32min, i64 14), ptr @endptr, align 861; CHECK-NEXT: [[PS4:%.*]] = getelementptr i8, ptr [[PS]], i64 1662; CHECK-NEXT: store i32 -2147483648, ptr [[PS4]], align 463; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @mo32min, i64 14), ptr @endptr, align 864; CHECK-NEXT: [[PS5:%.*]] = getelementptr i8, ptr [[PS]], i64 2065; CHECK-NEXT: store i32 -2147483648, ptr [[PS5]], align 466; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @x32min, i64 12), ptr @endptr, align 867; CHECK-NEXT: [[PS6:%.*]] = getelementptr i8, ptr [[PS]], i64 2468; CHECK-NEXT: store i32 -2147483648, ptr [[PS6]], align 469; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @mx32min, i64 12), ptr @endptr, align 870; CHECK-NEXT: [[PS7:%.*]] = getelementptr i8, ptr [[PS]], i64 2871; CHECK-NEXT: store i32 -2147483648, ptr [[PS7]], align 472; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @i32max, i64 11), ptr @endptr, align 873; CHECK-NEXT: [[PS8:%.*]] = getelementptr i8, ptr [[PS]], i64 3274; CHECK-NEXT: store i32 2147483647, ptr [[PS8]], align 475; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @mX01, i64 5), ptr @endptr, align 876; CHECK-NEXT: [[PS9:%.*]] = getelementptr i8, ptr [[PS]], i64 3677; CHECK-NEXT: store i32 -1, ptr [[PS9]], align 478; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @i32max_p1, i64 11), ptr @endptr, align 879; CHECK-NEXT: [[PS10:%.*]] = getelementptr i8, ptr [[PS]], i64 4080; CHECK-NEXT: store i32 -2147483648, ptr [[PS10]], align 481; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @ui32max, i64 11), ptr @endptr, align 882; CHECK-NEXT: [[PS11:%.*]] = getelementptr i8, ptr [[PS]], i64 4483; CHECK-NEXT: store i32 -1, ptr [[PS11]], align 484; CHECK-NEXT: ret void85;86; Fold a valid sequence with leading POSIX whitespace and a minus to87; (uint32_t)-123.88 %im123 = call i32 @strtoul(ptr @ws_im123, ptr @endptr, i32 10)89 store i32 %im123, ptr %ps90 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 194 store i32 %ip234, ptr %ps195 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 299 store i32 %i32min32m1, ptr %ps2100 101; Fold INT32_MIN.102 %i32min = call i32 @strtoul(ptr @i32min, ptr @endptr, i32 10)103 %ps3 = getelementptr i32, ptr %ps, i32 3104 store i32 %i32min, ptr %ps3105 106; Fold INT32_MIN in octal.107 %o32min = call i32 @strtoul(ptr @o32min, ptr @endptr, i32 0)108 %ps4 = getelementptr i32, ptr %ps, i32 4109 store i32 %o32min, ptr %ps4110 111; Fold -INT32_MIN in octal.112 %mo32min = call i32 @strtoul(ptr @mo32min, ptr @endptr, i32 0)113 %ps5 = getelementptr i32, ptr %ps, i32 5114 store i32 %mo32min, ptr %ps5115 116; Fold INT32_MIN in hex.117 %x32min = call i32 @strtoul(ptr @x32min, ptr @endptr, i32 0)118 %ps6 = getelementptr i32, ptr %ps, i32 6119 store i32 %x32min, ptr %ps6120 121; Fold -INT32_MIN in hex.122 %mx32min = call i32 @strtoul(ptr @mx32min, ptr @endptr, i32 0)123 %ps7 = getelementptr i32, ptr %ps, i32 7124 store i32 %x32min, ptr %ps7125 126; Fold INT32_MAX.127 %i32max = call i32 @strtoul(ptr @i32max, ptr @endptr, i32 10)128 %ps8 = getelementptr i32, ptr %ps, i32 8129 store i32 %i32max, ptr %ps8130 131; Fold -0x01.132 %mX01 = call i32 @strtoul(ptr @mX01, ptr @endptr, i32 0)133 %ps9 = getelementptr i32, ptr %ps, i32 9134 store i32 %mX01, ptr %ps9135 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 10139 store i32 %i32max32p1, ptr %ps10140 141; Fold UINT32_MAX.142 %ui32max = call i32 @strtoul(ptr @ui32max, ptr @endptr, i32 10)143 %ps11 = getelementptr i32, ptr %ps, i32 11144 store i32 %ui32max, ptr %ps11145 146 ret void147}148 149 150; Exercise not folding calls to 32-bit strtoul.151 152define 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 4156; CHECK-NEXT: [[MAXP1:%.*]] = call i32 @strtoul(ptr nonnull @ui32max_p1, ptr nonnull @endptr, i32 10)157; CHECK-NEXT: [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 4158; CHECK-NEXT: store i32 [[MAXP1]], ptr [[PS1]], align 4159; CHECK-NEXT: [[NWS:%.*]] = call i32 @strtoul(ptr nonnull @ws, ptr nonnull @endptr, i32 10)160; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 8161; CHECK-NEXT: store i32 [[NWS]], ptr [[PS2]], align 4162; CHECK-NEXT: [[NWSP6:%.*]] = call i32 @strtoul(ptr nonnull getelementptr inbounds nuw (i8, ptr @ws, i64 6), ptr nonnull @endptr, i32 10)163; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 12164; CHECK-NEXT: store i32 [[NWSP6]], ptr [[PS3]], align 4165; CHECK-NEXT: ret void166;167; Do not fold the result of conversion that overflows uint32_t. This168; 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 %ps171 172; Do not fold the result of conversion that's greater than UINT32_MAX173; (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 1176 store i32 %maxp1, ptr %ps1177 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 2181 store i32 %nws, ptr %ps2182 183; Do not fold an empty sequence. The library call may or may not end up184; storing EINVAL in errno.185 %pswsp6 = getelementptr [7 x i8], ptr @ws, i32 0, i32 6186 %nwsp6 = call i32 @strtoul(ptr %pswsp6, ptr @endptr, i32 10)187 %ps3 = getelementptr i32, ptr %ps, i32 3188 store i32 %nwsp6, ptr %ps3189 190 ret void191}192 193 194; Exercise folding calls to 64-bit strtoull.195 196define void @fold_strtoull(ptr %ps) {197; CHECK-LABEL: @fold_strtoull(198; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @ws_im123, i64 10), ptr @endptr, align 8199; CHECK-NEXT: store i64 -123, ptr [[PS:%.*]], align 4200; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @ws_ip234, i64 10), ptr @endptr, align 8201; CHECK-NEXT: [[PS1:%.*]] = getelementptr i8, ptr [[PS]], i64 8202; CHECK-NEXT: store i64 234, ptr [[PS1]], align 4203; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @i64min_m1, i64 21), ptr @endptr, align 8204; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 16205; CHECK-NEXT: store i64 9223372036854775807, ptr [[PS2]], align 4206; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @i32min, i64 12), ptr @endptr, align 8207; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 24208; CHECK-NEXT: store i64 -2147483648, ptr [[PS3]], align 4209; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @o32min, i64 14), ptr @endptr, align 8210; CHECK-NEXT: [[PS4:%.*]] = getelementptr i8, ptr [[PS]], i64 32211; CHECK-NEXT: store i64 2147483648, ptr [[PS4]], align 4212; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @x32min, i64 12), ptr @endptr, align 8213; CHECK-NEXT: [[PS5:%.*]] = getelementptr i8, ptr [[PS]], i64 40214; CHECK-NEXT: store i64 2147483648, ptr [[PS5]], align 4215; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @i64min, i64 21), ptr @endptr, align 8216; CHECK-NEXT: [[PS6:%.*]] = getelementptr i8, ptr [[PS]], i64 48217; CHECK-NEXT: store i64 -9223372036854775808, ptr [[PS6]], align 4218; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @i64max, i64 20), ptr @endptr, align 8219; CHECK-NEXT: [[PS7:%.*]] = getelementptr i8, ptr [[PS]], i64 56220; CHECK-NEXT: store i64 9223372036854775807, ptr [[PS7]], align 4221; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @i64max_p1, i64 20), ptr @endptr, align 8222; CHECK-NEXT: [[PS8:%.*]] = getelementptr i8, ptr [[PS]], i64 64223; CHECK-NEXT: store i64 -9223372036854775808, ptr [[PS8]], align 4224; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @ui64max, i64 21), ptr @endptr, align 8225; CHECK-NEXT: [[PS9:%.*]] = getelementptr i8, ptr [[PS]], i64 72226; CHECK-NEXT: store i64 -1, ptr [[PS9]], align 4227; CHECK-NEXT: store ptr getelementptr inbounds nuw (i8, ptr @x64max, i64 19), ptr @endptr, align 8228; CHECK-NEXT: [[PS10:%.*]] = getelementptr i8, ptr [[PS]], i64 80229; CHECK-NEXT: store i64 -1, ptr [[PS10]], align 4230; CHECK-NEXT: ret void231;232; Fold a valid sequence with leading POSIX whitespace and a minus to233; (uint64_t)-123.234 %im123 = call i64 @strtoull(ptr @ws_im123, ptr @endptr, i32 10)235 store i64 %im123, ptr %ps236 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 1240 store i64 %ip234, ptr %ps1241 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 2245 store i64 %i64min32m1, ptr %ps2246 247; Fold INT32_MIN.248 %i32min = call i64 @strtoull(ptr @i32min, ptr @endptr, i32 10)249 %ps3 = getelementptr i64, ptr %ps, i32 3250 store i64 %i32min, ptr %ps3251 252; Fold INT32_MIN in octal.253 %o32min = call i64 @strtoull(ptr @o32min, ptr @endptr, i32 0)254 %ps4 = getelementptr i64, ptr %ps, i32 4255 store i64 %o32min, ptr %ps4256 257; Fold INT32_MIN in hex.258 %x32min = call i64 @strtoull(ptr @x32min, ptr @endptr, i32 0)259 %ps5 = getelementptr i64, ptr %ps, i32 5260 store i64 %x32min, ptr %ps5261 262; Fold INT64_MIN.263 %i64min = call i64 @strtoull(ptr @i64min, ptr @endptr, i32 10)264 %ps6 = getelementptr i64, ptr %ps, i32 6265 store i64 %i64min, ptr %ps6266 267; Fold INT64_MAX.268 %i64max = call i64 @strtoull(ptr @i64max, ptr @endptr, i32 10)269 %ps7 = getelementptr i64, ptr %ps, i32 7270 store i64 %i64max, ptr %ps7271 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 8275 store i64 %i64max32p1, ptr %ps8276 277; Fold UINT64_MAX.278 %ui64max = call i64 @strtoull(ptr @ui64max, ptr @endptr, i32 10)279 %ps9 = getelementptr i64, ptr %ps, i32 9280 store i64 %ui64max, ptr %ps9281 282; Fold UINT64_MAX in hex.283 %x64max = call i64 @strtoull(ptr @x64max, ptr @endptr, i32 0)284 %ps10 = getelementptr i64, ptr %ps, i32 10285 store i64 %x64max, ptr %ps10286 287 ret void288}289 290 291; Exercise not folding calls to 64-bit strtoull.292 293define 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 8297; CHECK-NEXT: store i64 [[MAXP1]], ptr [[PS1]], align 4298; CHECK-NEXT: [[NWS:%.*]] = call i64 @strtoull(ptr nonnull @ws, ptr nonnull @endptr, i32 10)299; CHECK-NEXT: [[PS2:%.*]] = getelementptr i8, ptr [[PS]], i64 16300; CHECK-NEXT: store i64 [[NWS]], ptr [[PS2]], align 4301; CHECK-NEXT: [[NWSP6:%.*]] = call i64 @strtoull(ptr nonnull getelementptr inbounds nuw (i8, ptr @ws, i64 6), ptr nonnull @endptr, i32 10)302; CHECK-NEXT: [[PS3:%.*]] = getelementptr i8, ptr [[PS]], i64 24303; CHECK-NEXT: store i64 [[NWSP6]], ptr [[PS3]], align 4304; CHECK-NEXT: ret void305;306; Do not fold the result of conversion that overflows uint64_t. This307; 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 1310 store i64 %maxp1, ptr %ps1311 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 2315 store i64 %nws, ptr %ps2316 317; Do not fold an empty sequence. The library call may or may not end up318; storing EINVAL in errno.319 %pswsp6 = getelementptr [7 x i8], ptr @ws, i32 0, i32 6320 %nwsp6 = call i64 @strtoull(ptr %pswsp6, ptr @endptr, i32 10)321 %ps3 = getelementptr i64, ptr %ps, i32 3322 store i64 %nwsp6, ptr %ps3323 324 ret void325}326