1 ; RUN: llc < %s -mtriple=arm64-eabi -aarch64-redzone | FileCheck %s 2 3 define i64* @store64(i64* %ptr, i64 %index, i64 %spacing) { 4 ; CHECK-LABEL: store64: 5 ; CHECK: str x{{[0-9+]}}, [x{{[0-9+]}}], #8 6 ; CHECK: ret 7 %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 1 8 store i64 %spacing, i64* %ptr, align 4 9 ret i64* %incdec.ptr 10 } 11 12 define i64* @store64idxpos256(i64* %ptr, i64 %index, i64 %spacing) { 13 ; CHECK-LABEL: store64idxpos256: 14 ; CHECK: add x{{[0-9+]}}, x{{[0-9+]}}, #256 15 ; CHECK: str x{{[0-9+]}}, [x{{[0-9+]}}] 16 ; CHECK: ret 17 %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 32 18 store i64 %spacing, i64* %ptr, align 4 19 ret i64* %incdec.ptr 20 } 21 22 define i64* @store64idxneg256(i64* %ptr, i64 %index, i64 %spacing) { 23 ; CHECK-LABEL: store64idxneg256: 24 ; CHECK: str x{{[0-9+]}}, [x{{[0-9+]}}], #-256 25 ; CHECK: ret 26 %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 -32 27 store i64 %spacing, i64* %ptr, align 4 28 ret i64* %incdec.ptr 29 } 30 31 define i32* @store32(i32* %ptr, i32 %index, i32 %spacing) { 32 ; CHECK-LABEL: store32: 33 ; CHECK: str w{{[0-9+]}}, [x{{[0-9+]}}], #4 34 ; CHECK: ret 35 %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 1 36 store i32 %spacing, i32* %ptr, align 4 37 ret i32* %incdec.ptr 38 } 39 40 define i32* @store32idxpos256(i32* %ptr, i32 %index, i32 %spacing) { 41 ; CHECK-LABEL: store32idxpos256: 42 ; CHECK: add x{{[0-9+]}}, x{{[0-9+]}}, #256 43 ; CHECK: str w{{[0-9+]}}, [x{{[0-9+]}}] 44 ; CHECK: ret 45 %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 64 46 store i32 %spacing, i32* %ptr, align 4 47 ret i32* %incdec.ptr 48 } 49 50 define i32* @store32idxneg256(i32* %ptr, i32 %index, i32 %spacing) { 51 ; CHECK-LABEL: store32idxneg256: 52 ; CHECK: str w{{[0-9+]}}, [x{{[0-9+]}}], #-256 53 ; CHECK: ret 54 %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 -64 55 store i32 %spacing, i32* %ptr, align 4 56 ret i32* %incdec.ptr 57 } 58 59 define i16* @store16(i16* %ptr, i16 %index, i16 %spacing) { 60 ; CHECK-LABEL: store16: 61 ; CHECK: strh w{{[0-9+]}}, [x{{[0-9+]}}], #2 62 ; CHECK: ret 63 %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 1 64 store i16 %spacing, i16* %ptr, align 4 65 ret i16* %incdec.ptr 66 } 67 68 define i16* @store16idxpos256(i16* %ptr, i16 %index, i16 %spacing) { 69 ; CHECK-LABEL: store16idxpos256: 70 ; CHECK: add x{{[0-9+]}}, x{{[0-9+]}}, #256 71 ; CHECK: strh w{{[0-9+]}}, [x{{[0-9+]}}] 72 ; CHECK: ret 73 %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 128 74 store i16 %spacing, i16* %ptr, align 4 75 ret i16* %incdec.ptr 76 } 77 78 define i16* @store16idxneg256(i16* %ptr, i16 %index, i16 %spacing) { 79 ; CHECK-LABEL: store16idxneg256: 80 ; CHECK: strh w{{[0-9+]}}, [x{{[0-9+]}}], #-256 81 ; CHECK: ret 82 %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 -128 83 store i16 %spacing, i16* %ptr, align 4 84 ret i16* %incdec.ptr 85 } 86 87 define i8* @store8(i8* %ptr, i8 %index, i8 %spacing) { 88 ; CHECK-LABEL: store8: 89 ; CHECK: strb w{{[0-9+]}}, [x{{[0-9+]}}], #1 90 ; CHECK: ret 91 %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 1 92 store i8 %spacing, i8* %ptr, align 4 93 ret i8* %incdec.ptr 94 } 95 96 define i8* @store8idxpos256(i8* %ptr, i8 %index, i8 %spacing) { 97 ; CHECK-LABEL: store8idxpos256: 98 ; CHECK: add x{{[0-9+]}}, x{{[0-9+]}}, #256 99 ; CHECK: strb w{{[0-9+]}}, [x{{[0-9+]}}] 100 ; CHECK: ret 101 %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 256 102 store i8 %spacing, i8* %ptr, align 4 103 ret i8* %incdec.ptr 104 } 105 106 define i8* @store8idxneg256(i8* %ptr, i8 %index, i8 %spacing) { 107 ; CHECK-LABEL: store8idxneg256: 108 ; CHECK: strb w{{[0-9+]}}, [x{{[0-9+]}}], #-256 109 ; CHECK: ret 110 %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 -256 111 store i8 %spacing, i8* %ptr, align 4 112 ret i8* %incdec.ptr 113 } 114 115 define i32* @truncst64to32(i32* %ptr, i32 %index, i64 %spacing) { 116 ; CHECK-LABEL: truncst64to32: 117 ; CHECK: str w{{[0-9+]}}, [x{{[0-9+]}}], #4 118 ; CHECK: ret 119 %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 1 120 %trunc = trunc i64 %spacing to i32 121 store i32 %trunc, i32* %ptr, align 4 122 ret i32* %incdec.ptr 123 } 124 125 define i16* @truncst64to16(i16* %ptr, i16 %index, i64 %spacing) { 126 ; CHECK-LABEL: truncst64to16: 127 ; CHECK: strh w{{[0-9+]}}, [x{{[0-9+]}}], #2 128 ; CHECK: ret 129 %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 1 130 %trunc = trunc i64 %spacing to i16 131 store i16 %trunc, i16* %ptr, align 4 132 ret i16* %incdec.ptr 133 } 134 135 define i8* @truncst64to8(i8* %ptr, i8 %index, i64 %spacing) { 136 ; CHECK-LABEL: truncst64to8: 137 ; CHECK: strb w{{[0-9+]}}, [x{{[0-9+]}}], #1 138 ; CHECK: ret 139 %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 1 140 %trunc = trunc i64 %spacing to i8 141 store i8 %trunc, i8* %ptr, align 4 142 ret i8* %incdec.ptr 143 } 144 145 146 define half* @storef16(half* %ptr, half %index, half %spacing) nounwind { 147 ; CHECK-LABEL: storef16: 148 ; CHECK: str h{{[0-9+]}}, [x{{[0-9+]}}], #2 149 ; CHECK: ret 150 %incdec.ptr = getelementptr inbounds half, half* %ptr, i64 1 151 store half %spacing, half* %ptr, align 2 152 ret half* %incdec.ptr 153 } 154 155 define float* @storef32(float* %ptr, float %index, float %spacing) { 156 ; CHECK-LABEL: storef32: 157 ; CHECK: str s{{[0-9+]}}, [x{{[0-9+]}}], #4 158 ; CHECK: ret 159 %incdec.ptr = getelementptr inbounds float, float* %ptr, i64 1 160 store float %spacing, float* %ptr, align 4 161 ret float* %incdec.ptr 162 } 163 164 define double* @storef64(double* %ptr, double %index, double %spacing) { 165 ; CHECK-LABEL: storef64: 166 ; CHECK: str d{{[0-9+]}}, [x{{[0-9+]}}], #8 167 ; CHECK: ret 168 %incdec.ptr = getelementptr inbounds double, double* %ptr, i64 1 169 store double %spacing, double* %ptr, align 4 170 ret double* %incdec.ptr 171 } 172 173 174 define double* @pref64(double* %ptr, double %spacing) { 175 ; CHECK-LABEL: pref64: 176 ; CHECK: str d0, [x0, #32]! 177 ; CHECK-NEXT: ret 178 %incdec.ptr = getelementptr inbounds double, double* %ptr, i64 4 179 store double %spacing, double* %incdec.ptr, align 4 180 ret double *%incdec.ptr 181 } 182 183 define float* @pref32(float* %ptr, float %spacing) { 184 ; CHECK-LABEL: pref32: 185 ; CHECK: str s0, [x0, #12]! 186 ; CHECK-NEXT: ret 187 %incdec.ptr = getelementptr inbounds float, float* %ptr, i64 3 188 store float %spacing, float* %incdec.ptr, align 4 189 ret float *%incdec.ptr 190 } 191 192 define half* @pref16(half* %ptr, half %spacing) nounwind { 193 ; CHECK-LABEL: pref16: 194 ; CHECK: str h0, [x0, #6]! 195 ; CHECK-NEXT: ret 196 %incdec.ptr = getelementptr inbounds half, half* %ptr, i64 3 197 store half %spacing, half* %incdec.ptr, align 2 198 ret half *%incdec.ptr 199 } 200 201 define i64* @pre64(i64* %ptr, i64 %spacing) { 202 ; CHECK-LABEL: pre64: 203 ; CHECK: str x1, [x0, #16]! 204 ; CHECK-NEXT: ret 205 %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 2 206 store i64 %spacing, i64* %incdec.ptr, align 4 207 ret i64 *%incdec.ptr 208 } 209 210 define i64* @pre64idxpos256(i64* %ptr, i64 %spacing) { 211 ; CHECK-LABEL: pre64idxpos256: 212 ; CHECK: add x8, x0, #256 213 ; CHECK-NEXT: str x1, [x0, #256] 214 ; CHECK-NEXT: mov x0, x8 215 ; CHECK-NEXT: ret 216 %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 32 217 store i64 %spacing, i64* %incdec.ptr, align 4 218 ret i64 *%incdec.ptr 219 } 220 221 define i64* @pre64idxneg256(i64* %ptr, i64 %spacing) { 222 ; CHECK-LABEL: pre64idxneg256: 223 ; CHECK: str x1, [x0, #-256]! 224 ; CHECK-NEXT: ret 225 %incdec.ptr = getelementptr inbounds i64, i64* %ptr, i64 -32 226 store i64 %spacing, i64* %incdec.ptr, align 4 227 ret i64 *%incdec.ptr 228 } 229 230 define i32* @pre32(i32* %ptr, i32 %spacing) { 231 ; CHECK-LABEL: pre32: 232 ; CHECK: str w1, [x0, #8]! 233 ; CHECK-NEXT: ret 234 %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 2 235 store i32 %spacing, i32* %incdec.ptr, align 4 236 ret i32 *%incdec.ptr 237 } 238 239 define i32* @pre32idxpos256(i32* %ptr, i32 %spacing) { 240 ; CHECK-LABEL: pre32idxpos256: 241 ; CHECK: add x8, x0, #256 242 ; CHECK-NEXT: str w1, [x0, #256] 243 ; CHECK-NEXT: mov x0, x8 244 ; CHECK-NEXT: ret 245 %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 64 246 store i32 %spacing, i32* %incdec.ptr, align 4 247 ret i32 *%incdec.ptr 248 } 249 250 define i32* @pre32idxneg256(i32* %ptr, i32 %spacing) { 251 ; CHECK-LABEL: pre32idxneg256: 252 ; CHECK: str w1, [x0, #-256]! 253 ; CHECK-NEXT: ret 254 %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 -64 255 store i32 %spacing, i32* %incdec.ptr, align 4 256 ret i32 *%incdec.ptr 257 } 258 259 define i16* @pre16(i16* %ptr, i16 %spacing) { 260 ; CHECK-LABEL: pre16: 261 ; CHECK: strh w1, [x0, #4]! 262 ; CHECK-NEXT: ret 263 %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 2 264 store i16 %spacing, i16* %incdec.ptr, align 4 265 ret i16 *%incdec.ptr 266 } 267 268 define i16* @pre16idxpos256(i16* %ptr, i16 %spacing) { 269 ; CHECK-LABEL: pre16idxpos256: 270 ; CHECK: add x8, x0, #256 271 ; CHECK-NEXT: strh w1, [x0, #256] 272 ; CHECK-NEXT: mov x0, x8 273 ; CHECK-NEXT: ret 274 %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 128 275 store i16 %spacing, i16* %incdec.ptr, align 4 276 ret i16 *%incdec.ptr 277 } 278 279 define i16* @pre16idxneg256(i16* %ptr, i16 %spacing) { 280 ; CHECK-LABEL: pre16idxneg256: 281 ; CHECK: strh w1, [x0, #-256]! 282 ; CHECK-NEXT: ret 283 %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 -128 284 store i16 %spacing, i16* %incdec.ptr, align 4 285 ret i16 *%incdec.ptr 286 } 287 288 define i8* @pre8(i8* %ptr, i8 %spacing) { 289 ; CHECK-LABEL: pre8: 290 ; CHECK: strb w1, [x0, #2]! 291 ; CHECK-NEXT: ret 292 %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 2 293 store i8 %spacing, i8* %incdec.ptr, align 4 294 ret i8 *%incdec.ptr 295 } 296 297 define i8* @pre8idxpos256(i8* %ptr, i8 %spacing) { 298 ; CHECK-LABEL: pre8idxpos256: 299 ; CHECK: add x8, x0, #256 300 ; CHECK-NEXT: strb w1, [x0, #256] 301 ; CHECK-NEXT: mov x0, x8 302 ; CHECK-NEXT: ret 303 %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 256 304 store i8 %spacing, i8* %incdec.ptr, align 4 305 ret i8 *%incdec.ptr 306 } 307 308 define i8* @pre8idxneg256(i8* %ptr, i8 %spacing) { 309 ; CHECK-LABEL: pre8idxneg256: 310 ; CHECK: strb w1, [x0, #-256]! 311 ; CHECK-NEXT: ret 312 %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 -256 313 store i8 %spacing, i8* %incdec.ptr, align 4 314 ret i8 *%incdec.ptr 315 } 316 317 define i32* @pretrunc64to32(i32* %ptr, i64 %spacing) { 318 ; CHECK-LABEL: pretrunc64to32: 319 ; CHECK: str w1, [x0, #8]! 320 ; CHECK-NEXT: ret 321 %incdec.ptr = getelementptr inbounds i32, i32* %ptr, i64 2 322 %trunc = trunc i64 %spacing to i32 323 store i32 %trunc, i32* %incdec.ptr, align 4 324 ret i32 *%incdec.ptr 325 } 326 327 define i16* @pretrunc64to16(i16* %ptr, i64 %spacing) { 328 ; CHECK-LABEL: pretrunc64to16: 329 ; CHECK: strh w1, [x0, #4]! 330 ; CHECK-NEXT: ret 331 %incdec.ptr = getelementptr inbounds i16, i16* %ptr, i64 2 332 %trunc = trunc i64 %spacing to i16 333 store i16 %trunc, i16* %incdec.ptr, align 4 334 ret i16 *%incdec.ptr 335 } 336 337 define i8* @pretrunc64to8(i8* %ptr, i64 %spacing) { 338 ; CHECK-LABEL: pretrunc64to8: 339 ; CHECK: strb w1, [x0, #2]! 340 ; CHECK-NEXT: ret 341 %incdec.ptr = getelementptr inbounds i8, i8* %ptr, i64 2 342 %trunc = trunc i64 %spacing to i8 343 store i8 %trunc, i8* %incdec.ptr, align 4 344 ret i8 *%incdec.ptr 345 } 346 347 ;----- 348 ; Pre-indexed loads 349 ;----- 350 define double* @preidxf64(double* %src, double* %out) { 351 ; CHECK-LABEL: preidxf64: 352 ; CHECK: ldr d0, [x0, #8]! 353 ; CHECK: str d0, [x1] 354 ; CHECK: ret 355 %ptr = getelementptr inbounds double, double* %src, i64 1 356 %tmp = load double, double* %ptr, align 4 357 store double %tmp, double* %out, align 4 358 ret double* %ptr 359 } 360 361 define float* @preidxf32(float* %src, float* %out) { 362 ; CHECK-LABEL: preidxf32: 363 ; CHECK: ldr s0, [x0, #4]! 364 ; CHECK: str s0, [x1] 365 ; CHECK: ret 366 %ptr = getelementptr inbounds float, float* %src, i64 1 367 %tmp = load float, float* %ptr, align 4 368 store float %tmp, float* %out, align 4 369 ret float* %ptr 370 } 371 372 define half* @preidxf16(half* %src, half* %out) { 373 ; CHECK-LABEL: preidxf16: 374 ; CHECK: ldr h0, [x0, #2]! 375 ; CHECK: str h0, [x1] 376 ; CHECK: ret 377 %ptr = getelementptr inbounds half, half* %src, i64 1 378 %tmp = load half, half* %ptr, align 2 379 store half %tmp, half* %out, align 2 380 ret half* %ptr 381 } 382 383 define i64* @preidx64(i64* %src, i64* %out) { 384 ; CHECK-LABEL: preidx64: 385 ; CHECK: ldr x[[REG:[0-9]+]], [x0, #8]! 386 ; CHECK: str x[[REG]], [x1] 387 ; CHECK: ret 388 %ptr = getelementptr inbounds i64, i64* %src, i64 1 389 %tmp = load i64, i64* %ptr, align 4 390 store i64 %tmp, i64* %out, align 4 391 ret i64* %ptr 392 } 393 394 define i32* @preidx32(i32* %src, i32* %out) { 395 ; CHECK: ldr w[[REG:[0-9]+]], [x0, #4]! 396 ; CHECK: str w[[REG]], [x1] 397 ; CHECK: ret 398 %ptr = getelementptr inbounds i32, i32* %src, i64 1 399 %tmp = load i32, i32* %ptr, align 4 400 store i32 %tmp, i32* %out, align 4 401 ret i32* %ptr 402 } 403 404 define i16* @preidx16zext32(i16* %src, i32* %out) { 405 ; CHECK: ldrh w[[REG:[0-9]+]], [x0, #2]! 406 ; CHECK: str w[[REG]], [x1] 407 ; CHECK: ret 408 %ptr = getelementptr inbounds i16, i16* %src, i64 1 409 %tmp = load i16, i16* %ptr, align 4 410 %ext = zext i16 %tmp to i32 411 store i32 %ext, i32* %out, align 4 412 ret i16* %ptr 413 } 414 415 define i16* @preidx16zext64(i16* %src, i64* %out) { 416 ; CHECK: ldrh w[[REG:[0-9]+]], [x0, #2]! 417 ; CHECK: str x[[REG]], [x1] 418 ; CHECK: ret 419 %ptr = getelementptr inbounds i16, i16* %src, i64 1 420 %tmp = load i16, i16* %ptr, align 4 421 %ext = zext i16 %tmp to i64 422 store i64 %ext, i64* %out, align 4 423 ret i16* %ptr 424 } 425 426 define i8* @preidx8zext32(i8* %src, i32* %out) { 427 ; CHECK: ldrb w[[REG:[0-9]+]], [x0, #1]! 428 ; CHECK: str w[[REG]], [x1] 429 ; CHECK: ret 430 %ptr = getelementptr inbounds i8, i8* %src, i64 1 431 %tmp = load i8, i8* %ptr, align 4 432 %ext = zext i8 %tmp to i32 433 store i32 %ext, i32* %out, align 4 434 ret i8* %ptr 435 } 436 437 define i8* @preidx8zext64(i8* %src, i64* %out) { 438 ; CHECK: ldrb w[[REG:[0-9]+]], [x0, #1]! 439 ; CHECK: str x[[REG]], [x1] 440 ; CHECK: ret 441 %ptr = getelementptr inbounds i8, i8* %src, i64 1 442 %tmp = load i8, i8* %ptr, align 4 443 %ext = zext i8 %tmp to i64 444 store i64 %ext, i64* %out, align 4 445 ret i8* %ptr 446 } 447 448 define i32* @preidx32sext64(i32* %src, i64* %out) { 449 ; CHECK: ldrsw x[[REG:[0-9]+]], [x0, #4]! 450 ; CHECK: str x[[REG]], [x1] 451 ; CHECK: ret 452 %ptr = getelementptr inbounds i32, i32* %src, i64 1 453 %tmp = load i32, i32* %ptr, align 4 454 %ext = sext i32 %tmp to i64 455 store i64 %ext, i64* %out, align 8 456 ret i32* %ptr 457 } 458 459 define i16* @preidx16sext32(i16* %src, i32* %out) { 460 ; CHECK: ldrsh w[[REG:[0-9]+]], [x0, #2]! 461 ; CHECK: str w[[REG]], [x1] 462 ; CHECK: ret 463 %ptr = getelementptr inbounds i16, i16* %src, i64 1 464 %tmp = load i16, i16* %ptr, align 4 465 %ext = sext i16 %tmp to i32 466 store i32 %ext, i32* %out, align 4 467 ret i16* %ptr 468 } 469 470 define i16* @preidx16sext64(i16* %src, i64* %out) { 471 ; CHECK: ldrsh x[[REG:[0-9]+]], [x0, #2]! 472 ; CHECK: str x[[REG]], [x1] 473 ; CHECK: ret 474 %ptr = getelementptr inbounds i16, i16* %src, i64 1 475 %tmp = load i16, i16* %ptr, align 4 476 %ext = sext i16 %tmp to i64 477 store i64 %ext, i64* %out, align 4 478 ret i16* %ptr 479 } 480 481 define i8* @preidx8sext32(i8* %src, i32* %out) { 482 ; CHECK: ldrsb w[[REG:[0-9]+]], [x0, #1]! 483 ; CHECK: str w[[REG]], [x1] 484 ; CHECK: ret 485 %ptr = getelementptr inbounds i8, i8* %src, i64 1 486 %tmp = load i8, i8* %ptr, align 4 487 %ext = sext i8 %tmp to i32 488 store i32 %ext, i32* %out, align 4 489 ret i8* %ptr 490 } 491 492 define i8* @preidx8sext64(i8* %src, i64* %out) { 493 ; CHECK: ldrsb x[[REG:[0-9]+]], [x0, #1]! 494 ; CHECK: str x[[REG]], [x1] 495 ; CHECK: ret 496 %ptr = getelementptr inbounds i8, i8* %src, i64 1 497 %tmp = load i8, i8* %ptr, align 4 498 %ext = sext i8 %tmp to i64 499 store i64 %ext, i64* %out, align 4 500 ret i8* %ptr 501 } 502 503 ; This test checks if illegal post-index is generated 504 505 define i64* @postidx_clobber(i64* %addr) nounwind noinline ssp { 506 ; CHECK-LABEL: postidx_clobber: 507 ; CHECK-NOT: str x0, [x0], #8 508 ; ret 509 %paddr = bitcast i64* %addr to i64** 510 store i64* %addr, i64** %paddr 511 %newaddr = getelementptr i64, i64* %addr, i32 1 512 ret i64* %newaddr 513 } 514