1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py 2; RUN: llc -mtriple=aarch64-apple-darwin -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG 3; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort=1 -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST 4 5; Load / Store Base Register only 6define zeroext i1 @load_breg_i1(ptr %a) { 7; SDAG-LABEL: load_breg_i1: 8; SDAG: ; %bb.0: 9; SDAG-NEXT: ldrb w0, [x0] 10; SDAG-NEXT: ret 11; 12; FAST-LABEL: load_breg_i1: 13; FAST: ; %bb.0: 14; FAST-NEXT: ldrb w8, [x0] 15; FAST-NEXT: and w8, w8, #0x1 16; FAST-NEXT: and w0, w8, #0x1 17; FAST-NEXT: ret 18 %1 = load i1, ptr %a 19 ret i1 %1 20} 21 22define zeroext i8 @load_breg_i8(ptr %a) { 23; SDAG-LABEL: load_breg_i8: 24; SDAG: ; %bb.0: 25; SDAG-NEXT: ldrb w0, [x0] 26; SDAG-NEXT: ret 27; 28; FAST-LABEL: load_breg_i8: 29; FAST: ; %bb.0: 30; FAST-NEXT: ldrb w8, [x0] 31; FAST-NEXT: uxtb w0, w8 32; FAST-NEXT: ret 33 %1 = load i8, ptr %a 34 ret i8 %1 35} 36 37define zeroext i16 @load_breg_i16(ptr %a) { 38; SDAG-LABEL: load_breg_i16: 39; SDAG: ; %bb.0: 40; SDAG-NEXT: ldrh w0, [x0] 41; SDAG-NEXT: ret 42; 43; FAST-LABEL: load_breg_i16: 44; FAST: ; %bb.0: 45; FAST-NEXT: ldrh w8, [x0] 46; FAST-NEXT: uxth w0, w8 47; FAST-NEXT: ret 48 %1 = load i16, ptr %a 49 ret i16 %1 50} 51 52define i32 @load_breg_i32(ptr %a) { 53; CHECK-LABEL: load_breg_i32: 54; CHECK: ; %bb.0: 55; CHECK-NEXT: ldr w0, [x0] 56; CHECK-NEXT: ret 57 %1 = load i32, ptr %a 58 ret i32 %1 59} 60 61define i64 @load_breg_i64(ptr %a) { 62; CHECK-LABEL: load_breg_i64: 63; CHECK: ; %bb.0: 64; CHECK-NEXT: ldr x0, [x0] 65; CHECK-NEXT: ret 66 %1 = load i64, ptr %a 67 ret i64 %1 68} 69 70define float @load_breg_f32(ptr %a) { 71; CHECK-LABEL: load_breg_f32: 72; CHECK: ; %bb.0: 73; CHECK-NEXT: ldr s0, [x0] 74; CHECK-NEXT: ret 75 %1 = load float, ptr %a 76 ret float %1 77} 78 79define double @load_breg_f64(ptr %a) { 80; CHECK-LABEL: load_breg_f64: 81; CHECK: ; %bb.0: 82; CHECK-NEXT: ldr d0, [x0] 83; CHECK-NEXT: ret 84 %1 = load double, ptr %a 85 ret double %1 86} 87 88define void @store_breg_i1(ptr %a) { 89; CHECK-LABEL: store_breg_i1: 90; CHECK: ; %bb.0: 91; CHECK-NEXT: strb wzr, [x0] 92; CHECK-NEXT: ret 93 store i1 0, ptr %a 94 ret void 95} 96 97define void @store_breg_i1_2(ptr %a) { 98; SDAG-LABEL: store_breg_i1_2: 99; SDAG: ; %bb.0: 100; SDAG-NEXT: mov w8, #1 ; =0x1 101; SDAG-NEXT: strb w8, [x0] 102; SDAG-NEXT: ret 103; 104; FAST-LABEL: store_breg_i1_2: 105; FAST: ; %bb.0: 106; FAST-NEXT: mov w8, #1 ; =0x1 107; FAST-NEXT: and w8, w8, #0x1 108; FAST-NEXT: strb w8, [x0] 109; FAST-NEXT: ret 110 store i1 true, ptr %a 111 ret void 112} 113 114define void @store_breg_i8(ptr %a) { 115; CHECK-LABEL: store_breg_i8: 116; CHECK: ; %bb.0: 117; CHECK-NEXT: strb wzr, [x0] 118; CHECK-NEXT: ret 119 store i8 0, ptr %a 120 ret void 121} 122 123define void @store_breg_i16(ptr %a) { 124; CHECK-LABEL: store_breg_i16: 125; CHECK: ; %bb.0: 126; CHECK-NEXT: strh wzr, [x0] 127; CHECK-NEXT: ret 128 store i16 0, ptr %a 129 ret void 130} 131 132define void @store_breg_i32(ptr %a) { 133; CHECK-LABEL: store_breg_i32: 134; CHECK: ; %bb.0: 135; CHECK-NEXT: str wzr, [x0] 136; CHECK-NEXT: ret 137 store i32 0, ptr %a 138 ret void 139} 140 141define void @store_breg_i64(ptr %a) { 142; CHECK-LABEL: store_breg_i64: 143; CHECK: ; %bb.0: 144; CHECK-NEXT: str xzr, [x0] 145; CHECK-NEXT: ret 146 store i64 0, ptr %a 147 ret void 148} 149 150define void @store_breg_f32(ptr %a) { 151; CHECK-LABEL: store_breg_f32: 152; CHECK: ; %bb.0: 153; CHECK-NEXT: str wzr, [x0] 154; CHECK-NEXT: ret 155 store float 0.0, ptr %a 156 ret void 157} 158 159define void @store_breg_f64(ptr %a) { 160; CHECK-LABEL: store_breg_f64: 161; CHECK: ; %bb.0: 162; CHECK-NEXT: str xzr, [x0] 163; CHECK-NEXT: ret 164 store double 0.0, ptr %a 165 ret void 166} 167 168; Load Immediate 169define i32 @load_immoff_1() { 170; SDAG-LABEL: load_immoff_1: 171; SDAG: ; %bb.0: 172; SDAG-NEXT: mov w8, #128 ; =0x80 173; SDAG-NEXT: ldr w0, [x8] 174; SDAG-NEXT: ret 175; 176; FAST-LABEL: load_immoff_1: 177; FAST: ; %bb.0: 178; FAST-NEXT: mov x8, #128 ; =0x80 179; FAST-NEXT: ldr w0, [x8] 180; FAST-NEXT: ret 181 %1 = inttoptr i64 128 to ptr 182 %2 = load i32, ptr %1 183 ret i32 %2 184} 185 186; Load / Store Base Register + Immediate Offset 187; Max supported negative offset 188define i32 @load_breg_immoff_1(i64 %a) { 189; CHECK-LABEL: load_breg_immoff_1: 190; CHECK: ; %bb.0: 191; CHECK-NEXT: ldur w0, [x0, #-256] 192; CHECK-NEXT: ret 193 %1 = add i64 %a, -256 194 %2 = inttoptr i64 %1 to ptr 195 %3 = load i32, ptr %2 196 ret i32 %3 197} 198 199; Min not-supported negative offset 200define i32 @load_breg_immoff_2(i64 %a) { 201; CHECK-LABEL: load_breg_immoff_2: 202; CHECK: ; %bb.0: 203; CHECK-NEXT: sub x8, x0, #257 204; CHECK-NEXT: ldr w0, [x8] 205; CHECK-NEXT: ret 206 %1 = add i64 %a, -257 207 %2 = inttoptr i64 %1 to ptr 208 %3 = load i32, ptr %2 209 ret i32 %3 210} 211 212; Max supported unscaled offset 213define i32 @load_breg_immoff_3(i64 %a) { 214; CHECK-LABEL: load_breg_immoff_3: 215; CHECK: ; %bb.0: 216; CHECK-NEXT: ldur w0, [x0, #255] 217; CHECK-NEXT: ret 218 %1 = add i64 %a, 255 219 %2 = inttoptr i64 %1 to ptr 220 %3 = load i32, ptr %2 221 ret i32 %3 222} 223 224; Min un-supported unscaled offset 225define i32 @load_breg_immoff_4(i64 %a) { 226; CHECK-LABEL: load_breg_immoff_4: 227; CHECK: ; %bb.0: 228; CHECK-NEXT: add x8, x0, #257 229; CHECK-NEXT: ldr w0, [x8] 230; CHECK-NEXT: ret 231 %1 = add i64 %a, 257 232 %2 = inttoptr i64 %1 to ptr 233 %3 = load i32, ptr %2 234 ret i32 %3 235} 236 237; Max supported scaled offset 238define i32 @load_breg_immoff_5(i64 %a) { 239; CHECK-LABEL: load_breg_immoff_5: 240; CHECK: ; %bb.0: 241; CHECK-NEXT: ldr w0, [x0, #16380] 242; CHECK-NEXT: ret 243 %1 = add i64 %a, 16380 244 %2 = inttoptr i64 %1 to ptr 245 %3 = load i32, ptr %2 246 ret i32 %3 247} 248 249; Min un-supported scaled offset 250define i32 @load_breg_immoff_6(i64 %a) { 251; SDAG-LABEL: load_breg_immoff_6: 252; SDAG: ; %bb.0: 253; SDAG-NEXT: mov w8, #16384 ; =0x4000 254; SDAG-NEXT: ldr w0, [x0, x8] 255; SDAG-NEXT: ret 256; 257; FAST-LABEL: load_breg_immoff_6: 258; FAST: ; %bb.0: 259; FAST-NEXT: add x8, x0, #4, lsl #12 ; =16384 260; FAST-NEXT: ldr w0, [x8] 261; FAST-NEXT: ret 262 %1 = add i64 %a, 16384 263 %2 = inttoptr i64 %1 to ptr 264 %3 = load i32, ptr %2 265 ret i32 %3 266} 267 268; Max supported negative offset 269define void @store_breg_immoff_1(i64 %a) { 270; CHECK-LABEL: store_breg_immoff_1: 271; CHECK: ; %bb.0: 272; CHECK-NEXT: stur wzr, [x0, #-256] 273; CHECK-NEXT: ret 274 %1 = add i64 %a, -256 275 %2 = inttoptr i64 %1 to ptr 276 store i32 0, ptr %2 277 ret void 278} 279 280; Min not-supported negative offset 281define void @store_breg_immoff_2(i64 %a) { 282; CHECK-LABEL: store_breg_immoff_2: 283; CHECK: ; %bb.0: 284; CHECK-NEXT: sub x8, x0, #257 285; CHECK-NEXT: str wzr, [x8] 286; CHECK-NEXT: ret 287 %1 = add i64 %a, -257 288 %2 = inttoptr i64 %1 to ptr 289 store i32 0, ptr %2 290 ret void 291} 292 293; Max supported unscaled offset 294define void @store_breg_immoff_3(i64 %a) { 295; CHECK-LABEL: store_breg_immoff_3: 296; CHECK: ; %bb.0: 297; CHECK-NEXT: stur wzr, [x0, #255] 298; CHECK-NEXT: ret 299 %1 = add i64 %a, 255 300 %2 = inttoptr i64 %1 to ptr 301 store i32 0, ptr %2 302 ret void 303} 304 305; Min un-supported unscaled offset 306define void @store_breg_immoff_4(i64 %a) { 307; CHECK-LABEL: store_breg_immoff_4: 308; CHECK: ; %bb.0: 309; CHECK-NEXT: add x8, x0, #257 310; CHECK-NEXT: str wzr, [x8] 311; CHECK-NEXT: ret 312 %1 = add i64 %a, 257 313 %2 = inttoptr i64 %1 to ptr 314 store i32 0, ptr %2 315 ret void 316} 317 318; Max supported scaled offset 319define void @store_breg_immoff_5(i64 %a) { 320; CHECK-LABEL: store_breg_immoff_5: 321; CHECK: ; %bb.0: 322; CHECK-NEXT: str wzr, [x0, #16380] 323; CHECK-NEXT: ret 324 %1 = add i64 %a, 16380 325 %2 = inttoptr i64 %1 to ptr 326 store i32 0, ptr %2 327 ret void 328} 329 330; Min un-supported scaled offset 331define void @store_breg_immoff_6(i64 %a) { 332; SDAG-LABEL: store_breg_immoff_6: 333; SDAG: ; %bb.0: 334; SDAG-NEXT: mov w8, #16384 ; =0x4000 335; SDAG-NEXT: str wzr, [x0, x8] 336; SDAG-NEXT: ret 337; 338; FAST-LABEL: store_breg_immoff_6: 339; FAST: ; %bb.0: 340; FAST-NEXT: add x8, x0, #4, lsl #12 ; =16384 341; FAST-NEXT: str wzr, [x8] 342; FAST-NEXT: ret 343 %1 = add i64 %a, 16384 344 %2 = inttoptr i64 %1 to ptr 345 store i32 0, ptr %2 346 ret void 347} 348 349define i64 @load_breg_immoff_7(i64 %a) { 350; CHECK-LABEL: load_breg_immoff_7: 351; CHECK: ; %bb.0: 352; CHECK-NEXT: ldr x0, [x0, #48] 353; CHECK-NEXT: ret 354 %1 = add i64 %a, 48 355 %2 = inttoptr i64 %1 to ptr 356 %3 = load i64, ptr %2 357 ret i64 %3 358} 359 360; Flip add operands 361define i64 @load_breg_immoff_8(i64 %a) { 362; CHECK-LABEL: load_breg_immoff_8: 363; CHECK: ; %bb.0: 364; CHECK-NEXT: ldr x0, [x0, #48] 365; CHECK-NEXT: ret 366 %1 = add i64 48, %a 367 %2 = inttoptr i64 %1 to ptr 368 %3 = load i64, ptr %2 369 ret i64 %3 370} 371 372; Load Base Register + Register Offset 373define i64 @load_breg_offreg_1(i64 %a, i64 %b) { 374; CHECK-LABEL: load_breg_offreg_1: 375; CHECK: ; %bb.0: 376; CHECK-NEXT: ldr x0, [x0, x1] 377; CHECK-NEXT: ret 378 %1 = add i64 %a, %b 379 %2 = inttoptr i64 %1 to ptr 380 %3 = load i64, ptr %2 381 ret i64 %3 382} 383 384; Flip add operands 385define i64 @load_breg_offreg_2(i64 %a, i64 %b) { 386; CHECK-LABEL: load_breg_offreg_2: 387; CHECK: ; %bb.0: 388; CHECK-NEXT: ldr x0, [x1, x0] 389; CHECK-NEXT: ret 390 %1 = add i64 %b, %a 391 %2 = inttoptr i64 %1 to ptr 392 %3 = load i64, ptr %2 393 ret i64 %3 394} 395 396; Load Base Register + Register Offset + Immediate Offset 397define i64 @load_breg_offreg_immoff_1(i64 %a, i64 %b) { 398; CHECK-LABEL: load_breg_offreg_immoff_1: 399; CHECK: ; %bb.0: 400; CHECK-NEXT: add x8, x0, x1 401; CHECK-NEXT: ldr x0, [x8, #48] 402; CHECK-NEXT: ret 403 %1 = add i64 %a, %b 404 %2 = add i64 %1, 48 405 %3 = inttoptr i64 %2 to ptr 406 %4 = load i64, ptr %3 407 ret i64 %4 408} 409 410define i64 @load_breg_offreg_immoff_2(i64 %a, i64 %b) { 411; SDAG-LABEL: load_breg_offreg_immoff_2: 412; SDAG: ; %bb.0: 413; SDAG-NEXT: mov w8, #61440 ; =0xf000 414; SDAG-NEXT: add x9, x0, x1 415; SDAG-NEXT: ldr x0, [x9, x8] 416; SDAG-NEXT: ret 417; 418; FAST-LABEL: load_breg_offreg_immoff_2: 419; FAST: ; %bb.0: 420; FAST-NEXT: add x8, x0, #15, lsl #12 ; =61440 421; FAST-NEXT: ldr x0, [x8, x1] 422; FAST-NEXT: ret 423 %1 = add i64 %a, %b 424 %2 = add i64 %1, 61440 425 %3 = inttoptr i64 %2 to ptr 426 %4 = load i64, ptr %3 427 ret i64 %4 428} 429 430; Load Scaled Register Offset 431define i32 @load_shift_offreg_1(i64 %a) { 432; CHECK-LABEL: load_shift_offreg_1: 433; CHECK: ; %bb.0: 434; CHECK-NEXT: lsl x8, x0, #2 435; CHECK-NEXT: ldr w0, [x8] 436; CHECK-NEXT: ret 437 %1 = shl i64 %a, 2 438 %2 = inttoptr i64 %1 to ptr 439 %3 = load i32, ptr %2 440 ret i32 %3 441} 442 443define i32 @load_mul_offreg_1(i64 %a) { 444; CHECK-LABEL: load_mul_offreg_1: 445; CHECK: ; %bb.0: 446; CHECK-NEXT: lsl x8, x0, #2 447; CHECK-NEXT: ldr w0, [x8] 448; CHECK-NEXT: ret 449 %1 = mul i64 %a, 4 450 %2 = inttoptr i64 %1 to ptr 451 %3 = load i32, ptr %2 452 ret i32 %3 453} 454 455; Load Base Register + Scaled Register Offset 456define i32 @load_breg_shift_offreg_1(i64 %a, i64 %b) { 457; CHECK-LABEL: load_breg_shift_offreg_1: 458; CHECK: ; %bb.0: 459; CHECK-NEXT: ldr w0, [x1, x0, lsl #2] 460; CHECK-NEXT: ret 461 %1 = shl i64 %a, 2 462 %2 = add i64 %1, %b 463 %3 = inttoptr i64 %2 to ptr 464 %4 = load i32, ptr %3 465 ret i32 %4 466} 467 468define i32 @load_breg_shift_offreg_2(i64 %a, i64 %b) { 469; CHECK-LABEL: load_breg_shift_offreg_2: 470; CHECK: ; %bb.0: 471; CHECK-NEXT: ldr w0, [x1, x0, lsl #2] 472; CHECK-NEXT: ret 473 %1 = shl i64 %a, 2 474 %2 = add i64 %b, %1 475 %3 = inttoptr i64 %2 to ptr 476 %4 = load i32, ptr %3 477 ret i32 %4 478} 479 480define i32 @load_breg_shift_offreg_3(i64 %a, i64 %b) { 481; SDAG-LABEL: load_breg_shift_offreg_3: 482; SDAG: ; %bb.0: 483; SDAG-NEXT: lsl x8, x0, #2 484; SDAG-NEXT: ldr w0, [x8, x1, lsl #2] 485; SDAG-NEXT: ret 486; 487; FAST-LABEL: load_breg_shift_offreg_3: 488; FAST: ; %bb.0: 489; FAST-NEXT: lsl x8, x1, #2 490; FAST-NEXT: ldr w0, [x8, x0, lsl #2] 491; FAST-NEXT: ret 492 %1 = shl i64 %a, 2 493 %2 = shl i64 %b, 2 494 %3 = add i64 %1, %2 495 %4 = inttoptr i64 %3 to ptr 496 %5 = load i32, ptr %4 497 ret i32 %5 498} 499 500define i32 @load_breg_shift_offreg_4(i64 %a, i64 %b) { 501; SDAG-LABEL: load_breg_shift_offreg_4: 502; SDAG: ; %bb.0: 503; SDAG-NEXT: lsl x8, x1, #2 504; SDAG-NEXT: ldr w0, [x8, x0, lsl #2] 505; SDAG-NEXT: ret 506; 507; FAST-LABEL: load_breg_shift_offreg_4: 508; FAST: ; %bb.0: 509; FAST-NEXT: lsl x8, x0, #2 510; FAST-NEXT: ldr w0, [x8, x1, lsl #2] 511; FAST-NEXT: ret 512 %1 = shl i64 %a, 2 513 %2 = shl i64 %b, 2 514 %3 = add i64 %2, %1 515 %4 = inttoptr i64 %3 to ptr 516 %5 = load i32, ptr %4 517 ret i32 %5 518} 519 520define i32 @load_breg_shift_offreg_5(i64 %a, i64 %b) { 521; CHECK-LABEL: load_breg_shift_offreg_5: 522; CHECK: ; %bb.0: 523; CHECK-NEXT: lsl x8, x1, #3 524; CHECK-NEXT: ldr w0, [x8, x0, lsl #2] 525; CHECK-NEXT: ret 526 %1 = shl i64 %a, 2 527 %2 = shl i64 %b, 3 528 %3 = add i64 %1, %2 529 %4 = inttoptr i64 %3 to ptr 530 %5 = load i32, ptr %4 531 ret i32 %5 532} 533 534define i32 @load_breg_mul_offreg_1(i64 %a, i64 %b) { 535; CHECK-LABEL: load_breg_mul_offreg_1: 536; CHECK: ; %bb.0: 537; CHECK-NEXT: ldr w0, [x1, x0, lsl #2] 538; CHECK-NEXT: ret 539 %1 = mul i64 %a, 4 540 %2 = add i64 %1, %b 541 %3 = inttoptr i64 %2 to ptr 542 %4 = load i32, ptr %3 543 ret i32 %4 544} 545 546define zeroext i8 @load_breg_and_offreg_1(i64 %a, i64 %b) { 547; SDAG-LABEL: load_breg_and_offreg_1: 548; SDAG: ; %bb.0: 549; SDAG-NEXT: ldrb w0, [x1, w0, uxtw] 550; SDAG-NEXT: ret 551; 552; FAST-LABEL: load_breg_and_offreg_1: 553; FAST: ; %bb.0: 554; FAST-NEXT: ldrb w8, [x1, w0, uxtw] 555; FAST-NEXT: uxtb w0, w8 556; FAST-NEXT: ret 557 %1 = and i64 %a, 4294967295 558 %2 = add i64 %1, %b 559 %3 = inttoptr i64 %2 to ptr 560 %4 = load i8, ptr %3 561 ret i8 %4 562} 563 564define zeroext i16 @load_breg_and_offreg_2(i64 %a, i64 %b) { 565; SDAG-LABEL: load_breg_and_offreg_2: 566; SDAG: ; %bb.0: 567; SDAG-NEXT: ldrh w0, [x1, w0, uxtw #1] 568; SDAG-NEXT: ret 569; 570; FAST-LABEL: load_breg_and_offreg_2: 571; FAST: ; %bb.0: 572; FAST-NEXT: ldrh w8, [x1, w0, uxtw #1] 573; FAST-NEXT: uxth w0, w8 574; FAST-NEXT: ret 575 %1 = and i64 %a, 4294967295 576 %2 = shl i64 %1, 1 577 %3 = add i64 %2, %b 578 %4 = inttoptr i64 %3 to ptr 579 %5 = load i16, ptr %4 580 ret i16 %5 581} 582 583define i32 @load_breg_and_offreg_3(i64 %a, i64 %b) { 584; CHECK-LABEL: load_breg_and_offreg_3: 585; CHECK: ; %bb.0: 586; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2] 587; CHECK-NEXT: ret 588 %1 = and i64 %a, 4294967295 589 %2 = shl i64 %1, 2 590 %3 = add i64 %2, %b 591 %4 = inttoptr i64 %3 to ptr 592 %5 = load i32, ptr %4 593 ret i32 %5 594} 595 596define i64 @load_breg_and_offreg_4(i64 %a, i64 %b) { 597; CHECK-LABEL: load_breg_and_offreg_4: 598; CHECK: ; %bb.0: 599; CHECK-NEXT: ldr x0, [x1, w0, uxtw #3] 600; CHECK-NEXT: ret 601 %1 = and i64 %a, 4294967295 602 %2 = shl i64 %1, 3 603 %3 = add i64 %2, %b 604 %4 = inttoptr i64 %3 to ptr 605 %5 = load i64, ptr %4 606 ret i64 %5 607} 608 609; Not all 'and' instructions have immediates. 610define i64 @load_breg_and_offreg_5(i64 %a, i64 %b, i64 %c) { 611; CHECK-LABEL: load_breg_and_offreg_5: 612; CHECK: ; %bb.0: 613; CHECK-NEXT: and x8, x0, x2 614; CHECK-NEXT: ldr x0, [x8, x1] 615; CHECK-NEXT: ret 616 %1 = and i64 %a, %c 617 %2 = add i64 %1, %b 618 %3 = inttoptr i64 %2 to ptr 619 %4 = load i64, ptr %3 620 ret i64 %4 621} 622 623define i64 @load_breg_and_offreg_6(i64 %a, i64 %b, i64 %c) { 624; CHECK-LABEL: load_breg_and_offreg_6: 625; CHECK: ; %bb.0: 626; CHECK-NEXT: and x8, x0, x2 627; CHECK-NEXT: ldr x0, [x1, x8, lsl #3] 628; CHECK-NEXT: ret 629 %1 = and i64 %a, %c 630 %2 = shl i64 %1, 3 631 %3 = add i64 %2, %b 632 %4 = inttoptr i64 %3 to ptr 633 %5 = load i64, ptr %4 634 ret i64 %5 635} 636 637; Load Base Register + Scaled Register Offset + Sign/Zero extension 638define i32 @load_breg_zext_shift_offreg_1(i32 %a, i64 %b) { 639; CHECK-LABEL: load_breg_zext_shift_offreg_1: 640; CHECK: ; %bb.0: 641; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2] 642; CHECK-NEXT: ret 643 %1 = zext i32 %a to i64 644 %2 = shl i64 %1, 2 645 %3 = add i64 %2, %b 646 %4 = inttoptr i64 %3 to ptr 647 %5 = load i32, ptr %4 648 ret i32 %5 649} 650 651define i32 @load_breg_zext_shift_offreg_2(i32 %a, i64 %b) { 652; CHECK-LABEL: load_breg_zext_shift_offreg_2: 653; CHECK: ; %bb.0: 654; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2] 655; CHECK-NEXT: ret 656 %1 = zext i32 %a to i64 657 %2 = shl i64 %1, 2 658 %3 = add i64 %b, %2 659 %4 = inttoptr i64 %3 to ptr 660 %5 = load i32, ptr %4 661 ret i32 %5 662} 663 664define i32 @load_breg_zext_mul_offreg_1(i32 %a, i64 %b) { 665; CHECK-LABEL: load_breg_zext_mul_offreg_1: 666; CHECK: ; %bb.0: 667; CHECK-NEXT: ldr w0, [x1, w0, uxtw #2] 668; CHECK-NEXT: ret 669 %1 = zext i32 %a to i64 670 %2 = mul i64 %1, 4 671 %3 = add i64 %2, %b 672 %4 = inttoptr i64 %3 to ptr 673 %5 = load i32, ptr %4 674 ret i32 %5 675} 676 677define i32 @load_breg_sext_shift_offreg_1(i32 %a, i64 %b) { 678; CHECK-LABEL: load_breg_sext_shift_offreg_1: 679; CHECK: ; %bb.0: 680; CHECK-NEXT: ldr w0, [x1, w0, sxtw #2] 681; CHECK-NEXT: ret 682 %1 = sext i32 %a to i64 683 %2 = shl i64 %1, 2 684 %3 = add i64 %2, %b 685 %4 = inttoptr i64 %3 to ptr 686 %5 = load i32, ptr %4 687 ret i32 %5 688} 689 690define i32 @load_breg_sext_shift_offreg_2(i32 %a, i64 %b) { 691; CHECK-LABEL: load_breg_sext_shift_offreg_2: 692; CHECK: ; %bb.0: 693; CHECK-NEXT: ldr w0, [x1, w0, sxtw #2] 694; CHECK-NEXT: ret 695 %1 = sext i32 %a to i64 696 %2 = shl i64 %1, 2 697 %3 = add i64 %b, %2 698 %4 = inttoptr i64 %3 to ptr 699 %5 = load i32, ptr %4 700 ret i32 %5 701} 702 703; Make sure that we don't drop the first 'add' instruction. 704define i32 @load_breg_sext_shift_offreg_3(i32 %a, i64 %b) { 705; CHECK-LABEL: load_breg_sext_shift_offreg_3: 706; CHECK: ; %bb.0: 707; CHECK-NEXT: add w8, w0, #4 708; CHECK-NEXT: ldr w0, [x1, w8, sxtw #2] 709; CHECK-NEXT: ret 710 %1 = add i32 %a, 4 711 %2 = sext i32 %1 to i64 712 %3 = shl i64 %2, 2 713 %4 = add i64 %b, %3 714 %5 = inttoptr i64 %4 to ptr 715 %6 = load i32, ptr %5 716 ret i32 %6 717} 718 719 720define i32 @load_breg_sext_mul_offreg_1(i32 %a, i64 %b) { 721; CHECK-LABEL: load_breg_sext_mul_offreg_1: 722; CHECK: ; %bb.0: 723; CHECK-NEXT: ldr w0, [x1, w0, sxtw #2] 724; CHECK-NEXT: ret 725 %1 = sext i32 %a to i64 726 %2 = mul i64 %1, 4 727 %3 = add i64 %2, %b 728 %4 = inttoptr i64 %3 to ptr 729 %5 = load i32, ptr %4 730 ret i32 %5 731} 732 733; Load Scaled Register Offset + Immediate Offset + Sign/Zero extension 734define i64 @load_sext_shift_offreg_imm1(i32 %a) { 735; CHECK-LABEL: load_sext_shift_offreg_imm1: 736; CHECK: ; %bb.0: 737; CHECK-NEXT: ; kill: def $w0 killed $w0 def $x0 738; CHECK-NEXT: sbfiz x8, x0, #3, #32 739; CHECK-NEXT: ldr x0, [x8, #8] 740; CHECK-NEXT: ret 741 %1 = sext i32 %a to i64 742 %2 = shl i64 %1, 3 743 %3 = add i64 %2, 8 744 %4 = inttoptr i64 %3 to ptr 745 %5 = load i64, ptr %4 746 ret i64 %5 747} 748 749; Load Base Register + Scaled Register Offset + Immediate Offset + Sign/Zero extension 750define i64 @load_breg_sext_shift_offreg_imm1(i32 %a, i64 %b) { 751; CHECK-LABEL: load_breg_sext_shift_offreg_imm1: 752; CHECK: ; %bb.0: 753; CHECK-NEXT: add x8, x1, w0, sxtw #3 754; CHECK-NEXT: ldr x0, [x8, #8] 755; CHECK-NEXT: ret 756 %1 = sext i32 %a to i64 757 %2 = shl i64 %1, 3 758 %3 = add i64 %b, %2 759 %4 = add i64 %3, 8 760 %5 = inttoptr i64 %4 to ptr 761 %6 = load i64, ptr %5 762 ret i64 %6 763} 764 765; Test that the kill flag is not set - the machine instruction verifier does that for us. 766define i64 @kill_reg(i64 %a) { 767; SDAG-LABEL: kill_reg: 768; SDAG: ; %bb.0: 769; SDAG-NEXT: ldr x8, [x0, #88]! 770; SDAG-NEXT: add x0, x0, x8 771; SDAG-NEXT: ret 772; 773; FAST-LABEL: kill_reg: 774; FAST: ; %bb.0: 775; FAST-NEXT: sub x8, x0, #8 776; FAST-NEXT: ldr x9, [x0, #88] 777; FAST-NEXT: add x8, x8, #96 778; FAST-NEXT: add x0, x8, x9 779; FAST-NEXT: ret 780 %1 = sub i64 %a, 8 781 %2 = add i64 %1, 96 782 %3 = inttoptr i64 %2 to ptr 783 %4 = load i64, ptr %3 784 %5 = add i64 %2, %4 785 ret i64 %5 786} 787 788define void @store_fi(i64 %i) { 789; CHECK-LABEL: store_fi: 790; CHECK: ; %bb.0: 791; CHECK-NEXT: sub sp, sp, #32 792; CHECK-NEXT: .cfi_def_cfa_offset 32 793; CHECK-NEXT: mov x8, sp 794; CHECK-NEXT: mov w9, #47 ; =0x2f 795; CHECK-NEXT: str w9, [x8, x0, lsl #2] 796; CHECK-NEXT: add sp, sp, #32 797; CHECK-NEXT: ret 798 %1 = alloca [8 x i32] 799 %2 = ptrtoint ptr %1 to i64 800 %3 = mul i64 %i, 4 801 %4 = add i64 %2, %3 802 %5 = inttoptr i64 %4 to ptr 803 store i32 47, ptr %5, align 4 804 ret void 805} 806 807define i32 @load_fi(i64 %i) { 808; CHECK-LABEL: load_fi: 809; CHECK: ; %bb.0: 810; CHECK-NEXT: sub sp, sp, #32 811; CHECK-NEXT: .cfi_def_cfa_offset 32 812; CHECK-NEXT: mov x8, sp 813; CHECK-NEXT: ldr w0, [x8, x0, lsl #2] 814; CHECK-NEXT: add sp, sp, #32 815; CHECK-NEXT: ret 816 %1 = alloca [8 x i32] 817 %2 = ptrtoint ptr %1 to i64 818 %3 = mul i64 %i, 4 819 %4 = add i64 %2, %3 820 %5 = inttoptr i64 %4 to ptr 821 %6 = load i32, ptr %5, align 4 822 ret i32 %6 823} 824 825