Subject: bug#76559: 31.0.50; [-O3 + PGTK] Crash when 'copying as kill'/'killing word'

From: Po Lu <[email-masked]>
Date: Sun, 02 Mar 2025 13:10:08 +0800

Paul Eggert <[email-masked]> writes:

> On 2025-03-01 05:43, Po Lu wrote:
>> I surmise that it doesn't fix the underlying compiler issue if you add
>> __attribute__ ((force_inline)) to kbd_buffer_store_buffered_event, as it
>> is a product of an assumption by GCC's SRA pass that no two accesses of
>> a single local aggregate declaration with the same offset and size but
>> of different types alias.
>
> I don't see why that assumption would cause GCC to generate the wrong
> code here, as no single thread of execution would have two such
> accesses.

It doesn't take control flow into account, but rather _every statement
operand_ in the current procedure that addresses an aggregate declared
in the same procedure.  Just read perform_intra_sra in gcc/tree-sra.cc.
find_var_candidates, scan_function, analyze_all_variable_accesses, and
sra_modify_function_body, don't walk any manner of control dependence
graph, but all declarations and basic blocks defined in a function.

sort_and_splice_var_accesses excludes all but one access to a single
aggregate with the same offset and size.  Since the existence of a
record reference thereby excludes the union, totally_scalarizable_type_p
concludes that the access admits of "total secularization", and
analyze_all_variable_accesses proceeds to scalarize this record
reference.  Subsequently, sra_modify_assign observes that the access of
union access on the RHS of this statement (where the `ev' declaration in
evq_flush is substituted for `*event' by inlining):

      *kbd_store_ptr = *event;

has the same size and offset as the access to `event->ie' (`ev.ie'),
deletes the statement, and substitutes a series of loads produced by the
scalarization of the access to `ev.ie', without any regard to the type
of the RHS.  If it is arranged that `union buffered_input_event' be
declared before `struct input_event', the former will receive a lower
UID and a greater precedence with analyze_all_variable_accesses, and
exclude the loads of `struct input_event' from consideration, which
eliminates the problem in this specific instance because unions are not
totally scalarizable.