[Bug tree-optimization/93586] [10 Regression] wrong code at -O1 on x86_64-linux-gnu

rguenth at gcc dot gnu.org gcc-bugzilla@gcc.gnu.org
Wed Feb 5 09:29:00 GMT 2020


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=93586

Richard Biener <rguenth at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
                 CC|                            |hubicka at gcc dot gnu.org
           Assignee|unassigned at gcc dot gnu.org      |rguenth at gcc dot gnu.org

--- Comment #5 from Richard Biener <rguenth at gcc dot gnu.org> ---
DSE also happily removes the initializer parts for

int
main ()
{
  char c[1][4][1] = { { { 7 }, { 0 }, { 5 }, { 5 } } };
  for (int b = 0; b <= 3; b++)
    if (c[0][b][0])
      __builtin_abort ();
  return 0;
}

the code contains commentary explicitely noting this situation:

              /* If index is non-zero we need to check whether the reference
                 does not break the main invariant that bases are either
                 disjoint or equal.  Consider the example:

                 unsigned char out[][1];
                 out[1]="a";
                 out[i][0];

                 Here bases out and out are same, but after removing the
                 [i] index, this invariant no longer holds, because
                 out[i] points to the middle of array out.

                 TODO: If size of type of the skipped reference is an integer
                 multiply of the size of type of the other reference this
                 invariant can be verified, but even then it is not completely
                 safe with !flag_strict_aliasing if the other reference
contains
                 unbounded array accesses.
                 See   */

but it gets defeated by the accesses having c[0] in the base (but not in
the next dimension).  Then we end up asking nonoverlapping_array_refs_p
for c[0] vs. c[0][b_2] which are not matching dimensions thus -1 is
returned.  The next query is then for c[0][3] vs. c[0][b_2][0]
which returns 1(!? why's that not a mismatch)
and since there's no partial overlap we immeditately return success
(but seen_unmatched_ref_p is true)

          /* Try to disambiguate matched arrays.  */
          for (unsigned int i = 0; i < narray_refs1; i++)
            {
              int cmp = nonoverlapping_array_refs_p (component_refs1.pop (),
                                                     component_refs2.pop ());
              if (cmp == 1 && !partial_overlap)
                {
                  ++alias_stats
                    .nonoverlapping_refs_since_match_p_no_alias;
                  return 1;
                }
              partial_overlap = false;
              if (cmp == -1)
                seen_unmatched_ref_p = true;
            }

The mismatch doesn't happen because sizeof(char[1]) == sizeof(char).

 @@ -1291,6 +1292,11 @@ nonoverlapping_array_refs_p (tree ref1, tree ref2)

   tree elmt_type1 = TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref1, 0)));
   tree elmt_type2 = TREE_TYPE (TREE_TYPE (TREE_OPERAND (ref2, 0)));
+  /* If one element is an array but not the other there's an obvious
+     mismatch in dimensionality.  */
+  if ((TREE_CODE (elmt_type1) == ARRAY_TYPE)
+      != (TREE_CODE (elmt_type2) == ARRAY_TYPE))
+    return -1;

   if (TREE_OPERAND (ref1, 3))
     {

fixes that.  But maybe we're not even supposed to call the function
with such cases?  Honza?


More information about the Gcc-bugs mailing list