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). 4; 5; RUN: opt < %s -passes=instcombine -S | FileCheck %s 6 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 ptr 43 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 8 50; CHECK-NEXT: store i32 -123, ptr [[PS:%.*]], align 4 51; CHECK-NEXT: store ptr getelementptr inbounds nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 85; 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 90 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 95 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 100 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 105 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 110 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 115 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 120 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 125 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 130 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 135 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 140 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 145 146 ret void 147} 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 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 nuw (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 166; 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 171 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 177 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 182 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 189 190 ret void 191} 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 8 199; CHECK-NEXT: store i64 -123, ptr [[PS:%.*]], align 4 200; CHECK-NEXT: store ptr getelementptr inbounds nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 nuw (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 231; 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 236 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 241 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 246 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 251 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 256 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 261 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 266 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 271 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 276 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 281 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 286 287 ret void 288} 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 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 nuw (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 305; 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 311 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 316 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 323 324 ret void 325} 326