1 ; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort=1 -verify-machineinstrs < %s | FileCheck %s 2 3 ; 4 ; Test that we only use the sign/zero extend in the address calculation when 5 ; necessary. 6 ; 7 ; SHIFT 8 ; 9 define i64 @load_addr_shift_zext1(i32 %a, i64 %b) { 10 ; CHECK-LABEL: load_addr_shift_zext1 11 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, uxtw #3] 12 %1 = zext i32 %a to i64 13 %2 = shl i64 %1, 3 14 %3 = add i64 %b, %2 15 %4 = inttoptr i64 %3 to i64* 16 %5 = load i64, i64* %4 17 ret i64 %5 18 } 19 20 define i64 @load_addr_shift_zext2(i32 zeroext %a, i64 %b) { 21 ; CHECK-LABEL: load_addr_shift_zext2 22 ; CHECK: ldr {{x[0-9]+}}, [x1, x0, lsl #3] 23 %1 = zext i32 %a to i64 24 %2 = shl i64 %1, 3 25 %3 = add i64 %b, %2 26 %4 = inttoptr i64 %3 to i64* 27 %5 = load i64, i64* %4 28 ret i64 %5 29 } 30 31 define i64 @load_addr_shift_zext3(i32 signext %a, i64 %b) { 32 ; CHECK-LABEL: load_addr_shift_zext3 33 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, uxtw #3] 34 %1 = zext i32 %a to i64 35 %2 = shl i64 %1, 3 36 %3 = add i64 %b, %2 37 %4 = inttoptr i64 %3 to i64* 38 %5 = load i64, i64* %4 39 ret i64 %5 40 } 41 42 define i64 @load_addr_shift_sext1(i32 %a, i64 %b) { 43 ; CHECK-LABEL: load_addr_shift_sext1 44 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, sxtw #3] 45 %1 = sext i32 %a to i64 46 %2 = shl i64 %1, 3 47 %3 = add i64 %b, %2 48 %4 = inttoptr i64 %3 to i64* 49 %5 = load i64, i64* %4 50 ret i64 %5 51 } 52 53 define i64 @load_addr_shift_sext2(i32 zeroext %a, i64 %b) { 54 ; CHECK-LABEL: load_addr_shift_sext2 55 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, sxtw #3] 56 %1 = sext i32 %a to i64 57 %2 = shl i64 %1, 3 58 %3 = add i64 %b, %2 59 %4 = inttoptr i64 %3 to i64* 60 %5 = load i64, i64* %4 61 ret i64 %5 62 } 63 64 define i64 @load_addr_shift_sext3(i32 signext %a, i64 %b) { 65 ; CHECK-LABEL: load_addr_shift_sext3 66 ; CHECK: ldr {{x[0-9]+}}, [x1, x0, lsl #3] 67 %1 = sext i32 %a to i64 68 %2 = shl i64 %1, 3 69 %3 = add i64 %b, %2 70 %4 = inttoptr i64 %3 to i64* 71 %5 = load i64, i64* %4 72 ret i64 %5 73 } 74 75 ; 76 ; MUL 77 ; 78 define i64 @load_addr_mul_zext1(i32 %a, i64 %b) { 79 ; CHECK-LABEL: load_addr_mul_zext1 80 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, uxtw #3] 81 %1 = zext i32 %a to i64 82 %2 = mul i64 %1, 8 83 %3 = add i64 %b, %2 84 %4 = inttoptr i64 %3 to i64* 85 %5 = load i64, i64* %4 86 ret i64 %5 87 } 88 89 define i64 @load_addr_mul_zext2(i32 zeroext %a, i64 %b) { 90 ; CHECK-LABEL: load_addr_mul_zext2 91 ; CHECK: ldr {{x[0-9]+}}, [x1, x0, lsl #3] 92 %1 = zext i32 %a to i64 93 %2 = mul i64 %1, 8 94 %3 = add i64 %b, %2 95 %4 = inttoptr i64 %3 to i64* 96 %5 = load i64, i64* %4 97 ret i64 %5 98 } 99 100 define i64 @load_addr_mul_zext3(i32 signext %a, i64 %b) { 101 ; CHECK-LABEL: load_addr_mul_zext3 102 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, uxtw #3] 103 %1 = zext i32 %a to i64 104 %2 = mul i64 %1, 8 105 %3 = add i64 %b, %2 106 %4 = inttoptr i64 %3 to i64* 107 %5 = load i64, i64* %4 108 ret i64 %5 109 } 110 111 define i64 @load_addr_mul_sext1(i32 %a, i64 %b) { 112 ; CHECK-LABEL: load_addr_mul_sext1 113 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, sxtw #3] 114 %1 = sext i32 %a to i64 115 %2 = mul i64 %1, 8 116 %3 = add i64 %b, %2 117 %4 = inttoptr i64 %3 to i64* 118 %5 = load i64, i64* %4 119 ret i64 %5 120 } 121 122 define i64 @load_addr_mul_sext2(i32 zeroext %a, i64 %b) { 123 ; CHECK-LABEL: load_addr_mul_sext2 124 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, sxtw #3] 125 %1 = sext i32 %a to i64 126 %2 = mul i64 %1, 8 127 %3 = add i64 %b, %2 128 %4 = inttoptr i64 %3 to i64* 129 %5 = load i64, i64* %4 130 ret i64 %5 131 } 132 133 define i64 @load_addr_mul_sext3(i32 signext %a, i64 %b) { 134 ; CHECK-LABEL: load_addr_mul_sext3 135 ; CHECK: ldr {{x[0-9]+}}, [x1, x0, lsl #3] 136 %1 = sext i32 %a to i64 137 %2 = mul i64 %1, 8 138 %3 = add i64 %b, %2 139 %4 = inttoptr i64 %3 to i64* 140 %5 = load i64, i64* %4 141 ret i64 %5 142 } 143 144 145 ; 146 ; Test folding of the sign-/zero-extend into the load instruction. 147 ; 148 149 ; Unscaled 150 define i32 @load_unscaled_zext_i8_to_i32(i64 %a) { 151 ; CHECK-LABEL: load_unscaled_zext_i8_to_i32 152 ; CHECK: ldurb w0, [x0, #-8] 153 ; CHECK-NOT: uxtb 154 %1 = sub i64 %a, 8 155 %2 = inttoptr i64 %1 to i8* 156 %3 = load i8, i8* %2 157 %4 = zext i8 %3 to i32 158 ret i32 %4 159 } 160 161 define i32 @load_unscaled_zext_i16_to_i32(i64 %a) { 162 ; CHECK-LABEL: load_unscaled_zext_i16_to_i32 163 ; CHECK: ldurh w0, [x0, #-8] 164 ; CHECK-NOT: uxth 165 %1 = sub i64 %a, 8 166 %2 = inttoptr i64 %1 to i16* 167 %3 = load i16, i16* %2 168 %4 = zext i16 %3 to i32 169 ret i32 %4 170 } 171 172 define i64 @load_unscaled_zext_i8_to_i64(i64 %a) { 173 ; CHECK-LABEL: load_unscaled_zext_i8_to_i64 174 ; CHECK: ldurb w0, [x0, #-8] 175 ; CHECK-NOT: uxtb 176 %1 = sub i64 %a, 8 177 %2 = inttoptr i64 %1 to i8* 178 %3 = load i8, i8* %2 179 %4 = zext i8 %3 to i64 180 ret i64 %4 181 } 182 183 define i64 @load_unscaled_zext_i16_to_i64(i64 %a) { 184 ; CHECK-LABEL: load_unscaled_zext_i16_to_i64 185 ; CHECK: ldurh w0, [x0, #-8] 186 ; CHECK-NOT: uxth 187 %1 = sub i64 %a, 8 188 %2 = inttoptr i64 %1 to i16* 189 %3 = load i16, i16* %2 190 %4 = zext i16 %3 to i64 191 ret i64 %4 192 } 193 194 define i64 @load_unscaled_zext_i32_to_i64(i64 %a) { 195 ; CHECK-LABEL: load_unscaled_zext_i32_to_i64 196 ; CHECK: ldur w0, [x0, #-8] 197 ; CHECK-NOT: uxtw 198 %1 = sub i64 %a, 8 199 %2 = inttoptr i64 %1 to i32* 200 %3 = load i32, i32* %2 201 %4 = zext i32 %3 to i64 202 ret i64 %4 203 } 204 205 define i32 @load_unscaled_sext_i8_to_i32(i64 %a) { 206 ; CHECK-LABEL: load_unscaled_sext_i8_to_i32 207 ; CHECK: ldursb w0, [x0, #-8] 208 ; CHECK-NOT: sxtb 209 %1 = sub i64 %a, 8 210 %2 = inttoptr i64 %1 to i8* 211 %3 = load i8, i8* %2 212 %4 = sext i8 %3 to i32 213 ret i32 %4 214 } 215 216 define i32 @load_unscaled_sext_i16_to_i32(i64 %a) { 217 ; CHECK-LABEL: load_unscaled_sext_i16_to_i32 218 ; CHECK: ldursh w0, [x0, #-8] 219 ; CHECK-NOT: sxth 220 %1 = sub i64 %a, 8 221 %2 = inttoptr i64 %1 to i16* 222 %3 = load i16, i16* %2 223 %4 = sext i16 %3 to i32 224 ret i32 %4 225 } 226 227 define i64 @load_unscaled_sext_i8_to_i64(i64 %a) { 228 ; CHECK-LABEL: load_unscaled_sext_i8_to_i64 229 ; CHECK: ldursb x0, [x0, #-8] 230 ; CHECK-NOT: sxtb 231 %1 = sub i64 %a, 8 232 %2 = inttoptr i64 %1 to i8* 233 %3 = load i8, i8* %2 234 %4 = sext i8 %3 to i64 235 ret i64 %4 236 } 237 238 define i64 @load_unscaled_sext_i16_to_i64(i64 %a) { 239 ; CHECK-LABEL: load_unscaled_sext_i16_to_i64 240 ; CHECK: ldursh x0, [x0, #-8] 241 ; CHECK-NOT: sxth 242 %1 = sub i64 %a, 8 243 %2 = inttoptr i64 %1 to i16* 244 %3 = load i16, i16* %2 245 %4 = sext i16 %3 to i64 246 ret i64 %4 247 } 248 249 define i64 @load_unscaled_sext_i32_to_i64(i64 %a) { 250 ; CHECK-LABEL: load_unscaled_sext_i32_to_i64 251 ; CHECK: ldursw x0, [x0, #-8] 252 ; CHECK-NOT: sxtw 253 %1 = sub i64 %a, 8 254 %2 = inttoptr i64 %1 to i32* 255 %3 = load i32, i32* %2 256 %4 = sext i32 %3 to i64 257 ret i64 %4 258 } 259 260 ; Register 261 define i32 @load_register_zext_i8_to_i32(i64 %a, i64 %b) { 262 ; CHECK-LABEL: load_register_zext_i8_to_i32 263 ; CHECK: ldrb w0, [x0, x1] 264 ; CHECK-NOT: uxtb 265 %1 = add i64 %a, %b 266 %2 = inttoptr i64 %1 to i8* 267 %3 = load i8, i8* %2 268 %4 = zext i8 %3 to i32 269 ret i32 %4 270 } 271 272 define i32 @load_register_zext_i16_to_i32(i64 %a, i64 %b) { 273 ; CHECK-LABEL: load_register_zext_i16_to_i32 274 ; CHECK: ldrh w0, [x0, x1] 275 ; CHECK-NOT: uxth 276 %1 = add i64 %a, %b 277 %2 = inttoptr i64 %1 to i16* 278 %3 = load i16, i16* %2 279 %4 = zext i16 %3 to i32 280 ret i32 %4 281 } 282 283 define i64 @load_register_zext_i8_to_i64(i64 %a, i64 %b) { 284 ; CHECK-LABEL: load_register_zext_i8_to_i64 285 ; CHECK: ldrb w0, [x0, x1] 286 ; CHECK-NOT: uxtb 287 %1 = add i64 %a, %b 288 %2 = inttoptr i64 %1 to i8* 289 %3 = load i8, i8* %2 290 %4 = zext i8 %3 to i64 291 ret i64 %4 292 } 293 294 define i64 @load_register_zext_i16_to_i64(i64 %a, i64 %b) { 295 ; CHECK-LABEL: load_register_zext_i16_to_i64 296 ; CHECK: ldrh w0, [x0, x1] 297 ; CHECK-NOT: uxth 298 %1 = add i64 %a, %b 299 %2 = inttoptr i64 %1 to i16* 300 %3 = load i16, i16* %2 301 %4 = zext i16 %3 to i64 302 ret i64 %4 303 } 304 305 define i64 @load_register_zext_i32_to_i64(i64 %a, i64 %b) { 306 ; CHECK-LABEL: load_register_zext_i32_to_i64 307 ; CHECK: ldr w0, [x0, x1] 308 ; CHECK-NOT: uxtw 309 %1 = add i64 %a, %b 310 %2 = inttoptr i64 %1 to i32* 311 %3 = load i32, i32* %2 312 %4 = zext i32 %3 to i64 313 ret i64 %4 314 } 315 316 define i32 @load_register_sext_i8_to_i32(i64 %a, i64 %b) { 317 ; CHECK-LABEL: load_register_sext_i8_to_i32 318 ; CHECK: ldrsb w0, [x0, x1] 319 ; CHECK-NOT: sxtb 320 %1 = add i64 %a, %b 321 %2 = inttoptr i64 %1 to i8* 322 %3 = load i8, i8* %2 323 %4 = sext i8 %3 to i32 324 ret i32 %4 325 } 326 327 define i32 @load_register_sext_i16_to_i32(i64 %a, i64 %b) { 328 ; CHECK-LABEL: load_register_sext_i16_to_i32 329 ; CHECK: ldrsh w0, [x0, x1] 330 ; CHECK-NOT: sxth 331 %1 = add i64 %a, %b 332 %2 = inttoptr i64 %1 to i16* 333 %3 = load i16, i16* %2 334 %4 = sext i16 %3 to i32 335 ret i32 %4 336 } 337 338 define i64 @load_register_sext_i8_to_i64(i64 %a, i64 %b) { 339 ; CHECK-LABEL: load_register_sext_i8_to_i64 340 ; CHECK: ldrsb x0, [x0, x1] 341 ; CHECK-NOT: sxtb 342 %1 = add i64 %a, %b 343 %2 = inttoptr i64 %1 to i8* 344 %3 = load i8, i8* %2 345 %4 = sext i8 %3 to i64 346 ret i64 %4 347 } 348 349 define i64 @load_register_sext_i16_to_i64(i64 %a, i64 %b) { 350 ; CHECK-LABEL: load_register_sext_i16_to_i64 351 ; CHECK: ldrsh x0, [x0, x1] 352 ; CHECK-NOT: sxth 353 %1 = add i64 %a, %b 354 %2 = inttoptr i64 %1 to i16* 355 %3 = load i16, i16* %2 356 %4 = sext i16 %3 to i64 357 ret i64 %4 358 } 359 360 define i64 @load_register_sext_i32_to_i64(i64 %a, i64 %b) { 361 ; CHECK-LABEL: load_register_sext_i32_to_i64 362 ; CHECK: ldrsw x0, [x0, x1] 363 ; CHECK-NOT: sxtw 364 %1 = add i64 %a, %b 365 %2 = inttoptr i64 %1 to i32* 366 %3 = load i32, i32* %2 367 %4 = sext i32 %3 to i64 368 ret i64 %4 369 } 370 371 ; Extend 372 define i32 @load_extend_zext_i8_to_i32(i64 %a, i32 %b) { 373 ; CHECK-LABEL: load_extend_zext_i8_to_i32 374 ; CHECK: ldrb w0, [x0, w1, sxtw] 375 ; CHECK-NOT: uxtb 376 %1 = sext i32 %b to i64 377 %2 = add i64 %a, %1 378 %3 = inttoptr i64 %2 to i8* 379 %4 = load i8, i8* %3 380 %5 = zext i8 %4 to i32 381 ret i32 %5 382 } 383 384 define i32 @load_extend_zext_i16_to_i32(i64 %a, i32 %b) { 385 ; CHECK-LABEL: load_extend_zext_i16_to_i32 386 ; CHECK: ldrh w0, [x0, w1, sxtw] 387 ; CHECK-NOT: uxth 388 %1 = sext i32 %b to i64 389 %2 = add i64 %a, %1 390 %3 = inttoptr i64 %2 to i16* 391 %4 = load i16, i16* %3 392 %5 = zext i16 %4 to i32 393 ret i32 %5 394 } 395 396 define i64 @load_extend_zext_i8_to_i64(i64 %a, i32 %b) { 397 ; CHECK-LABEL: load_extend_zext_i8_to_i64 398 ; CHECK: ldrb w0, [x0, w1, sxtw] 399 ; CHECK-NOT: uxtb 400 %1 = sext i32 %b to i64 401 %2 = add i64 %a, %1 402 %3 = inttoptr i64 %2 to i8* 403 %4 = load i8, i8* %3 404 %5 = zext i8 %4 to i64 405 ret i64 %5 406 } 407 408 define i64 @load_extend_zext_i16_to_i64(i64 %a, i32 %b) { 409 ; CHECK-LABEL: load_extend_zext_i16_to_i64 410 ; CHECK: ldrh w0, [x0, w1, sxtw] 411 ; CHECK-NOT: uxth 412 %1 = sext i32 %b to i64 413 %2 = add i64 %a, %1 414 %3 = inttoptr i64 %2 to i16* 415 %4 = load i16, i16* %3 416 %5 = zext i16 %4 to i64 417 ret i64 %5 418 } 419 420 define i64 @load_extend_zext_i32_to_i64(i64 %a, i32 %b) { 421 ; CHECK-LABEL: load_extend_zext_i32_to_i64 422 ; CHECK: ldr w0, [x0, w1, sxtw] 423 ; CHECK-NOT: uxtw 424 %1 = sext i32 %b to i64 425 %2 = add i64 %a, %1 426 %3 = inttoptr i64 %2 to i32* 427 %4 = load i32, i32* %3 428 %5 = zext i32 %4 to i64 429 ret i64 %5 430 } 431 432 define i32 @load_extend_sext_i8_to_i32(i64 %a, i32 %b) { 433 ; CHECK-LABEL: load_extend_sext_i8_to_i32 434 ; CHECK: ldrsb w0, [x0, w1, sxtw] 435 ; CHECK-NOT: sxtb 436 %1 = sext i32 %b to i64 437 %2 = add i64 %a, %1 438 %3 = inttoptr i64 %2 to i8* 439 %4 = load i8, i8* %3 440 %5 = sext i8 %4 to i32 441 ret i32 %5 442 } 443 444 define i32 @load_extend_sext_i16_to_i32(i64 %a, i32 %b) { 445 ; CHECK-LABEL: load_extend_sext_i16_to_i32 446 ; CHECK: ldrsh w0, [x0, w1, sxtw] 447 ; CHECK-NOT: sxth 448 %1 = sext i32 %b to i64 449 %2 = add i64 %a, %1 450 %3 = inttoptr i64 %2 to i16* 451 %4 = load i16, i16* %3 452 %5 = sext i16 %4 to i32 453 ret i32 %5 454 } 455 456 define i64 @load_extend_sext_i8_to_i64(i64 %a, i32 %b) { 457 ; CHECK-LABEL: load_extend_sext_i8_to_i64 458 ; CHECK: ldrsb x0, [x0, w1, sxtw] 459 ; CHECK-NOT: sxtb 460 %1 = sext i32 %b to i64 461 %2 = add i64 %a, %1 462 %3 = inttoptr i64 %2 to i8* 463 %4 = load i8, i8* %3 464 %5 = sext i8 %4 to i64 465 ret i64 %5 466 } 467 468 define i64 @load_extend_sext_i16_to_i64(i64 %a, i32 %b) { 469 ; CHECK-LABEL: load_extend_sext_i16_to_i64 470 ; CHECK: ldrsh x0, [x0, w1, sxtw] 471 ; CHECK-NOT: sxth 472 %1 = sext i32 %b to i64 473 %2 = add i64 %a, %1 474 %3 = inttoptr i64 %2 to i16* 475 %4 = load i16, i16* %3 476 %5 = sext i16 %4 to i64 477 ret i64 %5 478 } 479 480 define i64 @load_extend_sext_i32_to_i64(i64 %a, i32 %b) { 481 ; CHECK-LABEL: load_extend_sext_i32_to_i64 482 ; CHECK: ldrsw x0, [x0, w1, sxtw] 483 ; CHECK-NOT: sxtw 484 %1 = sext i32 %b to i64 485 %2 = add i64 %a, %1 486 %3 = inttoptr i64 %2 to i32* 487 %4 = load i32, i32* %3 488 %5 = sext i32 %4 to i64 489 ret i64 %5 490 } 491 492