CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
679 lines
23 KiB
LLVM
679 lines
23 KiB
LLVM
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
|
|
; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2 -verify-machineinstrs < %s | FileCheck %s
|
|
|
|
; A simple EH test case that corresponds to the following C++ source:
|
|
;
|
|
; struct ZAResource {
|
|
; ~ZAResource() __arm_inout("za") {
|
|
; shared_za_call(); // simulate cleanup in destructor
|
|
; }
|
|
; };
|
|
;
|
|
; void za_with_raii(bool fail) __arm_inout("za") {
|
|
; ZAResource r;
|
|
; if (fail)
|
|
; throw "Unwinding needs ZA state reload";
|
|
; }
|
|
;
|
|
; Here if an exception is thrown we must call the ~ZAResource destructor while
|
|
; unwinding the stack. That requires us to restore ZA state before the
|
|
; shared_za_call in the cleanup block.
|
|
|
|
@.str = private unnamed_addr constant [32 x i8] c"Unwinding needs ZA state reload\00", align 1
|
|
@typeinfo_for_char_const_ptr = external constant ptr
|
|
|
|
define void @za_with_raii(i1 %fail) "aarch64_inout_za" personality ptr @__gxx_personality_v0 {
|
|
; CHECK-LABEL: za_with_raii:
|
|
; CHECK: .Lfunc_begin0:
|
|
; CHECK-NEXT: .cfi_startproc
|
|
; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
|
|
; CHECK-NEXT: .cfi_lsda 28, .Lexception0
|
|
; CHECK-NEXT: // %bb.0:
|
|
; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: str x19, [sp, #16] // 8-byte Spill
|
|
; CHECK-NEXT: mov x29, sp
|
|
; CHECK-NEXT: sub sp, sp, #16
|
|
; CHECK-NEXT: .cfi_def_cfa w29, 32
|
|
; CHECK-NEXT: .cfi_offset w19, -16
|
|
; CHECK-NEXT: .cfi_offset w30, -24
|
|
; CHECK-NEXT: .cfi_offset w29, -32
|
|
; CHECK-NEXT: rdsvl x8, #1
|
|
; CHECK-NEXT: mov x9, sp
|
|
; CHECK-NEXT: msub x9, x8, x8, x9
|
|
; CHECK-NEXT: mov sp, x9
|
|
; CHECK-NEXT: stp x9, x8, [x29, #-16]
|
|
; CHECK-NEXT: tbnz w0, #0, .LBB0_2
|
|
; CHECK-NEXT: // %bb.1: // %return_normally
|
|
; CHECK-NEXT: mov sp, x29
|
|
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
|
|
; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
|
|
; CHECK-NEXT: b shared_za_call
|
|
; CHECK-NEXT: .LBB0_2: // %throw_exception
|
|
; CHECK-NEXT: sub x8, x29, #16
|
|
; CHECK-NEXT: mov w0, #8 // =0x8
|
|
; CHECK-NEXT: msr TPIDR2_EL0, x8
|
|
; CHECK-NEXT: bl __cxa_allocate_exception
|
|
; CHECK-NEXT: adrp x8, .L.str
|
|
; CHECK-NEXT: add x8, x8, :lo12:.L.str
|
|
; CHECK-NEXT: str x8, [x0]
|
|
; CHECK-NEXT: .Ltmp0: // EH_LABEL
|
|
; CHECK-NEXT: adrp x1, :got:typeinfo_for_char_const_ptr
|
|
; CHECK-NEXT: mov x2, xzr
|
|
; CHECK-NEXT: ldr x1, [x1, :got_lo12:typeinfo_for_char_const_ptr]
|
|
; CHECK-NEXT: bl __cxa_throw
|
|
; CHECK-NEXT: .Ltmp1: // EH_LABEL
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #16
|
|
; CHECK-NEXT: cbnz x8, .LBB0_4
|
|
; CHECK-NEXT: // %bb.3: // %throw_exception
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB0_4: // %throw_exception
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: // %bb.5: // %throw_fail
|
|
; CHECK-NEXT: .LBB0_6: // %unwind_dtors
|
|
; CHECK-NEXT: .Ltmp2: // EH_LABEL
|
|
; CHECK-NEXT: mov x19, x0
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #16
|
|
; CHECK-NEXT: cbnz x8, .LBB0_8
|
|
; CHECK-NEXT: // %bb.7: // %unwind_dtors
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB0_8: // %unwind_dtors
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: bl shared_za_call
|
|
; CHECK-NEXT: sub x8, x29, #16
|
|
; CHECK-NEXT: mov x0, x19
|
|
; CHECK-NEXT: msr TPIDR2_EL0, x8
|
|
; CHECK-NEXT: bl _Unwind_Resume
|
|
br i1 %fail, label %throw_exception, label %return_normally
|
|
|
|
throw_exception:
|
|
%exception_ptr = tail call ptr @__cxa_allocate_exception(i64 8) #3
|
|
store ptr @.str, ptr %exception_ptr, align 16
|
|
invoke void @__cxa_throw(ptr nonnull %exception_ptr, ptr nonnull @typeinfo_for_char_const_ptr, ptr null)
|
|
to label %throw_fail unwind label %unwind_dtors
|
|
|
|
unwind_dtors:
|
|
%5 = landingpad { ptr, i32 }
|
|
cleanup
|
|
tail call void @shared_za_call()
|
|
resume { ptr, i32 } %5
|
|
|
|
return_normally:
|
|
tail call void @shared_za_call()
|
|
ret void
|
|
|
|
throw_fail:
|
|
unreachable
|
|
}
|
|
|
|
|
|
; Another simple exception handling example. Here we need to restore ZA in two
|
|
; places. After the may_throw() call to handle the case it does not throw, and
|
|
; within the catch block for the shared_za_call(). We also need to setup the
|
|
; lazy save around C++ exception ABI routines (to handle the _very_ unlikely
|
|
; case they use ZA state).
|
|
;
|
|
; void za_try_catch() __arm_inout("za") {
|
|
; try {
|
|
; may_throw();
|
|
; } catch (...) {
|
|
; shared_za_call();
|
|
; }
|
|
; shared_za_call();
|
|
; }
|
|
define void @try_catch() "aarch64_inout_za" personality ptr @__gxx_personality_v0 {
|
|
; CHECK-LABEL: try_catch:
|
|
; CHECK: .Lfunc_begin1:
|
|
; CHECK-NEXT: .cfi_startproc
|
|
; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
|
|
; CHECK-NEXT: .cfi_lsda 28, .Lexception1
|
|
; CHECK-NEXT: // %bb.0:
|
|
; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: mov x29, sp
|
|
; CHECK-NEXT: sub sp, sp, #16
|
|
; CHECK-NEXT: .cfi_def_cfa w29, 16
|
|
; CHECK-NEXT: .cfi_offset w30, -8
|
|
; CHECK-NEXT: .cfi_offset w29, -16
|
|
; CHECK-NEXT: rdsvl x8, #1
|
|
; CHECK-NEXT: mov x9, sp
|
|
; CHECK-NEXT: msub x9, x8, x8, x9
|
|
; CHECK-NEXT: mov sp, x9
|
|
; CHECK-NEXT: stp x9, x8, [x29, #-16]
|
|
; CHECK-NEXT: .Ltmp3: // EH_LABEL
|
|
; CHECK-NEXT: sub x8, x29, #16
|
|
; CHECK-NEXT: msr TPIDR2_EL0, x8
|
|
; CHECK-NEXT: bl may_throw
|
|
; CHECK-NEXT: .Ltmp4: // EH_LABEL
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #16
|
|
; CHECK-NEXT: cbnz x8, .LBB1_2
|
|
; CHECK-NEXT: // %bb.1:
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB1_2:
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: .LBB1_3: // %after_catch
|
|
; CHECK-NEXT: mov sp, x29
|
|
; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
|
|
; CHECK-NEXT: b shared_za_call
|
|
; CHECK-NEXT: .LBB1_4: // %catch
|
|
; CHECK-NEXT: .Ltmp5: // EH_LABEL
|
|
; CHECK-NEXT: bl __cxa_begin_catch
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #16
|
|
; CHECK-NEXT: cbnz x8, .LBB1_6
|
|
; CHECK-NEXT: // %bb.5: // %catch
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB1_6: // %catch
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: bl shared_za_call
|
|
; CHECK-NEXT: sub x8, x29, #16
|
|
; CHECK-NEXT: msr TPIDR2_EL0, x8
|
|
; CHECK-NEXT: bl __cxa_end_catch
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #16
|
|
; CHECK-NEXT: cbnz x8, .LBB1_8
|
|
; CHECK-NEXT: // %bb.7: // %catch
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB1_8: // %catch
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: b .LBB1_3
|
|
invoke void @may_throw()
|
|
to label %after_catch unwind label %catch
|
|
|
|
catch: ; preds = %0
|
|
%eh_info = landingpad { ptr, i32 }
|
|
catch ptr null
|
|
%exception_ptr = extractvalue { ptr, i32 } %eh_info, 0
|
|
tail call ptr @__cxa_begin_catch(ptr %exception_ptr)
|
|
tail call void @shared_za_call()
|
|
tail call void @__cxa_end_catch()
|
|
br label %after_catch
|
|
|
|
after_catch:
|
|
tail call void @shared_za_call()
|
|
ret void
|
|
}
|
|
|
|
; This example corresponds to:
|
|
;
|
|
; __arm_new("za") void try_catch_shared_za_callee()
|
|
; {
|
|
; try {
|
|
; shared_za_call();
|
|
; } catch(...) {
|
|
; noexcept_shared_za_call();
|
|
; }
|
|
; }
|
|
;
|
|
; In this example we don't setup a lazy save before shared_za_call(), however,
|
|
; we still enter the catch block in a ZA off state. This leads to us emitting a
|
|
; restore of a uninitialized save buffer in the catch block. This is not ideal
|
|
; but is valid in the SME ABI. Ideally, we would omit the save buffer and
|
|
; restore and simply set ZA to "on" in the catch block.
|
|
|
|
define void @try_catch_shared_za_callee() "aarch64_new_za" personality ptr @__gxx_personality_v0 {
|
|
; CHECK-LABEL: try_catch_shared_za_callee:
|
|
; CHECK: .Lfunc_begin2:
|
|
; CHECK-NEXT: .cfi_startproc
|
|
; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
|
|
; CHECK-NEXT: .cfi_lsda 28, .Lexception2
|
|
; CHECK-NEXT: // %bb.0:
|
|
; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: mov x29, sp
|
|
; CHECK-NEXT: sub sp, sp, #16
|
|
; CHECK-NEXT: .cfi_def_cfa w29, 16
|
|
; CHECK-NEXT: .cfi_offset w30, -8
|
|
; CHECK-NEXT: .cfi_offset w29, -16
|
|
; CHECK-NEXT: rdsvl x8, #1
|
|
; CHECK-NEXT: mov x9, sp
|
|
; CHECK-NEXT: msub x9, x8, x8, x9
|
|
; CHECK-NEXT: mov sp, x9
|
|
; CHECK-NEXT: stp x9, x8, [x29, #-16]
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: cbz x8, .LBB2_2
|
|
; CHECK-NEXT: // %bb.1:
|
|
; CHECK-NEXT: bl __arm_tpidr2_save
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: zero {za}
|
|
; CHECK-NEXT: .LBB2_2:
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: .Ltmp6: // EH_LABEL
|
|
; CHECK-NEXT: bl shared_za_call
|
|
; CHECK-NEXT: .Ltmp7: // EH_LABEL
|
|
; CHECK-NEXT: smstop za
|
|
; CHECK-NEXT: .LBB2_3: // %exit
|
|
; CHECK-NEXT: mov sp, x29
|
|
; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .LBB2_4: // %catch
|
|
; CHECK-NEXT: .Ltmp8: // EH_LABEL
|
|
; CHECK-NEXT: bl __cxa_begin_catch
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #16
|
|
; CHECK-NEXT: cbnz x8, .LBB2_6
|
|
; CHECK-NEXT: // %bb.5: // %catch
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB2_6: // %catch
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: bl noexcept_shared_za_call
|
|
; CHECK-NEXT: sub x8, x29, #16
|
|
; CHECK-NEXT: msr TPIDR2_EL0, x8
|
|
; CHECK-NEXT: bl __cxa_end_catch
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: smstop za
|
|
; CHECK-NEXT: b .LBB2_3
|
|
invoke void @shared_za_call() #4
|
|
to label %exit unwind label %catch
|
|
catch:
|
|
%eh_info = landingpad { ptr, i32 }
|
|
catch ptr null
|
|
%exception_ptr = extractvalue { ptr, i32 } %eh_info, 0
|
|
tail call ptr @__cxa_begin_catch(ptr %exception_ptr)
|
|
tail call void @noexcept_shared_za_call()
|
|
tail call void @__cxa_end_catch()
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; A simple ZT0 exception example that corresponds to:
|
|
;
|
|
; struct ZT0Resource {
|
|
; ~ZT0Resource() __arm_inout("zt0") {
|
|
; shared_zt0_call(); // simulate cleanup in destructor
|
|
; }
|
|
; };
|
|
;
|
|
; void za_with_raii() __arm_inout("zt0") {
|
|
; ZT0Resource r;
|
|
; may_throw();
|
|
; }
|
|
;
|
|
; This code may require reloading ZT0 in the cleanup for ~ZT0Resource().
|
|
;
|
|
define void @try_catch_shared_zt0_callee() "aarch64_inout_zt0" personality ptr @__gxx_personality_v0 {
|
|
; CHECK-LABEL: try_catch_shared_zt0_callee:
|
|
; CHECK: .Lfunc_begin3:
|
|
; CHECK-NEXT: .cfi_startproc
|
|
; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
|
|
; CHECK-NEXT: .cfi_lsda 28, .Lexception3
|
|
; CHECK-NEXT: // %bb.0:
|
|
; CHECK-NEXT: sub sp, sp, #96
|
|
; CHECK-NEXT: str x30, [sp, #64] // 8-byte Spill
|
|
; CHECK-NEXT: stp x20, x19, [sp, #80] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 96
|
|
; CHECK-NEXT: .cfi_offset w19, -8
|
|
; CHECK-NEXT: .cfi_offset w20, -16
|
|
; CHECK-NEXT: .cfi_offset w30, -32
|
|
; CHECK-NEXT: .Ltmp9: // EH_LABEL
|
|
; CHECK-NEXT: mov x19, sp
|
|
; CHECK-NEXT: str zt0, [x19]
|
|
; CHECK-NEXT: smstop za
|
|
; CHECK-NEXT: bl may_throw
|
|
; CHECK-NEXT: .Ltmp10: // EH_LABEL
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: ldr zt0, [x19]
|
|
; CHECK-NEXT: // %bb.1: // %return_normally
|
|
; CHECK-NEXT: ldp x20, x19, [sp, #80] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldr x30, [sp, #64] // 8-byte Reload
|
|
; CHECK-NEXT: add sp, sp, #96
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .LBB3_2: // %unwind_dtors
|
|
; CHECK-NEXT: .Ltmp11: // EH_LABEL
|
|
; CHECK-NEXT: mov x20, sp
|
|
; CHECK-NEXT: mov x19, x0
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: ldr zt0, [x20]
|
|
; CHECK-NEXT: bl shared_zt0_call
|
|
; CHECK-NEXT: str zt0, [x20]
|
|
; CHECK-NEXT: smstop za
|
|
; CHECK-NEXT: mov x0, x19
|
|
; CHECK-NEXT: bl _Unwind_Resume
|
|
invoke void @may_throw()
|
|
to label %return_normally unwind label %unwind_dtors
|
|
|
|
unwind_dtors:
|
|
%5 = landingpad { ptr, i32 }
|
|
cleanup
|
|
tail call void @shared_zt0_call()
|
|
resume { ptr, i32 } %5
|
|
|
|
return_normally:
|
|
ret void
|
|
}
|
|
|
|
; This example corresponds to:
|
|
;
|
|
; __arm_agnostic("sme_za_state") void try_catch_agnostic_za()
|
|
; {
|
|
; try {
|
|
; may_throw();
|
|
; } catch(...) {
|
|
; }
|
|
; }
|
|
;
|
|
; In this example we must execute __arm_sme_restore once we enter the catch block
|
|
; (before executing __arm_sme_save again, which would invalidate the prior save).
|
|
define void @try_catch_agnostic_za() "aarch64_za_state_agnostic" personality ptr @__gxx_personality_v0 {
|
|
; CHECK-LABEL: try_catch_agnostic_za:
|
|
; CHECK: .Lfunc_begin4:
|
|
; CHECK-NEXT: .cfi_startproc
|
|
; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
|
|
; CHECK-NEXT: .cfi_lsda 28, .Lexception4
|
|
; CHECK-NEXT: // %bb.0:
|
|
; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: str x19, [sp, #16] // 8-byte Spill
|
|
; CHECK-NEXT: mov x29, sp
|
|
; CHECK-NEXT: .cfi_def_cfa w29, 32
|
|
; CHECK-NEXT: .cfi_offset w19, -16
|
|
; CHECK-NEXT: .cfi_offset w30, -24
|
|
; CHECK-NEXT: .cfi_offset w29, -32
|
|
; CHECK-NEXT: bl __arm_sme_state_size
|
|
; CHECK-NEXT: sub sp, sp, x0
|
|
; CHECK-NEXT: mov x19, sp
|
|
; CHECK-NEXT: .Ltmp12: // EH_LABEL
|
|
; CHECK-NEXT: mov x0, x19
|
|
; CHECK-NEXT: bl __arm_sme_save
|
|
; CHECK-NEXT: bl may_throw
|
|
; CHECK-NEXT: .Ltmp13: // EH_LABEL
|
|
; CHECK-NEXT: mov x0, x19
|
|
; CHECK-NEXT: bl __arm_sme_restore
|
|
; CHECK-NEXT: .LBB4_1: // %exit
|
|
; CHECK-NEXT: mov sp, x29
|
|
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
|
|
; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .LBB4_2: // %catch
|
|
; CHECK-NEXT: .Ltmp14: // EH_LABEL
|
|
; CHECK-NEXT: bl __cxa_begin_catch
|
|
; CHECK-NEXT: bl __cxa_end_catch
|
|
; CHECK-NEXT: mov x0, x19
|
|
; CHECK-NEXT: bl __arm_sme_restore
|
|
; CHECK-NEXT: b .LBB4_1
|
|
invoke void @may_throw()
|
|
to label %exit unwind label %catch
|
|
catch:
|
|
%eh_info = landingpad { ptr, i32 }
|
|
catch ptr null
|
|
%exception_ptr = extractvalue { ptr, i32 } %eh_info, 0
|
|
tail call ptr @__cxa_begin_catch(ptr %exception_ptr)
|
|
tail call void @__cxa_end_catch()
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; This example corresponds to:
|
|
;
|
|
; __arm_agnostic("sme_za_state") void try_catch_agnostic_za_invoke()
|
|
; {
|
|
; try {
|
|
; agnostic_za_call();
|
|
; } catch(...) {
|
|
; }
|
|
; }
|
|
;
|
|
; In this example we preserve all SME state enabled by PSTATE.ZA using
|
|
; `__arm_sme_save` before agnostic_za_call(). This is because on all normal
|
|
; returns from an agnostic ZA function ZA state should be preserved. That means
|
|
; we need to make sure ZA state is saved in case agnostic_za_call() throws, and
|
|
; we need to restore ZA state after unwinding to the catch block.
|
|
|
|
define void @try_catch_agnostic_za_invoke() "aarch64_za_state_agnostic" personality ptr @__gxx_personality_v0 {
|
|
; CHECK-LABEL: try_catch_agnostic_za_invoke:
|
|
; CHECK: .Lfunc_begin5:
|
|
; CHECK-NEXT: .cfi_startproc
|
|
; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
|
|
; CHECK-NEXT: .cfi_lsda 28, .Lexception5
|
|
; CHECK-NEXT: // %bb.0: // %entry
|
|
; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: str x19, [sp, #16] // 8-byte Spill
|
|
; CHECK-NEXT: mov x29, sp
|
|
; CHECK-NEXT: .cfi_def_cfa w29, 32
|
|
; CHECK-NEXT: .cfi_offset w19, -16
|
|
; CHECK-NEXT: .cfi_offset w30, -24
|
|
; CHECK-NEXT: .cfi_offset w29, -32
|
|
; CHECK-NEXT: bl __arm_sme_state_size
|
|
; CHECK-NEXT: sub sp, sp, x0
|
|
; CHECK-NEXT: mov x19, sp
|
|
; CHECK-NEXT: .Ltmp15: // EH_LABEL
|
|
; CHECK-NEXT: mov x0, x19
|
|
; CHECK-NEXT: bl __arm_sme_save
|
|
; CHECK-NEXT: bl agnostic_za_call
|
|
; CHECK-NEXT: .Ltmp16: // EH_LABEL
|
|
; CHECK-NEXT: mov x0, x19
|
|
; CHECK-NEXT: bl __arm_sme_restore
|
|
; CHECK-NEXT: .LBB5_1: // %exit
|
|
; CHECK-NEXT: mov sp, x29
|
|
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Reload
|
|
; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .LBB5_2: // %catch
|
|
; CHECK-NEXT: .Ltmp17: // EH_LABEL
|
|
; CHECK-NEXT: bl __cxa_begin_catch
|
|
; CHECK-NEXT: bl __cxa_end_catch
|
|
; CHECK-NEXT: mov x0, x19
|
|
; CHECK-NEXT: bl __arm_sme_restore
|
|
; CHECK-NEXT: b .LBB5_1
|
|
entry:
|
|
invoke void @agnostic_za_call() "aarch64_za_state_agnostic"
|
|
to label %exit unwind label %catch
|
|
|
|
catch:
|
|
%eh_info = landingpad { ptr, i32 }
|
|
catch ptr null
|
|
%exception_ptr = extractvalue { ptr, i32 } %eh_info, 0
|
|
tail call ptr @__cxa_begin_catch(ptr %exception_ptr)
|
|
tail call void @__cxa_end_catch()
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
; This is the same `try_catch_agnostic_za_invoke`, but shows a lazy save would
|
|
; also need to be committed in a shared-ZA function calling an agnostic-ZA function.
|
|
define void @try_catch_inout_za_agnostic_za_callee() "aarch64_inout_za" personality ptr @__gxx_personality_v0 {
|
|
; CHECK-LABEL: try_catch_inout_za_agnostic_za_callee:
|
|
; CHECK: .Lfunc_begin6:
|
|
; CHECK-NEXT: .cfi_startproc
|
|
; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
|
|
; CHECK-NEXT: .cfi_lsda 28, .Lexception6
|
|
; CHECK-NEXT: // %bb.0: // %entry
|
|
; CHECK-NEXT: stp x29, x30, [sp, #-16]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: mov x29, sp
|
|
; CHECK-NEXT: sub sp, sp, #16
|
|
; CHECK-NEXT: .cfi_def_cfa w29, 16
|
|
; CHECK-NEXT: .cfi_offset w30, -8
|
|
; CHECK-NEXT: .cfi_offset w29, -16
|
|
; CHECK-NEXT: rdsvl x8, #1
|
|
; CHECK-NEXT: mov x9, sp
|
|
; CHECK-NEXT: msub x9, x8, x8, x9
|
|
; CHECK-NEXT: mov sp, x9
|
|
; CHECK-NEXT: stp x9, x8, [x29, #-16]
|
|
; CHECK-NEXT: .Ltmp18: // EH_LABEL
|
|
; CHECK-NEXT: sub x8, x29, #16
|
|
; CHECK-NEXT: msr TPIDR2_EL0, x8
|
|
; CHECK-NEXT: bl agnostic_za_call
|
|
; CHECK-NEXT: .Ltmp19: // EH_LABEL
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #16
|
|
; CHECK-NEXT: cbnz x8, .LBB6_2
|
|
; CHECK-NEXT: // %bb.1: // %entry
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB6_2: // %entry
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: .LBB6_3: // %exit
|
|
; CHECK-NEXT: mov sp, x29
|
|
; CHECK-NEXT: ldp x29, x30, [sp], #16 // 16-byte Folded Reload
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .LBB6_4: // %catch
|
|
; CHECK-NEXT: .Ltmp20: // EH_LABEL
|
|
; CHECK-NEXT: bl __cxa_begin_catch
|
|
; CHECK-NEXT: bl __cxa_end_catch
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #16
|
|
; CHECK-NEXT: cbnz x8, .LBB6_6
|
|
; CHECK-NEXT: // %bb.5: // %catch
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB6_6: // %catch
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: b .LBB6_3
|
|
entry:
|
|
invoke void @agnostic_za_call()
|
|
to label %exit unwind label %catch
|
|
|
|
catch:
|
|
%eh_info = landingpad { ptr, i32 }
|
|
catch ptr null
|
|
%exception_ptr = extractvalue { ptr, i32 } %eh_info, 0
|
|
tail call ptr @__cxa_begin_catch(ptr %exception_ptr)
|
|
tail call void @__cxa_end_catch()
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @try_catch_inout_zt0() "aarch64_inout_zt0" personality ptr @__gxx_personality_v0 {
|
|
; CHECK-LABEL: try_catch_inout_zt0:
|
|
; CHECK: .Lfunc_begin7:
|
|
; CHECK-NEXT: .cfi_startproc
|
|
; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
|
|
; CHECK-NEXT: .cfi_lsda 28, .Lexception7
|
|
; CHECK-NEXT: // %bb.0: // %entry
|
|
; CHECK-NEXT: sub sp, sp, #80
|
|
; CHECK-NEXT: stp x30, x19, [sp, #64] // 16-byte Folded Spill
|
|
; CHECK-NEXT: .cfi_def_cfa_offset 80
|
|
; CHECK-NEXT: .cfi_offset w19, -8
|
|
; CHECK-NEXT: .cfi_offset w30, -16
|
|
; CHECK-NEXT: .Ltmp21: // EH_LABEL
|
|
; CHECK-NEXT: mov x19, sp
|
|
; CHECK-NEXT: str zt0, [x19]
|
|
; CHECK-NEXT: smstop za
|
|
; CHECK-NEXT: bl may_throw
|
|
; CHECK-NEXT: .Ltmp22: // EH_LABEL
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: ldr zt0, [x19]
|
|
; CHECK-NEXT: .LBB7_1: // %exit
|
|
; CHECK-NEXT: ldp x30, x19, [sp, #64] // 16-byte Folded Reload
|
|
; CHECK-NEXT: add sp, sp, #80
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .LBB7_2: // %catch
|
|
; CHECK-NEXT: .Ltmp23: // EH_LABEL
|
|
; CHECK-NEXT: bl __cxa_begin_catch
|
|
; CHECK-NEXT: bl __cxa_end_catch
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: ldr zt0, [x19]
|
|
; CHECK-NEXT: b .LBB7_1
|
|
entry:
|
|
invoke void @may_throw()
|
|
to label %exit unwind label %catch
|
|
|
|
catch:
|
|
%eh_info = landingpad { ptr, i32 }
|
|
catch ptr null
|
|
%exception_ptr = extractvalue { ptr, i32 } %eh_info, 0
|
|
tail call ptr @__cxa_begin_catch(ptr %exception_ptr)
|
|
tail call void @__cxa_end_catch()
|
|
br label %exit
|
|
|
|
exit:
|
|
ret void
|
|
}
|
|
|
|
define void @try_catch_shared_za_callee_zt0_saved(ptr %callee) "aarch64_inout_za" "aarch64_in_zt0" personality ptr @__gxx_personality_v0 {
|
|
; CHECK-LABEL: try_catch_shared_za_callee_zt0_saved:
|
|
; CHECK: .Lfunc_begin8:
|
|
; CHECK-NEXT: .cfi_startproc
|
|
; CHECK-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
|
|
; CHECK-NEXT: .cfi_lsda 28, .Lexception8
|
|
; CHECK-NEXT: // %bb.0:
|
|
; CHECK-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
|
|
; CHECK-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill
|
|
; CHECK-NEXT: mov x29, sp
|
|
; CHECK-NEXT: sub sp, sp, #80
|
|
; CHECK-NEXT: .cfi_def_cfa w29, 32
|
|
; CHECK-NEXT: .cfi_offset w19, -8
|
|
; CHECK-NEXT: .cfi_offset w20, -16
|
|
; CHECK-NEXT: .cfi_offset w30, -24
|
|
; CHECK-NEXT: .cfi_offset w29, -32
|
|
; CHECK-NEXT: rdsvl x8, #1
|
|
; CHECK-NEXT: mov x9, sp
|
|
; CHECK-NEXT: msub x9, x8, x8, x9
|
|
; CHECK-NEXT: mov sp, x9
|
|
; CHECK-NEXT: mov x19, x0
|
|
; CHECK-NEXT: stp x9, x8, [x29, #-80]
|
|
; CHECK-NEXT: .Ltmp24: // EH_LABEL
|
|
; CHECK-NEXT: sub x20, x29, #64
|
|
; CHECK-NEXT: sub x8, x29, #80
|
|
; CHECK-NEXT: str zt0, [x20]
|
|
; CHECK-NEXT: msr TPIDR2_EL0, x8
|
|
; CHECK-NEXT: bl may_throw
|
|
; CHECK-NEXT: .Ltmp25: // EH_LABEL
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #80
|
|
; CHECK-NEXT: cbnz x8, .LBB8_2
|
|
; CHECK-NEXT: // %bb.1:
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB8_2:
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: ldr zt0, [x20]
|
|
; CHECK-NEXT: // %bb.3: // %return_normally
|
|
; CHECK-NEXT: mov sp, x29
|
|
; CHECK-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload
|
|
; CHECK-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
|
|
; CHECK-NEXT: ret
|
|
; CHECK-NEXT: .LBB8_4: // %unwind_dtors
|
|
; CHECK-NEXT: .Ltmp26: // EH_LABEL
|
|
; CHECK-NEXT: mov x20, x0
|
|
; CHECK-NEXT: smstart za
|
|
; CHECK-NEXT: mrs x8, TPIDR2_EL0
|
|
; CHECK-NEXT: sub x0, x29, #80
|
|
; CHECK-NEXT: cbnz x8, .LBB8_6
|
|
; CHECK-NEXT: // %bb.5: // %unwind_dtors
|
|
; CHECK-NEXT: bl __arm_tpidr2_restore
|
|
; CHECK-NEXT: .LBB8_6: // %unwind_dtors
|
|
; CHECK-NEXT: msr TPIDR2_EL0, xzr
|
|
; CHECK-NEXT: blr x19
|
|
; CHECK-NEXT: sub x8, x29, #80
|
|
; CHECK-NEXT: mov x0, x20
|
|
; CHECK-NEXT: msr TPIDR2_EL0, x8
|
|
; CHECK-NEXT: bl _Unwind_Resume
|
|
invoke void @may_throw()
|
|
to label %return_normally unwind label %unwind_dtors
|
|
|
|
unwind_dtors:
|
|
%5 = landingpad { ptr, i32 }
|
|
cleanup
|
|
call void %callee() "aarch64_inout_za"
|
|
resume { ptr, i32 } %5
|
|
|
|
return_normally:
|
|
ret void
|
|
}
|
|
|
|
declare ptr @__cxa_allocate_exception(i64)
|
|
declare void @__cxa_throw(ptr, ptr, ptr)
|
|
declare ptr @__cxa_begin_catch(ptr)
|
|
declare void @__cxa_end_catch()
|
|
declare i32 @__gxx_personality_v0(...)
|
|
|
|
declare void @may_throw()
|
|
declare void @shared_za_call() "aarch64_inout_za"
|
|
declare void @noexcept_shared_za_call() "aarch64_inout_za"
|
|
declare void @shared_zt0_call() "aarch64_inout_zt0"
|
|
declare void @agnostic_za_call() "aarch64_za_state_agnostic"
|