# 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 ...