1; RUN: llc < %s -mtriple=arm64-eabi -aarch64-redzone | FileCheck %s 2 3define 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 12define 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 22define 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 31define 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 40define 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 50define 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 59define 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 68define 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 78define 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 87define 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 96define 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 106define 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 115define 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 125define 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 135define 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 146define 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 155define 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 164define 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 174define 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 183define 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 192define 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 201define 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 210define 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 221define 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 230define 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 239define 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 250define 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 259define 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 268define 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 279define 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 288define 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 297define 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 308define 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 317define 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 327define 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 337define 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;----- 350define 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 361define 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 372define 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 383define 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 394define 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 404define 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 415define 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 426define 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 437define 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 448define 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 459define 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 470define 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 481define 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 492define 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 505define 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