https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93891
--- Comment #3 from Richard Biener <rguenth at gcc dot gnu.org> --- So FRE/PRE see _91 = __MEM <const struct A> ((const struct A &)__first_58).p; __MEM <struct A> (__cur_59).p = _91; _92 = __MEM <int> (_91); if (_92 <= 0) goto __BB5(precise(0)); else goto __BB6(precise(134217728)); __BB(5,precise(0)): __builtin_unreachable (); __BB(6,guessed_local(-1430369669)): _93 = _92 + 1; __MEM <int> (_91) = _93; _94 = __first_58->p; _95 = __MEM <int> (_94); _96 = _95 + _Literal (int) -1; __MEM <int> (_94) = _96; but FRE4 sees _91 = MEM[base: __first_58, offset: _Literal (int * *) 0]; MEM[base: __cur_59, offset: _Literal (int * *) 0] = _91; _92 = __MEM <int> (_91); if (_92 <= 0) goto __BB5(precise(0)); else goto __BB6(precise(134217728)); __BB(5,precise(0)): __builtin_unreachable (); __BB(6,guessed_local(-1430369669)): _93 = _92 + 1; __MEM <int> (_91) = _93; _94 = MEM[base: __first_58, offset: _Literal (int * *) 0]; _95 = __MEM <int> (_94); _96 = _95 + _Literal (int) -1; __MEM <int> (_94) = _96; which might be enough different TBAA-wise to have the intermediate def stmt skipped. Ah, so we don't do if (is_gimple_reg_type (TREE_TYPE (lhs)) && types_compatible_p (TREE_TYPE (lhs), vr->type) && ref->ref) because we've valueized something in __first_75->sp and thus ref->ref is NULL and we need ref->ref for the alignment check. But we can use data->orig_ref.ref then. That doesn't help it seems because the load was entered differently in the hash table (a different vuse via the last_vuse mechanism - that's the immediately preceeding clobber we disambiguated against). Ideally the hash tables would contain entries for all virtual uses the expression is valid in but that's somewhat hard to encode (well, maybe simply not hash the vuse and record orig and last vuse and then do dominance checks to see if a query vuse falls in range). First piece of a fix: diff --git a/gcc/tree-ssa-sccvn.c b/gcc/tree-ssa-sccvn.c index a3fba2878f8..5d78be7e9d3 100644 --- a/gcc/tree-ssa-sccvn.c +++ b/gcc/tree-ssa-sccvn.c @@ -2455,7 +2455,7 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, and return the found value. */ if (is_gimple_reg_type (TREE_TYPE (lhs)) && types_compatible_p (TREE_TYPE (lhs), vr->type) - && ref->ref) + && (ref->ref || data->orig_ref.ref)) { tree *saved_last_vuse_ptr = data->last_vuse_ptr; /* Do not update last_vuse_ptr in vn_reference_lookup_2. */ @@ -2480,7 +2480,9 @@ vn_reference_lookup_3 (ao_ref *ref, tree vuse, void *data_, -fno-strict-aliasing. So simply resort to alignment to rule out overlaps. Do this check last because it is quite expensive compared to the hash-lookup above. */ - && multiple_p (get_object_alignment (ref->ref), ref->size) + && multiple_p (get_object_alignment + (ref->ref ? ref->ref : data->orig_ref.ref), + ref->size) && multiple_p (get_object_alignment (lhs), ref->size)) return res; }