https://gcc.gnu.org/bugzilla/show_bug.cgi?id=96338
Bug ID: 96338 Summary: [SVE] Unnecessary register saves in exception handler Product: gcc Version: 11.0 Status: UNCONFIRMED Keywords: missed-optimization Severity: enhancement Priority: P3 Component: rtl-optimization Assignee: unassigned at gcc dot gnu.org Reporter: rsandifo at gcc dot gnu.org Target Milestone: --- Compiling the following testcase with -march=armv8.2-a+sve -O2: --------------------------------------------------------------------- void bar (__SVFloat32_t); void foo (__SVFloat32_t x) { try { bar (x); } catch (...) { bar (x); throw; } } --------------------------------------------------------------------- gives an EH handler like the following; --------------------------------------------------------------------- .cfi_restore_state str z8, [sp, #2, mul vl] .cfi_escape 0x10,0x48,0x8,0x8f,0,0x92,0x2e,0,0x40,0x1e,0x22 str z9, [sp, #3, mul vl] .cfi_escape 0x10,0x49,0x8,0x8f,0,0x92,0x2e,0,0x48,0x1e,0x22 str z10, [sp, #4, mul vl] .cfi_escape 0x10,0x4a,0x9,0x8f,0,0x92,0x2e,0,0x8,0x20,0x1e,0x22 str z11, [sp, #5, mul vl] .cfi_escape 0x10,0x4b,0x9,0x8f,0,0x92,0x2e,0,0x8,0x28,0x1e,0x22 str z12, [sp, #6, mul vl] .cfi_escape 0x10,0x4c,0x9,0x8f,0,0x92,0x2e,0,0x8,0x30,0x1e,0x22 str z13, [sp, #7, mul vl] .cfi_escape 0x10,0x4d,0x9,0x8f,0,0x92,0x2e,0,0x8,0x38,0x1e,0x22 str z14, [sp, #8, mul vl] .cfi_escape 0x10,0x4e,0x9,0x8f,0,0x92,0x2e,0,0x8,0x40,0x1e,0x22 str z15, [sp, #9, mul vl] .cfi_escape 0x10,0x4f,0x9,0x8f,0,0x92,0x2e,0,0x8,0x48,0x1e,0x22 str z16, [sp, #10, mul vl] str z17, [sp, #11, mul vl] str z18, [sp, #12, mul vl] str z19, [sp, #13, mul vl] str z20, [sp, #14, mul vl] str z21, [sp, #15, mul vl] str z22, [sp, #16, mul vl] str z23, [sp, #17, mul vl] str p5, [sp, #1, mul vl] str p6, [sp, #2, mul vl] str p7, [sp, #3, mul vl] str p8, [sp, #4, mul vl] str p9, [sp, #5, mul vl] str p10, [sp, #6, mul vl] str p11, [sp, #7, mul vl] str p12, [sp, #8, mul vl] str p13, [sp, #9, mul vl] str p14, [sp, #10, mul vl] str p15, [sp, #11, mul vl] str p4, [sp] bl __cxa_begin_catch add x0, sp, 32 ldr z0, [x0, #18, mul vl] .LEHB1: bl _Z3bar13__SVFloat32_t bl __cxa_rethrow .LEHE1: .L5: mov x19, x0 bl __cxa_end_catch mov x0, x19 .LEHB2: bl _Unwind_Resume --------------------------------------------------------------------- The spills of z8-z23 and p4-p15 are completely unnecessary, since the noreturn _Unwind_Resume call ensures that this code never returns to foo's caller. I think the fix is to make ira.c:update_equiv_regs_prescan a bit smarter: if a call occurs in a block that has no path to the exit block, then we only need to consider (parts of) registers that are clobbered by the callee but preserved by both eh_edge_abi and the current function's abi. If, as is usual, eh_edge_abi is the lowest common denominator among the available ABIs, no callees will clobber something that is preserved by eh_edge_abi.