https://gcc.gnu.org/bugzilla/show_bug.cgi?id=114432
--- Comment #8 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Stefan Schulze Frielinghaus <[email protected]>: https://gcc.gnu.org/g:8d381a5e520aeebe387c6f6353357e76d489ed7f commit r17-5257-g8d381a5e520aeebe387c6f6353357e76d489ed7f Author: Stefan Schulze Frielinghaus <[email protected]> Date: Fri Oct 16 16:40:26 2026 +0200 explow: Restore stack_pointer_delta for allocate_stack [PR114432] Function allocate_dynamic_stack_space() saves and restores stack_pointer_delta only if expander allocate_stack is not available. On s390 with -mbackchain the expander becomes available and changes stack_pointer_delta indirectly by calling into anti_adjust_stack() (as the else branch does when the expander is not available). In that case nothing is saved or restored, so the altered stack_pointer_delta leaks. With -fstack-check, expand_function_end() emits a function-entry probe through anti_adjust_stack_and_probe() which then picks up the leaked value. This can be observed in reproducer pr114432-1.c where the entry-probe insns 47 and 50 carry wrong REG_ARGS_SIZE notes: (insn 47 2 48 2 (parallel [ (set (reg/f:DI 15 %r15) (plus:DI (reg/f:DI 15 %r15) (const_int -8216 [0xffffffffffffdfe8]))) (clobber (reg:CC 33 %cc)) ]) "pr114432-1.c":7:1 -1 (expr_list:REG_ARGS_SIZE (const_int 8304 [0x2070]) <--- should be 8216 (nil))) ... (insn 50 49 3 2 (parallel [ (set (reg/f:DI 15 %r15) (plus:DI (reg/f:DI 15 %r15) (const_int 8216 [0x2018]))) (clobber (reg:CC 33 %cc)) ]) "pr114432-1.c":7:1 -1 (expr_list:REG_ARGS_SIZE (const_int 88 [0x58]) <--- should be 0 (nil))) ... (insn 30 29 31 7 (set (reg/f:DI 15 %r15) (reg/f:DI 62 [ saved_stack.1_6 ])) -1 (expr_list:REG_ARGS_SIZE (const_int 0 [0]) <--- ok (nil))) Here the constant-sized alloca with a size of 88 bytes leaks into REG_ARGS_SIZE (8304 = 8216 + 88). Note, REG_ARGS_SIZE for insn 30 is correct since the insn restores the stack pointer after the alloca (the zero is hard coded in expand_stack_restore()). The entry probe, ending in insn 50, falls through into the loop head with the leaked 88 bytes, whereas the back edge of the loop arrives with 0 bytes (insn 30 restores the stack). Due to those two traces with differing args_sizes, args_size_undefined is set. Because -fexceptions makes a call in the loop trace possibly throwing, and no insn in that trace sets args_size before the first throwing call, args_size_defined_for_eh is not set. This renders the assert gcc_assert (!ti->args_size_undefined || ti->args_size_defined_for_eh); failing in connect_traces(). Fixed by saving/restoring stack_pointer_delta for allocate_stack, too. PR middle-end/114432 gcc/ChangeLog: * explow.cc (allocate_dynamic_stack_space): Save and restore stack_pointer_delta also if expander allocate_stack is available. gcc/testsuite/ChangeLog: * gcc.target/s390/pr114432-1.c: New test.
