1; RUN: llc -mtriple=aarch64-linux-gnu -aarch64-atomic-cfg-tidy=0 -verify-machineinstrs -o - %s | FileCheck %s 2 3; This file contains tests for the AArch64 load/store optimizer. 4 5%padding = type { i8*, i8*, i8*, i8* } 6%s.word = type { i32, i32 } 7%s.doubleword = type { i64, i32 } 8%s.quadword = type { fp128, i32 } 9%s.float = type { float, i32 } 10%s.double = type { double, i32 } 11%struct.word = type { %padding, %s.word } 12%struct.doubleword = type { %padding, %s.doubleword } 13%struct.quadword = type { %padding, %s.quadword } 14%struct.float = type { %padding, %s.float } 15%struct.double = type { %padding, %s.double } 16 17; Check the following transform: 18; 19; (ldr|str) X, [x0, #32] 20; ... 21; add x0, x0, #32 22; -> 23; (ldr|str) X, [x0, #32]! 24; 25; with X being either w1, x1, s0, d0 or q0. 26 27declare void @bar_word(%s.word*, i32) 28 29define void @load-pre-indexed-word(%struct.word* %ptr) nounwind { 30; CHECK-LABEL: load-pre-indexed-word 31; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #32]! 32entry: 33 %a = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1, i32 0 34 %add = load i32* %a, align 4 35 br label %bar 36bar: 37 %c = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1 38 tail call void @bar_word(%s.word* %c, i32 %add) 39 ret void 40} 41 42define void @store-pre-indexed-word(%struct.word* %ptr, i32 %val) nounwind { 43; CHECK-LABEL: store-pre-indexed-word 44; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #32]! 45entry: 46 %a = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1, i32 0 47 store i32 %val, i32* %a, align 4 48 br label %bar 49bar: 50 %c = getelementptr inbounds %struct.word* %ptr, i64 0, i32 1 51 tail call void @bar_word(%s.word* %c, i32 %val) 52 ret void 53} 54 55declare void @bar_doubleword(%s.doubleword*, i64) 56 57define void @load-pre-indexed-doubleword(%struct.doubleword* %ptr) nounwind { 58; CHECK-LABEL: load-pre-indexed-doubleword 59; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #32]! 60entry: 61 %a = getelementptr inbounds %struct.doubleword* %ptr, i64 0, i32 1, i32 0 62 %add = load i64* %a, align 4 63 br label %bar 64bar: 65 %c = getelementptr inbounds %struct.doubleword* %ptr, i64 0, i32 1 66 tail call void @bar_doubleword(%s.doubleword* %c, i64 %add) 67 ret void 68} 69 70define void @store-pre-indexed-doubleword(%struct.doubleword* %ptr, i64 %val) nounwind { 71; CHECK-LABEL: store-pre-indexed-doubleword 72; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #32]! 73entry: 74 %a = getelementptr inbounds %struct.doubleword* %ptr, i64 0, i32 1, i32 0 75 store i64 %val, i64* %a, align 4 76 br label %bar 77bar: 78 %c = getelementptr inbounds %struct.doubleword* %ptr, i64 0, i32 1 79 tail call void @bar_doubleword(%s.doubleword* %c, i64 %val) 80 ret void 81} 82 83declare void @bar_quadword(%s.quadword*, fp128) 84 85define void @load-pre-indexed-quadword(%struct.quadword* %ptr) nounwind { 86; CHECK-LABEL: load-pre-indexed-quadword 87; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]! 88entry: 89 %a = getelementptr inbounds %struct.quadword* %ptr, i64 0, i32 1, i32 0 90 %add = load fp128* %a, align 4 91 br label %bar 92bar: 93 %c = getelementptr inbounds %struct.quadword* %ptr, i64 0, i32 1 94 tail call void @bar_quadword(%s.quadword* %c, fp128 %add) 95 ret void 96} 97 98define void @store-pre-indexed-quadword(%struct.quadword* %ptr, fp128 %val) nounwind { 99; CHECK-LABEL: store-pre-indexed-quadword 100; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]! 101entry: 102 %a = getelementptr inbounds %struct.quadword* %ptr, i64 0, i32 1, i32 0 103 store fp128 %val, fp128* %a, align 4 104 br label %bar 105bar: 106 %c = getelementptr inbounds %struct.quadword* %ptr, i64 0, i32 1 107 tail call void @bar_quadword(%s.quadword* %c, fp128 %val) 108 ret void 109} 110 111declare void @bar_float(%s.float*, float) 112 113define void @load-pre-indexed-float(%struct.float* %ptr) nounwind { 114; CHECK-LABEL: load-pre-indexed-float 115; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #32]! 116entry: 117 %a = getelementptr inbounds %struct.float* %ptr, i64 0, i32 1, i32 0 118 %add = load float* %a, align 4 119 br label %bar 120bar: 121 %c = getelementptr inbounds %struct.float* %ptr, i64 0, i32 1 122 tail call void @bar_float(%s.float* %c, float %add) 123 ret void 124} 125 126define void @store-pre-indexed-float(%struct.float* %ptr, float %val) nounwind { 127; CHECK-LABEL: store-pre-indexed-float 128; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #32]! 129entry: 130 %a = getelementptr inbounds %struct.float* %ptr, i64 0, i32 1, i32 0 131 store float %val, float* %a, align 4 132 br label %bar 133bar: 134 %c = getelementptr inbounds %struct.float* %ptr, i64 0, i32 1 135 tail call void @bar_float(%s.float* %c, float %val) 136 ret void 137} 138 139declare void @bar_double(%s.double*, double) 140 141define void @load-pre-indexed-double(%struct.double* %ptr) nounwind { 142; CHECK-LABEL: load-pre-indexed-double 143; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #32]! 144entry: 145 %a = getelementptr inbounds %struct.double* %ptr, i64 0, i32 1, i32 0 146 %add = load double* %a, align 4 147 br label %bar 148bar: 149 %c = getelementptr inbounds %struct.double* %ptr, i64 0, i32 1 150 tail call void @bar_double(%s.double* %c, double %add) 151 ret void 152} 153 154define void @store-pre-indexed-double(%struct.double* %ptr, double %val) nounwind { 155; CHECK-LABEL: store-pre-indexed-double 156; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #32]! 157entry: 158 %a = getelementptr inbounds %struct.double* %ptr, i64 0, i32 1, i32 0 159 store double %val, double* %a, align 4 160 br label %bar 161bar: 162 %c = getelementptr inbounds %struct.double* %ptr, i64 0, i32 1 163 tail call void @bar_double(%s.double* %c, double %val) 164 ret void 165} 166 167; Check the following transform: 168; 169; add x8, x8, #16 170; ... 171; ldr X, [x8] 172; -> 173; ldr X, [x8, #16]! 174; 175; with X being either w0, x0, s0, d0 or q0. 176 177%pre.struct.i32 = type { i32, i32, i32} 178%pre.struct.i64 = type { i32, i64, i64} 179%pre.struct.i128 = type { i32, <2 x i64>, <2 x i64>} 180%pre.struct.float = type { i32, float, float} 181%pre.struct.double = type { i32, double, double} 182 183define i32 @load-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond, 184 %pre.struct.i32* %load2) nounwind { 185; CHECK-LABEL: load-pre-indexed-word2 186; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #4]! 187 br i1 %cond, label %if.then, label %if.end 188if.then: 189 %load1 = load %pre.struct.i32** %this 190 %gep1 = getelementptr inbounds %pre.struct.i32* %load1, i64 0, i32 1 191 br label %return 192if.end: 193 %gep2 = getelementptr inbounds %pre.struct.i32* %load2, i64 0, i32 2 194 br label %return 195return: 196 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 197 %ret = load i32* %retptr 198 ret i32 %ret 199} 200 201define i64 @load-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond, 202 %pre.struct.i64* %load2) nounwind { 203; CHECK-LABEL: load-pre-indexed-doubleword2 204; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #8]! 205 br i1 %cond, label %if.then, label %if.end 206if.then: 207 %load1 = load %pre.struct.i64** %this 208 %gep1 = getelementptr inbounds %pre.struct.i64* %load1, i64 0, i32 1 209 br label %return 210if.end: 211 %gep2 = getelementptr inbounds %pre.struct.i64* %load2, i64 0, i32 2 212 br label %return 213return: 214 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 215 %ret = load i64* %retptr 216 ret i64 %ret 217} 218 219define <2 x i64> @load-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond, 220 %pre.struct.i128* %load2) nounwind { 221; CHECK-LABEL: load-pre-indexed-quadword2 222; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #16]! 223 br i1 %cond, label %if.then, label %if.end 224if.then: 225 %load1 = load %pre.struct.i128** %this 226 %gep1 = getelementptr inbounds %pre.struct.i128* %load1, i64 0, i32 1 227 br label %return 228if.end: 229 %gep2 = getelementptr inbounds %pre.struct.i128* %load2, i64 0, i32 2 230 br label %return 231return: 232 %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ] 233 %ret = load <2 x i64>* %retptr 234 ret <2 x i64> %ret 235} 236 237define float @load-pre-indexed-float2(%pre.struct.float** %this, i1 %cond, 238 %pre.struct.float* %load2) nounwind { 239; CHECK-LABEL: load-pre-indexed-float2 240; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #4]! 241 br i1 %cond, label %if.then, label %if.end 242if.then: 243 %load1 = load %pre.struct.float** %this 244 %gep1 = getelementptr inbounds %pre.struct.float* %load1, i64 0, i32 1 245 br label %return 246if.end: 247 %gep2 = getelementptr inbounds %pre.struct.float* %load2, i64 0, i32 2 248 br label %return 249return: 250 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 251 %ret = load float* %retptr 252 ret float %ret 253} 254 255define double @load-pre-indexed-double2(%pre.struct.double** %this, i1 %cond, 256 %pre.struct.double* %load2) nounwind { 257; CHECK-LABEL: load-pre-indexed-double2 258; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #8]! 259 br i1 %cond, label %if.then, label %if.end 260if.then: 261 %load1 = load %pre.struct.double** %this 262 %gep1 = getelementptr inbounds %pre.struct.double* %load1, i64 0, i32 1 263 br label %return 264if.end: 265 %gep2 = getelementptr inbounds %pre.struct.double* %load2, i64 0, i32 2 266 br label %return 267return: 268 %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ] 269 %ret = load double* %retptr 270 ret double %ret 271} 272 273; Check the following transform: 274; 275; add x8, x8, #16 276; ... 277; str X, [x8] 278; -> 279; str X, [x8, #16]! 280; 281; with X being either w0, x0, s0, d0 or q0. 282 283define void @store-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond, 284 %pre.struct.i32* %load2, 285 i32 %val) nounwind { 286; CHECK-LABEL: store-pre-indexed-word2 287; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #4]! 288 br i1 %cond, label %if.then, label %if.end 289if.then: 290 %load1 = load %pre.struct.i32** %this 291 %gep1 = getelementptr inbounds %pre.struct.i32* %load1, i64 0, i32 1 292 br label %return 293if.end: 294 %gep2 = getelementptr inbounds %pre.struct.i32* %load2, i64 0, i32 2 295 br label %return 296return: 297 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 298 store i32 %val, i32* %retptr 299 ret void 300} 301 302define void @store-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond, 303 %pre.struct.i64* %load2, 304 i64 %val) nounwind { 305; CHECK-LABEL: store-pre-indexed-doubleword2 306; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #8]! 307 br i1 %cond, label %if.then, label %if.end 308if.then: 309 %load1 = load %pre.struct.i64** %this 310 %gep1 = getelementptr inbounds %pre.struct.i64* %load1, i64 0, i32 1 311 br label %return 312if.end: 313 %gep2 = getelementptr inbounds %pre.struct.i64* %load2, i64 0, i32 2 314 br label %return 315return: 316 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 317 store i64 %val, i64* %retptr 318 ret void 319} 320 321define void @store-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond, 322 %pre.struct.i128* %load2, 323 <2 x i64> %val) nounwind { 324; CHECK-LABEL: store-pre-indexed-quadword2 325; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #16]! 326 br i1 %cond, label %if.then, label %if.end 327if.then: 328 %load1 = load %pre.struct.i128** %this 329 %gep1 = getelementptr inbounds %pre.struct.i128* %load1, i64 0, i32 1 330 br label %return 331if.end: 332 %gep2 = getelementptr inbounds %pre.struct.i128* %load2, i64 0, i32 2 333 br label %return 334return: 335 %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ] 336 store <2 x i64> %val, <2 x i64>* %retptr 337 ret void 338} 339 340define void @store-pre-indexed-float2(%pre.struct.float** %this, i1 %cond, 341 %pre.struct.float* %load2, 342 float %val) nounwind { 343; CHECK-LABEL: store-pre-indexed-float2 344; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #4]! 345 br i1 %cond, label %if.then, label %if.end 346if.then: 347 %load1 = load %pre.struct.float** %this 348 %gep1 = getelementptr inbounds %pre.struct.float* %load1, i64 0, i32 1 349 br label %return 350if.end: 351 %gep2 = getelementptr inbounds %pre.struct.float* %load2, i64 0, i32 2 352 br label %return 353return: 354 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 355 store float %val, float* %retptr 356 ret void 357} 358 359define void @store-pre-indexed-double2(%pre.struct.double** %this, i1 %cond, 360 %pre.struct.double* %load2, 361 double %val) nounwind { 362; CHECK-LABEL: store-pre-indexed-double2 363; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #8]! 364 br i1 %cond, label %if.then, label %if.end 365if.then: 366 %load1 = load %pre.struct.double** %this 367 %gep1 = getelementptr inbounds %pre.struct.double* %load1, i64 0, i32 1 368 br label %return 369if.end: 370 %gep2 = getelementptr inbounds %pre.struct.double* %load2, i64 0, i32 2 371 br label %return 372return: 373 %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ] 374 store double %val, double* %retptr 375 ret void 376} 377 378; Check the following transform: 379; 380; ldr X, [x20] 381; ... 382; add x20, x20, #32 383; -> 384; ldr X, [x20], #32 385; 386; with X being either w0, x0, s0, d0 or q0. 387 388define void @load-post-indexed-word(i32* %array, i64 %count) nounwind { 389; CHECK-LABEL: load-post-indexed-word 390; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #16 391entry: 392 %gep1 = getelementptr i32* %array, i64 2 393 br label %body 394 395body: 396 %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ] 397 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 398 %gep2 = getelementptr i32* %iv2, i64 -1 399 %load = load i32* %gep2 400 call void @use-word(i32 %load) 401 %load2 = load i32* %iv2 402 call void @use-word(i32 %load2) 403 %iv.next = add i64 %iv, -4 404 %gep3 = getelementptr i32* %iv2, i64 4 405 %cond = icmp eq i64 %iv.next, 0 406 br i1 %cond, label %exit, label %body 407 408exit: 409 ret void 410} 411 412define void @load-post-indexed-doubleword(i64* %array, i64 %count) nounwind { 413; CHECK-LABEL: load-post-indexed-doubleword 414; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #32 415entry: 416 %gep1 = getelementptr i64* %array, i64 2 417 br label %body 418 419body: 420 %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ] 421 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 422 %gep2 = getelementptr i64* %iv2, i64 -1 423 %load = load i64* %gep2 424 call void @use-doubleword(i64 %load) 425 %load2 = load i64* %iv2 426 call void @use-doubleword(i64 %load2) 427 %iv.next = add i64 %iv, -4 428 %gep3 = getelementptr i64* %iv2, i64 4 429 %cond = icmp eq i64 %iv.next, 0 430 br i1 %cond, label %exit, label %body 431 432exit: 433 ret void 434} 435 436define void @load-post-indexed-quadword(<2 x i64>* %array, i64 %count) nounwind { 437; CHECK-LABEL: load-post-indexed-quadword 438; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #64 439entry: 440 %gep1 = getelementptr <2 x i64>* %array, i64 2 441 br label %body 442 443body: 444 %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ] 445 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 446 %gep2 = getelementptr <2 x i64>* %iv2, i64 -1 447 %load = load <2 x i64>* %gep2 448 call void @use-quadword(<2 x i64> %load) 449 %load2 = load <2 x i64>* %iv2 450 call void @use-quadword(<2 x i64> %load2) 451 %iv.next = add i64 %iv, -4 452 %gep3 = getelementptr <2 x i64>* %iv2, i64 4 453 %cond = icmp eq i64 %iv.next, 0 454 br i1 %cond, label %exit, label %body 455 456exit: 457 ret void 458} 459 460define void @load-post-indexed-float(float* %array, i64 %count) nounwind { 461; CHECK-LABEL: load-post-indexed-float 462; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #16 463entry: 464 %gep1 = getelementptr float* %array, i64 2 465 br label %body 466 467body: 468 %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ] 469 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 470 %gep2 = getelementptr float* %iv2, i64 -1 471 %load = load float* %gep2 472 call void @use-float(float %load) 473 %load2 = load float* %iv2 474 call void @use-float(float %load2) 475 %iv.next = add i64 %iv, -4 476 %gep3 = getelementptr float* %iv2, i64 4 477 %cond = icmp eq i64 %iv.next, 0 478 br i1 %cond, label %exit, label %body 479 480exit: 481 ret void 482} 483 484define void @load-post-indexed-double(double* %array, i64 %count) nounwind { 485; CHECK-LABEL: load-post-indexed-double 486; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #32 487entry: 488 %gep1 = getelementptr double* %array, i64 2 489 br label %body 490 491body: 492 %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ] 493 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 494 %gep2 = getelementptr double* %iv2, i64 -1 495 %load = load double* %gep2 496 call void @use-double(double %load) 497 %load2 = load double* %iv2 498 call void @use-double(double %load2) 499 %iv.next = add i64 %iv, -4 500 %gep3 = getelementptr double* %iv2, i64 4 501 %cond = icmp eq i64 %iv.next, 0 502 br i1 %cond, label %exit, label %body 503 504exit: 505 ret void 506} 507 508; Check the following transform: 509; 510; str X, [x20] 511; ... 512; add x20, x20, #32 513; -> 514; str X, [x20], #32 515; 516; with X being either w0, x0, s0, d0 or q0. 517 518define void @store-post-indexed-word(i32* %array, i64 %count, i32 %val) nounwind { 519; CHECK-LABEL: store-post-indexed-word 520; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #16 521entry: 522 %gep1 = getelementptr i32* %array, i64 2 523 br label %body 524 525body: 526 %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ] 527 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 528 %gep2 = getelementptr i32* %iv2, i64 -1 529 %load = load i32* %gep2 530 call void @use-word(i32 %load) 531 store i32 %val, i32* %iv2 532 %iv.next = add i64 %iv, -4 533 %gep3 = getelementptr i32* %iv2, i64 4 534 %cond = icmp eq i64 %iv.next, 0 535 br i1 %cond, label %exit, label %body 536 537exit: 538 ret void 539} 540 541define void @store-post-indexed-doubleword(i64* %array, i64 %count, i64 %val) nounwind { 542; CHECK-LABEL: store-post-indexed-doubleword 543; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #32 544entry: 545 %gep1 = getelementptr i64* %array, i64 2 546 br label %body 547 548body: 549 %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ] 550 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 551 %gep2 = getelementptr i64* %iv2, i64 -1 552 %load = load i64* %gep2 553 call void @use-doubleword(i64 %load) 554 store i64 %val, i64* %iv2 555 %iv.next = add i64 %iv, -4 556 %gep3 = getelementptr i64* %iv2, i64 4 557 %cond = icmp eq i64 %iv.next, 0 558 br i1 %cond, label %exit, label %body 559 560exit: 561 ret void 562} 563 564define void @store-post-indexed-quadword(<2 x i64>* %array, i64 %count, <2 x i64> %val) nounwind { 565; CHECK-LABEL: store-post-indexed-quadword 566; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #64 567entry: 568 %gep1 = getelementptr <2 x i64>* %array, i64 2 569 br label %body 570 571body: 572 %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ] 573 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 574 %gep2 = getelementptr <2 x i64>* %iv2, i64 -1 575 %load = load <2 x i64>* %gep2 576 call void @use-quadword(<2 x i64> %load) 577 store <2 x i64> %val, <2 x i64>* %iv2 578 %iv.next = add i64 %iv, -4 579 %gep3 = getelementptr <2 x i64>* %iv2, i64 4 580 %cond = icmp eq i64 %iv.next, 0 581 br i1 %cond, label %exit, label %body 582 583exit: 584 ret void 585} 586 587define void @store-post-indexed-float(float* %array, i64 %count, float %val) nounwind { 588; CHECK-LABEL: store-post-indexed-float 589; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #16 590entry: 591 %gep1 = getelementptr float* %array, i64 2 592 br label %body 593 594body: 595 %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ] 596 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 597 %gep2 = getelementptr float* %iv2, i64 -1 598 %load = load float* %gep2 599 call void @use-float(float %load) 600 store float %val, float* %iv2 601 %iv.next = add i64 %iv, -4 602 %gep3 = getelementptr float* %iv2, i64 4 603 %cond = icmp eq i64 %iv.next, 0 604 br i1 %cond, label %exit, label %body 605 606exit: 607 ret void 608} 609 610define void @store-post-indexed-double(double* %array, i64 %count, double %val) nounwind { 611; CHECK-LABEL: store-post-indexed-double 612; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #32 613entry: 614 %gep1 = getelementptr double* %array, i64 2 615 br label %body 616 617body: 618 %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ] 619 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 620 %gep2 = getelementptr double* %iv2, i64 -1 621 %load = load double* %gep2 622 call void @use-double(double %load) 623 store double %val, double* %iv2 624 %iv.next = add i64 %iv, -4 625 %gep3 = getelementptr double* %iv2, i64 4 626 %cond = icmp eq i64 %iv.next, 0 627 br i1 %cond, label %exit, label %body 628 629exit: 630 ret void 631} 632 633declare void @use-word(i32) 634declare void @use-doubleword(i64) 635declare void @use-quadword(<2 x i64>) 636declare void @use-float(float) 637declare void @use-double(double) 638 639; Check the following transform: 640; 641; (ldr|str) X, [x20] 642; ... 643; sub x20, x20, #16 644; -> 645; (ldr|str) X, [x20], #-16 646; 647; with X being either w0, x0, s0, d0 or q0. 648 649define void @post-indexed-sub-word(i32* %a, i32* %b, i64 %count) nounwind { 650; CHECK-LABEL: post-indexed-sub-word 651; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #-8 652; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #-8 653 br label %for.body 654for.body: 655 %phi1 = phi i32* [ %gep4, %for.body ], [ %b, %0 ] 656 %phi2 = phi i32* [ %gep3, %for.body ], [ %a, %0 ] 657 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 658 %gep1 = getelementptr i32* %phi1, i64 -1 659 %load1 = load i32* %gep1 660 %gep2 = getelementptr i32* %phi2, i64 -1 661 store i32 %load1, i32* %gep2 662 %load2 = load i32* %phi1 663 store i32 %load2, i32* %phi2 664 %dec.i = add nsw i64 %i, -1 665 %gep3 = getelementptr i32* %phi2, i64 -2 666 %gep4 = getelementptr i32* %phi1, i64 -2 667 %cond = icmp sgt i64 %dec.i, 0 668 br i1 %cond, label %for.body, label %end 669end: 670 ret void 671} 672 673define void @post-indexed-sub-doubleword(i64* %a, i64* %b, i64 %count) nounwind { 674; CHECK-LABEL: post-indexed-sub-doubleword 675; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #-16 676; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #-16 677 br label %for.body 678for.body: 679 %phi1 = phi i64* [ %gep4, %for.body ], [ %b, %0 ] 680 %phi2 = phi i64* [ %gep3, %for.body ], [ %a, %0 ] 681 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 682 %gep1 = getelementptr i64* %phi1, i64 -1 683 %load1 = load i64* %gep1 684 %gep2 = getelementptr i64* %phi2, i64 -1 685 store i64 %load1, i64* %gep2 686 %load2 = load i64* %phi1 687 store i64 %load2, i64* %phi2 688 %dec.i = add nsw i64 %i, -1 689 %gep3 = getelementptr i64* %phi2, i64 -2 690 %gep4 = getelementptr i64* %phi1, i64 -2 691 %cond = icmp sgt i64 %dec.i, 0 692 br i1 %cond, label %for.body, label %end 693end: 694 ret void 695} 696 697define void @post-indexed-sub-quadword(<2 x i64>* %a, <2 x i64>* %b, i64 %count) nounwind { 698; CHECK-LABEL: post-indexed-sub-quadword 699; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #-32 700; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #-32 701 br label %for.body 702for.body: 703 %phi1 = phi <2 x i64>* [ %gep4, %for.body ], [ %b, %0 ] 704 %phi2 = phi <2 x i64>* [ %gep3, %for.body ], [ %a, %0 ] 705 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 706 %gep1 = getelementptr <2 x i64>* %phi1, i64 -1 707 %load1 = load <2 x i64>* %gep1 708 %gep2 = getelementptr <2 x i64>* %phi2, i64 -1 709 store <2 x i64> %load1, <2 x i64>* %gep2 710 %load2 = load <2 x i64>* %phi1 711 store <2 x i64> %load2, <2 x i64>* %phi2 712 %dec.i = add nsw i64 %i, -1 713 %gep3 = getelementptr <2 x i64>* %phi2, i64 -2 714 %gep4 = getelementptr <2 x i64>* %phi1, i64 -2 715 %cond = icmp sgt i64 %dec.i, 0 716 br i1 %cond, label %for.body, label %end 717end: 718 ret void 719} 720 721define void @post-indexed-sub-float(float* %a, float* %b, i64 %count) nounwind { 722; CHECK-LABEL: post-indexed-sub-float 723; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #-8 724; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #-8 725 br label %for.body 726for.body: 727 %phi1 = phi float* [ %gep4, %for.body ], [ %b, %0 ] 728 %phi2 = phi float* [ %gep3, %for.body ], [ %a, %0 ] 729 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 730 %gep1 = getelementptr float* %phi1, i64 -1 731 %load1 = load float* %gep1 732 %gep2 = getelementptr float* %phi2, i64 -1 733 store float %load1, float* %gep2 734 %load2 = load float* %phi1 735 store float %load2, float* %phi2 736 %dec.i = add nsw i64 %i, -1 737 %gep3 = getelementptr float* %phi2, i64 -2 738 %gep4 = getelementptr float* %phi1, i64 -2 739 %cond = icmp sgt i64 %dec.i, 0 740 br i1 %cond, label %for.body, label %end 741end: 742 ret void 743} 744 745define void @post-indexed-sub-double(double* %a, double* %b, i64 %count) nounwind { 746; CHECK-LABEL: post-indexed-sub-double 747; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #-16 748; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #-16 749 br label %for.body 750for.body: 751 %phi1 = phi double* [ %gep4, %for.body ], [ %b, %0 ] 752 %phi2 = phi double* [ %gep3, %for.body ], [ %a, %0 ] 753 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 754 %gep1 = getelementptr double* %phi1, i64 -1 755 %load1 = load double* %gep1 756 %gep2 = getelementptr double* %phi2, i64 -1 757 store double %load1, double* %gep2 758 %load2 = load double* %phi1 759 store double %load2, double* %phi2 760 %dec.i = add nsw i64 %i, -1 761 %gep3 = getelementptr double* %phi2, i64 -2 762 %gep4 = getelementptr double* %phi1, i64 -2 763 %cond = icmp sgt i64 %dec.i, 0 764 br i1 %cond, label %for.body, label %end 765end: 766 ret void 767} 768