| # RUN: llc -mtriple=armv7-none-none-eabihf -mcpu=cortex-r5 -o - %s -run-pass=prologepilog \ |
| # RUN: | FileCheck --check-prefix=CHECK-R-ARM %s |
| # RUN: llc -mtriple=armv7-none-none-eabihf -mcpu=cortex-r4 -o - %s -run-pass=prologepilog \ |
| # RUN: | FileCheck --check-prefix=CHECK-R-ARM %s |
| # RUN: llc -mtriple=thumbv7-none-none-eabihf -mcpu=cortex-r5 -o - %s -run-pass=prologepilog \ |
| # RUN: | FileCheck --check-prefix=CHECK-R-THUMB %s |
| # RUN: llc -mtriple=thumbv7-none-none-eabihf -mcpu=cortex-r4 -o - %s -run-pass=prologepilog \ |
| # RUN: | FileCheck --check-prefix=CHECK-R-THUMB %s |
| # RUN: llc -mtriple=thumbv7-none-none-eabihf -mcpu=cortex-m3 -o - %s -run-pass=prologepilog \ |
| # RUN: | FileCheck --check-prefix=CHECK-M-THUMB %s |
| # RUN: llc -mtriple=thumbv7-none-none-eabihf -mcpu=cortex-m4 -o - %s -run-pass=prologepilog \ |
| # RUN: | FileCheck --check-prefix=CHECK-M-THUMB %s |
| # RUN: llc -mtriple=thumbv8-none-none-eabihf -mcpu=cortex-m33 -o - %s -run-pass=prologepilog \ |
| # RUN: | FileCheck --check-prefix=CHECK-M-THUMB %s |
| |
| # ============================================================================= |
| # ============================ cortex-r arm-mode ============================== |
| # ============================================================================= |
| # This IRQ will save 104 bytes: |
| # |
| # |---------+------+----------| |
| # | reg | size | zone | |
| # |---------+------+----------| |
| # | LR | 4x1 | GPR | |
| # | R12-R10 | 4x3 | | |
| # | R5-R0 | 4x6 | | |
| # |---------+------+----------| |
| # | FPEXC | 4x1 | FPStatus | |
| # | FPSCR | 4x1 | | |
| # |---------+------+----------| |
| # | D7-D0 | 8x8 | FPRegs | |
| # |---------+------+----------| |
| # | | 112 | | |
| # |---------+------+----------| |
| # |
| # ================================= Prologue ================================= |
| # |
| # Frame pointer (r11) will be store at $original_sp - 12, but we can't save the |
| # FP until after we save the GPR zone of registers. The GPR zone of registers |
| # moves the stack by 40 bytes. So $original_sp = $current_sp + 40. Thus, |
| # $current_sp + 40 - 12 = $current_sp + 28. Thus, we see the instruction: |
| # |
| # $r11 = ADDri $sp, 28 |
| # |
| # We don't have dwarf information for the FPEXC and FPSCR registers, so there's |
| # no CFI_INSTRUCTION for those saves. So, we should see an 8 byte disparity in |
| # the register offsets. $r0 is -40, and $d7 is -56. |
| # |
| # (-40) - (-56) = 16. |
| # 16 = 8 (bytes from $d7) + 8 (bytes from FPSCR + FPEXC) |
| # |
| # There's an extra BFC to force the stack to be aligned. |
| # |
| # $sp = BFC $sp, 4294967288 /* ~0x7 */ |
| # |
| # ================================= Epilogue ================================= |
| # |
| # We use the frame pointer to restore the SP. Since $r11 is currently pointing |
| # to the previous $r11's stack position (aka base_of_stack - 12), and we |
| # allocated 112 bytes, $sp = $r11 - (112 - 12), or $sp = $r11 - 100, which is |
| # why we see this instruction: |
| # |
| # $sp = SUBri $r11, 100 |
| |
| # CHECK-R-ARM-LABEL: name: irq_fn |
| # CHECK-R-ARM-LABEL: bb.0 (%ir-block.0): |
| # CHECK-R-ARM: $sp = frame-setup STMDB_UPD $sp, 14 /* CC::al */, $noreg, killed $r0, killed $r1, killed $r2, killed $r3, killed $r4, killed $r5, killed $r10, killed $r11, killed $r12, killed $lr |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 40 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -4 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $ra_auth_code, -8 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $r11, -12 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $r10, -16 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $r5, -20 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $r4, -24 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $r3, -28 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $r2, -32 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $r1, -36 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $r0, -40 |
| # CHECK-R-ARM-NEXT: $r11 = frame-setup ADDri killed $sp, 28, 14 /* CC::al */, $noreg, $noreg |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION def_cfa $r11, 12 |
| # CHECK-R-ARM-NEXT: $r4 = frame-setup VMRS 14 /* CC::al */, $noreg, implicit $fpscr |
| # CHECK-R-ARM-NEXT: $r5 = frame-setup VMRS_FPEXC 14 /* CC::al */, $noreg, implicit $fpscr |
| # CHECK-R-ARM-NEXT: $sp = frame-setup STMDB_UPD $sp, 14 /* CC::al */, $noreg, $r4, $r5 |
| # CHECK-R-ARM-NEXT: $sp = frame-setup VSTMDDB_UPD $sp, 14 /* CC::al */, $noreg, killed $d0, killed $d1, killed $d2, killed $d3, killed $d4, killed $d5, killed $d6, killed $d7 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $d7, -56 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $d6, -64 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $d5, -72 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $d4, -80 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $d3, -88 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $d2, -96 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $d1, -104 |
| # CHECK-R-ARM-NEXT: frame-setup CFI_INSTRUCTION offset $d0, -112 |
| # CHECK-R-ARM-NEXT: $sp = BFC killed $sp, 4294967288, 14 /* CC::al */, $noreg |
| # CHECK-R-ARM-NEXT: BL @bar, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp |
| # CHECK-R-ARM-NEXT: $sp = frame-destroy SUBri killed $r11, 100, 14 /* CC::al */, $noreg, $noreg |
| # CHECK-R-ARM-NEXT: $sp = frame-destroy VLDMDIA_UPD $sp, 14 /* CC::al */, $noreg, def $d0, def $d1, def $d2, def $d3, def $d4, def $d5, def $d6, def $d7 |
| # CHECK-R-ARM-NEXT: $sp = frame-destroy LDMIA_UPD $sp, 14 /* CC::al */, $noreg, def $r4, def $r5 |
| # CHECK-R-ARM-NEXT: frame-destroy VMSR $r4, 14 /* CC::al */, $noreg, implicit-def $fpscr |
| # CHECK-R-ARM-NEXT: frame-destroy VMSR_FPEXC $r5, 14 /* CC::al */, $noreg, implicit-def $fpscr |
| |
| # ============================================================================= |
| # =========================== cortex-r thumb-mode ============================= |
| # ============================================================================= |
| # This IRQ will save 112 bytes: |
| # |
| # |-------+------+----------| |
| # | reg | size | zone | |
| # |-------+------+----------| |
| # | LR | 4x1 | GPR | |
| # | R12 | 4x1 | | |
| # | R7-R0 | 4x8 | | |
| # |-------+------+----------| |
| # | FPEXC | 4x1 | FPStatus | |
| # | FPSCR | 4x1 | | |
| # |-------+------+----------| |
| # | D7-D0 | 8x8 | FPRegs | |
| # |-------+------+----------| |
| # | | 112 | | |
| # |-------+------+----------| |
| # |
| # ================================= Prologue ================================= |
| # |
| # Frame pointer (r7) will be store at $original_sp - 12, but we can't save the |
| # FP until after we save the GPR zone of registers. The GPR zone of registers |
| # moves the stack by 40 bytes. So $original_sp = $current_sp + 40. Thus, |
| # $current_sp + 40 - 12 = $current_sp + 28. Thus, we see the instruction: |
| # |
| # $r7 = t2ADDri $sp, 28 |
| # |
| # We don't have dwarf information for the FPEXC and FPSCR registers, so there's |
| # no CFI_INSTRUCTION for those saves. So, we should see an 8 byte disparity in |
| # the register offsets. $r0 is -40, and $d7 is -56. |
| # |
| # (-32) - (-48) = 16. |
| # 16 = 8 (bytes from $d7) + 8 (bytes from FPSCR + FPEXC) |
| # |
| # There's an extra BFC to force the stack to be aligned. This is done in 3 |
| # steps, because the value of $sp needs to be moved into a low register |
| # (r0-r7), and then operated on, and then moved back. |
| # |
| # $r4 = tMOVr $sp, 14 |
| # $r4 = t2BFC $r4, 4294967288 /* ~0x7 */, 14 |
| # $sp = tMOVr $r4, 14 |
| # |
| # ================================= Epilogue ================================= |
| # |
| # We use the frame pointer to restore the SP. Since $r7 is currently pointing |
| # to the previous $r7's stack position (aka base_of_stack - 12), and we |
| # allocated 112 bytes, $sp = $r7 - (112 - 12), or $sp = $r7 - 100, which is |
| # why we see this instruction: |
| # |
| # $r4 = t2SUBri $r7, 100 |
| # $sp = tMOVr $r4 |
| |
| # CHECK-R-THUMB-LABEL: name: irq_fn |
| # CHECK-R-THUMB-LABEL: bb.0 (%ir-block.0): |
| # CHECK-R-THUMB: $sp = frame-setup t2STMDB_UPD $sp, 14 /* CC::al */, $noreg, killed $r0, killed $r1, killed $r2, killed $r3, killed $r4, killed $r5, killed $r6, killed $r7, killed $r12, killed $lr |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 40 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -4 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $ra_auth_code, -8 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r7, -12 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r6, -16 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r5, -20 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r4, -24 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r3, -28 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r2, -32 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r1, -36 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r0, -40 |
| # CHECK-R-THUMB-NEXT: $r7 = frame-setup t2ADDri killed $sp, 28, 14 /* CC::al */, $noreg, $noreg |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION def_cfa $r7, 12 |
| # CHECK-R-THUMB-NEXT: $r4 = frame-setup VMRS 14 /* CC::al */, $noreg, implicit $fpscr |
| # CHECK-R-THUMB-NEXT: $r5 = frame-setup VMRS_FPEXC 14 /* CC::al */, $noreg, implicit $fpscr |
| # CHECK-R-THUMB-NEXT: $sp = frame-setup t2STMDB_UPD $sp, 14 /* CC::al */, $noreg, $r4, $r5 |
| # CHECK-R-THUMB-NEXT: $sp = frame-setup VSTMDDB_UPD $sp, 14 /* CC::al */, $noreg, killed $d0, killed $d1, killed $d2, killed $d3, killed $d4, killed $d5, killed $d6, killed $d7 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d7, -56 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d6, -64 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d5, -72 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d4, -80 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d3, -88 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d2, -96 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d1, -104 |
| # CHECK-R-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d0, -112 |
| # CHECK-R-THUMB-NEXT: $r4 = tMOVr killed $sp, 14 /* CC::al */, $noreg |
| # CHECK-R-THUMB-NEXT: $r4 = t2BFC killed $r4, 4294967288, 14 /* CC::al */, $noreg |
| # CHECK-R-THUMB-NEXT: $sp = tMOVr killed $r4, 14 /* CC::al */, $noreg |
| # CHECK-R-THUMB-NEXT: BL @bar, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp |
| # CHECK-R-THUMB-NEXT: $r4 = frame-destroy t2SUBri killed $r7, 100, 14 /* CC::al */, $noreg, $noreg |
| # CHECK-R-THUMB-NEXT: $sp = frame-destroy tMOVr $r4, 14 /* CC::al */, $noreg |
| # CHECK-R-THUMB-NEXT: $sp = frame-destroy VLDMDIA_UPD $sp, 14 /* CC::al */, $noreg, def $d0, def $d1, def $d2, def $d3, def $d4, def $d5, def $d6, def $d7 |
| # CHECK-R-THUMB-NEXT: $sp = frame-destroy t2LDMIA_UPD $sp, 14 /* CC::al */, $noreg, def $r4, def $r5 |
| # CHECK-R-THUMB-NEXT: frame-destroy VMSR $r4, 14 /* CC::al */, $noreg, implicit-def $fpscr |
| # CHECK-R-THUMB-NEXT: frame-destroy VMSR_FPEXC $r5, 14 /* CC::al */, $noreg, implicit-def $fpscr |
| # CHECK-R-THUMB-NEXT: $sp = frame-destroy t2LDMIA_UPD $sp, 14 /* CC::al */, $noreg, def $r0, def $r1, def $r2, def $r3, def $r4, def $r5, def $r6, def $r7, def $r12, def $lr |
| # CHECK-R-THUMB-NEXT: SUBS_PC_LR 4, 14 /* CC::al */, $noreg |
| |
| # ============================================================================= |
| # ============================== cortex-m thumb =============================== |
| # ============================================================================= |
| # This IRQ will save 88 bytes: |
| # |
| # |---------+------+----------| |
| # | reg | size | zone | |
| # |---------+------+----------| |
| # | LR | 4x1 | GPR | |
| # | R7-R6 | 4x2 | | |
| # | R4 | 4x1 | | |
| # |---------+------+----------| |
| # | FPSCR | 4x1 | FPStatus | |
| # |---------+------+----------| |
| # | EMPTY | 4x1 | Align | |
| # |---------+------+----------| |
| # | D7-D0 | 8x8 | FPRegs | |
| # |---------+------+----------| |
| # | | 88 | | |
| # |---------+------+----------| |
| |
| # CHECK-M-THUMB-LABEL: name: irq_fn |
| # CHECK-M-THUMB-LABEL: bb.0 (%ir-block.0): |
| # CHECK-M-THUMB: $sp = frame-setup t2STMDB_UPD $sp, 14 /* CC::al */, $noreg, killed $r4, killed $r6, killed $r7, killed $lr |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION def_cfa_offset 16 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $lr, -4 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r7, -8 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r6, -12 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $r4, -16 |
| # CHECK-M-THUMB-NEXT: $r7 = frame-setup t2ADDri killed $sp, 8, 14 /* CC::al */, $noreg, $noreg |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION def_cfa $r7, 8 |
| # CHECK-M-THUMB-NEXT: $r4 = frame-setup VMRS 14 /* CC::al */, $noreg, implicit $fpscr |
| # CHECK-M-THUMB-NEXT: $sp = frame-setup t2STMDB_UPD $sp, 14 /* CC::al */, $noreg, $r4 |
| # CHECK-M-THUMB-NEXT: $sp = frame-setup tSUBspi $sp, 1, 14 /* CC::al */, $noreg |
| # CHECK-M-THUMB-NEXT: $sp = frame-setup VSTMDDB_UPD $sp, 14 /* CC::al */, $noreg, killed $d0, killed $d1, killed $d2, killed $d3, killed $d4, killed $d5, killed $d6, killed $d7 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d7, -32 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d6, -40 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d5, -48 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d4, -56 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d3, -64 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d2, -72 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d1, -80 |
| # CHECK-M-THUMB-NEXT: frame-setup CFI_INSTRUCTION offset $d0, -88 |
| # CHECK-M-THUMB-NEXT: $r4 = tMOVr killed $sp, 14 /* CC::al */, $noreg |
| # CHECK-M-THUMB-NEXT: $r4 = t2BFC killed $r4, 4294967288, 14 /* CC::al */, $noreg |
| # CHECK-M-THUMB-NEXT: $sp = tMOVr killed $r4, 14 /* CC::al */, $noreg |
| # CHECK-M-THUMB-NEXT: BL @bar, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp |
| # CHECK-M-THUMB-NEXT: $r4 = frame-destroy t2SUBri killed $r7, 80, 14 /* CC::al */, $noreg, $noreg |
| # CHECK-M-THUMB-NEXT: $sp = frame-destroy tMOVr $r4, 14 /* CC::al */, $noreg |
| # CHECK-M-THUMB-NEXT: $sp = frame-destroy VLDMDIA_UPD $sp, 14 /* CC::al */, $noreg, def $d0, def $d1, def $d2, def $d3, def $d4, def $d5, def $d6, def $d7 |
| # CHECK-M-THUMB-NEXT: $sp = frame-destroy tADDspi $sp, 1, 14 /* CC::al */, $noreg |
| # CHECK-M-THUMB-NEXT: $sp = frame-destroy t2LDMIA_UPD $sp, 14 /* CC::al */, $noreg, def $r4 |
| # CHECK-M-THUMB-NEXT: frame-destroy VMSR $r4, 14 /* CC::al */, $noreg, implicit-def $fpscr |
| # CHECK-M-THUMB-NEXT: $sp = frame-destroy t2LDMIA_UPD $sp, 14 /* CC::al */, $noreg, def $r4, def $r6, def $r7, def $lr |
| # CHECK-M-THUMB-NEXT: SUBS_PC_LR 4, 14 /* CC::al */, $noreg |
| |
| --- | |
| ; ModuleID = '/scratch/benson/tools2/llvm_cgt/llvm-project/llvm/test/CodeGen/ARM/fp-attr-fpscr.ll' |
| source_filename = "/scratch/benson/tools2/llvm_cgt/llvm-project/llvm/test/CodeGen/ARM/fp-attr-fpscr.ll" |
| target datalayout = "e-m:e-p:32:32-Fi8-i64:64-v128:64:128-a:0:32-n32-S64" |
| |
| declare arm_aapcscc void @bar() |
| |
| ; Function Attrs: alignstack(8) |
| define arm_aapcscc void @irq_fn() #1 { |
| call arm_aapcscc void @bar() |
| ret void |
| } |
| |
| attributes #1 = { alignstack=8 "interrupt"="IRQ" "target-features"="+fpregs" "save-fp" } |
| |
| ... |
| --- |
| name: irq_fn |
| frameInfo: |
| adjustsStack: true |
| alignment: 16 |
| body: | |
| bb.0 (%ir-block.0): |
| ADJCALLSTACKDOWN 0, 0, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp |
| BL @bar, csr_aapcs, implicit-def dead $lr, implicit $sp, implicit-def $sp |
| ADJCALLSTACKUP 0, -1, 14 /* CC::al */, $noreg, implicit-def dead $sp, implicit $sp |
| SUBS_PC_LR 4, 14 /* CC::al */, $noreg |
| ... |