http://gcc.gnu.org/bugzilla/show_bug.cgi?id=60291
--- Comment #9 from Richard Biener <rguenth at gcc dot gnu.org> --- Ok, so the rest is hash collisions in the mem-attrs hash. We also do useless work here: case MEM_REF: { addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (exp, 0)))); ... set_mem_attributes (temp, exp, 0); set_mem_addr_space (temp, as); set_mem_attributes already handles MEM_REFs properly: /* Address-space information is on the base object. */ if (TREE_CODE (base) == MEM_REF || TREE_CODE (base) == TARGET_MEM_REF) as = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (TREE_OPERAND (base, 0)))); so removing that would cut expand time in half. Oh, and expand_debug_expr even gets addr-spaces wrong (in cfgexpand.c). We have 1107000 callso to set_mem_attrs but 151459000 calls to mem_attrs_htab_eq. The hash function is somewhat ad-hoc apart from hashing MEM_EXPR via iterative_hash_expr. We hash MEM_REFs via hashing their operands recursively but we compare them more strictly factoring in properties of types involved. I don't see an easy way to make the hashing stronger (given PR58521 and its fix). There is always the old idea of simply removing that mem_attr sharing completely ... At -O0 we could simply always force a NULL_TREE MEM_EXPR for example.