1 ; RUN: llc -mtriple=aarch64-apple-darwin -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=SDAG 2 ; RUN: llc -mtriple=aarch64-apple-darwin -fast-isel -fast-isel-abort=1 -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK --check-prefix=FAST 3 4 ; Load / Store Base Register only 5 define zeroext i1 @load_breg_i1(i1* %a) { 6 ; CHECK-LABEL: load_breg_i1 7 ; CHECK: ldrb {{w[0-9]+}}, [x0] 8 %1 = load i1, i1* %a 9 ret i1 %1 10 } 11 12 define zeroext i8 @load_breg_i8(i8* %a) { 13 ; CHECK-LABEL: load_breg_i8 14 ; CHECK: ldrb {{w[0-9]+}}, [x0] 15 %1 = load i8, i8* %a 16 ret i8 %1 17 } 18 19 define zeroext i16 @load_breg_i16(i16* %a) { 20 ; CHECK-LABEL: load_breg_i16 21 ; CHECK: ldrh {{w[0-9]+}}, [x0] 22 %1 = load i16, i16* %a 23 ret i16 %1 24 } 25 26 define i32 @load_breg_i32(i32* %a) { 27 ; CHECK-LABEL: load_breg_i32 28 ; CHECK: ldr {{w[0-9]+}}, [x0] 29 %1 = load i32, i32* %a 30 ret i32 %1 31 } 32 33 define i64 @load_breg_i64(i64* %a) { 34 ; CHECK-LABEL: load_breg_i64 35 ; CHECK: ldr {{x[0-9]+}}, [x0] 36 %1 = load i64, i64* %a 37 ret i64 %1 38 } 39 40 define float @load_breg_f32(float* %a) { 41 ; CHECK-LABEL: load_breg_f32 42 ; CHECK: ldr {{s[0-9]+}}, [x0] 43 %1 = load float, float* %a 44 ret float %1 45 } 46 47 define double @load_breg_f64(double* %a) { 48 ; CHECK-LABEL: load_breg_f64 49 ; CHECK: ldr {{d[0-9]+}}, [x0] 50 %1 = load double, double* %a 51 ret double %1 52 } 53 54 define void @store_breg_i1(i1* %a) { 55 ; CHECK-LABEL: store_breg_i1 56 ; CHECK: strb wzr, [x0] 57 store i1 0, i1* %a 58 ret void 59 } 60 61 define void @store_breg_i1_2(i1* %a) { 62 ; CHECK-LABEL: store_breg_i1_2 63 ; CHECK: strb {{w[0-9]+}}, [x0] 64 store i1 true, i1* %a 65 ret void 66 } 67 68 define void @store_breg_i8(i8* %a) { 69 ; CHECK-LABEL: store_breg_i8 70 ; CHECK: strb wzr, [x0] 71 store i8 0, i8* %a 72 ret void 73 } 74 75 define void @store_breg_i16(i16* %a) { 76 ; CHECK-LABEL: store_breg_i16 77 ; CHECK: strh wzr, [x0] 78 store i16 0, i16* %a 79 ret void 80 } 81 82 define void @store_breg_i32(i32* %a) { 83 ; CHECK-LABEL: store_breg_i32 84 ; CHECK: str wzr, [x0] 85 store i32 0, i32* %a 86 ret void 87 } 88 89 define void @store_breg_i64(i64* %a) { 90 ; CHECK-LABEL: store_breg_i64 91 ; CHECK: str xzr, [x0] 92 store i64 0, i64* %a 93 ret void 94 } 95 96 define void @store_breg_f32(float* %a) { 97 ; CHECK-LABEL: store_breg_f32 98 ; CHECK: str wzr, [x0] 99 store float 0.0, float* %a 100 ret void 101 } 102 103 define void @store_breg_f64(double* %a) { 104 ; CHECK-LABEL: store_breg_f64 105 ; CHECK: str xzr, [x0] 106 store double 0.0, double* %a 107 ret void 108 } 109 110 ; Load Immediate 111 define i32 @load_immoff_1() { 112 ; CHECK-LABEL: load_immoff_1 113 ; CHECK: orr {{w|x}}[[REG:[0-9]+]], {{wzr|xzr}}, #0x80 114 ; CHECK: ldr {{w[0-9]+}}, {{\[}}x[[REG]]{{\]}} 115 %1 = inttoptr i64 128 to i32* 116 %2 = load i32, i32* %1 117 ret i32 %2 118 } 119 120 ; Load / Store Base Register + Immediate Offset 121 ; Max supported negative offset 122 define i32 @load_breg_immoff_1(i64 %a) { 123 ; CHECK-LABEL: load_breg_immoff_1 124 ; CHECK: ldur {{w[0-9]+}}, [x0, #-256] 125 %1 = add i64 %a, -256 126 %2 = inttoptr i64 %1 to i32* 127 %3 = load i32, i32* %2 128 ret i32 %3 129 } 130 131 ; Min not-supported negative offset 132 define i32 @load_breg_immoff_2(i64 %a) { 133 ; CHECK-LABEL: load_breg_immoff_2 134 ; CHECK: sub [[REG:x[0-9]+]], x0, #257 135 ; CHECK-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}} 136 %1 = add i64 %a, -257 137 %2 = inttoptr i64 %1 to i32* 138 %3 = load i32, i32* %2 139 ret i32 %3 140 } 141 142 ; Max supported unscaled offset 143 define i32 @load_breg_immoff_3(i64 %a) { 144 ; CHECK-LABEL: load_breg_immoff_3 145 ; CHECK: ldur {{w[0-9]+}}, [x0, #255] 146 %1 = add i64 %a, 255 147 %2 = inttoptr i64 %1 to i32* 148 %3 = load i32, i32* %2 149 ret i32 %3 150 } 151 152 ; Min un-supported unscaled offset 153 define i32 @load_breg_immoff_4(i64 %a) { 154 ; CHECK-LABEL: load_breg_immoff_4 155 ; CHECK: add [[REG:x[0-9]+]], x0, #257 156 ; CHECK-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}} 157 %1 = add i64 %a, 257 158 %2 = inttoptr i64 %1 to i32* 159 %3 = load i32, i32* %2 160 ret i32 %3 161 } 162 163 ; Max supported scaled offset 164 define i32 @load_breg_immoff_5(i64 %a) { 165 ; CHECK-LABEL: load_breg_immoff_5 166 ; CHECK: ldr {{w[0-9]+}}, [x0, #16380] 167 %1 = add i64 %a, 16380 168 %2 = inttoptr i64 %1 to i32* 169 %3 = load i32, i32* %2 170 ret i32 %3 171 } 172 173 ; Min un-supported scaled offset 174 define i32 @load_breg_immoff_6(i64 %a) { 175 ; SDAG-LABEL: load_breg_immoff_6 176 ; SDAG: orr w[[NUM:[0-9]+]], wzr, #0x4000 177 ; SDAG-NEXT: ldr {{w[0-9]+}}, [x0, x[[NUM]]] 178 ; FAST-LABEL: load_breg_immoff_6 179 ; FAST: add [[REG:x[0-9]+]], x0, #4, lsl #12 180 ; FAST-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}} 181 %1 = add i64 %a, 16384 182 %2 = inttoptr i64 %1 to i32* 183 %3 = load i32, i32* %2 184 ret i32 %3 185 } 186 187 ; Max supported negative offset 188 define void @store_breg_immoff_1(i64 %a) { 189 ; CHECK-LABEL: store_breg_immoff_1 190 ; CHECK: stur wzr, [x0, #-256] 191 %1 = add i64 %a, -256 192 %2 = inttoptr i64 %1 to i32* 193 store i32 0, i32* %2 194 ret void 195 } 196 197 ; Min not-supported negative offset 198 define void @store_breg_immoff_2(i64 %a) { 199 ; CHECK-LABEL: store_breg_immoff_2 200 ; CHECK: sub [[REG:x[0-9]+]], x0, #257 201 ; CHECK-NEXT: str wzr, {{\[}}[[REG]]{{\]}} 202 %1 = add i64 %a, -257 203 %2 = inttoptr i64 %1 to i32* 204 store i32 0, i32* %2 205 ret void 206 } 207 208 ; Max supported unscaled offset 209 define void @store_breg_immoff_3(i64 %a) { 210 ; CHECK-LABEL: store_breg_immoff_3 211 ; CHECK: stur wzr, [x0, #255] 212 %1 = add i64 %a, 255 213 %2 = inttoptr i64 %1 to i32* 214 store i32 0, i32* %2 215 ret void 216 } 217 218 ; Min un-supported unscaled offset 219 define void @store_breg_immoff_4(i64 %a) { 220 ; CHECK-LABEL: store_breg_immoff_4 221 ; CHECK: add [[REG:x[0-9]+]], x0, #257 222 ; CHECK-NEXT: str wzr, {{\[}}[[REG]]{{\]}} 223 %1 = add i64 %a, 257 224 %2 = inttoptr i64 %1 to i32* 225 store i32 0, i32* %2 226 ret void 227 } 228 229 ; Max supported scaled offset 230 define void @store_breg_immoff_5(i64 %a) { 231 ; CHECK-LABEL: store_breg_immoff_5 232 ; CHECK: str wzr, [x0, #16380] 233 %1 = add i64 %a, 16380 234 %2 = inttoptr i64 %1 to i32* 235 store i32 0, i32* %2 236 ret void 237 } 238 239 ; Min un-supported scaled offset 240 define void @store_breg_immoff_6(i64 %a) { 241 ; SDAG-LABEL: store_breg_immoff_6 242 ; SDAG: orr w[[NUM:[0-9]+]], wzr, #0x4000 243 ; SDAG-NEXT: str wzr, [x0, x[[NUM]]] 244 ; FAST-LABEL: store_breg_immoff_6 245 ; FAST: add [[REG:x[0-9]+]], x0, #4, lsl #12 246 ; FAST-NEXT: str wzr, {{\[}}[[REG]]{{\]}} 247 %1 = add i64 %a, 16384 248 %2 = inttoptr i64 %1 to i32* 249 store i32 0, i32* %2 250 ret void 251 } 252 253 define i64 @load_breg_immoff_7(i64 %a) { 254 ; CHECK-LABEL: load_breg_immoff_7 255 ; CHECK: ldr {{x[0-9]+}}, [x0, #48] 256 %1 = add i64 %a, 48 257 %2 = inttoptr i64 %1 to i64* 258 %3 = load i64, i64* %2 259 ret i64 %3 260 } 261 262 ; Flip add operands 263 define i64 @load_breg_immoff_8(i64 %a) { 264 ; CHECK-LABEL: load_breg_immoff_8 265 ; CHECK: ldr {{x[0-9]+}}, [x0, #48] 266 %1 = add i64 48, %a 267 %2 = inttoptr i64 %1 to i64* 268 %3 = load i64, i64* %2 269 ret i64 %3 270 } 271 272 ; Load Base Register + Register Offset 273 define i64 @load_breg_offreg_1(i64 %a, i64 %b) { 274 ; CHECK-LABEL: load_breg_offreg_1 275 ; CHECK: ldr {{x[0-9]+}}, [x0, x1] 276 %1 = add i64 %a, %b 277 %2 = inttoptr i64 %1 to i64* 278 %3 = load i64, i64* %2 279 ret i64 %3 280 } 281 282 ; Flip add operands 283 define i64 @load_breg_offreg_2(i64 %a, i64 %b) { 284 ; CHECK-LABEL: load_breg_offreg_2 285 ; CHECK: ldr {{x[0-9]+}}, [x1, x0] 286 %1 = add i64 %b, %a 287 %2 = inttoptr i64 %1 to i64* 288 %3 = load i64, i64* %2 289 ret i64 %3 290 } 291 292 ; Load Base Register + Register Offset + Immediate Offset 293 define i64 @load_breg_offreg_immoff_1(i64 %a, i64 %b) { 294 ; CHECK-LABEL: load_breg_offreg_immoff_1 295 ; CHECK: add [[REG:x[0-9]+]], x0, x1 296 ; CHECK-NEXT: ldr x0, {{\[}}[[REG]], #48{{\]}} 297 %1 = add i64 %a, %b 298 %2 = add i64 %1, 48 299 %3 = inttoptr i64 %2 to i64* 300 %4 = load i64, i64* %3 301 ret i64 %4 302 } 303 304 define i64 @load_breg_offreg_immoff_2(i64 %a, i64 %b) { 305 ; SDAG-LABEL: load_breg_offreg_immoff_2 306 ; SDAG: add [[REG1:x[0-9]+]], x0, x1 307 ; SDAG-NEXT: orr w[[NUM:[0-9]+]], wzr, #0xf000 308 ; SDAG-NEXT: ldr x0, {{\[}}[[REG1]], x[[NUM]]] 309 ; FAST-LABEL: load_breg_offreg_immoff_2 310 ; FAST: add [[REG:x[0-9]+]], x0, #15, lsl #12 311 ; FAST-NEXT: ldr x0, {{\[}}[[REG]], x1{{\]}} 312 %1 = add i64 %a, %b 313 %2 = add i64 %1, 61440 314 %3 = inttoptr i64 %2 to i64* 315 %4 = load i64, i64* %3 316 ret i64 %4 317 } 318 319 ; Load Scaled Register Offset 320 define i32 @load_shift_offreg_1(i64 %a) { 321 ; CHECK-LABEL: load_shift_offreg_1 322 ; CHECK: lsl [[REG:x[0-9]+]], x0, #2 323 ; CHECK: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}} 324 %1 = shl i64 %a, 2 325 %2 = inttoptr i64 %1 to i32* 326 %3 = load i32, i32* %2 327 ret i32 %3 328 } 329 330 define i32 @load_mul_offreg_1(i64 %a) { 331 ; CHECK-LABEL: load_mul_offreg_1 332 ; CHECK: lsl [[REG:x[0-9]+]], x0, #2 333 ; CHECK: ldr {{w[0-9]+}}, {{\[}}[[REG]]{{\]}} 334 %1 = mul i64 %a, 4 335 %2 = inttoptr i64 %1 to i32* 336 %3 = load i32, i32* %2 337 ret i32 %3 338 } 339 340 ; Load Base Register + Scaled Register Offset 341 define i32 @load_breg_shift_offreg_1(i64 %a, i64 %b) { 342 ; CHECK-LABEL: load_breg_shift_offreg_1 343 ; CHECK: ldr {{w[0-9]+}}, [x1, x0, lsl #2] 344 %1 = shl i64 %a, 2 345 %2 = add i64 %1, %b 346 %3 = inttoptr i64 %2 to i32* 347 %4 = load i32, i32* %3 348 ret i32 %4 349 } 350 351 define i32 @load_breg_shift_offreg_2(i64 %a, i64 %b) { 352 ; CHECK-LABEL: load_breg_shift_offreg_2 353 ; CHECK: ldr {{w[0-9]+}}, [x1, x0, lsl #2] 354 %1 = shl i64 %a, 2 355 %2 = add i64 %b, %1 356 %3 = inttoptr i64 %2 to i32* 357 %4 = load i32, i32* %3 358 ret i32 %4 359 } 360 361 define i32 @load_breg_shift_offreg_3(i64 %a, i64 %b) { 362 ; SDAG-LABEL: load_breg_shift_offreg_3 363 ; SDAG: lsl [[REG:x[0-9]+]], x0, #2 364 ; SDAG-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x1, lsl #2{{\]}} 365 ; FAST-LABEL: load_breg_shift_offreg_3 366 ; FAST: lsl [[REG:x[0-9]+]], x1, #2 367 ; FAST-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}} 368 %1 = shl i64 %a, 2 369 %2 = shl i64 %b, 2 370 %3 = add i64 %1, %2 371 %4 = inttoptr i64 %3 to i32* 372 %5 = load i32, i32* %4 373 ret i32 %5 374 } 375 376 define i32 @load_breg_shift_offreg_4(i64 %a, i64 %b) { 377 ; SDAG-LABEL: load_breg_shift_offreg_4 378 ; SDAG: lsl [[REG:x[0-9]+]], x1, #2 379 ; SDAG-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}} 380 ; FAST-LABEL: load_breg_shift_offreg_4 381 ; FAST: lsl [[REG:x[0-9]+]], x0, #2 382 ; FAST-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x1, lsl #2{{\]}} 383 %1 = shl i64 %a, 2 384 %2 = shl i64 %b, 2 385 %3 = add i64 %2, %1 386 %4 = inttoptr i64 %3 to i32* 387 %5 = load i32, i32* %4 388 ret i32 %5 389 } 390 391 define i32 @load_breg_shift_offreg_5(i64 %a, i64 %b) { 392 ; SDAG-LABEL: load_breg_shift_offreg_5 393 ; SDAG: lsl [[REG:x[0-9]+]], x1, #3 394 ; SDAG-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}} 395 ; FAST-LABEL: load_breg_shift_offreg_5 396 ; FAST: lsl [[REG:x[0-9]+]], x1, #3 397 ; FAST-NEXT: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}} 398 %1 = shl i64 %a, 2 399 %2 = shl i64 %b, 3 400 %3 = add i64 %1, %2 401 %4 = inttoptr i64 %3 to i32* 402 %5 = load i32, i32* %4 403 ret i32 %5 404 } 405 406 define i32 @load_breg_mul_offreg_1(i64 %a, i64 %b) { 407 ; CHECK-LABEL: load_breg_mul_offreg_1 408 ; CHECK: ldr {{w[0-9]+}}, [x1, x0, lsl #2] 409 %1 = mul i64 %a, 4 410 %2 = add i64 %1, %b 411 %3 = inttoptr i64 %2 to i32* 412 %4 = load i32, i32* %3 413 ret i32 %4 414 } 415 416 define zeroext i8 @load_breg_and_offreg_1(i64 %a, i64 %b) { 417 ; CHECK-LABEL: load_breg_and_offreg_1 418 ; CHECK: ldrb {{w[0-9]+}}, [x1, w0, uxtw] 419 %1 = and i64 %a, 4294967295 420 %2 = add i64 %1, %b 421 %3 = inttoptr i64 %2 to i8* 422 %4 = load i8, i8* %3 423 ret i8 %4 424 } 425 426 define zeroext i16 @load_breg_and_offreg_2(i64 %a, i64 %b) { 427 ; CHECK-LABEL: load_breg_and_offreg_2 428 ; CHECK: ldrh {{w[0-9]+}}, [x1, w0, uxtw #1] 429 %1 = and i64 %a, 4294967295 430 %2 = shl i64 %1, 1 431 %3 = add i64 %2, %b 432 %4 = inttoptr i64 %3 to i16* 433 %5 = load i16, i16* %4 434 ret i16 %5 435 } 436 437 define i32 @load_breg_and_offreg_3(i64 %a, i64 %b) { 438 ; CHECK-LABEL: load_breg_and_offreg_3 439 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, uxtw #2] 440 %1 = and i64 %a, 4294967295 441 %2 = shl i64 %1, 2 442 %3 = add i64 %2, %b 443 %4 = inttoptr i64 %3 to i32* 444 %5 = load i32, i32* %4 445 ret i32 %5 446 } 447 448 define i64 @load_breg_and_offreg_4(i64 %a, i64 %b) { 449 ; CHECK-LABEL: load_breg_and_offreg_4 450 ; CHECK: ldr {{x[0-9]+}}, [x1, w0, uxtw #3] 451 %1 = and i64 %a, 4294967295 452 %2 = shl i64 %1, 3 453 %3 = add i64 %2, %b 454 %4 = inttoptr i64 %3 to i64* 455 %5 = load i64, i64* %4 456 ret i64 %5 457 } 458 459 ; Not all 'and' instructions have immediates. 460 define i64 @load_breg_and_offreg_5(i64 %a, i64 %b, i64 %c) { 461 ; CHECK-LABEL: load_breg_and_offreg_5 462 ; CHECK: and [[REG:x[0-9]+]], x0, x2 463 ; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}[[REG]], x1{{\]}} 464 %1 = and i64 %a, %c 465 %2 = add i64 %1, %b 466 %3 = inttoptr i64 %2 to i64* 467 %4 = load i64, i64* %3 468 ret i64 %4 469 } 470 471 define i64 @load_breg_and_offreg_6(i64 %a, i64 %b, i64 %c) { 472 ; CHECK-LABEL: load_breg_and_offreg_6 473 ; CHECK: and [[REG:x[0-9]+]], x0, x2 474 ; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}x1, [[REG]], lsl #3{{\]}} 475 %1 = and i64 %a, %c 476 %2 = shl i64 %1, 3 477 %3 = add i64 %2, %b 478 %4 = inttoptr i64 %3 to i64* 479 %5 = load i64, i64* %4 480 ret i64 %5 481 } 482 483 ; Load Base Register + Scaled Register Offset + Sign/Zero extension 484 define i32 @load_breg_zext_shift_offreg_1(i32 %a, i64 %b) { 485 ; CHECK-LABEL: load_breg_zext_shift_offreg_1 486 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, uxtw #2] 487 %1 = zext i32 %a to i64 488 %2 = shl i64 %1, 2 489 %3 = add i64 %2, %b 490 %4 = inttoptr i64 %3 to i32* 491 %5 = load i32, i32* %4 492 ret i32 %5 493 } 494 495 define i32 @load_breg_zext_shift_offreg_2(i32 %a, i64 %b) { 496 ; CHECK-LABEL: load_breg_zext_shift_offreg_2 497 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, uxtw #2] 498 %1 = zext i32 %a to i64 499 %2 = shl i64 %1, 2 500 %3 = add i64 %b, %2 501 %4 = inttoptr i64 %3 to i32* 502 %5 = load i32, i32* %4 503 ret i32 %5 504 } 505 506 define i32 @load_breg_zext_mul_offreg_1(i32 %a, i64 %b) { 507 ; CHECK-LABEL: load_breg_zext_mul_offreg_1 508 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, uxtw #2] 509 %1 = zext i32 %a to i64 510 %2 = mul i64 %1, 4 511 %3 = add i64 %2, %b 512 %4 = inttoptr i64 %3 to i32* 513 %5 = load i32, i32* %4 514 ret i32 %5 515 } 516 517 define i32 @load_breg_sext_shift_offreg_1(i32 %a, i64 %b) { 518 ; CHECK-LABEL: load_breg_sext_shift_offreg_1 519 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, sxtw #2] 520 %1 = sext i32 %a to i64 521 %2 = shl i64 %1, 2 522 %3 = add i64 %2, %b 523 %4 = inttoptr i64 %3 to i32* 524 %5 = load i32, i32* %4 525 ret i32 %5 526 } 527 528 define i32 @load_breg_sext_shift_offreg_2(i32 %a, i64 %b) { 529 ; CHECK-LABEL: load_breg_sext_shift_offreg_2 530 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, sxtw #2] 531 %1 = sext i32 %a to i64 532 %2 = shl i64 %1, 2 533 %3 = add i64 %b, %2 534 %4 = inttoptr i64 %3 to i32* 535 %5 = load i32, i32* %4 536 ret i32 %5 537 } 538 539 ; Make sure that we don't drop the first 'add' instruction. 540 define i32 @load_breg_sext_shift_offreg_3(i32 %a, i64 %b) { 541 ; CHECK-LABEL: load_breg_sext_shift_offreg_3 542 ; CHECK: add [[REG:w[0-9]+]], w0, #4 543 ; CHECK: ldr {{w[0-9]+}}, {{\[}}x1, [[REG]], sxtw #2{{\]}} 544 %1 = add i32 %a, 4 545 %2 = sext i32 %1 to i64 546 %3 = shl i64 %2, 2 547 %4 = add i64 %b, %3 548 %5 = inttoptr i64 %4 to i32* 549 %6 = load i32, i32* %5 550 ret i32 %6 551 } 552 553 554 define i32 @load_breg_sext_mul_offreg_1(i32 %a, i64 %b) { 555 ; CHECK-LABEL: load_breg_sext_mul_offreg_1 556 ; CHECK: ldr {{w[0-9]+}}, [x1, w0, sxtw #2] 557 %1 = sext i32 %a to i64 558 %2 = mul i64 %1, 4 559 %3 = add i64 %2, %b 560 %4 = inttoptr i64 %3 to i32* 561 %5 = load i32, i32* %4 562 ret i32 %5 563 } 564 565 ; Load Scaled Register Offset + Immediate Offset + Sign/Zero extension 566 define i64 @load_sext_shift_offreg_imm1(i32 %a) { 567 ; CHECK-LABEL: load_sext_shift_offreg_imm1 568 ; CHECK: sbfiz [[REG:x[0-9]+]], {{x[0-9]+}}, #3, #32 569 ; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}[[REG]], #8{{\]}} 570 %1 = sext i32 %a to i64 571 %2 = shl i64 %1, 3 572 %3 = add i64 %2, 8 573 %4 = inttoptr i64 %3 to i64* 574 %5 = load i64, i64* %4 575 ret i64 %5 576 } 577 578 ; Load Base Register + Scaled Register Offset + Immediate Offset + Sign/Zero extension 579 define i64 @load_breg_sext_shift_offreg_imm1(i32 %a, i64 %b) { 580 ; CHECK-LABEL: load_breg_sext_shift_offreg_imm1 581 ; CHECK: add [[REG:x[0-9]+]], x1, w0, sxtw #3 582 ; CHECK-NEXT: ldr {{x[0-9]+}}, {{\[}}[[REG]], #8{{\]}} 583 %1 = sext i32 %a to i64 584 %2 = shl i64 %1, 3 585 %3 = add i64 %b, %2 586 %4 = add i64 %3, 8 587 %5 = inttoptr i64 %4 to i64* 588 %6 = load i64, i64* %5 589 ret i64 %6 590 } 591 592 ; Test that the kill flag is not set - the machine instruction verifier does that for us. 593 define i64 @kill_reg(i64 %a) { 594 %1 = sub i64 %a, 8 595 %2 = add i64 %1, 96 596 %3 = inttoptr i64 %2 to i64* 597 %4 = load i64, i64* %3 598 %5 = add i64 %2, %4 599 ret i64 %5 600 } 601 602 define void @store_fi(i64 %i) { 603 ; CHECK-LABEL: store_fi 604 ; CHECK: mov [[REG:x[0-9]+]], sp 605 ; CHECK: str {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}} 606 %1 = alloca [8 x i32] 607 %2 = ptrtoint [8 x i32]* %1 to i64 608 %3 = mul i64 %i, 4 609 %4 = add i64 %2, %3 610 %5 = inttoptr i64 %4 to i32* 611 store i32 47, i32* %5, align 4 612 ret void 613 } 614 615 define i32 @load_fi(i64 %i) { 616 ; CHECK-LABEL: load_fi 617 ; CHECK: mov [[REG:x[0-9]+]], sp 618 ; CHECK: ldr {{w[0-9]+}}, {{\[}}[[REG]], x0, lsl #2{{\]}} 619 %1 = alloca [8 x i32] 620 %2 = ptrtoint [8 x i32]* %1 to i64 621 %3 = mul i64 %i, 4 622 %4 = add i64 %2, %3 623 %5 = inttoptr i64 %4 to i32* 624 %6 = load i32, i32* %5, align 4 625 ret i32 %6 626 } 627 628