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; 9define 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 20define 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 31define 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 42define 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 53define 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 64define 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; 78define 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 89define 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 100define 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 111define 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 122define 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 133define 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 150define 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 161define 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 172define 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 183define 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 194define 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 205define 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 216define 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 227define 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 238define 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 249define 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 261define 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 272define 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 283define 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 294define 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 305define 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 316define 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 327define 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 338define 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 349define 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 360define 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 372define 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 384define 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 396define 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 408define 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 420define 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 432define 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 444define 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 456define 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 468define 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 480define 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