https://gcc.gnu.org/bugzilla/show_bug.cgi?id=85762
--- Comment #6 from Martin Jambor <jamborm at gcc dot gnu.org> --- The problem is that we now consider MEM_REFs loading a different type than the one of the underlying DECL as V_C_E and are equally careful about it. I this particular case, we have statements like. MEM[(struct box *)&D.389258].value = pos Where D.363334 is of type struct adaptor_cursor. If we follow the chain of first non-method fields, we get struct adaptor_cursor -> struct adaptor_value_type_ -> struct adaptor_value_type_2_ -> struct compressed_pair -> struct tagged -> struct getter -> struct getter -> struct compressed_tuple_ -> struct box, which is the type of the MEM_REF itself. So the MEM_REF is not really a V_C_E but instead represents a bunch of COMPONENT_REFs. The following patch makes all of the overhead go away but I guess the type walking results should be cached somehow and it also only works for MEM_REFs with zero offset, I'm not sure how likely it is to get MEM_REFs with equal semantics for fields with non-zero offset. diff --git a/gcc/tree-sra.c b/gcc/tree-sra.c index eeef31ba496..e94d01e0ffa 100644 --- a/gcc/tree-sra.c +++ b/gcc/tree-sra.c @@ -1169,10 +1169,27 @@ contains_vce_or_bfcref_p (const_tree ref) || TREE_CODE (TREE_OPERAND (ref, 0)) != ADDR_EXPR) return false; - tree mem = TREE_OPERAND (TREE_OPERAND (ref, 0), 0); + tree mem_type = TREE_TYPE (TREE_OPERAND (TREE_OPERAND (ref, 0), 0)); if (TYPE_MAIN_VARIANT (TREE_TYPE (ref)) - != TYPE_MAIN_VARIANT (TREE_TYPE (mem))) - return true; + != TYPE_MAIN_VARIANT (mem_type)) + { + while (TREE_CODE (mem_type) == RECORD_TYPE) + { + tree fld; + for (fld = TYPE_FIELDS (mem_type); fld; fld = DECL_CHAIN (fld)) + if (TREE_CODE (fld) == FIELD_DECL) + { + if (TYPE_MAIN_VARIANT (TREE_TYPE (ref)) + == TYPE_MAIN_VARIANT (TREE_TYPE (fld))) + return false; + mem_type = TREE_TYPE (fld); + break; + } + if (!fld) + break; + } + return true; + } return false; }