1700 lines · plain
1; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-enable-atomic-cfg-tidy=0 -disable-lsr -verify-machineinstrs -o - %s | FileCheck --check-prefix=CHECK --check-prefix=NOSTRICTALIGN %s2; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+strict-align -aarch64-enable-atomic-cfg-tidy=0 -disable-lsr -verify-machineinstrs -o - %s | FileCheck --check-prefix=CHECK --check-prefix=STRICTALIGN %s3 4; This file contains tests for the AArch64 load/store optimizer.5 6%padding = type { ptr, ptr, ptr, ptr }7%s.byte = type { i8, i8 }8%s.halfword = type { i16, i16 }9%s.word = type { i32, i32 }10%s.doubleword = type { i64, i32 }11%s.quadword = type { fp128, i32 }12%s.float = type { float, i32 }13%s.double = type { double, i32 }14%struct.byte = type { %padding, %s.byte }15%struct.halfword = type { %padding, %s.halfword }16%struct.word = type { %padding, %s.word }17%struct.doubleword = type { %padding, %s.doubleword }18%struct.quadword = type { %padding, %s.quadword }19%struct.float = type { %padding, %s.float }20%struct.double = type { %padding, %s.double }21 22; Check the following transform:23;24; (ldr|str) X, [x0, #32]25; ...26; add x0, x0, #3227; ->28; (ldr|str) X, [x0, #32]!29;30; with X being either w1, x1, s0, d0 or q0.31 32declare void @bar_byte(ptr, i8)33 34define void @load-pre-indexed-byte(ptr %ptr) nounwind {35; CHECK-LABEL: load-pre-indexed-byte36; CHECK: ldrb w{{[0-9]+}}, [x{{[0-9]+}}, #32]!37entry:38 %a = getelementptr inbounds %struct.byte, ptr %ptr, i64 0, i32 1, i32 039 %add = load i8, ptr %a, align 440 br label %bar41bar:42 %c = getelementptr inbounds %struct.byte, ptr %ptr, i64 0, i32 143 tail call void @bar_byte(ptr %c, i8 %add)44 ret void45}46 47define void @store-pre-indexed-byte(ptr %ptr, i8 %val) nounwind {48; CHECK-LABEL: store-pre-indexed-byte49; CHECK: strb w{{[0-9]+}}, [x{{[0-9]+}}, #32]!50entry:51 %a = getelementptr inbounds %struct.byte, ptr %ptr, i64 0, i32 1, i32 052 store i8 %val, ptr %a, align 453 br label %bar54bar:55 %c = getelementptr inbounds %struct.byte, ptr %ptr, i64 0, i32 156 tail call void @bar_byte(ptr %c, i8 %val)57 ret void58}59 60declare void @bar_halfword(ptr, i16)61 62define void @load-pre-indexed-halfword(ptr %ptr) nounwind {63; CHECK-LABEL: load-pre-indexed-halfword64; CHECK: ldrh w{{[0-9]+}}, [x{{[0-9]+}}, #32]!65entry:66 %a = getelementptr inbounds %struct.halfword, ptr %ptr, i64 0, i32 1, i32 067 %add = load i16, ptr %a, align 468 br label %bar69bar:70 %c = getelementptr inbounds %struct.halfword, ptr %ptr, i64 0, i32 171 tail call void @bar_halfword(ptr %c, i16 %add)72 ret void73}74 75define void @store-pre-indexed-halfword(ptr %ptr, i16 %val) nounwind {76; CHECK-LABEL: store-pre-indexed-halfword77; CHECK: strh w{{[0-9]+}}, [x{{[0-9]+}}, #32]!78entry:79 %a = getelementptr inbounds %struct.halfword, ptr %ptr, i64 0, i32 1, i32 080 store i16 %val, ptr %a, align 481 br label %bar82bar:83 %c = getelementptr inbounds %struct.halfword, ptr %ptr, i64 0, i32 184 tail call void @bar_halfword(ptr %c, i16 %val)85 ret void86}87 88declare void @bar_word(ptr, i32)89 90define void @load-pre-indexed-word(ptr %ptr) nounwind {91; CHECK-LABEL: load-pre-indexed-word92; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #32]!93entry:94 %a = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 1, i32 095 %add = load i32, ptr %a, align 496 br label %bar97bar:98 %c = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 199 tail call void @bar_word(ptr %c, i32 %add)100 ret void101}102 103define void @store-pre-indexed-word(ptr %ptr, i32 %val) nounwind {104; CHECK-LABEL: store-pre-indexed-word105; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #32]!106entry:107 %a = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 1, i32 0108 store i32 %val, ptr %a, align 4109 br label %bar110bar:111 %c = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 1112 tail call void @bar_word(ptr %c, i32 %val)113 ret void114}115 116declare void @bar_doubleword(ptr, i64)117 118define void @load-pre-indexed-doubleword(ptr %ptr) nounwind {119; CHECK-LABEL: load-pre-indexed-doubleword120; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #32]!121entry:122 %a = getelementptr inbounds %struct.doubleword, ptr %ptr, i64 0, i32 1, i32 0123 %add = load i64, ptr %a, align 8124 br label %bar125bar:126 %c = getelementptr inbounds %struct.doubleword, ptr %ptr, i64 0, i32 1127 tail call void @bar_doubleword(ptr %c, i64 %add)128 ret void129}130 131define void @store-pre-indexed-doubleword(ptr %ptr, i64 %val) nounwind {132; CHECK-LABEL: store-pre-indexed-doubleword133; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #32]!134entry:135 %a = getelementptr inbounds %struct.doubleword, ptr %ptr, i64 0, i32 1, i32 0136 store i64 %val, ptr %a, align 8137 br label %bar138bar:139 %c = getelementptr inbounds %struct.doubleword, ptr %ptr, i64 0, i32 1140 tail call void @bar_doubleword(ptr %c, i64 %val)141 ret void142}143 144declare void @bar_quadword(ptr, fp128)145 146define void @load-pre-indexed-quadword(ptr %ptr) nounwind {147; CHECK-LABEL: load-pre-indexed-quadword148; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]!149entry:150 %a = getelementptr inbounds %struct.quadword, ptr %ptr, i64 0, i32 1, i32 0151 %add = load fp128, ptr %a, align 16152 br label %bar153bar:154 %c = getelementptr inbounds %struct.quadword, ptr %ptr, i64 0, i32 1155 tail call void @bar_quadword(ptr %c, fp128 %add)156 ret void157}158 159define void @store-pre-indexed-quadword(ptr %ptr, fp128 %val) nounwind {160; CHECK-LABEL: store-pre-indexed-quadword161; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]!162entry:163 %a = getelementptr inbounds %struct.quadword, ptr %ptr, i64 0, i32 1, i32 0164 store fp128 %val, ptr %a, align 16165 br label %bar166bar:167 %c = getelementptr inbounds %struct.quadword, ptr %ptr, i64 0, i32 1168 tail call void @bar_quadword(ptr %c, fp128 %val)169 ret void170}171 172declare void @bar_float(ptr, float)173 174define void @load-pre-indexed-float(ptr %ptr) nounwind {175; CHECK-LABEL: load-pre-indexed-float176; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #32]!177entry:178 %a = getelementptr inbounds %struct.float, ptr %ptr, i64 0, i32 1, i32 0179 %add = load float, ptr %a, align 4180 br label %bar181bar:182 %c = getelementptr inbounds %struct.float, ptr %ptr, i64 0, i32 1183 tail call void @bar_float(ptr %c, float %add)184 ret void185}186 187define void @store-pre-indexed-float(ptr %ptr, float %val) nounwind {188; CHECK-LABEL: store-pre-indexed-float189; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #32]!190entry:191 %a = getelementptr inbounds %struct.float, ptr %ptr, i64 0, i32 1, i32 0192 store float %val, ptr %a, align 4193 br label %bar194bar:195 %c = getelementptr inbounds %struct.float, ptr %ptr, i64 0, i32 1196 tail call void @bar_float(ptr %c, float %val)197 ret void198}199 200declare void @bar_double(ptr, double)201 202define void @load-pre-indexed-double(ptr %ptr) nounwind {203; CHECK-LABEL: load-pre-indexed-double204; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #32]!205entry:206 %a = getelementptr inbounds %struct.double, ptr %ptr, i64 0, i32 1, i32 0207 %add = load double, ptr %a, align 8208 br label %bar209bar:210 %c = getelementptr inbounds %struct.double, ptr %ptr, i64 0, i32 1211 tail call void @bar_double(ptr %c, double %add)212 ret void213}214 215define void @store-pre-indexed-double(ptr %ptr, double %val) nounwind {216; CHECK-LABEL: store-pre-indexed-double217; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #32]!218entry:219 %a = getelementptr inbounds %struct.double, ptr %ptr, i64 0, i32 1, i32 0220 store double %val, ptr %a, align 8221 br label %bar222bar:223 %c = getelementptr inbounds %struct.double, ptr %ptr, i64 0, i32 1224 tail call void @bar_double(ptr %c, double %val)225 ret void226}227 228; Check the following transform:229;230; (ldp|stp) w1, w2 [x0, #32]231; ...232; add x0, x0, #32233; ->234; (ldp|stp) w1, w2, [x0, #32]!235;236 237define void @load-pair-pre-indexed-word(ptr %ptr) nounwind {238; CHECK-LABEL: load-pair-pre-indexed-word239; CHECK: ldp w{{[0-9]+}}, w{{[0-9]+}}, [x0, #32]!240; CHECK-NOT: add x0, x0, #32241entry:242 %a = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 1, i32 0243 %a1 = load i32, ptr %a, align 4244 %b = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 1, i32 1245 %b1 = load i32, ptr %b, align 4246 %add = add i32 %a1, %b1247 br label %bar248bar:249 %c = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 1250 tail call void @bar_word(ptr %c, i32 %add)251 ret void252}253 254define void @store-pair-pre-indexed-word(ptr %ptr, i32 %val) nounwind {255; CHECK-LABEL: store-pair-pre-indexed-word256; CHECK: stp w{{[0-9]+}}, w{{[0-9]+}}, [x0, #32]!257; CHECK-NOT: add x0, x0, #32258entry:259 %a = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 1, i32 0260 store i32 %val, ptr %a, align 4261 %b = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 1, i32 1262 store i32 %val, ptr %b, align 4263 br label %bar264bar:265 %c = getelementptr inbounds %struct.word, ptr %ptr, i64 0, i32 1266 tail call void @bar_word(ptr %c, i32 %val)267 ret void268}269 270; Check the following transform:271;272; add x8, x8, #16273; ...274; ldr X, [x8]275; ->276; ldr X, [x8, #16]!277;278; with X being either w0, x0, s0, d0 or q0.279 280%pre.struct.i32 = type { i32, i32, i32, i32, i32}281%pre.struct.i64 = type { i32, i64, i64, i64, i64}282%pre.struct.i128 = type { i32, <2 x i64>, <2 x i64>, <2 x i64>}283%pre.struct.float = type { i32, float, float, float}284%pre.struct.double = type { i32, double, double, double}285 286define i32 @load-pre-indexed-word2(ptr %this, i1 %cond,287 ptr %load2) nounwind {288; CHECK-LABEL: load-pre-indexed-word2289; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #4]!290 br i1 %cond, label %if.then, label %if.end291if.then:292 %load1 = load ptr, ptr %this293 %gep1 = getelementptr inbounds %pre.struct.i32, ptr %load1, i64 0, i32 1294 br label %return295if.end:296 %gep2 = getelementptr inbounds %pre.struct.i32, ptr %load2, i64 0, i32 2297 br label %return298return:299 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]300 %ret = load i32, ptr %retptr301 ret i32 %ret302}303 304define i64 @load-pre-indexed-doubleword2(ptr %this, i1 %cond,305 ptr %load2) nounwind {306; CHECK-LABEL: load-pre-indexed-doubleword2307; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #8]!308 br i1 %cond, label %if.then, label %if.end309if.then:310 %load1 = load ptr, ptr %this311 %gep1 = getelementptr inbounds %pre.struct.i64, ptr %load1, i64 0, i32 1312 br label %return313if.end:314 %gep2 = getelementptr inbounds %pre.struct.i64, ptr %load2, i64 0, i32 2315 br label %return316return:317 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]318 %ret = load i64, ptr %retptr319 ret i64 %ret320}321 322define <2 x i64> @load-pre-indexed-quadword2(ptr %this, i1 %cond,323 ptr %load2) nounwind {324; CHECK-LABEL: load-pre-indexed-quadword2325; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #16]!326 br i1 %cond, label %if.then, label %if.end327if.then:328 %load1 = load ptr, ptr %this329 %gep1 = getelementptr inbounds %pre.struct.i128, ptr %load1, i64 0, i32 1330 br label %return331if.end:332 %gep2 = getelementptr inbounds %pre.struct.i128, ptr %load2, i64 0, i32 2333 br label %return334return:335 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]336 %ret = load <2 x i64>, ptr %retptr337 ret <2 x i64> %ret338}339 340define float @load-pre-indexed-float2(ptr %this, i1 %cond,341 ptr %load2) nounwind {342; CHECK-LABEL: load-pre-indexed-float2343; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #4]!344 br i1 %cond, label %if.then, label %if.end345if.then:346 %load1 = load ptr, ptr %this347 %gep1 = getelementptr inbounds %pre.struct.float, ptr %load1, i64 0, i32 1348 br label %return349if.end:350 %gep2 = getelementptr inbounds %pre.struct.float, ptr %load2, i64 0, i32 2351 br label %return352return:353 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]354 %ret = load float, ptr %retptr355 ret float %ret356}357 358define double @load-pre-indexed-double2(ptr %this, i1 %cond,359 ptr %load2) nounwind {360; CHECK-LABEL: load-pre-indexed-double2361; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #8]!362 br i1 %cond, label %if.then, label %if.end363if.then:364 %load1 = load ptr, ptr %this365 %gep1 = getelementptr inbounds %pre.struct.double, ptr %load1, i64 0, i32 1366 br label %return367if.end:368 %gep2 = getelementptr inbounds %pre.struct.double, ptr %load2, i64 0, i32 2369 br label %return370return:371 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]372 %ret = load double, ptr %retptr373 ret double %ret374}375 376define i32 @load-pre-indexed-word3(ptr %this, i1 %cond,377 ptr %load2) nounwind {378; CHECK-LABEL: load-pre-indexed-word3379; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #12]!380 br i1 %cond, label %if.then, label %if.end381if.then:382 %load1 = load ptr, ptr %this383 %gep1 = getelementptr inbounds %pre.struct.i32, ptr %load1, i64 0, i32 3384 br label %return385if.end:386 %gep2 = getelementptr inbounds %pre.struct.i32, ptr %load2, i64 0, i32 4387 br label %return388return:389 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]390 %ret = load i32, ptr %retptr391 ret i32 %ret392}393 394define i64 @load-pre-indexed-doubleword3(ptr %this, i1 %cond,395 ptr %load2) nounwind {396; CHECK-LABEL: load-pre-indexed-doubleword3397; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #16]!398 br i1 %cond, label %if.then, label %if.end399if.then:400 %load1 = load ptr, ptr %this401 %gep1 = getelementptr inbounds %pre.struct.i64, ptr %load1, i64 0, i32 2402 br label %return403if.end:404 %gep2 = getelementptr inbounds %pre.struct.i64, ptr %load2, i64 0, i32 3405 br label %return406return:407 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]408 %ret = load i64, ptr %retptr409 ret i64 %ret410}411 412define <2 x i64> @load-pre-indexed-quadword3(ptr %this, i1 %cond,413 ptr %load2) nounwind {414; CHECK-LABEL: load-pre-indexed-quadword3415; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]!416 br i1 %cond, label %if.then, label %if.end417if.then:418 %load1 = load ptr, ptr %this419 %gep1 = getelementptr inbounds %pre.struct.i128, ptr %load1, i64 0, i32 2420 br label %return421if.end:422 %gep2 = getelementptr inbounds %pre.struct.i128, ptr %load2, i64 0, i32 3423 br label %return424return:425 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]426 %ret = load <2 x i64>, ptr %retptr427 ret <2 x i64> %ret428}429 430define float @load-pre-indexed-float3(ptr %this, i1 %cond,431 ptr %load2) nounwind {432; CHECK-LABEL: load-pre-indexed-float3433; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #8]!434 br i1 %cond, label %if.then, label %if.end435if.then:436 %load1 = load ptr, ptr %this437 %gep1 = getelementptr inbounds %pre.struct.float, ptr %load1, i64 0, i32 2438 br label %return439if.end:440 %gep2 = getelementptr inbounds %pre.struct.float, ptr %load2, i64 0, i32 3441 br label %return442return:443 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]444 %ret = load float, ptr %retptr445 ret float %ret446}447 448define double @load-pre-indexed-double3(ptr %this, i1 %cond,449 ptr %load2) nounwind {450; CHECK-LABEL: load-pre-indexed-double3451; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #16]!452 br i1 %cond, label %if.then, label %if.end453if.then:454 %load1 = load ptr, ptr %this455 %gep1 = getelementptr inbounds %pre.struct.double, ptr %load1, i64 0, i32 2456 br label %return457if.end:458 %gep2 = getelementptr inbounds %pre.struct.double, ptr %load2, i64 0, i32 3459 br label %return460return:461 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]462 %ret = load double, ptr %retptr463 ret double %ret464}465 466; Check the following transform:467;468; add x8, x8, #16469; ...470; str X, [x8]471; ->472; str X, [x8, #16]!473;474; with X being either w0, x0, s0, d0 or q0.475 476define void @store-pre-indexed-word2(ptr %this, i1 %cond,477 ptr %load2,478 i32 %val) nounwind {479; CHECK-LABEL: store-pre-indexed-word2480; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #4]!481 br i1 %cond, label %if.then, label %if.end482if.then:483 %load1 = load ptr, ptr %this484 %gep1 = getelementptr inbounds %pre.struct.i32, ptr %load1, i64 0, i32 1485 br label %return486if.end:487 %gep2 = getelementptr inbounds %pre.struct.i32, ptr %load2, i64 0, i32 2488 br label %return489return:490 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]491 store i32 %val, ptr %retptr492 ret void493}494 495define void @store-pre-indexed-doubleword2(ptr %this, i1 %cond,496 ptr %load2,497 i64 %val) nounwind {498; CHECK-LABEL: store-pre-indexed-doubleword2499; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #8]!500 br i1 %cond, label %if.then, label %if.end501if.then:502 %load1 = load ptr, ptr %this503 %gep1 = getelementptr inbounds %pre.struct.i64, ptr %load1, i64 0, i32 1504 br label %return505if.end:506 %gep2 = getelementptr inbounds %pre.struct.i64, ptr %load2, i64 0, i32 2507 br label %return508return:509 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]510 store i64 %val, ptr %retptr511 ret void512}513 514define void @store-pre-indexed-quadword2(ptr %this, i1 %cond,515 ptr %load2,516 <2 x i64> %val) nounwind {517; CHECK-LABEL: store-pre-indexed-quadword2518; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #16]!519 br i1 %cond, label %if.then, label %if.end520if.then:521 %load1 = load ptr, ptr %this522 %gep1 = getelementptr inbounds %pre.struct.i128, ptr %load1, i64 0, i32 1523 br label %return524if.end:525 %gep2 = getelementptr inbounds %pre.struct.i128, ptr %load2, i64 0, i32 2526 br label %return527return:528 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]529 store <2 x i64> %val, ptr %retptr530 ret void531}532 533define void @store-pre-indexed-float2(ptr %this, i1 %cond,534 ptr %load2,535 float %val) nounwind {536; CHECK-LABEL: store-pre-indexed-float2537; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #4]!538 br i1 %cond, label %if.then, label %if.end539if.then:540 %load1 = load ptr, ptr %this541 %gep1 = getelementptr inbounds %pre.struct.float, ptr %load1, i64 0, i32 1542 br label %return543if.end:544 %gep2 = getelementptr inbounds %pre.struct.float, ptr %load2, i64 0, i32 2545 br label %return546return:547 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]548 store float %val, ptr %retptr549 ret void550}551 552define void @store-pre-indexed-double2(ptr %this, i1 %cond,553 ptr %load2,554 double %val) nounwind {555; CHECK-LABEL: store-pre-indexed-double2556; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #8]!557 br i1 %cond, label %if.then, label %if.end558if.then:559 %load1 = load ptr, ptr %this560 %gep1 = getelementptr inbounds %pre.struct.double, ptr %load1, i64 0, i32 1561 br label %return562if.end:563 %gep2 = getelementptr inbounds %pre.struct.double, ptr %load2, i64 0, i32 2564 br label %return565return:566 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]567 store double %val, ptr %retptr568 ret void569}570 571define void @store-pre-indexed-word3(ptr %this, i1 %cond,572 ptr %load2,573 i32 %val) nounwind {574; CHECK-LABEL: store-pre-indexed-word3575; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #12]!576 br i1 %cond, label %if.then, label %if.end577if.then:578 %load1 = load ptr, ptr %this579 %gep1 = getelementptr inbounds %pre.struct.i32, ptr %load1, i64 0, i32 3580 br label %return581if.end:582 %gep2 = getelementptr inbounds %pre.struct.i32, ptr %load2, i64 0, i32 4583 br label %return584return:585 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]586 store i32 %val, ptr %retptr587 ret void588}589 590define void @store-pre-indexed-doubleword3(ptr %this, i1 %cond,591 ptr %load2,592 i64 %val) nounwind {593; CHECK-LABEL: store-pre-indexed-doubleword3594; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #24]!595 br i1 %cond, label %if.then, label %if.end596if.then:597 %load1 = load ptr, ptr %this598 %gep1 = getelementptr inbounds %pre.struct.i64, ptr %load1, i64 0, i32 3599 br label %return600if.end:601 %gep2 = getelementptr inbounds %pre.struct.i64, ptr %load2, i64 0, i32 4602 br label %return603return:604 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]605 store i64 %val, ptr %retptr606 ret void607}608 609define void @store-pre-indexed-quadword3(ptr %this, i1 %cond,610 ptr %load2,611 <2 x i64> %val) nounwind {612; CHECK-LABEL: store-pre-indexed-quadword3613; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]!614 br i1 %cond, label %if.then, label %if.end615if.then:616 %load1 = load ptr, ptr %this617 %gep1 = getelementptr inbounds %pre.struct.i128, ptr %load1, i64 0, i32 2618 br label %return619if.end:620 %gep2 = getelementptr inbounds %pre.struct.i128, ptr %load2, i64 0, i32 3621 br label %return622return:623 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]624 store <2 x i64> %val, ptr %retptr625 ret void626}627 628define void @store-pre-indexed-float3(ptr %this, i1 %cond,629 ptr %load2,630 float %val) nounwind {631; CHECK-LABEL: store-pre-indexed-float3632; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #8]!633 br i1 %cond, label %if.then, label %if.end634if.then:635 %load1 = load ptr, ptr %this636 %gep1 = getelementptr inbounds %pre.struct.float, ptr %load1, i64 0, i32 2637 br label %return638if.end:639 %gep2 = getelementptr inbounds %pre.struct.float, ptr %load2, i64 0, i32 3640 br label %return641return:642 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]643 store float %val, ptr %retptr644 ret void645}646 647define void @store-pre-indexed-double3(ptr %this, i1 %cond,648 ptr %load2,649 double %val) nounwind {650; CHECK-LABEL: store-pre-indexed-double3651; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #16]!652 br i1 %cond, label %if.then, label %if.end653if.then:654 %load1 = load ptr, ptr %this655 %gep1 = getelementptr inbounds %pre.struct.double, ptr %load1, i64 0, i32 2656 br label %return657if.end:658 %gep2 = getelementptr inbounds %pre.struct.double, ptr %load2, i64 0, i32 3659 br label %return660return:661 %retptr = phi ptr [ %gep1, %if.then ], [ %gep2, %if.end ]662 store double %val, ptr %retptr663 ret void664}665 666; Check the following transform:667;668; ldr X, [x20]669; ...670; add x20, x20, #32671; ->672; ldr X, [x20], #32673;674; with X being either w0, x0, s0, d0 or q0.675 676define void @load-post-indexed-byte(ptr %array, i64 %count) nounwind {677; CHECK-LABEL: load-post-indexed-byte678; CHECK: ldrb w{{[0-9]+}}, [x{{[0-9]+}}], #4679entry:680 %gep1 = getelementptr i8, ptr %array, i64 2681 br label %body682 683body:684 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]685 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]686 %gep2 = getelementptr i8, ptr %iv2, i64 -1687 %load = load i8, ptr %gep2688 call void @use-byte(i8 %load)689 %load2 = load i8, ptr %iv2690 call void @use-byte(i8 %load2)691 %iv.next = add i64 %iv, -4692 %gep3 = getelementptr i8, ptr %iv2, i64 4693 %cond = icmp eq i64 %iv.next, 0694 br i1 %cond, label %exit, label %body695 696exit:697 ret void698}699 700define void @load-post-indexed-halfword(ptr %array, i64 %count) nounwind {701; CHECK-LABEL: load-post-indexed-halfword702; CHECK: ldrh w{{[0-9]+}}, [x{{[0-9]+}}], #8703entry:704 %gep1 = getelementptr i16, ptr %array, i64 2705 br label %body706 707body:708 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]709 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]710 %gep2 = getelementptr i16, ptr %iv2, i64 -1711 %load = load i16, ptr %gep2712 call void @use-halfword(i16 %load)713 %load2 = load i16, ptr %iv2714 call void @use-halfword(i16 %load2)715 %iv.next = add i64 %iv, -4716 %gep3 = getelementptr i16, ptr %iv2, i64 4717 %cond = icmp eq i64 %iv.next, 0718 br i1 %cond, label %exit, label %body719 720exit:721 ret void722}723 724define void @load-post-indexed-word(ptr %array, i64 %count) nounwind {725; CHECK-LABEL: load-post-indexed-word726; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #16727entry:728 %gep1 = getelementptr i32, ptr %array, i64 2729 br label %body730 731body:732 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]733 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]734 %gep2 = getelementptr i32, ptr %iv2, i64 -1735 %load = load i32, ptr %gep2736 call void @use-word(i32 %load)737 %load2 = load i32, ptr %iv2738 call void @use-word(i32 %load2)739 %iv.next = add i64 %iv, -4740 %gep3 = getelementptr i32, ptr %iv2, i64 4741 %cond = icmp eq i64 %iv.next, 0742 br i1 %cond, label %exit, label %body743 744exit:745 ret void746}747 748define void @load-post-indexed-doubleword(ptr %array, i64 %count) nounwind {749; CHECK-LABEL: load-post-indexed-doubleword750; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #32751entry:752 %gep1 = getelementptr i64, ptr %array, i64 2753 br label %body754 755body:756 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]757 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]758 %gep2 = getelementptr i64, ptr %iv2, i64 -1759 %load = load i64, ptr %gep2760 call void @use-doubleword(i64 %load)761 %load2 = load i64, ptr %iv2762 call void @use-doubleword(i64 %load2)763 %iv.next = add i64 %iv, -4764 %gep3 = getelementptr i64, ptr %iv2, i64 4765 %cond = icmp eq i64 %iv.next, 0766 br i1 %cond, label %exit, label %body767 768exit:769 ret void770}771 772define void @load-post-indexed-quadword(ptr %array, i64 %count) nounwind {773; CHECK-LABEL: load-post-indexed-quadword774; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #64775entry:776 %gep1 = getelementptr <2 x i64>, ptr %array, i64 2777 br label %body778 779body:780 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]781 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]782 %gep2 = getelementptr <2 x i64>, ptr %iv2, i64 -1783 %load = load <2 x i64>, ptr %gep2784 call void @use-quadword(<2 x i64> %load)785 %load2 = load <2 x i64>, ptr %iv2786 call void @use-quadword(<2 x i64> %load2)787 %iv.next = add i64 %iv, -4788 %gep3 = getelementptr <2 x i64>, ptr %iv2, i64 4789 %cond = icmp eq i64 %iv.next, 0790 br i1 %cond, label %exit, label %body791 792exit:793 ret void794}795 796define void @load-post-indexed-float(ptr %array, i64 %count) nounwind {797; CHECK-LABEL: load-post-indexed-float798; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #16799entry:800 %gep1 = getelementptr float, ptr %array, i64 2801 br label %body802 803body:804 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]805 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]806 %gep2 = getelementptr float, ptr %iv2, i64 -1807 %load = load float, ptr %gep2808 call void @use-float(float %load)809 %load2 = load float, ptr %iv2810 call void @use-float(float %load2)811 %iv.next = add i64 %iv, -4812 %gep3 = getelementptr float, ptr %iv2, i64 4813 %cond = icmp eq i64 %iv.next, 0814 br i1 %cond, label %exit, label %body815 816exit:817 ret void818}819 820define void @load-post-indexed-double(ptr %array, i64 %count) nounwind {821; CHECK-LABEL: load-post-indexed-double822; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #32823entry:824 %gep1 = getelementptr double, ptr %array, i64 2825 br label %body826 827body:828 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]829 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]830 %gep2 = getelementptr double, ptr %iv2, i64 -1831 %load = load double, ptr %gep2832 call void @use-double(double %load)833 %load2 = load double, ptr %iv2834 call void @use-double(double %load2)835 %iv.next = add i64 %iv, -4836 %gep3 = getelementptr double, ptr %iv2, i64 4837 %cond = icmp eq i64 %iv.next, 0838 br i1 %cond, label %exit, label %body839 840exit:841 ret void842}843 844; Check the following transform:845;846; str X, [x20]847; ...848; add x20, x20, #32849; ->850; str X, [x20], #32851;852; with X being either w0, x0, s0, d0 or q0.853 854define void @store-post-indexed-byte(ptr %array, i64 %count, i8 %val) nounwind {855; CHECK-LABEL: store-post-indexed-byte856; CHECK: strb w{{[0-9]+}}, [x{{[0-9]+}}], #4857entry:858 %gep1 = getelementptr i8, ptr %array, i64 2859 br label %body860 861body:862 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]863 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]864 %gep2 = getelementptr i8, ptr %iv2, i64 -1865 %load = load i8, ptr %gep2866 call void @use-byte(i8 %load)867 store i8 %val, ptr %iv2868 %iv.next = add i64 %iv, -4869 %gep3 = getelementptr i8, ptr %iv2, i64 4870 %cond = icmp eq i64 %iv.next, 0871 br i1 %cond, label %exit, label %body872 873exit:874 ret void875}876 877define void @store-post-indexed-halfword(ptr %array, i64 %count, i16 %val) nounwind {878; CHECK-LABEL: store-post-indexed-halfword879; CHECK: strh w{{[0-9]+}}, [x{{[0-9]+}}], #8880entry:881 %gep1 = getelementptr i16, ptr %array, i64 2882 br label %body883 884body:885 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]886 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]887 %gep2 = getelementptr i16, ptr %iv2, i64 -1888 %load = load i16, ptr %gep2889 call void @use-halfword(i16 %load)890 store i16 %val, ptr %iv2891 %iv.next = add i64 %iv, -4892 %gep3 = getelementptr i16, ptr %iv2, i64 4893 %cond = icmp eq i64 %iv.next, 0894 br i1 %cond, label %exit, label %body895 896exit:897 ret void898}899 900define void @store-post-indexed-word(ptr %array, i64 %count, i32 %val) nounwind {901; CHECK-LABEL: store-post-indexed-word902; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #16903entry:904 %gep1 = getelementptr i32, ptr %array, i64 2905 br label %body906 907body:908 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]909 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]910 %gep2 = getelementptr i32, ptr %iv2, i64 -1911 %load = load i32, ptr %gep2912 call void @use-word(i32 %load)913 store i32 %val, ptr %iv2914 %iv.next = add i64 %iv, -4915 %gep3 = getelementptr i32, ptr %iv2, i64 4916 %cond = icmp eq i64 %iv.next, 0917 br i1 %cond, label %exit, label %body918 919exit:920 ret void921}922 923define void @store-post-indexed-doubleword(ptr %array, i64 %count, i64 %val) nounwind {924; CHECK-LABEL: store-post-indexed-doubleword925; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #32926entry:927 %gep1 = getelementptr i64, ptr %array, i64 2928 br label %body929 930body:931 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]932 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]933 %gep2 = getelementptr i64, ptr %iv2, i64 -1934 %load = load i64, ptr %gep2935 call void @use-doubleword(i64 %load)936 store i64 %val, ptr %iv2937 %iv.next = add i64 %iv, -4938 %gep3 = getelementptr i64, ptr %iv2, i64 4939 %cond = icmp eq i64 %iv.next, 0940 br i1 %cond, label %exit, label %body941 942exit:943 ret void944}945 946define void @store-post-indexed-quadword(ptr %array, i64 %count, <2 x i64> %val) nounwind {947; CHECK-LABEL: store-post-indexed-quadword948; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #64949entry:950 %gep1 = getelementptr <2 x i64>, ptr %array, i64 2951 br label %body952 953body:954 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]955 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]956 %gep2 = getelementptr <2 x i64>, ptr %iv2, i64 -1957 %load = load <2 x i64>, ptr %gep2958 call void @use-quadword(<2 x i64> %load)959 store <2 x i64> %val, ptr %iv2960 %iv.next = add i64 %iv, -4961 %gep3 = getelementptr <2 x i64>, ptr %iv2, i64 4962 %cond = icmp eq i64 %iv.next, 0963 br i1 %cond, label %exit, label %body964 965exit:966 ret void967}968 969define void @store-post-indexed-float(ptr %array, i64 %count, float %val) nounwind {970; CHECK-LABEL: store-post-indexed-float971; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #16972entry:973 %gep1 = getelementptr float, ptr %array, i64 2974 br label %body975 976body:977 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]978 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]979 %gep2 = getelementptr float, ptr %iv2, i64 -1980 %load = load float, ptr %gep2981 call void @use-float(float %load)982 store float %val, ptr %iv2983 %iv.next = add i64 %iv, -4984 %gep3 = getelementptr float, ptr %iv2, i64 4985 %cond = icmp eq i64 %iv.next, 0986 br i1 %cond, label %exit, label %body987 988exit:989 ret void990}991 992define void @store-post-indexed-double(ptr %array, i64 %count, double %val) nounwind {993; CHECK-LABEL: store-post-indexed-double994; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #32995entry:996 %gep1 = getelementptr double, ptr %array, i64 2997 br label %body998 999body:1000 %iv2 = phi ptr [ %gep3, %body ], [ %gep1, %entry ]1001 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ]1002 %gep2 = getelementptr double, ptr %iv2, i64 -11003 %load = load double, ptr %gep21004 call void @use-double(double %load)1005 store double %val, ptr %iv21006 %iv.next = add i64 %iv, -41007 %gep3 = getelementptr double, ptr %iv2, i64 41008 %cond = icmp eq i64 %iv.next, 01009 br i1 %cond, label %exit, label %body1010 1011exit:1012 ret void1013}1014 1015declare void @use-byte(i8)1016declare void @use-halfword(i16)1017declare void @use-word(i32)1018declare void @use-doubleword(i64)1019declare void @use-quadword(<2 x i64>)1020declare void @use-float(float)1021declare void @use-double(double)1022 1023; Check the following transform:1024;1025; stp w0, [x20]1026; ...1027; add x20, x20, #321028; ->1029; stp w0, [x20], #321030 1031define void @store-pair-post-indexed-word() nounwind {1032; CHECK-LABEL: store-pair-post-indexed-word1033; CHECK: stp w{{[0-9]+}}, w{{[0-9]+}}, [sp], #161034; CHECK: ret1035 %src = alloca { i32, i32 }, align 81036 %dst = alloca { i32, i32 }, align 81037 1038 %src.realp = getelementptr inbounds { i32, i32 }, ptr %src, i32 0, i32 01039 %src.real = load i32, ptr %src.realp1040 %src.imagp = getelementptr inbounds { i32, i32 }, ptr %src, i32 0, i32 11041 %src.imag = load i32, ptr %src.imagp1042 1043 %dst.realp = getelementptr inbounds { i32, i32 }, ptr %dst, i32 0, i32 01044 %dst.imagp = getelementptr inbounds { i32, i32 }, ptr %dst, i32 0, i32 11045 store i32 %src.real, ptr %dst.realp1046 store i32 %src.imag, ptr %dst.imagp1047 ret void1048}1049 1050define void @store-pair-post-indexed-doubleword() nounwind {1051; CHECK-LABEL: store-pair-post-indexed-doubleword1052; CHECK: stp x{{[0-9]+}}, x{{[0-9]+}}, [sp], #321053; CHECK: ret1054 %src = alloca { i64, i64 }, align 81055 %dst = alloca { i64, i64 }, align 81056 1057 %src.realp = getelementptr inbounds { i64, i64 }, ptr %src, i32 0, i32 01058 %src.real = load i64, ptr %src.realp1059 %src.imagp = getelementptr inbounds { i64, i64 }, ptr %src, i32 0, i32 11060 %src.imag = load i64, ptr %src.imagp1061 1062 %dst.realp = getelementptr inbounds { i64, i64 }, ptr %dst, i32 0, i32 01063 %dst.imagp = getelementptr inbounds { i64, i64 }, ptr %dst, i32 0, i32 11064 store i64 %src.real, ptr %dst.realp1065 store i64 %src.imag, ptr %dst.imagp1066 ret void1067}1068 1069define void @store-pair-post-indexed-float() nounwind {1070; CHECK-LABEL: store-pair-post-indexed-float1071; CHECK: stp s{{[0-9]+}}, s{{[0-9]+}}, [sp], #161072; CHECK: ret1073 %src = alloca { float, float }, align 81074 %dst = alloca { float, float }, align 81075 1076 %src.realp = getelementptr inbounds { float, float }, ptr %src, i32 0, i32 01077 %src.real = load float, ptr %src.realp1078 %src.imagp = getelementptr inbounds { float, float }, ptr %src, i32 0, i32 11079 %src.imag = load float, ptr %src.imagp1080 1081 %dst.realp = getelementptr inbounds { float, float }, ptr %dst, i32 0, i32 01082 %dst.imagp = getelementptr inbounds { float, float }, ptr %dst, i32 0, i32 11083 store float %src.real, ptr %dst.realp1084 store float %src.imag, ptr %dst.imagp1085 ret void1086}1087 1088define void @store-pair-post-indexed-double() nounwind {1089; CHECK-LABEL: store-pair-post-indexed-double1090; CHECK: stp d{{[0-9]+}}, d{{[0-9]+}}, [sp], #321091; CHECK: ret1092 %src = alloca { double, double }, align 81093 %dst = alloca { double, double }, align 81094 1095 %src.realp = getelementptr inbounds { double, double }, ptr %src, i32 0, i32 01096 %src.real = load double, ptr %src.realp1097 %src.imagp = getelementptr inbounds { double, double }, ptr %src, i32 0, i32 11098 %src.imag = load double, ptr %src.imagp1099 1100 %dst.realp = getelementptr inbounds { double, double }, ptr %dst, i32 0, i32 01101 %dst.imagp = getelementptr inbounds { double, double }, ptr %dst, i32 0, i32 11102 store double %src.real, ptr %dst.realp1103 store double %src.imag, ptr %dst.imagp1104 ret void1105}1106 1107; Check the following transform:1108;1109; (ldr|str) X, [x20]1110; ...1111; sub x20, x20, #161112; ->1113; (ldr|str) X, [x20], #-161114;1115; with X being either w0, x0, s0, d0 or q0.1116 1117define void @post-indexed-sub-word(ptr %a, ptr %b, i64 %count) nounwind {1118; CHECK-LABEL: post-indexed-sub-word1119; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #-81120; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #-81121 br label %for.body1122for.body:1123 %phi1 = phi ptr [ %gep4, %for.body ], [ %b, %0 ]1124 %phi2 = phi ptr [ %gep3, %for.body ], [ %a, %0 ]1125 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]1126 %gep1 = getelementptr i32, ptr %phi1, i64 -11127 %load1 = load i32, ptr %gep11128 %gep2 = getelementptr i32, ptr %phi2, i64 -11129 store i32 %load1, ptr %gep21130 %load2 = load i32, ptr %phi11131 store i32 %load2, ptr %phi21132 %dec.i = add nsw i64 %i, -11133 %gep3 = getelementptr i32, ptr %phi2, i64 -21134 %gep4 = getelementptr i32, ptr %phi1, i64 -21135 %cond = icmp sgt i64 %dec.i, 01136 br i1 %cond, label %for.body, label %end1137end:1138 ret void1139}1140 1141define void @post-indexed-sub-doubleword(ptr %a, ptr %b, i64 %count) nounwind {1142; CHECK-LABEL: post-indexed-sub-doubleword1143; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #-161144; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #-161145 br label %for.body1146for.body:1147 %phi1 = phi ptr [ %gep4, %for.body ], [ %b, %0 ]1148 %phi2 = phi ptr [ %gep3, %for.body ], [ %a, %0 ]1149 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]1150 %gep1 = getelementptr i64, ptr %phi1, i64 -11151 %load1 = load i64, ptr %gep11152 %gep2 = getelementptr i64, ptr %phi2, i64 -11153 store i64 %load1, ptr %gep21154 %load2 = load i64, ptr %phi11155 store i64 %load2, ptr %phi21156 %dec.i = add nsw i64 %i, -11157 %gep3 = getelementptr i64, ptr %phi2, i64 -21158 %gep4 = getelementptr i64, ptr %phi1, i64 -21159 %cond = icmp sgt i64 %dec.i, 01160 br i1 %cond, label %for.body, label %end1161end:1162 ret void1163}1164 1165define void @post-indexed-sub-quadword(ptr %a, ptr %b, i64 %count) nounwind {1166; CHECK-LABEL: post-indexed-sub-quadword1167; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #-321168; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #-321169 br label %for.body1170for.body:1171 %phi1 = phi ptr [ %gep4, %for.body ], [ %b, %0 ]1172 %phi2 = phi ptr [ %gep3, %for.body ], [ %a, %0 ]1173 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]1174 %gep1 = getelementptr <2 x i64>, ptr %phi1, i64 -11175 %load1 = load <2 x i64>, ptr %gep11176 %gep2 = getelementptr <2 x i64>, ptr %phi2, i64 -11177 store <2 x i64> %load1, ptr %gep21178 %load2 = load <2 x i64>, ptr %phi11179 store <2 x i64> %load2, ptr %phi21180 %dec.i = add nsw i64 %i, -11181 %gep3 = getelementptr <2 x i64>, ptr %phi2, i64 -21182 %gep4 = getelementptr <2 x i64>, ptr %phi1, i64 -21183 %cond = icmp sgt i64 %dec.i, 01184 br i1 %cond, label %for.body, label %end1185end:1186 ret void1187}1188 1189define void @post-indexed-sub-float(ptr %a, ptr %b, i64 %count) nounwind {1190; CHECK-LABEL: post-indexed-sub-float1191; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #-81192; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #-81193 br label %for.body1194for.body:1195 %phi1 = phi ptr [ %gep4, %for.body ], [ %b, %0 ]1196 %phi2 = phi ptr [ %gep3, %for.body ], [ %a, %0 ]1197 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]1198 %gep1 = getelementptr float, ptr %phi1, i64 -11199 %load1 = load float, ptr %gep11200 %gep2 = getelementptr float, ptr %phi2, i64 -11201 store float %load1, ptr %gep21202 %load2 = load float, ptr %phi11203 store float %load2, ptr %phi21204 %dec.i = add nsw i64 %i, -11205 %gep3 = getelementptr float, ptr %phi2, i64 -21206 %gep4 = getelementptr float, ptr %phi1, i64 -21207 %cond = icmp sgt i64 %dec.i, 01208 br i1 %cond, label %for.body, label %end1209end:1210 ret void1211}1212 1213define void @post-indexed-sub-double(ptr %a, ptr %b, i64 %count) nounwind {1214; CHECK-LABEL: post-indexed-sub-double1215; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #-161216; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #-161217 br label %for.body1218for.body:1219 %phi1 = phi ptr [ %gep4, %for.body ], [ %b, %0 ]1220 %phi2 = phi ptr [ %gep3, %for.body ], [ %a, %0 ]1221 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]1222 %gep1 = getelementptr double, ptr %phi1, i64 -11223 %load1 = load double, ptr %gep11224 %gep2 = getelementptr double, ptr %phi2, i64 -11225 store double %load1, ptr %gep21226 %load2 = load double, ptr %phi11227 store double %load2, ptr %phi21228 %dec.i = add nsw i64 %i, -11229 %gep3 = getelementptr double, ptr %phi2, i64 -21230 %gep4 = getelementptr double, ptr %phi1, i64 -21231 %cond = icmp sgt i64 %dec.i, 01232 br i1 %cond, label %for.body, label %end1233end:1234 ret void1235}1236 1237define void @post-indexed-sub-doubleword-offset-min(ptr %a, ptr %b, i64 %count) nounwind {1238; CHECK-LABEL: post-indexed-sub-doubleword-offset-min1239; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #-2561240; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #-2561241 br label %for.body1242for.body:1243 %phi1 = phi ptr [ %gep4, %for.body ], [ %b, %0 ]1244 %phi2 = phi ptr [ %gep3, %for.body ], [ %a, %0 ]1245 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]1246 %gep1 = getelementptr i64, ptr %phi1, i64 11247 %load1 = load i64, ptr %gep11248 %gep2 = getelementptr i64, ptr %phi2, i64 11249 store i64 %load1, ptr %gep21250 %load2 = load i64, ptr %phi11251 store i64 %load2, ptr %phi21252 %dec.i = add nsw i64 %i, -11253 %gep3 = getelementptr i64, ptr %phi2, i64 -321254 %gep4 = getelementptr i64, ptr %phi1, i64 -321255 %cond = icmp sgt i64 %dec.i, 01256 br i1 %cond, label %for.body, label %end1257end:1258 ret void1259}1260 1261define void @post-indexed-doubleword-offset-out-of-range(ptr %a, ptr %b, i64 %count) nounwind {1262; CHECK-LABEL: post-indexed-doubleword-offset-out-of-range1263; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}]1264; CHECK: add x{{[0-9]+}}, x{{[0-9]+}}, #2561265; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}]1266; CHECK: add x{{[0-9]+}}, x{{[0-9]+}}, #2561267 1268 br label %for.body1269for.body:1270 %phi1 = phi ptr [ %gep4, %for.body ], [ %b, %0 ]1271 %phi2 = phi ptr [ %gep3, %for.body ], [ %a, %0 ]1272 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]1273 %gep1 = getelementptr i64, ptr %phi1, i64 11274 %load1 = load i64, ptr %gep11275 %gep2 = getelementptr i64, ptr %phi2, i64 11276 store i64 %load1, ptr %gep21277 %load2 = load i64, ptr %phi11278 store i64 %load2, ptr %phi21279 %dec.i = add nsw i64 %i, -11280 %gep3 = getelementptr i64, ptr %phi2, i64 321281 %gep4 = getelementptr i64, ptr %phi1, i64 321282 %cond = icmp sgt i64 %dec.i, 01283 br i1 %cond, label %for.body, label %end1284end:1285 ret void1286}1287 1288define void @post-indexed-paired-min-offset(ptr %a, ptr %b, i64 %count) nounwind {1289; CHECK-LABEL: post-indexed-paired-min-offset1290; CHECK: ldp x{{[0-9]+}}, x{{[0-9]+}}, [x{{[0-9]+}}], #-5121291; CHECK: stp x{{[0-9]+}}, x{{[0-9]+}}, [x{{[0-9]+}}], #-5121292 br label %for.body1293for.body:1294 %phi1 = phi ptr [ %gep4, %for.body ], [ %b, %0 ]1295 %phi2 = phi ptr [ %gep3, %for.body ], [ %a, %0 ]1296 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]1297 %gep1 = getelementptr i64, ptr %phi1, i64 11298 %load1 = load i64, ptr %gep11299 %gep2 = getelementptr i64, ptr %phi2, i64 11300 %load2 = load i64, ptr %phi11301 store i64 %load1, ptr %gep21302 store i64 %load2, ptr %phi21303 %dec.i = add nsw i64 %i, -11304 %gep3 = getelementptr i64, ptr %phi2, i64 -641305 %gep4 = getelementptr i64, ptr %phi1, i64 -641306 %cond = icmp sgt i64 %dec.i, 01307 br i1 %cond, label %for.body, label %end1308end:1309 ret void1310}1311 1312define void @post-indexed-paired-offset-out-of-range(ptr %a, ptr %b, i64 %count) nounwind {1313; CHECK-LABEL: post-indexed-paired-offset-out-of-range1314; CHECK: ldp x{{[0-9]+}}, x{{[0-9]+}}, [x{{[0-9]+}}]1315; CHECK: add x{{[0-9]+}}, x{{[0-9]+}}, #5121316; CHECK: stp x{{[0-9]+}}, x{{[0-9]+}}, [x{{[0-9]+}}]1317; CHECK: add x{{[0-9]+}}, x{{[0-9]+}}, #5121318 br label %for.body1319for.body:1320 %phi1 = phi ptr [ %gep4, %for.body ], [ %b, %0 ]1321 %phi2 = phi ptr [ %gep3, %for.body ], [ %a, %0 ]1322 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ]1323 %gep1 = getelementptr i64, ptr %phi1, i64 11324 %load1 = load i64, ptr %phi11325 %gep2 = getelementptr i64, ptr %phi2, i64 11326 %load2 = load i64, ptr %gep11327 store i64 %load1, ptr %gep21328 store i64 %load2, ptr %phi21329 %dec.i = add nsw i64 %i, -11330 %gep3 = getelementptr i64, ptr %phi2, i64 641331 %gep4 = getelementptr i64, ptr %phi1, i64 641332 %cond = icmp sgt i64 %dec.i, 01333 br i1 %cond, label %for.body, label %end1334end:1335 ret void1336}1337 1338; DAGCombiner::MergeConsecutiveStores merges this into a vector store,1339; replaceZeroVectorStore should split the vector store back into1340; scalar stores which should get merged by AArch64LoadStoreOptimizer.1341define void @merge_zr32(ptr %p) {1342; CHECK-LABEL: merge_zr32:1343; CHECK: // %entry1344; NOSTRICTALIGN-NEXT: str xzr, [x{{[0-9]+}}]1345; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}]1346; CHECK-NEXT: ret1347entry:1348 store i32 0, ptr %p1349 %p1 = getelementptr i32, ptr %p, i32 11350 store i32 0, ptr %p11351 ret void1352}1353 1354; Same as merge_zr32 but the merged stores should also get paried.1355define void @merge_zr32_2(ptr %p) {1356; CHECK-LABEL: merge_zr32_2:1357; CHECK: // %entry1358; NOSTRICTALIGN-NEXT: stp xzr, xzr, [x{{[0-9]+}}]1359; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}]1360; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}, #8]1361; CHECK-NEXT: ret1362entry:1363 store i32 0, ptr %p1364 %p1 = getelementptr i32, ptr %p, i32 11365 store i32 0, ptr %p11366 %p2 = getelementptr i32, ptr %p, i64 21367 store i32 0, ptr %p21368 %p3 = getelementptr i32, ptr %p, i64 31369 store i32 0, ptr %p31370 ret void1371}1372 1373; Like merge_zr32_2, but checking the largest allowed stp immediate offset.1374define void @merge_zr32_2_offset(ptr %p) {1375; CHECK-LABEL: merge_zr32_2_offset:1376; CHECK: // %entry1377; NOSTRICTALIGN-NEXT: stp xzr, xzr, [x{{[0-9]+}}, #504]1378; STRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}, #504]1379; STRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}, #508]1380; STRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}, #512]1381; STRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}, #516]1382; CHECK-NEXT: ret1383entry:1384 %p0 = getelementptr i32, ptr %p, i32 1261385 store i32 0, ptr %p01386 %p1 = getelementptr i32, ptr %p, i32 1271387 store i32 0, ptr %p11388 %p2 = getelementptr i32, ptr %p, i64 1281389 store i32 0, ptr %p21390 %p3 = getelementptr i32, ptr %p, i64 1291391 store i32 0, ptr %p31392 ret void1393}1394 1395; Like merge_zr32, but replaceZeroVectorStore should not split this1396; vector store since the address offset is too large for the stp1397; instruction.1398define void @no_merge_zr32_2_offset(ptr %p) {1399; CHECK-LABEL: no_merge_zr32_2_offset:1400; CHECK: // %entry1401; NOSTRICTALIGN-NEXT: movi v[[REG:[0-9]]].2d, #00000000000000001402; NOSTRICTALIGN-NEXT: str q[[REG]], [x{{[0-9]+}}, #4096]1403; STRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}, #4096]1404; STRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}, #4100]1405; STRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}, #4104]1406; STRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}, #4108]1407; CHECK-NEXT: ret1408entry:1409 %p0 = getelementptr i32, ptr %p, i32 10241410 store i32 0, ptr %p01411 %p1 = getelementptr i32, ptr %p, i32 10251412 store i32 0, ptr %p11413 %p2 = getelementptr i32, ptr %p, i64 10261414 store i32 0, ptr %p21415 %p3 = getelementptr i32, ptr %p, i64 10271416 store i32 0, ptr %p31417 ret void1418}1419 1420; Like merge_zr32, but replaceZeroVectorStore should not split the1421; vector store since the zero constant vector has multiple uses, so we1422; err on the side that allows for stp q instruction generation.1423define void @merge_zr32_3(ptr %p) {1424; CHECK-LABEL: merge_zr32_3:1425; CHECK: // %entry1426; NOSTRICTALIGN-NEXT: movi v[[REG:[0-9]]].2d, #00000000000000001427; NOSTRICTALIGN-NEXT: stp q[[REG]], q[[REG]], [x{{[0-9]+}}]1428; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}]1429; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}, #8]1430; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}, #16]1431; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}, #24]1432; CHECK-NEXT: ret1433entry:1434 store i32 0, ptr %p1435 %p1 = getelementptr i32, ptr %p, i32 11436 store i32 0, ptr %p11437 %p2 = getelementptr i32, ptr %p, i64 21438 store i32 0, ptr %p21439 %p3 = getelementptr i32, ptr %p, i64 31440 store i32 0, ptr %p31441 %p4 = getelementptr i32, ptr %p, i64 41442 store i32 0, ptr %p41443 %p5 = getelementptr i32, ptr %p, i64 51444 store i32 0, ptr %p51445 %p6 = getelementptr i32, ptr %p, i64 61446 store i32 0, ptr %p61447 %p7 = getelementptr i32, ptr %p, i64 71448 store i32 0, ptr %p71449 ret void1450}1451 1452; Like merge_zr32, but with 2-vector type.1453define void @merge_zr32_2vec(ptr %p) {1454; CHECK-LABEL: merge_zr32_2vec:1455; CHECK: // %entry1456; NOSTRICTALIGN-NEXT: str xzr, [x{{[0-9]+}}]1457; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}]1458; CHECK-NEXT: ret1459entry:1460 store <2 x i32> zeroinitializer, ptr %p1461 ret void1462}1463 1464; Like merge_zr32, but with 3-vector type.1465define void @merge_zr32_3vec(ptr %p) {1466; CHECK-LABEL: merge_zr32_3vec:1467; CHECK: // %entry1468; NOSTRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}, #8]1469; NOSTRICTALIGN-NEXT: str xzr, [x{{[0-9]+}}]1470; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}, #4]1471; STRICTALIGN-NEXT: str wzr, [x{{[0-9]+}}]1472; CHECK-NEXT: ret1473entry:1474 store <3 x i32> zeroinitializer, ptr %p1475 ret void1476}1477 1478; Like merge_zr32, but with 4-vector type.1479define void @merge_zr32_4vec(ptr %p) {1480; CHECK-LABEL: merge_zr32_4vec:1481; CHECK: // %entry1482; NOSTRICTALIGN-NEXT: stp xzr, xzr, [x{{[0-9]+}}]1483; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}, #8]1484; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}]1485; CHECK-NEXT: ret1486entry:1487 store <4 x i32> zeroinitializer, ptr %p1488 ret void1489}1490 1491; Like merge_zr32, but with 2-vector float type.1492define void @merge_zr32_2vecf(ptr %p) {1493; CHECK-LABEL: merge_zr32_2vecf:1494; CHECK: // %entry1495; NOSTRICTALIGN-NEXT: str xzr, [x{{[0-9]+}}]1496; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}]1497; CHECK-NEXT: ret1498entry:1499 store <2 x float> zeroinitializer, ptr %p1500 ret void1501}1502 1503; Like merge_zr32, but with 4-vector float type.1504define void @merge_zr32_4vecf(ptr %p) {1505; CHECK-LABEL: merge_zr32_4vecf:1506; CHECK: // %entry1507; NOSTRICTALIGN-NEXT: stp xzr, xzr, [x{{[0-9]+}}]1508; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}, #8]1509; STRICTALIGN-NEXT: stp wzr, wzr, [x{{[0-9]+}}]1510; CHECK-NEXT: ret1511entry:1512 store <4 x float> zeroinitializer, ptr %p1513 ret void1514}1515 1516; Similar to merge_zr32, but for 64-bit values.1517define void @merge_zr64(ptr %p) {1518; CHECK-LABEL: merge_zr64:1519; CHECK: // %entry1520; CHECK-NEXT: stp xzr, xzr, [x{{[0-9]+}}]1521; CHECK-NEXT: ret1522entry:1523 store i64 0, ptr %p1524 %p1 = getelementptr i64, ptr %p, i64 11525 store i64 0, ptr %p11526 ret void1527}1528 1529; Similar to merge_zr32, but for 64-bit values and with unaligned stores.1530define void @merge_zr64_unalign(ptr %p) {1531; CHECK-LABEL: merge_zr64_unalign:1532; CHECK: // %entry1533; NOSTRICTALIGN-NEXT: stp xzr, xzr, [x{{[0-9]+}}]1534; STRICTALIGN: strb1535; STRICTALIGN: strb1536; STRICTALIGN: strb1537; STRICTALIGN: strb1538; STRICTALIGN: strb1539; STRICTALIGN: strb1540; STRICTALIGN: strb1541; STRICTALIGN: strb1542; STRICTALIGN: strb1543; STRICTALIGN: strb1544; STRICTALIGN: strb1545; STRICTALIGN: strb1546; STRICTALIGN: strb1547; STRICTALIGN: strb1548; STRICTALIGN: strb1549; STRICTALIGN: strb1550; CHECK-NEXT: ret1551entry:1552 store <2 x i64> zeroinitializer, ptr %p, align 11553 ret void1554}1555 1556; Similar to merge_zr32_3, replaceZeroVectorStore should not split the1557; vector store since the zero constant vector has multiple uses.1558define void @merge_zr64_2(ptr %p) {1559; CHECK-LABEL: merge_zr64_2:1560; CHECK: // %entry1561; NOSTRICTALIGN-NEXT: movi v[[REG:[0-9]]].2d, #00000000000000001562; NOSTRICTALIGN-NEXT: stp q[[REG]], q[[REG]], [x{{[0-9]+}}]1563; STRICTALIGN-NEXT: stp xzr, xzr, [x{{[0-9]+}}]1564; STRICTALIGN-NEXT: stp xzr, xzr, [x{{[0-9]+}}, #16]1565; CHECK-NEXT: ret1566entry:1567 store i64 0, ptr %p1568 %p1 = getelementptr i64, ptr %p, i64 11569 store i64 0, ptr %p11570 %p2 = getelementptr i64, ptr %p, i64 21571 store i64 0, ptr %p21572 %p3 = getelementptr i64, ptr %p, i64 31573 store i64 0, ptr %p31574 ret void1575}1576 1577; Like merge_zr64, but with 2-vector double type.1578define void @merge_zr64_2vecd(ptr %p) {1579; CHECK-LABEL: merge_zr64_2vecd:1580; CHECK: // %entry1581; CHECK-NEXT: stp xzr, xzr, [x{{[0-9]+}}]1582; CHECK-NEXT: ret1583entry:1584 store <2 x double> zeroinitializer, ptr %p1585 ret void1586}1587 1588; Like merge_zr64, but with 3-vector i64 type.1589define void @merge_zr64_3vec(ptr %p) {1590; CHECK-LABEL: merge_zr64_3vec:1591; CHECK: // %entry1592; CHECK-NEXT: stp xzr, xzr, [x{{[0-9]+}}, #8]1593; CHECK-NEXT: str xzr, [x{{[0-9]+}}]1594; CHECK-NEXT: ret1595entry:1596 store <3 x i64> zeroinitializer, ptr %p1597 ret void1598}1599 1600; Like merge_zr64_2, but with 4-vector double type.1601define void @merge_zr64_4vecd(ptr %p) {1602; CHECK-LABEL: merge_zr64_4vecd:1603; CHECK: // %entry1604; CHECK-NEXT: movi v[[REG:[0-9]]].2d, #00000000000000001605; CHECK-NEXT: stp q[[REG]], q[[REG]], [x{{[0-9]+}}]1606; CHECK-NEXT: ret1607entry:1608 store <4 x double> zeroinitializer, ptr %p1609 ret void1610}1611 1612; Verify that non-consecutive merges do not generate q01613define void @merge_multiple_128bit_stores(ptr %p) {1614; CHECK-LABEL: merge_multiple_128bit_stores1615; CHECK: // %entry1616; NOSTRICTALIGN-NEXT: movi v[[REG:[0-9]]].2d, #00000000000000001617; NOSTRICTALIGN-NEXT: str q0, [x0]1618; NOSTRICTALIGN-NEXT: stur q0, [x0, #24]1619; NOSTRICTALIGN-NEXT: str q0, [x0, #48]1620; STRICTALIGN-NEXT: stp xzr, xzr, [x0]1621; STRICTALIGN-NEXT: stp xzr, xzr, [x0, #24]1622; STRICTALIGN-NEXT: stp xzr, xzr, [x0, #48]1623; CHECK-NEXT: ret1624entry:1625 store i64 0, ptr %p1626 %p1 = getelementptr i64, ptr %p, i64 11627 store i64 0, ptr %p11628 %p3 = getelementptr i64, ptr %p, i64 31629 store i64 0, ptr %p31630 %p4 = getelementptr i64, ptr %p, i64 41631 store i64 0, ptr %p41632 %p6 = getelementptr i64, ptr %p, i64 61633 store i64 0, ptr %p61634 %p7 = getelementptr i64, ptr %p, i64 71635 store i64 0, ptr %p71636 ret void1637}1638 1639; Verify that large stores generate stp q1640define void @merge_multiple_128bit_stores_consec(ptr %p) {1641; CHECK-LABEL: merge_multiple_128bit_stores_consec1642; CHECK: // %entry1643; NOSTRICTALIGN-NEXT: movi v[[REG:[0-9]]].2d, #00000000000000001644; NOSTRICTALIGN-NEXT: stp q[[REG]], q[[REG]], [x{{[0-9]+}}]1645; NOSTRICTALIGN-NEXT: stp q[[REG]], q[[REG]], [x{{[0-9]+}}, #32]1646; STRICTALIGN-NEXT: stp xzr, xzr, [x0]1647; STRICTALIGN-NEXT: stp xzr, xzr, [x0, #16]1648; STRICTALIGN-NEXT: stp xzr, xzr, [x0, #32]1649; STRICTALIGN-NEXT: stp xzr, xzr, [x0, #48]1650; CHECK-NEXT: ret1651entry:1652 store i64 0, ptr %p1653 %p1 = getelementptr i64, ptr %p, i64 11654 store i64 0, ptr %p11655 %p2 = getelementptr i64, ptr %p, i64 21656 store i64 0, ptr %p21657 %p3 = getelementptr i64, ptr %p, i64 31658 store i64 0, ptr %p31659 %p4 = getelementptr i64, ptr %p, i64 41660 store i64 0, ptr %p41661 %p5 = getelementptr i64, ptr %p, i64 51662 store i64 0, ptr %p51663 %p6 = getelementptr i64, ptr %p, i64 61664 store i64 0, ptr %p61665 %p7 = getelementptr i64, ptr %p, i64 71666 store i64 0, ptr %p71667 ret void1668}1669 1670; Check for bug 34674 where invalid add of xzr was being generated.1671; CHECK-LABEL: bug34674:1672; CHECK: // %entry1673; CHECK-NEXT: mov [[ZREG:x[0-9]+]], xzr1674; CHECK-NEXT: mov x8, x01675; CHECK-NEXT: add x0, [[ZREG]], #11676; CHECK-NEXT: stp xzr, xzr, [x8]1677define i64 @bug34674(ptr %p) {1678entry:1679 store <2 x i64> zeroinitializer, ptr %p1680 %ld = load i64, ptr %p1681 %add = add i64 %ld, 11682 ret i64 %add1683}1684 1685; CHECK-LABEL: trunc_splat_zero:1686; CHECK-DAG: strh wzr, [x0]1687define void @trunc_splat_zero(ptr %ptr) {1688 store <2 x i8> zeroinitializer, ptr %ptr, align 21689 ret void1690}1691 1692; CHECK-LABEL: trunc_splat:1693; CHECK: mov [[VAL:w[0-9]+]], #421694; CHECK: movk [[VAL]], #42, lsl #161695; CHECK: str [[VAL]], [x0]1696define void @trunc_splat(ptr %ptr) {1697 store <2 x i16> <i16 42, i16 42>, ptr %ptr, align 41698 ret void1699}1700