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;
            }

Reply via email to