| ; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 6 | |
| ; RUN: llc -O1 -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,O1 | |
| ; RUN: llc -O0 -mtriple=aarch64 -verify-machineinstrs %s -o - | FileCheck %s --check-prefixes=CHECK,O0 | |
| ; Adapt the cases in RISCV/local-stack-slot-allocation.ll for AArch64. | |
| ; This test case test the LocalStackSlotAllocation pass that use a base register | |
| ; for the frame index that its offset is out-of-range (for AArch64 the immediate | |
| ; is 12 bits for the load store instruction (excludes vector load / store)) | |
| define void @use_frame_base_reg() { | |
| ; O1-LABEL: use_frame_base_reg: | |
| ; O1: // %bb.0: | |
| ; O1-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill | |
| ; O1-NEXT: sub sp, sp, #24, lsl #12 // =98304 | |
| ; O1-NEXT: sub sp, sp, #1712 | |
| ; O1-NEXT: .cfi_def_cfa_offset 100032 | |
| ; O1-NEXT: .cfi_offset w29, -16 | |
| ; O1-NEXT: add x8, sp, #24, lsl #12 // =98304 | |
| ; O1-NEXT: add x8, x8, #1704 | |
| ; O1-NEXT: ldrb wzr, [x8, #4] | |
| ; O1-NEXT: ldrb wzr, [x8] | |
| ; O1-NEXT: add sp, sp, #24, lsl #12 // =98304 | |
| ; O1-NEXT: add sp, sp, #1712 | |
| ; O1-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload | |
| ; O1-NEXT: ret | |
| ; | |
| ; O0-LABEL: use_frame_base_reg: | |
| ; O0: // %bb.0: | |
| ; O0-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill | |
| ; O0-NEXT: sub sp, sp, #24, lsl #12 // =98304 | |
| ; O0-NEXT: sub sp, sp, #1712 | |
| ; O0-NEXT: .cfi_def_cfa_offset 100032 | |
| ; O0-NEXT: .cfi_offset w29, -16 | |
| ; O0-NEXT: add x8, sp, #24, lsl #12 // =98304 | |
| ; O0-NEXT: ldrb w8, [x8, #1708] | |
| ; O0-NEXT: add x8, sp, #24, lsl #12 // =98304 | |
| ; O0-NEXT: ldrb w8, [x8, #1704] | |
| ; O0-NEXT: add sp, sp, #24, lsl #12 // =98304 | |
| ; O0-NEXT: add sp, sp, #1712 | |
| ; O0-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload | |
| ; O0-NEXT: ret | |
| %va = alloca i8, align 4 | |
| %va1 = alloca i8, align 4 | |
| %large = alloca [ 100000 x i8 ] | |
| %argp.cur = load volatile i8, ptr %va, align 4 | |
| %argp.next = load volatile i8, ptr %va1, align 4 | |
| ret void | |
| } | |
| ; Test containing a load with its own local offset. Make sure isFrameOffsetLegal | |
| ; considers it and creates a virtual base register. | |
| define void @load_with_offset() { | |
| ; O1-LABEL: load_with_offset: | |
| ; O1: // %bb.0: | |
| ; O1-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill | |
| ; O1-NEXT: sub sp, sp, #1, lsl #12 // =4096 | |
| ; O1-NEXT: sub sp, sp, #912 | |
| ; O1-NEXT: .cfi_def_cfa_offset 5024 | |
| ; O1-NEXT: .cfi_offset w29, -16 | |
| ; O1-NEXT: add x8, sp, #8 | |
| ; O1-NEXT: ldrb w9, [x8, #4088] | |
| ; O1-NEXT: strb w9, [x8, #4088] | |
| ; O1-NEXT: add sp, sp, #1, lsl #12 // =4096 | |
| ; O1-NEXT: add sp, sp, #912 | |
| ; O1-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload | |
| ; O1-NEXT: ret | |
| ; | |
| ; O0-LABEL: load_with_offset: | |
| ; O0: // %bb.0: | |
| ; O0-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill | |
| ; O0-NEXT: sub sp, sp, #1, lsl #12 // =4096 | |
| ; O0-NEXT: sub sp, sp, #912 | |
| ; O0-NEXT: .cfi_def_cfa_offset 5024 | |
| ; O0-NEXT: .cfi_offset w29, -16 | |
| ; O0-NEXT: add x8, sp, #1, lsl #12 // =4096 | |
| ; O0-NEXT: ldrb w8, [x8] | |
| ; O0-NEXT: add x9, sp, #1, lsl #12 // =4096 | |
| ; O0-NEXT: strb w8, [x9] | |
| ; O0-NEXT: add sp, sp, #1, lsl #12 // =4096 | |
| ; O0-NEXT: add sp, sp, #912 | |
| ; O0-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload | |
| ; O0-NEXT: ret | |
| %va = alloca [5000 x i8], align 4 | |
| %va_gep = getelementptr [5000 x i8], ptr %va, i64 0, i64 4088 | |
| %load = load volatile i8, ptr %va_gep, align 4 | |
| store volatile i8 %load, ptr %va_gep, align 4 | |
| ret void | |
| } | |
| ; Test containing a load with its own local offset that is smaller than the | |
| ; previous test case. Make sure we don't create a virtual base register. | |
| define void @load_with_offset2() { | |
| ; CHECK-LABEL: load_with_offset2: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: str x29, [sp, #-16]! // 8-byte Folded Spill | |
| ; CHECK-NEXT: sub sp, sp, #2512 | |
| ; CHECK-NEXT: .cfi_def_cfa_offset 2528 | |
| ; CHECK-NEXT: .cfi_offset w29, -16 | |
| ; CHECK-NEXT: ldrb w8, [sp, #1412] | |
| ; CHECK-NEXT: strb w8, [sp, #1412] | |
| ; CHECK-NEXT: add sp, sp, #2512 | |
| ; CHECK-NEXT: ldr x29, [sp], #16 // 8-byte Folded Reload | |
| ; CHECK-NEXT: ret | |
| %va = alloca [2500 x i8], align 4 | |
| %va_gep = getelementptr [2000 x i8], ptr %va, i64 0, i64 1400 | |
| %load = load volatile i8, ptr %va_gep, align 4 | |
| store volatile i8 %load, ptr %va_gep, align 4 | |
| ret void | |
| } | |
| define void @frame_pointer() "frame-pointer"="all" { | |
| ; CHECK-LABEL: frame_pointer: | |
| ; CHECK: // %bb.0: | |
| ; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill | |
| ; CHECK-NEXT: mov x29, sp | |
| ; CHECK-NEXT: sub sp, sp, #2512 | |
| ; CHECK-NEXT: .cfi_def_cfa w29, 16 | |
| ; CHECK-NEXT: .cfi_offset w30, -8 | |
| ; CHECK-NEXT: .cfi_offset w29, -16 | |
| ; CHECK-NEXT: ldrb w8, [sp, #564] | |
| ; CHECK-NEXT: strb w8, [sp, #564] | |
| ; CHECK-NEXT: add sp, sp, #2512 | |
| ; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload | |
| ; CHECK-NEXT: ret | |
| %va = alloca [2500 x i8], align 4 | |
| %va_gep = getelementptr [2000 x i8], ptr %va, i64 0, i64 552 | |
| %load = load volatile i8, ptr %va_gep, align 4 | |
| store volatile i8 %load, ptr %va_gep, align 4 | |
| ret void | |
| } |