Currently, the AMDGPU backend bumps the Stack Pointer by fixed size offsets in the prolog of device functions, and restores it by the same amount in the epilog. Prolog: sp += frameSize Epilog: sp -= frameSize If a function has dynamic stack realignment, Prolog: sp += frameSize + max_alignment Epilog: sp -= frameSize + max_alignment These calculations are not optimal in case of dynamic stack realignment, and completely fail in case of dynamic stack readjustment. This patch uses the saved Frame Pointer to restore SP. Prolog: fp = sp sp += frameSize Epilog: sp = fp In case of dynamic stack realignment, SP is restored from the saved Base Pointer. Prolog: fp = sp + (max_alignment - 1) fp = fp & (-max_alignment) bp = sp sp += frameSize + max_alignment Epilog: sp = bp (Note: The presence of BP has been enforced in case of any dynamic stack realignment.) --------- Co-authored-by: Pravin Jagtap <Pravin.Jagtap@amd.com> Co-authored-by: Matt Arsenault <arsenm2@gmail.com>
59 lines
3.6 KiB
LLVM
59 lines
3.6 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_mir_test_checks.py UTC_ARGS: --version 4
|
|
; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx1030 -stop-after=si-insert-waitcnts -verify-machineinstrs < %s | FileCheck %s
|
|
|
|
declare fastcc void @bar()
|
|
|
|
define fastcc i32 @foo() {
|
|
; CHECK-LABEL: name: foo
|
|
; CHECK: bb.0 (%ir-block.0):
|
|
; CHECK-NEXT: successors: %bb.1(0x80000000)
|
|
; CHECK-NEXT: liveins: $sgpr12, $sgpr13, $sgpr14, $sgpr15, $sgpr30, $sgpr31, $vgpr31, $sgpr4_sgpr5, $sgpr6_sgpr7, $sgpr8_sgpr9, $sgpr10_sgpr11
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: S_WAITCNT 0
|
|
; CHECK-NEXT: $sgpr16 = S_MOV_B32 $sgpr33
|
|
; CHECK-NEXT: $sgpr33 = S_MOV_B32 $sgpr32
|
|
; CHECK-NEXT: $sgpr17 = S_OR_SAVEEXEC_B32 -1, implicit-def $exec, implicit-def dead $scc, implicit $exec
|
|
; CHECK-NEXT: BUFFER_STORE_DWORD_OFFSET $vgpr40, $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr33, 0, 0, 0, implicit $exec :: (store (s32) into %stack.2, addrspace 5)
|
|
; CHECK-NEXT: $exec_lo = S_MOV_B32 killed $sgpr17
|
|
; CHECK-NEXT: $sgpr32 = frame-setup S_ADDK_I32 $sgpr32, 512, implicit-def dead $scc
|
|
; CHECK-NEXT: $vgpr40 = V_WRITELANE_B32 killed $sgpr16, 2, undef $vgpr40
|
|
; CHECK-NEXT: BUNDLE implicit-def $sgpr16_sgpr17, implicit-def $sgpr16, implicit-def $sgpr16_lo16, implicit-def $sgpr16_hi16, implicit-def $sgpr17, implicit-def $sgpr17_lo16, implicit-def $sgpr17_hi16, implicit-def $scc {
|
|
; CHECK-NEXT: $sgpr16_sgpr17 = S_GETPC_B64
|
|
; CHECK-NEXT: $sgpr16 = S_ADD_U32 internal $sgpr16, target-flags(amdgpu-gotprel32-lo) @bar + 4, implicit-def $scc
|
|
; CHECK-NEXT: $sgpr17 = S_ADDC_U32 internal $sgpr17, target-flags(amdgpu-gotprel32-hi) @bar + 12, implicit-def $scc, implicit internal $scc
|
|
; CHECK-NEXT: }
|
|
; CHECK-NEXT: S_WAITCNT_VSCNT undef $sgpr_null, 0
|
|
; CHECK-NEXT: BUFFER_GL1_INV implicit $exec
|
|
; CHECK-NEXT: BUFFER_GL0_INV implicit $exec
|
|
; CHECK-NEXT: renamable $sgpr16_sgpr17 = S_LOAD_DWORDX2_IMM killed renamable $sgpr16_sgpr17, 0, 0 :: (dereferenceable invariant load (s64) from got, addrspace 4)
|
|
; CHECK-NEXT: $vgpr40 = V_WRITELANE_B32 killed $sgpr30, 0, $vgpr40
|
|
; CHECK-NEXT: $vgpr40 = V_WRITELANE_B32 killed $sgpr31, 1, $vgpr40
|
|
; CHECK-NEXT: S_WAITCNT 49279
|
|
; CHECK-NEXT: dead $sgpr30_sgpr31 = SI_CALL killed renamable $sgpr16_sgpr17, @bar, csr_amdgpu, implicit killed $sgpr4_sgpr5, implicit killed $sgpr6_sgpr7, implicit killed $sgpr8_sgpr9, implicit killed $sgpr10_sgpr11, implicit killed $sgpr12, implicit killed $sgpr13, implicit killed $sgpr14, implicit killed $sgpr15, implicit killed $vgpr31, implicit $sgpr0_sgpr1_sgpr2_sgpr3
|
|
; CHECK-NEXT: $vcc_lo = S_MOV_B32 $exec_lo
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: bb.1 (%ir-block.1):
|
|
; CHECK-NEXT: successors: %bb.2(0x04000000), %bb.1(0x7c000000)
|
|
; CHECK-NEXT: liveins: $vcc_lo
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: S_CBRANCH_VCCNZ %bb.1, implicit $vcc_lo
|
|
; CHECK-NEXT: {{ $}}
|
|
; CHECK-NEXT: bb.2.DummyReturnBlock:
|
|
; CHECK-NEXT: $sgpr31 = V_READLANE_B32 $vgpr40, 1
|
|
; CHECK-NEXT: $sgpr30 = V_READLANE_B32 $vgpr40, 0
|
|
; CHECK-NEXT: $sgpr32 = S_MOV_B32 $sgpr33
|
|
; CHECK-NEXT: $sgpr4 = V_READLANE_B32 $vgpr40, 2
|
|
; CHECK-NEXT: $sgpr5 = S_OR_SAVEEXEC_B32 -1, implicit-def $exec, implicit-def dead $scc, implicit $exec
|
|
; CHECK-NEXT: $vgpr40 = BUFFER_LOAD_DWORD_OFFSET $sgpr0_sgpr1_sgpr2_sgpr3, $sgpr33, 0, 0, 0, implicit $exec :: (load (s32) from %stack.2, addrspace 5)
|
|
; CHECK-NEXT: $exec_lo = S_MOV_B32 killed $sgpr5
|
|
; CHECK-NEXT: $sgpr33 = S_MOV_B32 killed $sgpr4
|
|
; CHECK-NEXT: S_WAITCNT 16240
|
|
; CHECK-NEXT: S_SETPC_B64_return undef $sgpr30_sgpr31, implicit undef $vgpr0
|
|
fence acquire
|
|
call fastcc void @bar()
|
|
br label %1
|
|
|
|
1:
|
|
br label %1
|
|
}
|