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.

Reply via email to