blob: b6dee97ea29625002c609ea9e8490f22453c8ac0 [file] [log] [blame]
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5
; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2 -aarch64-new-sme-abi -verify-machineinstrs < %s | FileCheck %s
; RUN: llc -mtriple=aarch64-linux-gnu -mattr=+sme2 -verify-machineinstrs < %s | FileCheck %s --check-prefix=CHECK-SDAG
; 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 Folded 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 Folded 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
;
; CHECK-SDAG-LABEL: za_with_raii:
; CHECK-SDAG: .Lfunc_begin0:
; CHECK-SDAG-NEXT: .cfi_startproc
; CHECK-SDAG-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
; CHECK-SDAG-NEXT: .cfi_lsda 28, .Lexception0
; CHECK-SDAG-NEXT: // %bb.0:
; CHECK-SDAG-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
; CHECK-SDAG-NEXT: stp x20, x19, [sp, #16] // 16-byte Folded Spill
; CHECK-SDAG-NEXT: mov x29, sp
; CHECK-SDAG-NEXT: sub sp, sp, #16
; CHECK-SDAG-NEXT: .cfi_def_cfa w29, 32
; CHECK-SDAG-NEXT: .cfi_offset w19, -8
; CHECK-SDAG-NEXT: .cfi_offset w20, -16
; CHECK-SDAG-NEXT: .cfi_offset w30, -24
; CHECK-SDAG-NEXT: .cfi_offset w29, -32
; CHECK-SDAG-NEXT: rdsvl x8, #1
; CHECK-SDAG-NEXT: mov x9, sp
; CHECK-SDAG-NEXT: msub x9, x8, x8, x9
; CHECK-SDAG-NEXT: mov sp, x9
; CHECK-SDAG-NEXT: stp x9, x8, [x29, #-16]
; CHECK-SDAG-NEXT: tbnz w0, #0, .LBB0_2
; CHECK-SDAG-NEXT: // %bb.1: // %return_normally
; CHECK-SDAG-NEXT: mov sp, x29
; CHECK-SDAG-NEXT: ldp x20, x19, [sp, #16] // 16-byte Folded Reload
; CHECK-SDAG-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
; CHECK-SDAG-NEXT: b shared_za_call
; CHECK-SDAG-NEXT: .LBB0_2: // %throw_exception
; CHECK-SDAG-NEXT: sub x20, x29, #16
; CHECK-SDAG-NEXT: mov w0, #8 // =0x8
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, x20
; CHECK-SDAG-NEXT: bl __cxa_allocate_exception
; CHECK-SDAG-NEXT: mov x8, x0
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x9, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x9, .LBB0_4
; CHECK-SDAG-NEXT: // %bb.3: // %throw_exception
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB0_4: // %throw_exception
; CHECK-SDAG-NEXT: adrp x9, .L.str
; CHECK-SDAG-NEXT: add x9, x9, :lo12:.L.str
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-NEXT: str x9, [x8]
; CHECK-SDAG-NEXT: .Ltmp0: // EH_LABEL
; CHECK-SDAG-NEXT: adrp x1, :got:typeinfo_for_char_const_ptr
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, x20
; CHECK-SDAG-NEXT: mov x0, x8
; CHECK-SDAG-NEXT: ldr x1, [x1, :got_lo12:typeinfo_for_char_const_ptr]
; CHECK-SDAG-NEXT: mov x2, xzr
; CHECK-SDAG-NEXT: bl __cxa_throw
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB0_6
; CHECK-SDAG-NEXT: // %bb.5: // %throw_exception
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB0_6: // %throw_exception
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-NEXT: .Ltmp1: // EH_LABEL
; CHECK-SDAG-NEXT: // %bb.7: // %throw_fail
; CHECK-SDAG-NEXT: .LBB0_8: // %unwind_dtors
; CHECK-SDAG-NEXT: .Ltmp2: // EH_LABEL
; CHECK-SDAG-NEXT: mov x19, x0
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB0_10
; CHECK-SDAG-NEXT: // %bb.9: // %unwind_dtors
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB0_10: // %unwind_dtors
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-NEXT: bl shared_za_call
; CHECK-SDAG-NEXT: mov x0, x19
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, x20
; CHECK-SDAG-NEXT: bl _Unwind_Resume
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB0_12
; CHECK-SDAG-NEXT: // %bb.11: // %unwind_dtors
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB0_12: // %unwind_dtors
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
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: .LBB1_1: // %after_catch
; CHECK-NEXT: smstart za
; CHECK-NEXT: mrs x8, TPIDR2_EL0
; CHECK-NEXT: sub x0, x29, #16
; CHECK-NEXT: cbnz x8, .LBB1_3
; CHECK-NEXT: // %bb.2: // %after_catch
; CHECK-NEXT: bl __arm_tpidr2_restore
; CHECK-NEXT: .LBB1_3: // %after_catch
; CHECK-NEXT: msr TPIDR2_EL0, xzr
; 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: b .LBB1_1
;
; CHECK-SDAG-LABEL: try_catch:
; CHECK-SDAG: .Lfunc_begin1:
; CHECK-SDAG-NEXT: .cfi_startproc
; CHECK-SDAG-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
; CHECK-SDAG-NEXT: .cfi_lsda 28, .Lexception1
; CHECK-SDAG-NEXT: // %bb.0:
; CHECK-SDAG-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
; CHECK-SDAG-NEXT: str x19, [sp, #16] // 8-byte Folded Spill
; CHECK-SDAG-NEXT: mov x29, sp
; CHECK-SDAG-NEXT: sub sp, sp, #16
; CHECK-SDAG-NEXT: .cfi_def_cfa w29, 32
; CHECK-SDAG-NEXT: .cfi_offset w19, -16
; CHECK-SDAG-NEXT: .cfi_offset w30, -24
; CHECK-SDAG-NEXT: .cfi_offset w29, -32
; CHECK-SDAG-NEXT: rdsvl x8, #1
; CHECK-SDAG-NEXT: mov x9, sp
; CHECK-SDAG-NEXT: msub x9, x8, x8, x9
; CHECK-SDAG-NEXT: mov sp, x9
; CHECK-SDAG-NEXT: stp x9, x8, [x29, #-16]
; CHECK-SDAG-NEXT: .Ltmp3: // EH_LABEL
; CHECK-SDAG-NEXT: sub x19, x29, #16
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, x19
; CHECK-SDAG-NEXT: bl may_throw
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB1_2
; CHECK-SDAG-NEXT: // %bb.1:
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB1_2:
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-NEXT: .Ltmp4: // EH_LABEL
; CHECK-SDAG-NEXT: .LBB1_3: // %after_catch
; CHECK-SDAG-NEXT: mov sp, x29
; CHECK-SDAG-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload
; CHECK-SDAG-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
; CHECK-SDAG-NEXT: b shared_za_call
; CHECK-SDAG-NEXT: .LBB1_4: // %catch
; CHECK-SDAG-NEXT: .Ltmp5: // EH_LABEL
; CHECK-SDAG-NEXT: mov x1, x0
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB1_6
; CHECK-SDAG-NEXT: // %bb.5: // %catch
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB1_6: // %catch
; CHECK-SDAG-NEXT: mov x0, x1
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, x19
; CHECK-SDAG-NEXT: bl __cxa_begin_catch
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB1_8
; CHECK-SDAG-NEXT: // %bb.7: // %catch
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB1_8: // %catch
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-NEXT: bl shared_za_call
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, x19
; CHECK-SDAG-NEXT: bl __cxa_end_catch
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB1_10
; CHECK-SDAG-NEXT: // %bb.9: // %catch
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB1_10: // %catch
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-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: .LBB2_3: // %exit
; CHECK-NEXT: smstop za
; 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: b .LBB2_3
;
; CHECK-SDAG-LABEL: try_catch_shared_za_callee:
; CHECK-SDAG: .Lfunc_begin2:
; CHECK-SDAG-NEXT: .cfi_startproc
; CHECK-SDAG-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
; CHECK-SDAG-NEXT: .cfi_lsda 28, .Lexception2
; CHECK-SDAG-NEXT: // %bb.0: // %prelude
; CHECK-SDAG-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
; CHECK-SDAG-NEXT: str x19, [sp, #16] // 8-byte Folded Spill
; CHECK-SDAG-NEXT: mov x29, sp
; CHECK-SDAG-NEXT: sub sp, sp, #16
; CHECK-SDAG-NEXT: .cfi_def_cfa w29, 32
; CHECK-SDAG-NEXT: .cfi_offset w19, -16
; CHECK-SDAG-NEXT: .cfi_offset w30, -24
; CHECK-SDAG-NEXT: .cfi_offset w29, -32
; CHECK-SDAG-NEXT: rdsvl x8, #1
; CHECK-SDAG-NEXT: mov x9, sp
; CHECK-SDAG-NEXT: msub x9, x8, x8, x9
; CHECK-SDAG-NEXT: mov sp, x9
; CHECK-SDAG-NEXT: stp x9, x8, [x29, #-16]
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: cbz x8, .LBB2_2
; CHECK-SDAG-NEXT: // %bb.1: // %save.za
; CHECK-SDAG-NEXT: bl __arm_tpidr2_save
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-NEXT: .LBB2_2:
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: zero {za}
; CHECK-SDAG-NEXT: .Ltmp6: // EH_LABEL
; CHECK-SDAG-NEXT: bl shared_za_call
; CHECK-SDAG-NEXT: .Ltmp7: // EH_LABEL
; CHECK-SDAG-NEXT: .LBB2_3: // %exit
; CHECK-SDAG-NEXT: smstop za
; CHECK-SDAG-NEXT: mov sp, x29
; CHECK-SDAG-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload
; CHECK-SDAG-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
; CHECK-SDAG-NEXT: ret
; CHECK-SDAG-NEXT: .LBB2_4: // %catch
; CHECK-SDAG-NEXT: .Ltmp8: // EH_LABEL
; CHECK-SDAG-NEXT: mov x1, x0
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: sub x19, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB2_6
; CHECK-SDAG-NEXT: // %bb.5: // %catch
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB2_6: // %catch
; CHECK-SDAG-NEXT: mov x0, x1
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, x19
; CHECK-SDAG-NEXT: bl __cxa_begin_catch
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB2_8
; CHECK-SDAG-NEXT: // %bb.7: // %catch
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB2_8: // %catch
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-NEXT: bl noexcept_shared_za_call
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, x19
; CHECK-SDAG-NEXT: bl __cxa_end_catch
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: mrs x8, TPIDR2_EL0
; CHECK-SDAG-NEXT: sub x0, x29, #16
; CHECK-SDAG-NEXT: cbnz x8, .LBB2_10
; CHECK-SDAG-NEXT: // %bb.9: // %catch
; CHECK-SDAG-NEXT: bl __arm_tpidr2_restore
; CHECK-SDAG-NEXT: .LBB2_10: // %catch
; CHECK-SDAG-NEXT: msr TPIDR2_EL0, xzr
; CHECK-SDAG-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().
;
; FIXME: Codegen with `-aarch64-new-sme-abi` is broken with ZT0 (as it is not implemented).
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: 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: stp x9, x8, [x29, #-80]
; CHECK-NEXT: .Ltmp9: // EH_LABEL
; CHECK-NEXT: sub x19, x29, #64
; CHECK-NEXT: str zt0, [x19]
; CHECK-NEXT: smstop za
; CHECK-NEXT: bl may_throw
; CHECK-NEXT: smstart za
; CHECK-NEXT: ldr zt0, [x19]
; CHECK-NEXT: .Ltmp10: // EH_LABEL
; CHECK-NEXT: // %bb.1: // %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: .LBB3_2: // %unwind_dtors
; CHECK-NEXT: .Ltmp11: // EH_LABEL
; CHECK-NEXT: sub x20, x29, #64
; CHECK-NEXT: mov x19, x0
; CHECK-NEXT: smstart za
; CHECK-NEXT: mrs x8, TPIDR2_EL0
; CHECK-NEXT: sub x0, x29, #80
; CHECK-NEXT: cbnz x8, .LBB3_4
; CHECK-NEXT: // %bb.3: // %unwind_dtors
; CHECK-NEXT: bl __arm_tpidr2_restore
; CHECK-NEXT: .LBB3_4: // %unwind_dtors
; CHECK-NEXT: msr TPIDR2_EL0, xzr
; 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
; CHECK-NEXT: smstart za
; CHECK-NEXT: ldr zt0, [x20]
;
; CHECK-SDAG-LABEL: try_catch_shared_zt0_callee:
; CHECK-SDAG: .Lfunc_begin3:
; CHECK-SDAG-NEXT: .cfi_startproc
; CHECK-SDAG-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
; CHECK-SDAG-NEXT: .cfi_lsda 28, .Lexception3
; CHECK-SDAG-NEXT: // %bb.0:
; CHECK-SDAG-NEXT: sub sp, sp, #96
; CHECK-SDAG-NEXT: str x30, [sp, #64] // 8-byte Folded Spill
; CHECK-SDAG-NEXT: stp x20, x19, [sp, #80] // 16-byte Folded Spill
; CHECK-SDAG-NEXT: .cfi_def_cfa_offset 96
; CHECK-SDAG-NEXT: .cfi_offset w19, -8
; CHECK-SDAG-NEXT: .cfi_offset w20, -16
; CHECK-SDAG-NEXT: .cfi_offset w30, -32
; CHECK-SDAG-NEXT: .Ltmp9: // EH_LABEL
; CHECK-SDAG-NEXT: mov x19, sp
; CHECK-SDAG-NEXT: str zt0, [x19]
; CHECK-SDAG-NEXT: smstop za
; CHECK-SDAG-NEXT: bl may_throw
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: ldr zt0, [x19]
; CHECK-SDAG-NEXT: .Ltmp10: // EH_LABEL
; CHECK-SDAG-NEXT: // %bb.1: // %return_normally
; CHECK-SDAG-NEXT: ldp x20, x19, [sp, #80] // 16-byte Folded Reload
; CHECK-SDAG-NEXT: ldr x30, [sp, #64] // 8-byte Folded Reload
; CHECK-SDAG-NEXT: add sp, sp, #96
; CHECK-SDAG-NEXT: ret
; CHECK-SDAG-NEXT: .LBB3_2: // %unwind_dtors
; CHECK-SDAG-NEXT: .Ltmp11: // EH_LABEL
; CHECK-SDAG-NEXT: mov x20, sp
; CHECK-SDAG-NEXT: mov x19, x0
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: ldr zt0, [x20]
; CHECK-SDAG-NEXT: bl shared_zt0_call
; CHECK-SDAG-NEXT: str zt0, [x20]
; CHECK-SDAG-NEXT: smstop za
; CHECK-SDAG-NEXT: mov x0, x19
; CHECK-SDAG-NEXT: bl _Unwind_Resume
; CHECK-SDAG-NEXT: smstart za
; CHECK-SDAG-NEXT: ldr zt0, [x20]
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 Folded 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: .LBB4_1: // %exit
; CHECK-NEXT: mov x0, x19
; CHECK-NEXT: bl __arm_sme_restore
; CHECK-NEXT: mov sp, x29
; CHECK-NEXT: ldr x19, [sp, #16] // 8-byte Folded 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: b .LBB4_1
;
; CHECK-SDAG-LABEL: try_catch_agnostic_za:
; CHECK-SDAG: .Lfunc_begin4:
; CHECK-SDAG-NEXT: .cfi_startproc
; CHECK-SDAG-NEXT: .cfi_personality 156, DW.ref.__gxx_personality_v0
; CHECK-SDAG-NEXT: .cfi_lsda 28, .Lexception4
; CHECK-SDAG-NEXT: // %bb.0:
; CHECK-SDAG-NEXT: stp x29, x30, [sp, #-32]! // 16-byte Folded Spill
; CHECK-SDAG-NEXT: str x19, [sp, #16] // 8-byte Folded Spill
; CHECK-SDAG-NEXT: mov x29, sp
; CHECK-SDAG-NEXT: .cfi_def_cfa w29, 32
; CHECK-SDAG-NEXT: .cfi_offset w19, -16
; CHECK-SDAG-NEXT: .cfi_offset w30, -24
; CHECK-SDAG-NEXT: .cfi_offset w29, -32
; CHECK-SDAG-NEXT: bl __arm_sme_state_size
; CHECK-SDAG-NEXT: sub sp, sp, x0
; CHECK-SDAG-NEXT: mov x19, sp
; CHECK-SDAG-NEXT: .Ltmp12: // EH_LABEL
; CHECK-SDAG-NEXT: mov x0, x19
; CHECK-SDAG-NEXT: bl __arm_sme_save
; CHECK-SDAG-NEXT: bl may_throw
; CHECK-SDAG-NEXT: mov x0, x19
; CHECK-SDAG-NEXT: bl __arm_sme_restore
; CHECK-SDAG-NEXT: .Ltmp13: // EH_LABEL
; CHECK-SDAG-NEXT: .LBB4_1: // %exit
; CHECK-SDAG-NEXT: mov sp, x29
; CHECK-SDAG-NEXT: ldr x19, [sp, #16] // 8-byte Folded Reload
; CHECK-SDAG-NEXT: ldp x29, x30, [sp], #32 // 16-byte Folded Reload
; CHECK-SDAG-NEXT: ret
; CHECK-SDAG-NEXT: .LBB4_2: // %catch
; CHECK-SDAG-NEXT: .Ltmp14: // EH_LABEL
; CHECK-SDAG-NEXT: mov x1, x0
; CHECK-SDAG-NEXT: mov x0, x19
; CHECK-SDAG-NEXT: bl __arm_sme_restore
; CHECK-SDAG-NEXT: mov x0, x19
; CHECK-SDAG-NEXT: bl __arm_sme_save
; CHECK-SDAG-NEXT: mov x0, x1
; CHECK-SDAG-NEXT: bl __cxa_begin_catch
; CHECK-SDAG-NEXT: mov x0, x19
; CHECK-SDAG-NEXT: bl __arm_sme_restore
; CHECK-SDAG-NEXT: mov x0, x19
; CHECK-SDAG-NEXT: bl __arm_sme_save
; CHECK-SDAG-NEXT: bl __cxa_end_catch
; CHECK-SDAG-NEXT: mov x0, x19
; CHECK-SDAG-NEXT: bl __arm_sme_restore
; CHECK-SDAG-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
}
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"