
This patch reworks how VG is handled around streaming mode changes. Previously, for functions with streaming mode changes, we would: - Save the incoming VG in the prologue - Emit `.cfi_offset vg, <offset>` and `.cfi_restore vg` around streaming mode changes Additionally, for locally streaming functions, we would: - Also save the streaming VG in the prologue - Emit `.cfi_offset vg, <incoming VG offset>` in the prologue - Emit `.cfi_offset vg, <streaming VG offset>` and `.cfi_restore vg` around streaming mode changes In both cases, this ends up doing more than necessary and would be hard for an unwinder to parse, as using `.cfi_offset` in this way does not follow the semantics of the underlying DWARF CFI opcodes. So the new scheme in this patch is to: In functions with streaming mode changes (inc locally streaming) - Save the incoming VG in the prologue - Emit `.cfi_offset vg, <offset>` in the prologue (not at streaming mode changes) - Emit `.cfi_restore vg` after the saved VG has been deallocated - This will be in the function epilogue, where VG is always the same as the entry VG - Explicitly reference the incoming VG expressions for SVE callee-saves in functions with streaming mode changes - Ensure the CFA is not described in terms of VG in functions with streaming mode changes A more in-depth discussion of this scheme is available in: https://gist.github.com/MacDue/b7a5c45d131d2440858165bfc903e97b But the TLDR is that following this scheme, SME unwinding can be implemented with minimal changes to existing unwinders. All unwinders need to do is initialize VG to `CNTD` at the start of unwinding, then everything else is handled by standard opcodes (which don't need changes to handle VG).
79 lines
3.3 KiB
LLVM
79 lines
3.3 KiB
LLVM
; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve -mattr=+sme2 -enable-machine-outliner -aarch64-streaming-hazard-size=0 -verify-machineinstrs < %s | FileCheck %s
|
|
; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sve -mattr=+sme2 -enable-machine-outliner -aarch64-streaming-hazard-size=0 -verify-machineinstrs < %s | FileCheck %s -check-prefix=OUTLINER
|
|
|
|
declare void @callee();
|
|
|
|
define void @streaming_mode_change1() #0 {
|
|
; CHECK-LABEL: streaming_mode_change1:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: stp d15, d14, [sp, #-80]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp d13, d12, [sp, #16] // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp d11, d10, [sp, #32] // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill
|
|
; CHECK-NEXT: str x30, [sp, #64] // 8-byte Folded Spill
|
|
; CHECK-NEXT: smstop sm
|
|
; CHECK-NEXT: bl callee
|
|
; CHECK-NEXT: smstart sm
|
|
; CHECK-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldr x30, [sp, #64] // 8-byte Folded Reload
|
|
; CHECK-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldp d15, d14, [sp], #80 // 16-byte Folded Reload
|
|
; CHECK-NEXT: ret
|
|
;
|
|
; OUTLINER-LABEL: streaming_mode_change1:
|
|
; OUTLINER-NOT: OUTLINED_FUNCTION_
|
|
call void @callee();
|
|
ret void;
|
|
}
|
|
|
|
define void @streaming_mode_change2() #0 {
|
|
; CHECK-LABEL: streaming_mode_change2:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: stp d15, d14, [sp, #-80]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp d13, d12, [sp, #16] // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp d11, d10, [sp, #32] // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill
|
|
; CHECK-NEXT: str x30, [sp, #64] // 8-byte Folded Spill
|
|
; CHECK-NEXT: smstop sm
|
|
; CHECK-NEXT: bl callee
|
|
; CHECK-NEXT: smstart sm
|
|
; CHECK-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldr x30, [sp, #64] // 8-byte Folded Reload
|
|
; CHECK-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldp d15, d14, [sp], #80 // 16-byte Folded Reload
|
|
; CHECK-NEXT: ret
|
|
;
|
|
; OUTLINER-LABEL: streaming_mode_change2:
|
|
; OUTLINER-NOT: OUTLINED_FUNCTION_
|
|
call void @callee();
|
|
ret void;
|
|
}
|
|
|
|
define void @streaming_mode_change3() #0 {
|
|
; CHECK-LABEL: streaming_mode_change3:
|
|
; CHECK: // %bb.0:
|
|
; CHECK-NEXT: stp d15, d14, [sp, #-80]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp d13, d12, [sp, #16] // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp d11, d10, [sp, #32] // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp d9, d8, [sp, #48] // 16-byte Folded Spill
|
|
; CHECK-NEXT: str x30, [sp, #64] // 8-byte Folded Spill
|
|
; CHECK-NEXT: smstop sm
|
|
; CHECK-NEXT: bl callee
|
|
; CHECK-NEXT: smstart sm
|
|
; CHECK-NEXT: ldp d9, d8, [sp, #48] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldr x30, [sp, #64] // 8-byte Folded Reload
|
|
; CHECK-NEXT: ldp d11, d10, [sp, #32] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldp d13, d12, [sp, #16] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldp d15, d14, [sp], #80 // 16-byte Folded Reload
|
|
; CHECK-NEXT: ret
|
|
;
|
|
; OUTLINER-LABEL: streaming_mode_change3:
|
|
; OUTLINER-NOT: OUTLINED_FUNCTION_
|
|
call void @callee();
|
|
ret void;
|
|
}
|
|
|
|
attributes #0 = { "aarch64_pstate_sm_enabled" nounwind }
|