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.byte = type { i8, i8 } 7%s.halfword = type { i16, i16 } 8%s.word = type { i32, i32 } 9%s.doubleword = type { i64, i32 } 10%s.quadword = type { fp128, i32 } 11%s.float = type { float, i32 } 12%s.double = type { double, i32 } 13%struct.byte = type { %padding, %s.byte } 14%struct.halfword = type { %padding, %s.halfword } 15%struct.word = type { %padding, %s.word } 16%struct.doubleword = type { %padding, %s.doubleword } 17%struct.quadword = type { %padding, %s.quadword } 18%struct.float = type { %padding, %s.float } 19%struct.double = type { %padding, %s.double } 20 21; Check the following transform: 22; 23; (ldr|str) X, [x0, #32] 24; ... 25; add x0, x0, #32 26; -> 27; (ldr|str) X, [x0, #32]! 28; 29; with X being either w1, x1, s0, d0 or q0. 30 31declare void @bar_byte(%s.byte*, i8) 32 33define void @load-pre-indexed-byte(%struct.byte* %ptr) nounwind { 34; CHECK-LABEL: load-pre-indexed-byte 35; CHECK: ldrb w{{[0-9]+}}, [x{{[0-9]+}}, #32]! 36entry: 37 %a = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1, i32 0 38 %add = load i8, i8* %a, align 4 39 br label %bar 40bar: 41 %c = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1 42 tail call void @bar_byte(%s.byte* %c, i8 %add) 43 ret void 44} 45 46define void @store-pre-indexed-byte(%struct.byte* %ptr, i8 %val) nounwind { 47; CHECK-LABEL: store-pre-indexed-byte 48; CHECK: strb w{{[0-9]+}}, [x{{[0-9]+}}, #32]! 49entry: 50 %a = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1, i32 0 51 store i8 %val, i8* %a, align 4 52 br label %bar 53bar: 54 %c = getelementptr inbounds %struct.byte, %struct.byte* %ptr, i64 0, i32 1 55 tail call void @bar_byte(%s.byte* %c, i8 %val) 56 ret void 57} 58 59declare void @bar_halfword(%s.halfword*, i16) 60 61define void @load-pre-indexed-halfword(%struct.halfword* %ptr) nounwind { 62; CHECK-LABEL: load-pre-indexed-halfword 63; CHECK: ldrh w{{[0-9]+}}, [x{{[0-9]+}}, #32]! 64entry: 65 %a = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1, i32 0 66 %add = load i16, i16* %a, align 4 67 br label %bar 68bar: 69 %c = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1 70 tail call void @bar_halfword(%s.halfword* %c, i16 %add) 71 ret void 72} 73 74define void @store-pre-indexed-halfword(%struct.halfword* %ptr, i16 %val) nounwind { 75; CHECK-LABEL: store-pre-indexed-halfword 76; CHECK: strh w{{[0-9]+}}, [x{{[0-9]+}}, #32]! 77entry: 78 %a = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1, i32 0 79 store i16 %val, i16* %a, align 4 80 br label %bar 81bar: 82 %c = getelementptr inbounds %struct.halfword, %struct.halfword* %ptr, i64 0, i32 1 83 tail call void @bar_halfword(%s.halfword* %c, i16 %val) 84 ret void 85} 86 87declare void @bar_word(%s.word*, i32) 88 89define void @load-pre-indexed-word(%struct.word* %ptr) nounwind { 90; CHECK-LABEL: load-pre-indexed-word 91; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #32]! 92entry: 93 %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0 94 %add = load i32, i32* %a, align 4 95 br label %bar 96bar: 97 %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1 98 tail call void @bar_word(%s.word* %c, i32 %add) 99 ret void 100} 101 102define void @store-pre-indexed-word(%struct.word* %ptr, i32 %val) nounwind { 103; CHECK-LABEL: store-pre-indexed-word 104; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #32]! 105entry: 106 %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0 107 store i32 %val, i32* %a, align 4 108 br label %bar 109bar: 110 %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1 111 tail call void @bar_word(%s.word* %c, i32 %val) 112 ret void 113} 114 115declare void @bar_doubleword(%s.doubleword*, i64) 116 117define void @load-pre-indexed-doubleword(%struct.doubleword* %ptr) nounwind { 118; CHECK-LABEL: load-pre-indexed-doubleword 119; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #32]! 120entry: 121 %a = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1, i32 0 122 %add = load i64, i64* %a, align 4 123 br label %bar 124bar: 125 %c = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1 126 tail call void @bar_doubleword(%s.doubleword* %c, i64 %add) 127 ret void 128} 129 130define void @store-pre-indexed-doubleword(%struct.doubleword* %ptr, i64 %val) nounwind { 131; CHECK-LABEL: store-pre-indexed-doubleword 132; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #32]! 133entry: 134 %a = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1, i32 0 135 store i64 %val, i64* %a, align 4 136 br label %bar 137bar: 138 %c = getelementptr inbounds %struct.doubleword, %struct.doubleword* %ptr, i64 0, i32 1 139 tail call void @bar_doubleword(%s.doubleword* %c, i64 %val) 140 ret void 141} 142 143declare void @bar_quadword(%s.quadword*, fp128) 144 145define void @load-pre-indexed-quadword(%struct.quadword* %ptr) nounwind { 146; CHECK-LABEL: load-pre-indexed-quadword 147; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]! 148entry: 149 %a = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1, i32 0 150 %add = load fp128, fp128* %a, align 4 151 br label %bar 152bar: 153 %c = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1 154 tail call void @bar_quadword(%s.quadword* %c, fp128 %add) 155 ret void 156} 157 158define void @store-pre-indexed-quadword(%struct.quadword* %ptr, fp128 %val) nounwind { 159; CHECK-LABEL: store-pre-indexed-quadword 160; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]! 161entry: 162 %a = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1, i32 0 163 store fp128 %val, fp128* %a, align 4 164 br label %bar 165bar: 166 %c = getelementptr inbounds %struct.quadword, %struct.quadword* %ptr, i64 0, i32 1 167 tail call void @bar_quadword(%s.quadword* %c, fp128 %val) 168 ret void 169} 170 171declare void @bar_float(%s.float*, float) 172 173define void @load-pre-indexed-float(%struct.float* %ptr) nounwind { 174; CHECK-LABEL: load-pre-indexed-float 175; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #32]! 176entry: 177 %a = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1, i32 0 178 %add = load float, float* %a, align 4 179 br label %bar 180bar: 181 %c = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1 182 tail call void @bar_float(%s.float* %c, float %add) 183 ret void 184} 185 186define void @store-pre-indexed-float(%struct.float* %ptr, float %val) nounwind { 187; CHECK-LABEL: store-pre-indexed-float 188; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #32]! 189entry: 190 %a = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1, i32 0 191 store float %val, float* %a, align 4 192 br label %bar 193bar: 194 %c = getelementptr inbounds %struct.float, %struct.float* %ptr, i64 0, i32 1 195 tail call void @bar_float(%s.float* %c, float %val) 196 ret void 197} 198 199declare void @bar_double(%s.double*, double) 200 201define void @load-pre-indexed-double(%struct.double* %ptr) nounwind { 202; CHECK-LABEL: load-pre-indexed-double 203; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #32]! 204entry: 205 %a = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1, i32 0 206 %add = load double, double* %a, align 4 207 br label %bar 208bar: 209 %c = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1 210 tail call void @bar_double(%s.double* %c, double %add) 211 ret void 212} 213 214define void @store-pre-indexed-double(%struct.double* %ptr, double %val) nounwind { 215; CHECK-LABEL: store-pre-indexed-double 216; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #32]! 217entry: 218 %a = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1, i32 0 219 store double %val, double* %a, align 4 220 br label %bar 221bar: 222 %c = getelementptr inbounds %struct.double, %struct.double* %ptr, i64 0, i32 1 223 tail call void @bar_double(%s.double* %c, double %val) 224 ret void 225} 226 227; Check the following transform: 228; 229; (ldp|stp) w1, w2 [x0, #32] 230; ... 231; add x0, x0, #32 232; -> 233; (ldp|stp) w1, w2, [x0, #32]! 234; 235 236define void @load-pair-pre-indexed-word(%struct.word* %ptr) nounwind { 237; CHECK-LABEL: load-pair-pre-indexed-word 238; CHECK: ldp w{{[0-9]+}}, w{{[0-9]+}}, [x0, #32]! 239; CHECK-NOT: add x0, x0, #32 240entry: 241 %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0 242 %a1 = load i32, i32* %a, align 4 243 %b = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 1 244 %b1 = load i32, i32* %b, align 4 245 %add = add i32 %a1, %b1 246 br label %bar 247bar: 248 %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1 249 tail call void @bar_word(%s.word* %c, i32 %add) 250 ret void 251} 252 253define void @store-pair-pre-indexed-word(%struct.word* %ptr, i32 %val) nounwind { 254; CHECK-LABEL: store-pair-pre-indexed-word 255; CHECK: stp w{{[0-9]+}}, w{{[0-9]+}}, [x0, #32]! 256; CHECK-NOT: add x0, x0, #32 257entry: 258 %a = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 0 259 store i32 %val, i32* %a, align 4 260 %b = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1, i32 1 261 store i32 %val, i32* %b, align 4 262 br label %bar 263bar: 264 %c = getelementptr inbounds %struct.word, %struct.word* %ptr, i64 0, i32 1 265 tail call void @bar_word(%s.word* %c, i32 %val) 266 ret void 267} 268 269; Check the following transform: 270; 271; add x8, x8, #16 272; ... 273; ldr X, [x8] 274; -> 275; ldr X, [x8, #16]! 276; 277; with X being either w0, x0, s0, d0 or q0. 278 279%pre.struct.i32 = type { i32, i32, i32, i32, i32} 280%pre.struct.i64 = type { i32, i64, i64, i64, i64} 281%pre.struct.i128 = type { i32, <2 x i64>, <2 x i64>, <2 x i64>} 282%pre.struct.float = type { i32, float, float, float} 283%pre.struct.double = type { i32, double, double, double} 284 285define i32 @load-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond, 286 %pre.struct.i32* %load2) nounwind { 287; CHECK-LABEL: load-pre-indexed-word2 288; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #4]! 289 br i1 %cond, label %if.then, label %if.end 290if.then: 291 %load1 = load %pre.struct.i32*, %pre.struct.i32** %this 292 %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 1 293 br label %return 294if.end: 295 %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2 296 br label %return 297return: 298 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 299 %ret = load i32, i32* %retptr 300 ret i32 %ret 301} 302 303define i64 @load-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond, 304 %pre.struct.i64* %load2) nounwind { 305; CHECK-LABEL: load-pre-indexed-doubleword2 306; CHECK: ldr 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*, %pre.struct.i64** %this 310 %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 1 311 br label %return 312if.end: 313 %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2 314 br label %return 315return: 316 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 317 %ret = load i64, i64* %retptr 318 ret i64 %ret 319} 320 321define <2 x i64> @load-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond, 322 %pre.struct.i128* %load2) nounwind { 323; CHECK-LABEL: load-pre-indexed-quadword2 324; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #16]! 325 br i1 %cond, label %if.then, label %if.end 326if.then: 327 %load1 = load %pre.struct.i128*, %pre.struct.i128** %this 328 %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 1 329 br label %return 330if.end: 331 %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2 332 br label %return 333return: 334 %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ] 335 %ret = load <2 x i64>, <2 x i64>* %retptr 336 ret <2 x i64> %ret 337} 338 339define float @load-pre-indexed-float2(%pre.struct.float** %this, i1 %cond, 340 %pre.struct.float* %load2) nounwind { 341; CHECK-LABEL: load-pre-indexed-float2 342; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #4]! 343 br i1 %cond, label %if.then, label %if.end 344if.then: 345 %load1 = load %pre.struct.float*, %pre.struct.float** %this 346 %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 1 347 br label %return 348if.end: 349 %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2 350 br label %return 351return: 352 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 353 %ret = load float, float* %retptr 354 ret float %ret 355} 356 357define double @load-pre-indexed-double2(%pre.struct.double** %this, i1 %cond, 358 %pre.struct.double* %load2) nounwind { 359; CHECK-LABEL: load-pre-indexed-double2 360; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #8]! 361 br i1 %cond, label %if.then, label %if.end 362if.then: 363 %load1 = load %pre.struct.double*, %pre.struct.double** %this 364 %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 1 365 br label %return 366if.end: 367 %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2 368 br label %return 369return: 370 %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ] 371 %ret = load double, double* %retptr 372 ret double %ret 373} 374 375define i32 @load-pre-indexed-word3(%pre.struct.i32** %this, i1 %cond, 376 %pre.struct.i32* %load2) nounwind { 377; CHECK-LABEL: load-pre-indexed-word3 378; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}, #12]! 379 br i1 %cond, label %if.then, label %if.end 380if.then: 381 %load1 = load %pre.struct.i32*, %pre.struct.i32** %this 382 %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 3 383 br label %return 384if.end: 385 %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4 386 br label %return 387return: 388 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 389 %ret = load i32, i32* %retptr 390 ret i32 %ret 391} 392 393define i64 @load-pre-indexed-doubleword3(%pre.struct.i64** %this, i1 %cond, 394 %pre.struct.i64* %load2) nounwind { 395; CHECK-LABEL: load-pre-indexed-doubleword3 396; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}, #16]! 397 br i1 %cond, label %if.then, label %if.end 398if.then: 399 %load1 = load %pre.struct.i64*, %pre.struct.i64** %this 400 %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 2 401 br label %return 402if.end: 403 %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 3 404 br label %return 405return: 406 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 407 %ret = load i64, i64* %retptr 408 ret i64 %ret 409} 410 411define <2 x i64> @load-pre-indexed-quadword3(%pre.struct.i128** %this, i1 %cond, 412 %pre.struct.i128* %load2) nounwind { 413; CHECK-LABEL: load-pre-indexed-quadword3 414; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}, #32]! 415 br i1 %cond, label %if.then, label %if.end 416if.then: 417 %load1 = load %pre.struct.i128*, %pre.struct.i128** %this 418 %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 2 419 br label %return 420if.end: 421 %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3 422 br label %return 423return: 424 %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ] 425 %ret = load <2 x i64>, <2 x i64>* %retptr 426 ret <2 x i64> %ret 427} 428 429define float @load-pre-indexed-float3(%pre.struct.float** %this, i1 %cond, 430 %pre.struct.float* %load2) nounwind { 431; CHECK-LABEL: load-pre-indexed-float3 432; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}, #8]! 433 br i1 %cond, label %if.then, label %if.end 434if.then: 435 %load1 = load %pre.struct.float*, %pre.struct.float** %this 436 %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 2 437 br label %return 438if.end: 439 %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3 440 br label %return 441return: 442 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 443 %ret = load float, float* %retptr 444 ret float %ret 445} 446 447define double @load-pre-indexed-double3(%pre.struct.double** %this, i1 %cond, 448 %pre.struct.double* %load2) nounwind { 449; CHECK-LABEL: load-pre-indexed-double3 450; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}, #16]! 451 br i1 %cond, label %if.then, label %if.end 452if.then: 453 %load1 = load %pre.struct.double*, %pre.struct.double** %this 454 %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 2 455 br label %return 456if.end: 457 %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3 458 br label %return 459return: 460 %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ] 461 %ret = load double, double* %retptr 462 ret double %ret 463} 464 465; Check the following transform: 466; 467; add x8, x8, #16 468; ... 469; str X, [x8] 470; -> 471; str X, [x8, #16]! 472; 473; with X being either w0, x0, s0, d0 or q0. 474 475define void @store-pre-indexed-word2(%pre.struct.i32** %this, i1 %cond, 476 %pre.struct.i32* %load2, 477 i32 %val) nounwind { 478; CHECK-LABEL: store-pre-indexed-word2 479; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #4]! 480 br i1 %cond, label %if.then, label %if.end 481if.then: 482 %load1 = load %pre.struct.i32*, %pre.struct.i32** %this 483 %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 1 484 br label %return 485if.end: 486 %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2 487 br label %return 488return: 489 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 490 store i32 %val, i32* %retptr 491 ret void 492} 493 494define void @store-pre-indexed-doubleword2(%pre.struct.i64** %this, i1 %cond, 495 %pre.struct.i64* %load2, 496 i64 %val) nounwind { 497; CHECK-LABEL: store-pre-indexed-doubleword2 498; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #8]! 499 br i1 %cond, label %if.then, label %if.end 500if.then: 501 %load1 = load %pre.struct.i64*, %pre.struct.i64** %this 502 %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 1 503 br label %return 504if.end: 505 %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2 506 br label %return 507return: 508 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 509 store i64 %val, i64* %retptr 510 ret void 511} 512 513define void @store-pre-indexed-quadword2(%pre.struct.i128** %this, i1 %cond, 514 %pre.struct.i128* %load2, 515 <2 x i64> %val) nounwind { 516; CHECK-LABEL: store-pre-indexed-quadword2 517; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #16]! 518 br i1 %cond, label %if.then, label %if.end 519if.then: 520 %load1 = load %pre.struct.i128*, %pre.struct.i128** %this 521 %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 1 522 br label %return 523if.end: 524 %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2 525 br label %return 526return: 527 %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ] 528 store <2 x i64> %val, <2 x i64>* %retptr 529 ret void 530} 531 532define void @store-pre-indexed-float2(%pre.struct.float** %this, i1 %cond, 533 %pre.struct.float* %load2, 534 float %val) nounwind { 535; CHECK-LABEL: store-pre-indexed-float2 536; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #4]! 537 br i1 %cond, label %if.then, label %if.end 538if.then: 539 %load1 = load %pre.struct.float*, %pre.struct.float** %this 540 %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 1 541 br label %return 542if.end: 543 %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2 544 br label %return 545return: 546 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 547 store float %val, float* %retptr 548 ret void 549} 550 551define void @store-pre-indexed-double2(%pre.struct.double** %this, i1 %cond, 552 %pre.struct.double* %load2, 553 double %val) nounwind { 554; CHECK-LABEL: store-pre-indexed-double2 555; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #8]! 556 br i1 %cond, label %if.then, label %if.end 557if.then: 558 %load1 = load %pre.struct.double*, %pre.struct.double** %this 559 %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 1 560 br label %return 561if.end: 562 %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2 563 br label %return 564return: 565 %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ] 566 store double %val, double* %retptr 567 ret void 568} 569 570define void @store-pre-indexed-word3(%pre.struct.i32** %this, i1 %cond, 571 %pre.struct.i32* %load2, 572 i32 %val) nounwind { 573; CHECK-LABEL: store-pre-indexed-word3 574; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}, #12]! 575 br i1 %cond, label %if.then, label %if.end 576if.then: 577 %load1 = load %pre.struct.i32*, %pre.struct.i32** %this 578 %gep1 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load1, i64 0, i32 3 579 br label %return 580if.end: 581 %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4 582 br label %return 583return: 584 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 585 store i32 %val, i32* %retptr 586 ret void 587} 588 589define void @store-pre-indexed-doubleword3(%pre.struct.i64** %this, i1 %cond, 590 %pre.struct.i64* %load2, 591 i64 %val) nounwind { 592; CHECK-LABEL: store-pre-indexed-doubleword3 593; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}, #24]! 594 br i1 %cond, label %if.then, label %if.end 595if.then: 596 %load1 = load %pre.struct.i64*, %pre.struct.i64** %this 597 %gep1 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load1, i64 0, i32 3 598 br label %return 599if.end: 600 %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 4 601 br label %return 602return: 603 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 604 store i64 %val, i64* %retptr 605 ret void 606} 607 608define void @store-pre-indexed-quadword3(%pre.struct.i128** %this, i1 %cond, 609 %pre.struct.i128* %load2, 610 <2 x i64> %val) nounwind { 611; CHECK-LABEL: store-pre-indexed-quadword3 612; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}, #32]! 613 br i1 %cond, label %if.then, label %if.end 614if.then: 615 %load1 = load %pre.struct.i128*, %pre.struct.i128** %this 616 %gep1 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load1, i64 0, i32 2 617 br label %return 618if.end: 619 %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3 620 br label %return 621return: 622 %retptr = phi <2 x i64>* [ %gep1, %if.then ], [ %gep2, %if.end ] 623 store <2 x i64> %val, <2 x i64>* %retptr 624 ret void 625} 626 627define void @store-pre-indexed-float3(%pre.struct.float** %this, i1 %cond, 628 %pre.struct.float* %load2, 629 float %val) nounwind { 630; CHECK-LABEL: store-pre-indexed-float3 631; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}, #8]! 632 br i1 %cond, label %if.then, label %if.end 633if.then: 634 %load1 = load %pre.struct.float*, %pre.struct.float** %this 635 %gep1 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load1, i64 0, i32 2 636 br label %return 637if.end: 638 %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3 639 br label %return 640return: 641 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 642 store float %val, float* %retptr 643 ret void 644} 645 646define void @store-pre-indexed-double3(%pre.struct.double** %this, i1 %cond, 647 %pre.struct.double* %load2, 648 double %val) nounwind { 649; CHECK-LABEL: store-pre-indexed-double3 650; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}, #16]! 651 br i1 %cond, label %if.then, label %if.end 652if.then: 653 %load1 = load %pre.struct.double*, %pre.struct.double** %this 654 %gep1 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load1, i64 0, i32 2 655 br label %return 656if.end: 657 %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3 658 br label %return 659return: 660 %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ] 661 store double %val, double* %retptr 662 ret void 663} 664 665; Check the following transform: 666; 667; ldr X, [x20] 668; ... 669; add x20, x20, #32 670; -> 671; ldr X, [x20], #32 672; 673; with X being either w0, x0, s0, d0 or q0. 674 675define void @load-post-indexed-byte(i8* %array, i64 %count) nounwind { 676; CHECK-LABEL: load-post-indexed-byte 677; CHECK: ldrb w{{[0-9]+}}, [x{{[0-9]+}}], #4 678entry: 679 %gep1 = getelementptr i8, i8* %array, i64 2 680 br label %body 681 682body: 683 %iv2 = phi i8* [ %gep3, %body ], [ %gep1, %entry ] 684 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 685 %gep2 = getelementptr i8, i8* %iv2, i64 -1 686 %load = load i8, i8* %gep2 687 call void @use-byte(i8 %load) 688 %load2 = load i8, i8* %iv2 689 call void @use-byte(i8 %load2) 690 %iv.next = add i64 %iv, -4 691 %gep3 = getelementptr i8, i8* %iv2, i64 4 692 %cond = icmp eq i64 %iv.next, 0 693 br i1 %cond, label %exit, label %body 694 695exit: 696 ret void 697} 698 699define void @load-post-indexed-halfword(i16* %array, i64 %count) nounwind { 700; CHECK-LABEL: load-post-indexed-halfword 701; CHECK: ldrh w{{[0-9]+}}, [x{{[0-9]+}}], #8 702entry: 703 %gep1 = getelementptr i16, i16* %array, i64 2 704 br label %body 705 706body: 707 %iv2 = phi i16* [ %gep3, %body ], [ %gep1, %entry ] 708 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 709 %gep2 = getelementptr i16, i16* %iv2, i64 -1 710 %load = load i16, i16* %gep2 711 call void @use-halfword(i16 %load) 712 %load2 = load i16, i16* %iv2 713 call void @use-halfword(i16 %load2) 714 %iv.next = add i64 %iv, -4 715 %gep3 = getelementptr i16, i16* %iv2, i64 4 716 %cond = icmp eq i64 %iv.next, 0 717 br i1 %cond, label %exit, label %body 718 719exit: 720 ret void 721} 722 723define void @load-post-indexed-word(i32* %array, i64 %count) nounwind { 724; CHECK-LABEL: load-post-indexed-word 725; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #16 726entry: 727 %gep1 = getelementptr i32, i32* %array, i64 2 728 br label %body 729 730body: 731 %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ] 732 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 733 %gep2 = getelementptr i32, i32* %iv2, i64 -1 734 %load = load i32, i32* %gep2 735 call void @use-word(i32 %load) 736 %load2 = load i32, i32* %iv2 737 call void @use-word(i32 %load2) 738 %iv.next = add i64 %iv, -4 739 %gep3 = getelementptr i32, i32* %iv2, i64 4 740 %cond = icmp eq i64 %iv.next, 0 741 br i1 %cond, label %exit, label %body 742 743exit: 744 ret void 745} 746 747define void @load-post-indexed-doubleword(i64* %array, i64 %count) nounwind { 748; CHECK-LABEL: load-post-indexed-doubleword 749; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #32 750entry: 751 %gep1 = getelementptr i64, i64* %array, i64 2 752 br label %body 753 754body: 755 %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ] 756 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 757 %gep2 = getelementptr i64, i64* %iv2, i64 -1 758 %load = load i64, i64* %gep2 759 call void @use-doubleword(i64 %load) 760 %load2 = load i64, i64* %iv2 761 call void @use-doubleword(i64 %load2) 762 %iv.next = add i64 %iv, -4 763 %gep3 = getelementptr i64, i64* %iv2, i64 4 764 %cond = icmp eq i64 %iv.next, 0 765 br i1 %cond, label %exit, label %body 766 767exit: 768 ret void 769} 770 771define void @load-post-indexed-quadword(<2 x i64>* %array, i64 %count) nounwind { 772; CHECK-LABEL: load-post-indexed-quadword 773; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #64 774entry: 775 %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2 776 br label %body 777 778body: 779 %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ] 780 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 781 %gep2 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 -1 782 %load = load <2 x i64>, <2 x i64>* %gep2 783 call void @use-quadword(<2 x i64> %load) 784 %load2 = load <2 x i64>, <2 x i64>* %iv2 785 call void @use-quadword(<2 x i64> %load2) 786 %iv.next = add i64 %iv, -4 787 %gep3 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 4 788 %cond = icmp eq i64 %iv.next, 0 789 br i1 %cond, label %exit, label %body 790 791exit: 792 ret void 793} 794 795define void @load-post-indexed-float(float* %array, i64 %count) nounwind { 796; CHECK-LABEL: load-post-indexed-float 797; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #16 798entry: 799 %gep1 = getelementptr float, float* %array, i64 2 800 br label %body 801 802body: 803 %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ] 804 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 805 %gep2 = getelementptr float, float* %iv2, i64 -1 806 %load = load float, float* %gep2 807 call void @use-float(float %load) 808 %load2 = load float, float* %iv2 809 call void @use-float(float %load2) 810 %iv.next = add i64 %iv, -4 811 %gep3 = getelementptr float, float* %iv2, i64 4 812 %cond = icmp eq i64 %iv.next, 0 813 br i1 %cond, label %exit, label %body 814 815exit: 816 ret void 817} 818 819define void @load-post-indexed-double(double* %array, i64 %count) nounwind { 820; CHECK-LABEL: load-post-indexed-double 821; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #32 822entry: 823 %gep1 = getelementptr double, double* %array, i64 2 824 br label %body 825 826body: 827 %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ] 828 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 829 %gep2 = getelementptr double, double* %iv2, i64 -1 830 %load = load double, double* %gep2 831 call void @use-double(double %load) 832 %load2 = load double, double* %iv2 833 call void @use-double(double %load2) 834 %iv.next = add i64 %iv, -4 835 %gep3 = getelementptr double, double* %iv2, i64 4 836 %cond = icmp eq i64 %iv.next, 0 837 br i1 %cond, label %exit, label %body 838 839exit: 840 ret void 841} 842 843; Check the following transform: 844; 845; str X, [x20] 846; ... 847; add x20, x20, #32 848; -> 849; str X, [x20], #32 850; 851; with X being either w0, x0, s0, d0 or q0. 852 853define void @store-post-indexed-byte(i8* %array, i64 %count, i8 %val) nounwind { 854; CHECK-LABEL: store-post-indexed-byte 855; CHECK: strb w{{[0-9]+}}, [x{{[0-9]+}}], #4 856entry: 857 %gep1 = getelementptr i8, i8* %array, i64 2 858 br label %body 859 860body: 861 %iv2 = phi i8* [ %gep3, %body ], [ %gep1, %entry ] 862 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 863 %gep2 = getelementptr i8, i8* %iv2, i64 -1 864 %load = load i8, i8* %gep2 865 call void @use-byte(i8 %load) 866 store i8 %val, i8* %iv2 867 %iv.next = add i64 %iv, -4 868 %gep3 = getelementptr i8, i8* %iv2, i64 4 869 %cond = icmp eq i64 %iv.next, 0 870 br i1 %cond, label %exit, label %body 871 872exit: 873 ret void 874} 875 876define void @store-post-indexed-halfword(i16* %array, i64 %count, i16 %val) nounwind { 877; CHECK-LABEL: store-post-indexed-halfword 878; CHECK: strh w{{[0-9]+}}, [x{{[0-9]+}}], #8 879entry: 880 %gep1 = getelementptr i16, i16* %array, i64 2 881 br label %body 882 883body: 884 %iv2 = phi i16* [ %gep3, %body ], [ %gep1, %entry ] 885 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 886 %gep2 = getelementptr i16, i16* %iv2, i64 -1 887 %load = load i16, i16* %gep2 888 call void @use-halfword(i16 %load) 889 store i16 %val, i16* %iv2 890 %iv.next = add i64 %iv, -4 891 %gep3 = getelementptr i16, i16* %iv2, i64 4 892 %cond = icmp eq i64 %iv.next, 0 893 br i1 %cond, label %exit, label %body 894 895exit: 896 ret void 897} 898 899define void @store-post-indexed-word(i32* %array, i64 %count, i32 %val) nounwind { 900; CHECK-LABEL: store-post-indexed-word 901; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #16 902entry: 903 %gep1 = getelementptr i32, i32* %array, i64 2 904 br label %body 905 906body: 907 %iv2 = phi i32* [ %gep3, %body ], [ %gep1, %entry ] 908 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 909 %gep2 = getelementptr i32, i32* %iv2, i64 -1 910 %load = load i32, i32* %gep2 911 call void @use-word(i32 %load) 912 store i32 %val, i32* %iv2 913 %iv.next = add i64 %iv, -4 914 %gep3 = getelementptr i32, i32* %iv2, i64 4 915 %cond = icmp eq i64 %iv.next, 0 916 br i1 %cond, label %exit, label %body 917 918exit: 919 ret void 920} 921 922define void @store-post-indexed-doubleword(i64* %array, i64 %count, i64 %val) nounwind { 923; CHECK-LABEL: store-post-indexed-doubleword 924; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #32 925entry: 926 %gep1 = getelementptr i64, i64* %array, i64 2 927 br label %body 928 929body: 930 %iv2 = phi i64* [ %gep3, %body ], [ %gep1, %entry ] 931 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 932 %gep2 = getelementptr i64, i64* %iv2, i64 -1 933 %load = load i64, i64* %gep2 934 call void @use-doubleword(i64 %load) 935 store i64 %val, i64* %iv2 936 %iv.next = add i64 %iv, -4 937 %gep3 = getelementptr i64, i64* %iv2, i64 4 938 %cond = icmp eq i64 %iv.next, 0 939 br i1 %cond, label %exit, label %body 940 941exit: 942 ret void 943} 944 945define void @store-post-indexed-quadword(<2 x i64>* %array, i64 %count, <2 x i64> %val) nounwind { 946; CHECK-LABEL: store-post-indexed-quadword 947; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #64 948entry: 949 %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2 950 br label %body 951 952body: 953 %iv2 = phi <2 x i64>* [ %gep3, %body ], [ %gep1, %entry ] 954 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 955 %gep2 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 -1 956 %load = load <2 x i64>, <2 x i64>* %gep2 957 call void @use-quadword(<2 x i64> %load) 958 store <2 x i64> %val, <2 x i64>* %iv2 959 %iv.next = add i64 %iv, -4 960 %gep3 = getelementptr <2 x i64>, <2 x i64>* %iv2, i64 4 961 %cond = icmp eq i64 %iv.next, 0 962 br i1 %cond, label %exit, label %body 963 964exit: 965 ret void 966} 967 968define void @store-post-indexed-float(float* %array, i64 %count, float %val) nounwind { 969; CHECK-LABEL: store-post-indexed-float 970; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #16 971entry: 972 %gep1 = getelementptr float, float* %array, i64 2 973 br label %body 974 975body: 976 %iv2 = phi float* [ %gep3, %body ], [ %gep1, %entry ] 977 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 978 %gep2 = getelementptr float, float* %iv2, i64 -1 979 %load = load float, float* %gep2 980 call void @use-float(float %load) 981 store float %val, float* %iv2 982 %iv.next = add i64 %iv, -4 983 %gep3 = getelementptr float, float* %iv2, i64 4 984 %cond = icmp eq i64 %iv.next, 0 985 br i1 %cond, label %exit, label %body 986 987exit: 988 ret void 989} 990 991define void @store-post-indexed-double(double* %array, i64 %count, double %val) nounwind { 992; CHECK-LABEL: store-post-indexed-double 993; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #32 994entry: 995 %gep1 = getelementptr double, double* %array, i64 2 996 br label %body 997 998body: 999 %iv2 = phi double* [ %gep3, %body ], [ %gep1, %entry ] 1000 %iv = phi i64 [ %iv.next, %body ], [ %count, %entry ] 1001 %gep2 = getelementptr double, double* %iv2, i64 -1 1002 %load = load double, double* %gep2 1003 call void @use-double(double %load) 1004 store double %val, double* %iv2 1005 %iv.next = add i64 %iv, -4 1006 %gep3 = getelementptr double, double* %iv2, i64 4 1007 %cond = icmp eq i64 %iv.next, 0 1008 br i1 %cond, label %exit, label %body 1009 1010exit: 1011 ret void 1012} 1013 1014declare void @use-byte(i8) 1015declare void @use-halfword(i16) 1016declare void @use-word(i32) 1017declare void @use-doubleword(i64) 1018declare void @use-quadword(<2 x i64>) 1019declare void @use-float(float) 1020declare void @use-double(double) 1021 1022; Check the following transform: 1023; 1024; stp w0, [x20] 1025; ... 1026; add x20, x20, #32 1027; -> 1028; stp w0, [x20], #32 1029 1030define void @store-pair-post-indexed-word() nounwind { 1031; CHECK-LABEL: store-pair-post-indexed-word 1032; CHECK: stp w{{[0-9]+}}, w{{[0-9]+}}, [sp], #16 1033; CHECK: ret 1034 %src = alloca { i32, i32 }, align 8 1035 %dst = alloca { i32, i32 }, align 8 1036 1037 %src.realp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %src, i32 0, i32 0 1038 %src.real = load i32, i32* %src.realp 1039 %src.imagp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %src, i32 0, i32 1 1040 %src.imag = load i32, i32* %src.imagp 1041 1042 %dst.realp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %dst, i32 0, i32 0 1043 %dst.imagp = getelementptr inbounds { i32, i32 }, { i32, i32 }* %dst, i32 0, i32 1 1044 store i32 %src.real, i32* %dst.realp 1045 store i32 %src.imag, i32* %dst.imagp 1046 ret void 1047} 1048 1049define void @store-pair-post-indexed-doubleword() nounwind { 1050; CHECK-LABEL: store-pair-post-indexed-doubleword 1051; CHECK: stp x{{[0-9]+}}, x{{[0-9]+}}, [sp], #32 1052; CHECK: ret 1053 %src = alloca { i64, i64 }, align 8 1054 %dst = alloca { i64, i64 }, align 8 1055 1056 %src.realp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %src, i32 0, i32 0 1057 %src.real = load i64, i64* %src.realp 1058 %src.imagp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %src, i32 0, i32 1 1059 %src.imag = load i64, i64* %src.imagp 1060 1061 %dst.realp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %dst, i32 0, i32 0 1062 %dst.imagp = getelementptr inbounds { i64, i64 }, { i64, i64 }* %dst, i32 0, i32 1 1063 store i64 %src.real, i64* %dst.realp 1064 store i64 %src.imag, i64* %dst.imagp 1065 ret void 1066} 1067 1068define void @store-pair-post-indexed-float() nounwind { 1069; CHECK-LABEL: store-pair-post-indexed-float 1070; CHECK: stp s{{[0-9]+}}, s{{[0-9]+}}, [sp], #16 1071; CHECK: ret 1072 %src = alloca { float, float }, align 8 1073 %dst = alloca { float, float }, align 8 1074 1075 %src.realp = getelementptr inbounds { float, float }, { float, float }* %src, i32 0, i32 0 1076 %src.real = load float, float* %src.realp 1077 %src.imagp = getelementptr inbounds { float, float }, { float, float }* %src, i32 0, i32 1 1078 %src.imag = load float, float* %src.imagp 1079 1080 %dst.realp = getelementptr inbounds { float, float }, { float, float }* %dst, i32 0, i32 0 1081 %dst.imagp = getelementptr inbounds { float, float }, { float, float }* %dst, i32 0, i32 1 1082 store float %src.real, float* %dst.realp 1083 store float %src.imag, float* %dst.imagp 1084 ret void 1085} 1086 1087define void @store-pair-post-indexed-double() nounwind { 1088; CHECK-LABEL: store-pair-post-indexed-double 1089; CHECK: stp d{{[0-9]+}}, d{{[0-9]+}}, [sp], #32 1090; CHECK: ret 1091 %src = alloca { double, double }, align 8 1092 %dst = alloca { double, double }, align 8 1093 1094 %src.realp = getelementptr inbounds { double, double }, { double, double }* %src, i32 0, i32 0 1095 %src.real = load double, double* %src.realp 1096 %src.imagp = getelementptr inbounds { double, double }, { double, double }* %src, i32 0, i32 1 1097 %src.imag = load double, double* %src.imagp 1098 1099 %dst.realp = getelementptr inbounds { double, double }, { double, double }* %dst, i32 0, i32 0 1100 %dst.imagp = getelementptr inbounds { double, double }, { double, double }* %dst, i32 0, i32 1 1101 store double %src.real, double* %dst.realp 1102 store double %src.imag, double* %dst.imagp 1103 ret void 1104} 1105 1106; Check the following transform: 1107; 1108; (ldr|str) X, [x20] 1109; ... 1110; sub x20, x20, #16 1111; -> 1112; (ldr|str) X, [x20], #-16 1113; 1114; with X being either w0, x0, s0, d0 or q0. 1115 1116define void @post-indexed-sub-word(i32* %a, i32* %b, i64 %count) nounwind { 1117; CHECK-LABEL: post-indexed-sub-word 1118; CHECK: ldr w{{[0-9]+}}, [x{{[0-9]+}}], #-8 1119; CHECK: str w{{[0-9]+}}, [x{{[0-9]+}}], #-8 1120 br label %for.body 1121for.body: 1122 %phi1 = phi i32* [ %gep4, %for.body ], [ %b, %0 ] 1123 %phi2 = phi i32* [ %gep3, %for.body ], [ %a, %0 ] 1124 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 1125 %gep1 = getelementptr i32, i32* %phi1, i64 -1 1126 %load1 = load i32, i32* %gep1 1127 %gep2 = getelementptr i32, i32* %phi2, i64 -1 1128 store i32 %load1, i32* %gep2 1129 %load2 = load i32, i32* %phi1 1130 store i32 %load2, i32* %phi2 1131 %dec.i = add nsw i64 %i, -1 1132 %gep3 = getelementptr i32, i32* %phi2, i64 -2 1133 %gep4 = getelementptr i32, i32* %phi1, i64 -2 1134 %cond = icmp sgt i64 %dec.i, 0 1135 br i1 %cond, label %for.body, label %end 1136end: 1137 ret void 1138} 1139 1140define void @post-indexed-sub-doubleword(i64* %a, i64* %b, i64 %count) nounwind { 1141; CHECK-LABEL: post-indexed-sub-doubleword 1142; CHECK: ldr x{{[0-9]+}}, [x{{[0-9]+}}], #-16 1143; CHECK: str x{{[0-9]+}}, [x{{[0-9]+}}], #-16 1144 br label %for.body 1145for.body: 1146 %phi1 = phi i64* [ %gep4, %for.body ], [ %b, %0 ] 1147 %phi2 = phi i64* [ %gep3, %for.body ], [ %a, %0 ] 1148 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 1149 %gep1 = getelementptr i64, i64* %phi1, i64 -1 1150 %load1 = load i64, i64* %gep1 1151 %gep2 = getelementptr i64, i64* %phi2, i64 -1 1152 store i64 %load1, i64* %gep2 1153 %load2 = load i64, i64* %phi1 1154 store i64 %load2, i64* %phi2 1155 %dec.i = add nsw i64 %i, -1 1156 %gep3 = getelementptr i64, i64* %phi2, i64 -2 1157 %gep4 = getelementptr i64, i64* %phi1, i64 -2 1158 %cond = icmp sgt i64 %dec.i, 0 1159 br i1 %cond, label %for.body, label %end 1160end: 1161 ret void 1162} 1163 1164define void @post-indexed-sub-quadword(<2 x i64>* %a, <2 x i64>* %b, i64 %count) nounwind { 1165; CHECK-LABEL: post-indexed-sub-quadword 1166; CHECK: ldr q{{[0-9]+}}, [x{{[0-9]+}}], #-32 1167; CHECK: str q{{[0-9]+}}, [x{{[0-9]+}}], #-32 1168 br label %for.body 1169for.body: 1170 %phi1 = phi <2 x i64>* [ %gep4, %for.body ], [ %b, %0 ] 1171 %phi2 = phi <2 x i64>* [ %gep3, %for.body ], [ %a, %0 ] 1172 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 1173 %gep1 = getelementptr <2 x i64>, <2 x i64>* %phi1, i64 -1 1174 %load1 = load <2 x i64>, <2 x i64>* %gep1 1175 %gep2 = getelementptr <2 x i64>, <2 x i64>* %phi2, i64 -1 1176 store <2 x i64> %load1, <2 x i64>* %gep2 1177 %load2 = load <2 x i64>, <2 x i64>* %phi1 1178 store <2 x i64> %load2, <2 x i64>* %phi2 1179 %dec.i = add nsw i64 %i, -1 1180 %gep3 = getelementptr <2 x i64>, <2 x i64>* %phi2, i64 -2 1181 %gep4 = getelementptr <2 x i64>, <2 x i64>* %phi1, i64 -2 1182 %cond = icmp sgt i64 %dec.i, 0 1183 br i1 %cond, label %for.body, label %end 1184end: 1185 ret void 1186} 1187 1188define void @post-indexed-sub-float(float* %a, float* %b, i64 %count) nounwind { 1189; CHECK-LABEL: post-indexed-sub-float 1190; CHECK: ldr s{{[0-9]+}}, [x{{[0-9]+}}], #-8 1191; CHECK: str s{{[0-9]+}}, [x{{[0-9]+}}], #-8 1192 br label %for.body 1193for.body: 1194 %phi1 = phi float* [ %gep4, %for.body ], [ %b, %0 ] 1195 %phi2 = phi float* [ %gep3, %for.body ], [ %a, %0 ] 1196 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 1197 %gep1 = getelementptr float, float* %phi1, i64 -1 1198 %load1 = load float, float* %gep1 1199 %gep2 = getelementptr float, float* %phi2, i64 -1 1200 store float %load1, float* %gep2 1201 %load2 = load float, float* %phi1 1202 store float %load2, float* %phi2 1203 %dec.i = add nsw i64 %i, -1 1204 %gep3 = getelementptr float, float* %phi2, i64 -2 1205 %gep4 = getelementptr float, float* %phi1, i64 -2 1206 %cond = icmp sgt i64 %dec.i, 0 1207 br i1 %cond, label %for.body, label %end 1208end: 1209 ret void 1210} 1211 1212define void @post-indexed-sub-double(double* %a, double* %b, i64 %count) nounwind { 1213; CHECK-LABEL: post-indexed-sub-double 1214; CHECK: ldr d{{[0-9]+}}, [x{{[0-9]+}}], #-16 1215; CHECK: str d{{[0-9]+}}, [x{{[0-9]+}}], #-16 1216 br label %for.body 1217for.body: 1218 %phi1 = phi double* [ %gep4, %for.body ], [ %b, %0 ] 1219 %phi2 = phi double* [ %gep3, %for.body ], [ %a, %0 ] 1220 %i = phi i64 [ %dec.i, %for.body], [ %count, %0 ] 1221 %gep1 = getelementptr double, double* %phi1, i64 -1 1222 %load1 = load double, double* %gep1 1223 %gep2 = getelementptr double, double* %phi2, i64 -1 1224 store double %load1, double* %gep2 1225 %load2 = load double, double* %phi1 1226 store double %load2, double* %phi2 1227 %dec.i = add nsw i64 %i, -1 1228 %gep3 = getelementptr double, double* %phi2, i64 -2 1229 %gep4 = getelementptr double, double* %phi1, i64 -2 1230 %cond = icmp sgt i64 %dec.i, 0 1231 br i1 %cond, label %for.body, label %end 1232end: 1233 ret void 1234} 1235