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 31 declare void @bar_byte(%s.byte*, i8) 32 33 define 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]! 36 entry: 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 40 bar: 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 46 define 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]! 49 entry: 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 53 bar: 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 59 declare void @bar_halfword(%s.halfword*, i16) 60 61 define 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]! 64 entry: 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 68 bar: 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 74 define 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]! 77 entry: 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 81 bar: 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 87 declare void @bar_word(%s.word*, i32) 88 89 define 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]! 92 entry: 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 96 bar: 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 102 define 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]! 105 entry: 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 109 bar: 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 115 declare void @bar_doubleword(%s.doubleword*, i64) 116 117 define 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]! 120 entry: 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 124 bar: 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 130 define 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]! 133 entry: 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 137 bar: 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 143 declare void @bar_quadword(%s.quadword*, fp128) 144 145 define 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]! 148 entry: 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 152 bar: 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 158 define 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]! 161 entry: 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 165 bar: 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 171 declare void @bar_float(%s.float*, float) 172 173 define 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]! 176 entry: 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 180 bar: 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 186 define 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]! 189 entry: 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 193 bar: 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 199 declare void @bar_double(%s.double*, double) 200 201 define 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]! 204 entry: 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 208 bar: 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 214 define 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]! 217 entry: 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 221 bar: 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 236 define 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 240 entry: 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 247 bar: 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 253 define 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 257 entry: 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 263 bar: 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 285 define 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 290 if.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 294 if.end: 295 %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2 296 br label %return 297 return: 298 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 299 %ret = load i32, i32* %retptr 300 ret i32 %ret 301 } 302 303 define 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 308 if.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 312 if.end: 313 %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2 314 br label %return 315 return: 316 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 317 %ret = load i64, i64* %retptr 318 ret i64 %ret 319 } 320 321 define <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 326 if.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 330 if.end: 331 %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2 332 br label %return 333 return: 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 339 define 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 344 if.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 348 if.end: 349 %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2 350 br label %return 351 return: 352 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 353 %ret = load float, float* %retptr 354 ret float %ret 355 } 356 357 define 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 362 if.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 366 if.end: 367 %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2 368 br label %return 369 return: 370 %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ] 371 %ret = load double, double* %retptr 372 ret double %ret 373 } 374 375 define 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 380 if.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 384 if.end: 385 %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4 386 br label %return 387 return: 388 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 389 %ret = load i32, i32* %retptr 390 ret i32 %ret 391 } 392 393 define 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 398 if.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 402 if.end: 403 %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 3 404 br label %return 405 return: 406 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 407 %ret = load i64, i64* %retptr 408 ret i64 %ret 409 } 410 411 define <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 416 if.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 420 if.end: 421 %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3 422 br label %return 423 return: 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 429 define 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 434 if.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 438 if.end: 439 %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3 440 br label %return 441 return: 442 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 443 %ret = load float, float* %retptr 444 ret float %ret 445 } 446 447 define 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 452 if.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 456 if.end: 457 %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3 458 br label %return 459 return: 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 475 define 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 481 if.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 485 if.end: 486 %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 2 487 br label %return 488 return: 489 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 490 store i32 %val, i32* %retptr 491 ret void 492 } 493 494 define 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 500 if.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 504 if.end: 505 %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 2 506 br label %return 507 return: 508 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 509 store i64 %val, i64* %retptr 510 ret void 511 } 512 513 define 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 519 if.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 523 if.end: 524 %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 2 525 br label %return 526 return: 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 532 define 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 538 if.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 542 if.end: 543 %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 2 544 br label %return 545 return: 546 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 547 store float %val, float* %retptr 548 ret void 549 } 550 551 define 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 557 if.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 561 if.end: 562 %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 2 563 br label %return 564 return: 565 %retptr = phi double* [ %gep1, %if.then ], [ %gep2, %if.end ] 566 store double %val, double* %retptr 567 ret void 568 } 569 570 define 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 576 if.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 580 if.end: 581 %gep2 = getelementptr inbounds %pre.struct.i32, %pre.struct.i32* %load2, i64 0, i32 4 582 br label %return 583 return: 584 %retptr = phi i32* [ %gep1, %if.then ], [ %gep2, %if.end ] 585 store i32 %val, i32* %retptr 586 ret void 587 } 588 589 define 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 595 if.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 599 if.end: 600 %gep2 = getelementptr inbounds %pre.struct.i64, %pre.struct.i64* %load2, i64 0, i32 4 601 br label %return 602 return: 603 %retptr = phi i64* [ %gep1, %if.then ], [ %gep2, %if.end ] 604 store i64 %val, i64* %retptr 605 ret void 606 } 607 608 define 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 614 if.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 618 if.end: 619 %gep2 = getelementptr inbounds %pre.struct.i128, %pre.struct.i128* %load2, i64 0, i32 3 620 br label %return 621 return: 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 627 define 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 633 if.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 637 if.end: 638 %gep2 = getelementptr inbounds %pre.struct.float, %pre.struct.float* %load2, i64 0, i32 3 639 br label %return 640 return: 641 %retptr = phi float* [ %gep1, %if.then ], [ %gep2, %if.end ] 642 store float %val, float* %retptr 643 ret void 644 } 645 646 define 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 652 if.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 656 if.end: 657 %gep2 = getelementptr inbounds %pre.struct.double, %pre.struct.double* %load2, i64 0, i32 3 658 br label %return 659 return: 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 675 define 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 678 entry: 679 %gep1 = getelementptr i8, i8* %array, i64 2 680 br label %body 681 682 body: 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 695 exit: 696 ret void 697 } 698 699 define 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 702 entry: 703 %gep1 = getelementptr i16, i16* %array, i64 2 704 br label %body 705 706 body: 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 719 exit: 720 ret void 721 } 722 723 define 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 726 entry: 727 %gep1 = getelementptr i32, i32* %array, i64 2 728 br label %body 729 730 body: 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 743 exit: 744 ret void 745 } 746 747 define 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 750 entry: 751 %gep1 = getelementptr i64, i64* %array, i64 2 752 br label %body 753 754 body: 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 767 exit: 768 ret void 769 } 770 771 define 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 774 entry: 775 %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2 776 br label %body 777 778 body: 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 791 exit: 792 ret void 793 } 794 795 define 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 798 entry: 799 %gep1 = getelementptr float, float* %array, i64 2 800 br label %body 801 802 body: 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 815 exit: 816 ret void 817 } 818 819 define 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 822 entry: 823 %gep1 = getelementptr double, double* %array, i64 2 824 br label %body 825 826 body: 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 839 exit: 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 853 define 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 856 entry: 857 %gep1 = getelementptr i8, i8* %array, i64 2 858 br label %body 859 860 body: 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 872 exit: 873 ret void 874 } 875 876 define 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 879 entry: 880 %gep1 = getelementptr i16, i16* %array, i64 2 881 br label %body 882 883 body: 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 895 exit: 896 ret void 897 } 898 899 define 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 902 entry: 903 %gep1 = getelementptr i32, i32* %array, i64 2 904 br label %body 905 906 body: 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 918 exit: 919 ret void 920 } 921 922 define 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 925 entry: 926 %gep1 = getelementptr i64, i64* %array, i64 2 927 br label %body 928 929 body: 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 941 exit: 942 ret void 943 } 944 945 define 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 948 entry: 949 %gep1 = getelementptr <2 x i64>, <2 x i64>* %array, i64 2 950 br label %body 951 952 body: 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 964 exit: 965 ret void 966 } 967 968 define 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 971 entry: 972 %gep1 = getelementptr float, float* %array, i64 2 973 br label %body 974 975 body: 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 987 exit: 988 ret void 989 } 990 991 define 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 994 entry: 995 %gep1 = getelementptr double, double* %array, i64 2 996 br label %body 997 998 body: 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 1010 exit: 1011 ret void 1012 } 1013 1014 declare void @use-byte(i8) 1015 declare void @use-halfword(i16) 1016 declare void @use-word(i32) 1017 declare void @use-doubleword(i64) 1018 declare void @use-quadword(<2 x i64>) 1019 declare void @use-float(float) 1020 declare 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 1030 define 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 1049 define 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 1068 define 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 1087 define 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 1116 define 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 1121 for.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 1136 end: 1137 ret void 1138 } 1139 1140 define 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 1145 for.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 1160 end: 1161 ret void 1162 } 1163 1164 define 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 1169 for.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 1184 end: 1185 ret void 1186 } 1187 1188 define 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 1193 for.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 1208 end: 1209 ret void 1210 } 1211 1212 define 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 1217 for.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 1232 end: 1233 ret void 1234 } 1235