GCC's intraprocedural SRA pass operates by collecting all references to decls of aggregate type in a procedure, and creating a tree in which every node represents all references to each decl which share an identical offset and size such that the most general reference appears nearest to the top. In creating such a tree, it assumes that a sorting function will arrange a vector of references in decreasing order of generality: larger references appear before smaller ones, aggregate references before complex or vector references, integral reference before reals, references to types of greater precision before those of lesser precision, and, all else being equal, the sorting is stabilized by reference to the order in which the operand types are defined. Accordingly, the first element of the vector is assumed to provide the root of a tree. The compiler proceeds by "totally scalarizing" a decl's references from its root, if it is of record type and every field is itself scalar or scalarizable, and scalarizing all statements that reference the same decl with the same offset and size in the manner previously defined. Many properties of every reference to a declaration are fixed at this time, such as whether the declaration is completely encompassed by scalarized variables, which fails when a union or a struct is excluded from a decl's access tree for being identical in offset and size, but has a different data layout from the type of the access at its root. In Emacs's case it should be possible to circumvent this problem by creating an incomplete declaration of `union buffered_input_event' before `struct input_event', so that the union may be defined first and inhibit total scalarization, but this will not address the oversight in GCC. This eliminates the miscompilation, but also a minor class of optimizations. I believe this optimization must be re-engineered if it is optimally to scalarize combinations of union and member references. diff --git a/gcc/tree-sra.cc b/gcc/tree-sra.cc index c26559edc66..edd9b477b39 100644 --- a/gcc/tree-sra.cc +++ b/gcc/tree-sra.cc @@ -2483,6 +2483,19 @@ sort_and_splice_var_accesses (tree var) } unscalarizable_region = true; } + else if (AGGREGATE_TYPE_P (access->type) + && AGGREGATE_TYPE_P (ac2->type) + && !types_compatible_p (access->type, ac2->type)) + { + if (dump_file && (dump_flags & TDF_DETAILS)) + { + fprintf (dump_file, "Cannot scalarize the following region " + "because data may be scalarized in an incompatible " + "format.\n"); + dump_access (dump_file, access, false); + } + unscalarizable_region = true; + } else if (types_risk_mangled_binary_repr_p (access->type, ac2->type)) { if (dump_file && (dump_flags & TDF_DETAILS))