542 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc -aarch64-enable-subreg-liveness-tracking -mtriple=arm64-eabi < %s | FileCheck %s3; rdar://102322524 5@object = external hidden global i64, section "__DATA, __objc_ivar", align 86 7; base + offset (imm9)8define void @t1(ptr %object) {9; CHECK-LABEL: t1:10; CHECK: // %bb.0:11; CHECK-NEXT: ldr xzr, [x0, #8]12; CHECK-NEXT: ret13 %incdec.ptr = getelementptr inbounds i64, ptr %object, i64 114 %tmp = load volatile i64, ptr %incdec.ptr, align 815 ret void16}17 18; base + offset (> imm9)19define void @t2(ptr %object) {20; CHECK-LABEL: t2:21; CHECK: // %bb.0:22; CHECK-NEXT: sub x8, x0, #26423; CHECK-NEXT: ldr xzr, [x8]24; CHECK-NEXT: ret25 %incdec.ptr = getelementptr inbounds i64, ptr %object, i64 -3326 %tmp = load volatile i64, ptr %incdec.ptr, align 827 ret void28}29 30; base + unsigned offset (> imm9 and <= imm12 * size of type in bytes)31define void @t3(ptr %object) {32; CHECK-LABEL: t3:33; CHECK: // %bb.0:34; CHECK-NEXT: ldr xzr, [x0, #32760]35; CHECK-NEXT: ret36 %incdec.ptr = getelementptr inbounds i64, ptr %object, i64 409537 %tmp = load volatile i64, ptr %incdec.ptr, align 838 ret void39}40 41; base + unsigned offset (> imm12 * size of type in bytes)42define void @t4(ptr %object) {43; CHECK-LABEL: t4:44; CHECK: // %bb.0:45; CHECK-NEXT: mov w8, #32768 // =0x800046; CHECK-NEXT: ldr xzr, [x0, x8]47; CHECK-NEXT: ret48 %incdec.ptr = getelementptr inbounds i64, ptr %object, i64 409649 %tmp = load volatile i64, ptr %incdec.ptr, align 850 ret void51}52 53; base + reg54define void @t5(i64 %a) {55; CHECK-LABEL: t5:56; CHECK: // %bb.0:57; CHECK-NEXT: adrp x8, object58; CHECK-NEXT: add x8, x8, :lo12:object59; CHECK-NEXT: ldr xzr, [x8, x0, lsl #3]60; CHECK-NEXT: ret61 %incdec.ptr = getelementptr inbounds i64, ptr @object, i64 %a62 %tmp = load volatile i64, ptr %incdec.ptr, align 863 ret void64}65 66; base + reg + imm67define void @t6(i64 %a, ptr %object) {68; CHECK-LABEL: t6:69; CHECK: // %bb.0:70; CHECK-NEXT: add x8, x1, x0, lsl #371; CHECK-NEXT: mov w9, #32768 // =0x800072; CHECK-NEXT: ldr xzr, [x8, x9]73; CHECK-NEXT: ret74 %tmp1 = getelementptr inbounds i64, ptr %object, i64 %a75 %incdec.ptr = getelementptr inbounds i64, ptr %tmp1, i64 409676 %tmp = load volatile i64, ptr %incdec.ptr, align 877 ret void78}79 80; Test base + wide immediate81define void @t7(i64 %a) {82; CHECK-LABEL: t7:83; CHECK: // %bb.0:84; CHECK-NEXT: mov w8, #65535 // =0xffff85; CHECK-NEXT: ldr xzr, [x0, x8]86; CHECK-NEXT: ret87 %1 = add i64 %a, 65535 ;0xffff88 %2 = inttoptr i64 %1 to ptr89 %3 = load volatile i64, ptr %2, align 890 ret void91}92 93define void @t8(i64 %a) {94; CHECK-LABEL: t8:95; CHECK: // %bb.0:96; CHECK-NEXT: mov x8, #-4662 // =0xffffffffffffedca97; CHECK-NEXT: ldr xzr, [x0, x8]98; CHECK-NEXT: ret99 %1 = sub i64 %a, 4662 ;-4662 is 0xffffffffffffedca100 %2 = inttoptr i64 %1 to ptr101 %3 = load volatile i64, ptr %2, align 8102 ret void103}104 105define void @t9(i64 %a) {106; CHECK-LABEL: t9:107; CHECK: // %bb.0:108; CHECK-NEXT: mov x8, #-305463297 // =0xffffffffedcaffff109; CHECK-NEXT: ldr xzr, [x0, x8]110; CHECK-NEXT: ret111 %1 = add i64 -305463297, %a ;-305463297 is 0xffffffffedcaffff112 %2 = inttoptr i64 %1 to ptr113 %3 = load volatile i64, ptr %2, align 8114 ret void115}116 117define void @t10(i64 %a) {118; CHECK-LABEL: t10:119; CHECK: // %bb.0:120; CHECK-NEXT: mov x8, #81909218222800896 // =0x123000000000000121; CHECK-NEXT: ldr xzr, [x0, x8]122; CHECK-NEXT: ret123 %1 = add i64 %a, 81909218222800896 ;0x123000000000000124 %2 = inttoptr i64 %1 to ptr125 %3 = load volatile i64, ptr %2, align 8126 ret void127}128 129define void @t11(i64 %a) {130; CHECK-LABEL: t11:131; CHECK: // %bb.0:132; CHECK-NEXT: mov w8, #17767 // =0x4567133; CHECK-NEXT: movk w8, #291, lsl #16134; CHECK-NEXT: ldr xzr, [x0, x8]135; CHECK-NEXT: ret136 %1 = add i64 %a, 19088743 ;0x1234567137 %2 = inttoptr i64 %1 to ptr138 %3 = load volatile i64, ptr %2, align 8139 ret void140}141 142; Test some boundaries that should not use movz/movn/orr143define void @t12(i64 %a) {144; CHECK-LABEL: t12:145; CHECK: // %bb.0:146; CHECK-NEXT: add x8, x0, #4095147; CHECK-NEXT: ldr xzr, [x8]148; CHECK-NEXT: ret149 %1 = add i64 %a, 4095 ;0xfff150 %2 = inttoptr i64 %1 to ptr151 %3 = load volatile i64, ptr %2, align 8152 ret void153}154 155define void @t13(i64 %a) {156; CHECK-LABEL: t13:157; CHECK: // %bb.0:158; CHECK-NEXT: sub x8, x0, #4095159; CHECK-NEXT: ldr xzr, [x8]160; CHECK-NEXT: ret161 %1 = add i64 %a, -4095 ;-0xfff162 %2 = inttoptr i64 %1 to ptr163 %3 = load volatile i64, ptr %2, align 8164 ret void165}166 167define void @t14(i64 %a) {168; CHECK-LABEL: t14:169; CHECK: // %bb.0:170; CHECK-NEXT: add x8, x0, #291, lsl #12 // =1191936171; CHECK-NEXT: ldr xzr, [x8]172; CHECK-NEXT: ret173 %1 = add i64 %a, 1191936 ;0x123000174 %2 = inttoptr i64 %1 to ptr175 %3 = load volatile i64, ptr %2, align 8176 ret void177}178 179define void @t15(i64 %a) {180; CHECK-LABEL: t15:181; CHECK: // %bb.0:182; CHECK-NEXT: sub x8, x0, #291, lsl #12 // =1191936183; CHECK-NEXT: ldr xzr, [x8]184; CHECK-NEXT: ret185 %1 = add i64 %a, -1191936 ;0xFFFFFFFFFFEDD000186 %2 = inttoptr i64 %1 to ptr187 %3 = load volatile i64, ptr %2, align 8188 ret void189}190 191define void @t16(i64 %a) {192; CHECK-LABEL: t16:193; CHECK: // %bb.0:194; CHECK-NEXT: ldr xzr, [x0, #28672]195; CHECK-NEXT: ret196 %1 = add i64 %a, 28672 ;0x7000197 %2 = inttoptr i64 %1 to ptr198 %3 = load volatile i64, ptr %2, align 8199 ret void200}201 202define void @t17(i64 %a) {203; CHECK-LABEL: t17:204; CHECK: // %bb.0:205; CHECK-NEXT: ldur xzr, [x0, #-256]206; CHECK-NEXT: ret207 %1 = add i64 %a, -256 ;-0x100208 %2 = inttoptr i64 %1 to ptr209 %3 = load volatile i64, ptr %2, align 8210 ret void211}212 213; LDRBBroX214define i8 @LdOffset_i8(ptr %a) {215; CHECK-LABEL: LdOffset_i8:216; CHECK: // %bb.0:217; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288218; CHECK-NEXT: ldrb w0, [x8, #3704]219; CHECK-NEXT: ret220 %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992221 %val = load i8, ptr %arrayidx, align 1222 ret i8 %val223}224 225; LDRBBroX226define i32 @LdOffset_i8_zext32(ptr %a) {227; CHECK-LABEL: LdOffset_i8_zext32:228; CHECK: // %bb.0:229; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288230; CHECK-NEXT: ldrb w0, [x8, #3704]231; CHECK-NEXT: ret232 %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992233 %val = load i8, ptr %arrayidx, align 1234 %conv = zext i8 %val to i32235 ret i32 %conv236}237 238; LDRSBWroX239define i32 @LdOffset_i8_sext32(ptr %a) {240; CHECK-LABEL: LdOffset_i8_sext32:241; CHECK: // %bb.0:242; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288243; CHECK-NEXT: ldrsb w0, [x8, #3704]244; CHECK-NEXT: ret245 %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992246 %val = load i8, ptr %arrayidx, align 1247 %conv = sext i8 %val to i32248 ret i32 %conv249}250 251; LDRBBroX252define i64 @LdOffset_i8_zext64(ptr %a) {253; CHECK-LABEL: LdOffset_i8_zext64:254; CHECK: // %bb.0:255; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288256; CHECK-NEXT: ldrb w0, [x8, #3704]257; CHECK-NEXT: ret258 %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992259 %val = load i8, ptr %arrayidx, align 1260 %conv = zext i8 %val to i64261 ret i64 %conv262}263 264; LDRSBXroX265define i64 @LdOffset_i8_sext64(ptr %a) {266; CHECK-LABEL: LdOffset_i8_sext64:267; CHECK: // %bb.0:268; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288269; CHECK-NEXT: ldrsb x0, [x8, #3704]270; CHECK-NEXT: ret271 %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992272 %val = load i8, ptr %arrayidx, align 1273 %conv = sext i8 %val to i64274 ret i64 %conv275}276 277; LDRHHroX278define i16 @LdOffset_i16(ptr %a) {279; CHECK-LABEL: LdOffset_i16:280; CHECK: // %bb.0:281; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576282; CHECK-NEXT: ldrh w0, [x8, #7408]283; CHECK-NEXT: ret284 %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992285 %val = load i16, ptr %arrayidx, align 2286 ret i16 %val287}288 289; LDRHHroX290define i32 @LdOffset_i16_zext32(ptr %a) {291; CHECK-LABEL: LdOffset_i16_zext32:292; CHECK: // %bb.0:293; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576294; CHECK-NEXT: ldrh w0, [x8, #7408]295; CHECK-NEXT: ret296 %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992297 %val = load i16, ptr %arrayidx, align 2298 %conv = zext i16 %val to i32299 ret i32 %conv300}301 302; LDRSHWroX303define i32 @LdOffset_i16_sext32(ptr %a) {304; CHECK-LABEL: LdOffset_i16_sext32:305; CHECK: // %bb.0:306; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576307; CHECK-NEXT: ldrsh w0, [x8, #7408]308; CHECK-NEXT: ret309 %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992310 %val = load i16, ptr %arrayidx, align 2311 %conv = sext i16 %val to i32312 ret i32 %conv313}314 315; LDRHHroX316define i64 @LdOffset_i16_zext64(ptr %a) {317; CHECK-LABEL: LdOffset_i16_zext64:318; CHECK: // %bb.0:319; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576320; CHECK-NEXT: ldrh w0, [x8, #7408]321; CHECK-NEXT: ret322 %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992323 %val = load i16, ptr %arrayidx, align 2324 %conv = zext i16 %val to i64325 ret i64 %conv326}327 328; LDRSHXroX329define i64 @LdOffset_i16_sext64(ptr %a) {330; CHECK-LABEL: LdOffset_i16_sext64:331; CHECK: // %bb.0:332; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576333; CHECK-NEXT: ldrsh x0, [x8, #7408]334; CHECK-NEXT: ret335 %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992336 %val = load i16, ptr %arrayidx, align 2337 %conv = sext i16 %val to i64338 ret i64 %conv339}340 341; LDRWroX342define i32 @LdOffset_i32(ptr %a) {343; CHECK-LABEL: LdOffset_i32:344; CHECK: // %bb.0:345; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152346; CHECK-NEXT: ldr w0, [x8, #14816]347; CHECK-NEXT: ret348 %arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992349 %val = load i32, ptr %arrayidx, align 4350 ret i32 %val351}352 353; LDRWroX354define i64 @LdOffset_i32_zext64(ptr %a) {355; CHECK-LABEL: LdOffset_i32_zext64:356; CHECK: // %bb.0:357; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152358; CHECK-NEXT: ldr w0, [x8, #14816]359; CHECK-NEXT: ret360 %arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992361 %val = load i32, ptr %arrayidx, align 2362 %conv = zext i32 %val to i64363 ret i64 %conv364}365 366; LDRSWroX367define i64 @LdOffset_i32_sext64(ptr %a) {368; CHECK-LABEL: LdOffset_i32_sext64:369; CHECK: // %bb.0:370; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152371; CHECK-NEXT: ldrsw x0, [x8, #14816]372; CHECK-NEXT: ret373 %arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992374 %val = load i32, ptr %arrayidx, align 2375 %conv = sext i32 %val to i64376 ret i64 %conv377}378 379; LDRXroX380define i64 @LdOffset_i64(ptr %a) {381; CHECK-LABEL: LdOffset_i64:382; CHECK: // %bb.0:383; CHECK-NEXT: add x8, x0, #2024, lsl #12 // =8290304384; CHECK-NEXT: ldr x0, [x8, #29632]385; CHECK-NEXT: ret386 %arrayidx = getelementptr inbounds i64, ptr %a, i64 1039992387 %val = load i64, ptr %arrayidx, align 4388 ret i64 %val389}390 391; LDRDroX392define <2 x i32> @LdOffset_v2i32(ptr %a) {393; CHECK-LABEL: LdOffset_v2i32:394; CHECK: // %bb.0:395; CHECK-NEXT: add x8, x0, #2024, lsl #12 // =8290304396; CHECK-NEXT: ldr d0, [x8, #29632]397; CHECK-NEXT: ret398 %arrayidx = getelementptr inbounds <2 x i32>, ptr %a, i64 1039992399 %val = load <2 x i32>, ptr %arrayidx, align 4400 ret <2 x i32> %val401}402 403; LDRQroX404define <2 x i64> @LdOffset_v2i64(ptr %a) {405; CHECK-LABEL: LdOffset_v2i64:406; CHECK: // %bb.0:407; CHECK-NEXT: add x8, x0, #4048, lsl #12 // =16580608408; CHECK-NEXT: ldr q0, [x8, #59264]409; CHECK-NEXT: ret410 %arrayidx = getelementptr inbounds <2 x i64>, ptr %a, i64 1039992411 %val = load <2 x i64>, ptr %arrayidx, align 4412 ret <2 x i64> %val413}414 415; LDRSBWroX416define double @LdOffset_i8_f64(ptr %a) {417; CHECK-LABEL: LdOffset_i8_f64:418; CHECK: // %bb.0:419; CHECK-NEXT: add x8, x0, #253, lsl #12 // =1036288420; CHECK-NEXT: ldrsb w8, [x8, #3704]421; CHECK-NEXT: scvtf d0, w8422; CHECK-NEXT: ret423 %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039992424 %val = load i8, ptr %arrayidx, align 1425 %conv = sitofp i8 %val to double426 ret double %conv427}428 429; LDRSHWroX430define double @LdOffset_i16_f64(ptr %a) {431; CHECK-LABEL: LdOffset_i16_f64:432; CHECK: // %bb.0:433; CHECK-NEXT: add x8, x0, #506, lsl #12 // =2072576434; CHECK-NEXT: ldrsh w8, [x8, #7408]435; CHECK-NEXT: scvtf d0, w8436; CHECK-NEXT: ret437 %arrayidx = getelementptr inbounds i16, ptr %a, i64 1039992438 %val = load i16, ptr %arrayidx, align 2439 %conv = sitofp i16 %val to double440 ret double %conv441}442 443; LDRSroX444define double @LdOffset_i32_f64(ptr %a) {445; CHECK-LABEL: LdOffset_i32_f64:446; CHECK: // %bb.0:447; CHECK-NEXT: add x8, x0, #1012, lsl #12 // =4145152448; CHECK-NEXT: ldr s0, [x8, #14816]449; CHECK-NEXT: ucvtf d0, d0450; CHECK-NEXT: ret451 %arrayidx = getelementptr inbounds i32, ptr %a, i64 1039992452 %val = load i32, ptr %arrayidx, align 4453 %conv = uitofp i32 %val to double454 ret double %conv455}456 457; LDRDroX458define double @LdOffset_i64_f64(ptr %a) {459; CHECK-LABEL: LdOffset_i64_f64:460; CHECK: // %bb.0:461; CHECK-NEXT: add x8, x0, #2024, lsl #12 // =8290304462; CHECK-NEXT: ldr d0, [x8, #29632]463; CHECK-NEXT: scvtf d0, d0464; CHECK-NEXT: ret465 %arrayidx = getelementptr inbounds i64, ptr %a, i64 1039992466 %val = load i64, ptr %arrayidx, align 8467 %conv = sitofp i64 %val to double468 ret double %conv469}470 471define i64 @LdOffset_i64_multi_offset(ptr %a) {472; CHECK-LABEL: LdOffset_i64_multi_offset:473; CHECK: // %bb.0:474; CHECK-NEXT: add x8, x0, #2031, lsl #12 // =8318976475; CHECK-NEXT: ldr x9, [x8, #960]476; CHECK-NEXT: ldr x8, [x8, #3016]477; CHECK-NEXT: add x0, x8, x9478; CHECK-NEXT: ret479 %arrayidx = getelementptr inbounds i64, ptr %a, i64 1039992480 %val0 = load i64, ptr %arrayidx, align 8481 %arrayidx1 = getelementptr inbounds i64, ptr %a, i64 1040249482 %val1 = load i64, ptr %arrayidx1, align 8483 %add = add nsw i64 %val1, %val0484 ret i64 %add485}486 487define i64 @LdOffset_i64_multi_offset_with_commmon_base(ptr %a) {488; CHECK-LABEL: LdOffset_i64_multi_offset_with_commmon_base:489; CHECK: // %bb.0:490; CHECK-NEXT: add x8, x0, #507, lsl #12 // =2076672491; CHECK-NEXT: ldr x9, [x8, #26464]492; CHECK-NEXT: ldr x8, [x8, #26496]493; CHECK-NEXT: add x0, x8, x9494; CHECK-NEXT: ret495 %b = getelementptr inbounds i16, ptr %a, i64 1038336496 %arrayidx = getelementptr inbounds i64, ptr %b, i64 3308497 %val0 = load i64, ptr %arrayidx, align 8498 %arrayidx1 = getelementptr inbounds i64, ptr %b, i64 3312499 %val1 = load i64, ptr %arrayidx1, align 8500 %add = add nsw i64 %val1, %val0501 ret i64 %add502}503 504; Negative test: the offset is odd505define i32 @LdOffset_i16_odd_offset(ptr nocapture noundef readonly %a) {506; CHECK-LABEL: LdOffset_i16_odd_offset:507; CHECK: // %bb.0:508; CHECK-NEXT: mov w8, #56953 // =0xde79509; CHECK-NEXT: movk w8, #15, lsl #16510; CHECK-NEXT: ldrsh w0, [x0, x8]511; CHECK-NEXT: ret512 %arrayidx = getelementptr inbounds i8, ptr %a, i64 1039993513 %val = load i16, ptr %arrayidx, align 2514 %conv = sext i16 %val to i32515 ret i32 %conv516}517 518; Already encoded with a single mov MOVNWi519define i8 @LdOffset_i8_movnwi(ptr %a) {520; CHECK-LABEL: LdOffset_i8_movnwi:521; CHECK: // %bb.0:522; CHECK-NEXT: mov w8, #16777215 // =0xffffff523; CHECK-NEXT: ldrb w0, [x0, x8]524; CHECK-NEXT: ret525 %arrayidx = getelementptr inbounds i8, ptr %a, i64 16777215526 %val = load i8, ptr %arrayidx, align 1527 ret i8 %val528}529 530; Negative test: the offset is too large to encoded with a add531define i8 @LdOffset_i8_too_large(ptr %a) {532; CHECK-LABEL: LdOffset_i8_too_large:533; CHECK: // %bb.0:534; CHECK-NEXT: mov w8, #1 // =0x1535; CHECK-NEXT: movk w8, #256, lsl #16536; CHECK-NEXT: ldrb w0, [x0, x8]537; CHECK-NEXT: ret538 %arrayidx = getelementptr inbounds i8, ptr %a, i64 16777217539 %val = load i8, ptr %arrayidx, align 1540 ret i8 %val541}542