443 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py2; RUN: llc < %s -mtriple=arm64-eabi -verify-machineinstrs | FileCheck %s3 4define i32 @ldp_int(ptr %p) nounwind {5; CHECK-LABEL: ldp_int:6; CHECK: // %bb.0:7; CHECK-NEXT: ldp w8, w9, [x0]8; CHECK-NEXT: add w0, w9, w89; CHECK-NEXT: ret10 %tmp = load i32, ptr %p, align 411 %add.ptr = getelementptr inbounds i32, ptr %p, i64 112 %tmp1 = load i32, ptr %add.ptr, align 413 %add = add nsw i32 %tmp1, %tmp14 ret i32 %add15}16 17define i64 @ldp_sext_int(ptr %p) nounwind {18; CHECK-LABEL: ldp_sext_int:19; CHECK: // %bb.0:20; CHECK-NEXT: ldpsw x8, x9, [x0]21; CHECK-NEXT: add x0, x9, x822; CHECK-NEXT: ret23 %tmp = load i32, ptr %p, align 424 %add.ptr = getelementptr inbounds i32, ptr %p, i64 125 %tmp1 = load i32, ptr %add.ptr, align 426 %sexttmp = sext i32 %tmp to i6427 %sexttmp1 = sext i32 %tmp1 to i6428 %add = add nsw i64 %sexttmp1, %sexttmp29 ret i64 %add30}31 32define i64 @ldp_half_sext_res0_int(ptr %p) nounwind {33; CHECK-LABEL: ldp_half_sext_res0_int:34; CHECK: // %bb.0:35; CHECK-NEXT: ldp w8, w9, [x0]36; CHECK-NEXT: // kill: def $w8 killed $w8 def $x837; CHECK-NEXT: sxtw x8, w838; CHECK-NEXT: add x0, x9, x839; CHECK-NEXT: ret40 %tmp = load i32, ptr %p, align 441 %add.ptr = getelementptr inbounds i32, ptr %p, i64 142 %tmp1 = load i32, ptr %add.ptr, align 443 %sexttmp = sext i32 %tmp to i6444 %sexttmp1 = zext i32 %tmp1 to i6445 %add = add nsw i64 %sexttmp1, %sexttmp46 ret i64 %add47}48 49define i64 @ldp_half_sext_res1_int(ptr %p) nounwind {50; CHECK-LABEL: ldp_half_sext_res1_int:51; CHECK: // %bb.0:52; CHECK-NEXT: ldp w8, w9, [x0]53; CHECK-NEXT: // kill: def $w9 killed $w9 def $x954; CHECK-NEXT: sxtw x9, w955; CHECK-NEXT: add x0, x9, x856; CHECK-NEXT: ret57 %tmp = load i32, ptr %p, align 458 %add.ptr = getelementptr inbounds i32, ptr %p, i64 159 %tmp1 = load i32, ptr %add.ptr, align 460 %sexttmp = zext i32 %tmp to i6461 %sexttmp1 = sext i32 %tmp1 to i6462 %add = add nsw i64 %sexttmp1, %sexttmp63 ret i64 %add64}65 66 67define i64 @ldp_long(ptr %p) nounwind {68; CHECK-LABEL: ldp_long:69; CHECK: // %bb.0:70; CHECK-NEXT: ldp x8, x9, [x0]71; CHECK-NEXT: add x0, x9, x872; CHECK-NEXT: ret73 %tmp = load i64, ptr %p, align 874 %add.ptr = getelementptr inbounds i64, ptr %p, i64 175 %tmp1 = load i64, ptr %add.ptr, align 876 %add = add nsw i64 %tmp1, %tmp77 ret i64 %add78}79 80define float @ldp_float(ptr %p) nounwind {81; CHECK-LABEL: ldp_float:82; CHECK: // %bb.0:83; CHECK-NEXT: ldp s0, s1, [x0]84; CHECK-NEXT: fadd s0, s0, s185; CHECK-NEXT: ret86 %tmp = load float, ptr %p, align 487 %add.ptr = getelementptr inbounds float, ptr %p, i64 188 %tmp1 = load float, ptr %add.ptr, align 489 %add = fadd float %tmp, %tmp190 ret float %add91}92 93define double @ldp_double(ptr %p) nounwind {94; CHECK-LABEL: ldp_double:95; CHECK: // %bb.0:96; CHECK-NEXT: ldp d0, d1, [x0]97; CHECK-NEXT: fadd d0, d0, d198; CHECK-NEXT: ret99 %tmp = load double, ptr %p, align 8100 %add.ptr = getelementptr inbounds double, ptr %p, i64 1101 %tmp1 = load double, ptr %add.ptr, align 8102 %add = fadd double %tmp, %tmp1103 ret double %add104}105 106define <2 x double> @ldp_doublex2(ptr %p) nounwind {107; CHECK-LABEL: ldp_doublex2:108; CHECK: // %bb.0:109; CHECK-NEXT: ldp q0, q1, [x0]110; CHECK-NEXT: fadd v0.2d, v0.2d, v1.2d111; CHECK-NEXT: ret112 %tmp = load <2 x double>, ptr %p, align 16113 %add.ptr = getelementptr inbounds <2 x double>, ptr %p, i64 1114 %tmp1 = load <2 x double>, ptr %add.ptr, align 16115 %add = fadd <2 x double> %tmp, %tmp1116 ret <2 x double> %add117}118 119; Test the load/store optimizer---combine ldurs into a ldp, if appropriate120define i32 @ldur_int(ptr %a) nounwind {121; CHECK-LABEL: ldur_int:122; CHECK: // %bb.0:123; CHECK-NEXT: ldp w9, w8, [x0, #-8]124; CHECK-NEXT: add w0, w8, w9125; CHECK-NEXT: ret126 %p1 = getelementptr inbounds i32, ptr %a, i32 -1127 %tmp1 = load i32, ptr %p1, align 2128 %p2 = getelementptr inbounds i32, ptr %a, i32 -2129 %tmp2 = load i32, ptr %p2, align 2130 %tmp3 = add i32 %tmp1, %tmp2131 ret i32 %tmp3132}133 134define i64 @ldur_sext_int(ptr %a) nounwind {135; CHECK-LABEL: ldur_sext_int:136; CHECK: // %bb.0:137; CHECK-NEXT: ldpsw x9, x8, [x0, #-8]138; CHECK-NEXT: add x0, x8, x9139; CHECK-NEXT: ret140 %p1 = getelementptr inbounds i32, ptr %a, i32 -1141 %tmp1 = load i32, ptr %p1, align 2142 %p2 = getelementptr inbounds i32, ptr %a, i32 -2143 %tmp2 = load i32, ptr %p2, align 2144 %sexttmp1 = sext i32 %tmp1 to i64145 %sexttmp2 = sext i32 %tmp2 to i64146 %tmp3 = add i64 %sexttmp1, %sexttmp2147 ret i64 %tmp3148}149 150define i64 @ldur_half_sext_int_res0(ptr %a) nounwind {151; CHECK-LABEL: ldur_half_sext_int_res0:152; CHECK: // %bb.0:153; CHECK-NEXT: ldp w9, w8, [x0, #-8]154; CHECK-NEXT: // kill: def $w9 killed $w9 def $x9155; CHECK-NEXT: sxtw x9, w9156; CHECK-NEXT: add x0, x8, x9157; CHECK-NEXT: ret158 %p1 = getelementptr inbounds i32, ptr %a, i32 -1159 %tmp1 = load i32, ptr %p1, align 2160 %p2 = getelementptr inbounds i32, ptr %a, i32 -2161 %tmp2 = load i32, ptr %p2, align 2162 %sexttmp1 = zext i32 %tmp1 to i64163 %sexttmp2 = sext i32 %tmp2 to i64164 %tmp3 = add i64 %sexttmp1, %sexttmp2165 ret i64 %tmp3166}167 168define i64 @ldur_half_sext_int_res1(ptr %a) nounwind {169; CHECK-LABEL: ldur_half_sext_int_res1:170; CHECK: // %bb.0:171; CHECK-NEXT: ldp w9, w8, [x0, #-8]172; CHECK-NEXT: // kill: def $w8 killed $w8 def $x8173; CHECK-NEXT: sxtw x8, w8174; CHECK-NEXT: add x0, x8, x9175; CHECK-NEXT: ret176 %p1 = getelementptr inbounds i32, ptr %a, i32 -1177 %tmp1 = load i32, ptr %p1, align 2178 %p2 = getelementptr inbounds i32, ptr %a, i32 -2179 %tmp2 = load i32, ptr %p2, align 2180 %sexttmp1 = sext i32 %tmp1 to i64181 %sexttmp2 = zext i32 %tmp2 to i64182 %tmp3 = add i64 %sexttmp1, %sexttmp2183 ret i64 %tmp3184}185 186 187define i64 @ldur_long(ptr %a) nounwind ssp {188; CHECK-LABEL: ldur_long:189; CHECK: // %bb.0:190; CHECK-NEXT: ldp x9, x8, [x0, #-16]191; CHECK-NEXT: add x0, x8, x9192; CHECK-NEXT: ret193 %p1 = getelementptr inbounds i64, ptr %a, i64 -1194 %tmp1 = load i64, ptr %p1, align 2195 %p2 = getelementptr inbounds i64, ptr %a, i64 -2196 %tmp2 = load i64, ptr %p2, align 2197 %tmp3 = add i64 %tmp1, %tmp2198 ret i64 %tmp3199}200 201define float @ldur_float(ptr %a) {202; CHECK-LABEL: ldur_float:203; CHECK: // %bb.0:204; CHECK-NEXT: ldp s1, s0, [x0, #-8]205; CHECK-NEXT: fadd s0, s0, s1206; CHECK-NEXT: ret207 %p1 = getelementptr inbounds float, ptr %a, i64 -1208 %tmp1 = load float, ptr %p1, align 2209 %p2 = getelementptr inbounds float, ptr %a, i64 -2210 %tmp2 = load float, ptr %p2, align 2211 %tmp3 = fadd float %tmp1, %tmp2212 ret float %tmp3213}214 215define double @ldur_double(ptr %a) {216; CHECK-LABEL: ldur_double:217; CHECK: // %bb.0:218; CHECK-NEXT: ldp d1, d0, [x0, #-16]219; CHECK-NEXT: fadd d0, d0, d1220; CHECK-NEXT: ret221 %p1 = getelementptr inbounds double, ptr %a, i64 -1222 %tmp1 = load double, ptr %p1, align 2223 %p2 = getelementptr inbounds double, ptr %a, i64 -2224 %tmp2 = load double, ptr %p2, align 2225 %tmp3 = fadd double %tmp1, %tmp2226 ret double %tmp3227}228 229define <2 x double> @ldur_doublex2(ptr %a) {230; CHECK-LABEL: ldur_doublex2:231; CHECK: // %bb.0:232; CHECK-NEXT: ldp q1, q0, [x0, #-32]233; CHECK-NEXT: fadd v0.2d, v0.2d, v1.2d234; CHECK-NEXT: ret235 %p1 = getelementptr inbounds <2 x double>, ptr %a, i64 -1236 %tmp1 = load <2 x double>, ptr %p1, align 2237 %p2 = getelementptr inbounds <2 x double>, ptr %a, i64 -2238 %tmp2 = load <2 x double>, ptr %p2, align 2239 %tmp3 = fadd <2 x double> %tmp1, %tmp2240 ret <2 x double> %tmp3241}242 243; Now check some boundary conditions244define i64 @pairUpBarelyIn(ptr %a) nounwind ssp {245; CHECK-LABEL: pairUpBarelyIn:246; CHECK: // %bb.0:247; CHECK-NEXT: ldp x9, x8, [x0, #-256]248; CHECK-NEXT: add x0, x8, x9249; CHECK-NEXT: ret250 %p1 = getelementptr inbounds i64, ptr %a, i64 -31251 %tmp1 = load i64, ptr %p1, align 2252 %p2 = getelementptr inbounds i64, ptr %a, i64 -32253 %tmp2 = load i64, ptr %p2, align 2254 %tmp3 = add i64 %tmp1, %tmp2255 ret i64 %tmp3256}257 258define i64 @pairUpBarelyInSext(ptr %a) nounwind ssp {259; CHECK-LABEL: pairUpBarelyInSext:260; CHECK: // %bb.0:261; CHECK-NEXT: ldpsw x9, x8, [x0, #-256]262; CHECK-NEXT: add x0, x8, x9263; CHECK-NEXT: ret264 %p1 = getelementptr inbounds i32, ptr %a, i64 -63265 %tmp1 = load i32, ptr %p1, align 2266 %p2 = getelementptr inbounds i32, ptr %a, i64 -64267 %tmp2 = load i32, ptr %p2, align 2268 %sexttmp1 = sext i32 %tmp1 to i64269 %sexttmp2 = sext i32 %tmp2 to i64270 %tmp3 = add i64 %sexttmp1, %sexttmp2271 ret i64 %tmp3272}273 274define i64 @pairUpBarelyInHalfSextRes0(ptr %a) nounwind ssp {275; CHECK-LABEL: pairUpBarelyInHalfSextRes0:276; CHECK: // %bb.0:277; CHECK-NEXT: ldp w9, w8, [x0, #-256]278; CHECK-NEXT: // kill: def $w9 killed $w9 def $x9279; CHECK-NEXT: sxtw x9, w9280; CHECK-NEXT: add x0, x8, x9281; CHECK-NEXT: ret282 %p1 = getelementptr inbounds i32, ptr %a, i64 -63283 %tmp1 = load i32, ptr %p1, align 2284 %p2 = getelementptr inbounds i32, ptr %a, i64 -64285 %tmp2 = load i32, ptr %p2, align 2286 %sexttmp1 = zext i32 %tmp1 to i64287 %sexttmp2 = sext i32 %tmp2 to i64288 %tmp3 = add i64 %sexttmp1, %sexttmp2289 ret i64 %tmp3290}291 292define i64 @pairUpBarelyInHalfSextRes1(ptr %a) nounwind ssp {293; CHECK-LABEL: pairUpBarelyInHalfSextRes1:294; CHECK: // %bb.0:295; CHECK-NEXT: ldp w9, w8, [x0, #-256]296; CHECK-NEXT: // kill: def $w8 killed $w8 def $x8297; CHECK-NEXT: sxtw x8, w8298; CHECK-NEXT: add x0, x8, x9299; CHECK-NEXT: ret300 %p1 = getelementptr inbounds i32, ptr %a, i64 -63301 %tmp1 = load i32, ptr %p1, align 2302 %p2 = getelementptr inbounds i32, ptr %a, i64 -64303 %tmp2 = load i32, ptr %p2, align 2304 %sexttmp1 = sext i32 %tmp1 to i64305 %sexttmp2 = zext i32 %tmp2 to i64306 %tmp3 = add i64 %sexttmp1, %sexttmp2307 ret i64 %tmp3308}309 310define i64 @pairUpBarelyOut(ptr %a) nounwind ssp {311; Don't be fragile about which loads or manipulations of the base register312; are used---just check that there isn't an ldp before the add313; CHECK-LABEL: pairUpBarelyOut:314; CHECK: // %bb.0:315; CHECK-NEXT: sub x8, x0, #264316; CHECK-NEXT: ldur x9, [x0, #-256]317; CHECK-NEXT: ldr x8, [x8]318; CHECK-NEXT: add x0, x9, x8319; CHECK-NEXT: ret320 %p1 = getelementptr inbounds i64, ptr %a, i64 -32321 %tmp1 = load i64, ptr %p1, align 2322 %p2 = getelementptr inbounds i64, ptr %a, i64 -33323 %tmp2 = load i64, ptr %p2, align 2324 %tmp3 = add i64 %tmp1, %tmp2325 ret i64 %tmp3326}327 328define i64 @pairUpBarelyOutSext(ptr %a) nounwind ssp {329; Don't be fragile about which loads or manipulations of the base register330; are used---just check that there isn't an ldp before the add331; CHECK-LABEL: pairUpBarelyOutSext:332; CHECK: // %bb.0:333; CHECK-NEXT: sub x8, x0, #260334; CHECK-NEXT: ldursw x9, [x0, #-256]335; CHECK-NEXT: ldrsw x8, [x8]336; CHECK-NEXT: add x0, x9, x8337; CHECK-NEXT: ret338 %p1 = getelementptr inbounds i32, ptr %a, i64 -64339 %tmp1 = load i32, ptr %p1, align 2340 %p2 = getelementptr inbounds i32, ptr %a, i64 -65341 %tmp2 = load i32, ptr %p2, align 2342 %sexttmp1 = sext i32 %tmp1 to i64343 %sexttmp2 = sext i32 %tmp2 to i64344 %tmp3 = add i64 %sexttmp1, %sexttmp2345 ret i64 %tmp3346}347 348define i64 @pairUpNotAligned(ptr %a) nounwind ssp {349; CHECK-LABEL: pairUpNotAligned:350; CHECK: // %bb.0:351; CHECK-NEXT: ldur x8, [x0, #-143]352; CHECK-NEXT: ldur x9, [x0, #-135]353; CHECK-NEXT: add x0, x8, x9354; CHECK-NEXT: ret355 %p1 = getelementptr inbounds i64, ptr %a, i64 -18356 %bp1 = bitcast ptr %p1 to ptr357 %bp1p1 = getelementptr inbounds i8, ptr %bp1, i64 1358 %dp1 = bitcast ptr %bp1p1 to ptr359 %tmp1 = load i64, ptr %dp1, align 1360 361 %p2 = getelementptr inbounds i64, ptr %a, i64 -17362 %bp2 = bitcast ptr %p2 to ptr363 %bp2p1 = getelementptr inbounds i8, ptr %bp2, i64 1364 %dp2 = bitcast ptr %bp2p1 to ptr365 %tmp2 = load i64, ptr %dp2, align 1366 367 %tmp3 = add i64 %tmp1, %tmp2368 ret i64 %tmp3369}370 371define i64 @pairUpNotAlignedSext(ptr %a) nounwind ssp {372; CHECK-LABEL: pairUpNotAlignedSext:373; CHECK: // %bb.0:374; CHECK-NEXT: ldursw x8, [x0, #-71]375; CHECK-NEXT: ldursw x9, [x0, #-67]376; CHECK-NEXT: add x0, x8, x9377; CHECK-NEXT: ret378 %p1 = getelementptr inbounds i32, ptr %a, i64 -18379 %bp1 = bitcast ptr %p1 to ptr380 %bp1p1 = getelementptr inbounds i8, ptr %bp1, i64 1381 %dp1 = bitcast ptr %bp1p1 to ptr382 %tmp1 = load i32, ptr %dp1, align 1383 384 %p2 = getelementptr inbounds i32, ptr %a, i64 -17385 %bp2 = bitcast ptr %p2 to ptr386 %bp2p1 = getelementptr inbounds i8, ptr %bp2, i64 1387 %dp2 = bitcast ptr %bp2p1 to ptr388 %tmp2 = load i32, ptr %dp2, align 1389 390 %sexttmp1 = sext i32 %tmp1 to i64391 %sexttmp2 = sext i32 %tmp2 to i64392 %tmp3 = add i64 %sexttmp1, %sexttmp2393 ret i64 %tmp3394}395 396declare void @use-ptr(ptr)397 398define i64 @ldp_sext_int_pre(ptr %p) nounwind {399; CHECK-LABEL: ldp_sext_int_pre:400; CHECK: // %bb.0:401; CHECK-NEXT: stp x30, x19, [sp, #-16]! // 16-byte Folded Spill402; CHECK-NEXT: mov x19, x0403; CHECK-NEXT: add x0, x0, #8404; CHECK-NEXT: bl "use-ptr"405; CHECK-NEXT: ldpsw x8, x9, [x19, #8]406; CHECK-NEXT: add x0, x9, x8407; CHECK-NEXT: ldp x30, x19, [sp], #16 // 16-byte Folded Reload408; CHECK-NEXT: ret409 %ptr = getelementptr inbounds i32, ptr %p, i64 2410 call void @use-ptr(ptr %ptr)411 %add.ptr = getelementptr inbounds i32, ptr %ptr, i64 0412 %tmp = load i32, ptr %add.ptr, align 4413 %add.ptr1 = getelementptr inbounds i32, ptr %ptr, i64 1414 %tmp1 = load i32, ptr %add.ptr1, align 4415 %sexttmp = sext i32 %tmp to i64416 %sexttmp1 = sext i32 %tmp1 to i64417 %add = add nsw i64 %sexttmp1, %sexttmp418 ret i64 %add419}420 421define i64 @ldp_sext_int_post(ptr %p) nounwind {422; CHECK-LABEL: ldp_sext_int_post:423; CHECK: // %bb.0:424; CHECK-NEXT: str x30, [sp, #-32]! // 8-byte Folded Spill425; CHECK-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill426; CHECK-NEXT: ldpsw x19, x20, [x0], #8427; CHECK-NEXT: bl "use-ptr"428; CHECK-NEXT: add x0, x20, x19429; CHECK-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload430; CHECK-NEXT: ldr x30, [sp], #32 // 8-byte Folded Reload431; CHECK-NEXT: ret432 %tmp = load i32, ptr %p, align 4433 %add.ptr = getelementptr inbounds i32, ptr %p, i64 1434 %tmp1 = load i32, ptr %add.ptr, align 4435 %sexttmp = sext i32 %tmp to i64436 %sexttmp1 = sext i32 %tmp1 to i64437 %ptr = getelementptr inbounds i32, ptr %add.ptr, i64 1438 call void @use-ptr(ptr %ptr)439 %add = add nsw i64 %sexttmp1, %sexttmp440 ret i64 %add441}442 443