https://gcc.gnu.org/bugzilla/show_bug.cgi?id=122976
--- Comment #15 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The releases/gcc-14 branch has been updated by Martin Jambor <[email protected]>: https://gcc.gnu.org/g:3f981fc5f1894e14b4cc7bce1b3785099542e4f1 commit r14-12580-g3f981fc5f1894e14b4cc7bce1b3785099542e4f1 Author: Martin Jambor <[email protected]> Date: Wed Apr 15 18:28:32 2026 +0200 sra: Dont use build_reconstructed_reference on MEM_REFs changin types (PR122976) PR122976 is basically a variant of PR105860 but instead of a union there is a MEM_REF with a different type from the underlying DECL it accesses. Like in the other bug, this confuses build_reconstructed_reference which then finds wrong compatible base and proceeds to identify a bogus FIELD_DECL to assign to a new access, leading to memory accesses to a wrong place. This is caught by the internal verifier when checking but unfortunately leads to miscompilation without it. The patch fixes this by clearing grp_same_access_path of such accesses so that build_reconstructed_reference is not used at all for them. The original testcase no longer exhibits the bug on master since r16-3201-gee67004474d521 (Andrew Pinski: forwprop: Copy prop aggregates into args) but it turns out that my artificial one still triggers. If you want more details on what is going on, here they are, the issue involves two VAR_DECLs: struct tySequence__6H5Oh5UUvVCLiakt9aTwtUQ ISRA.487D.19501; struct tyObject_Rlp__dNpAlq42D2iOFkwuW8WMyQ nextRef_1D.19109; where the types are (NI is int64_t): struct tySequence__6H5Oh5UUvVCLiakt9aTwtUQ { NI len; tySequence__6H5Oh5UUvVCLiakt9aTwtUQ_Content* p; }; struct tyObject_Rlp__dNpAlq42D2iOFkwuW8WMyQ { tySequence__6H5Oh5UUvVCLiakt9aTwtUQ bytes; NI position; }; And an assignment between them: ISRA.487D.19501 = MEM[(struct tySequence__6H5Oh5UUvVCLiakt9aTwtUQ *)&nextRef_1D.19109]; which triggers code that tries to create accesses for LHS corresponding to those collected for nextRef_1. Unfortunately the one for offset 64 was created from access: MEM[(struct tyTuple__hnCuDR9cLe2lA3YIkwKIyuA *)&nextRef_1D.19109].Field1D.6487.lenD.5644 = 0; which brings a third type into the mix: struct tyTuple__hnCuDR9cLe2lA3YIkwKIyuA { NI Field0; tySequence__6H5Oh5UUvVCLiakt9aTwtUQ Field1; }; which is setting the len field after the type-cast but in terms of the underlying type of the DECL, it is actually setting the pointer field. Because SRA looks at the accesses rather than the types, it also means that the access for the pointer was represented by a signed 64bit integer and the stored expression was the above, two COMPONENT_REFs bolted on top of the type changing MEM_REF. The access also got the grp_same_access_path flag set, meaning we'd try to preserve the "access path," the chain of handled_references in many contexts such as propagating the accesses across assignments. And there things went wrong, build_reconstructed_reference found the MEM_REF, realized it was compatible with the base DECL and happily assumed that means that whatever was used on top of the MEM_REF can be used on top of the DECL to access the corresponding bit of memory. The wrong bit was not clearing grp_same_access_path, which we for example cleared when the MEM_REF had a non-zero offset and so this patch detects the situation and clears it. gcc/ChangeLog: 2026-03-15 Martin Jambor <[email protected]> PR tree-optimization/122976 * tree-sra.cc (path_comparable_for_same_access): Return false if the base is a MEM_REF with a different underlying type. gcc/testsuite/ChangeLog: 2026-03-18 Martin Jambor <[email protected]> PR tree-optimization/122976 * gcc.dg/tree-ssa/pr122976.c: New test. (cherry picked from commit 0c286ea4006d31d066e7b11714e04f4be0a912de)
