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

--- Comment #2 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
The bug is in the way we handle overlapping stores.  The problem is that all we
do if there is overlap is:
      if (IN_RANGE (info->bitpos, merged_store->start,
                    merged_store->start + merged_store->width - 1))
        {
          /* Only allow overlapping stores of constants.  */
          if (info->rhs_code == INTEGER_CST
              && merged_store->stores[0]->rhs_code == INTEGER_CST)
            {
              merged_store->merge_overlapping (info);
              continue;
            }
        }
otherwise we:
      /* |---store 1---| <gap> |---store 2---|.
         Gap between stores or the rhs not compatible.  Start a new group.  */

      /* Try to apply all the stores recorded for the group to determine
         the bitpattern they write and discard it if that fails.
         This will also reject single-store groups.  */
      if (!merged_store->apply_stores ())
        delete merged_store;
      else
        m_merged_store_groups.safe_push (merged_store);

      merged_store = new merged_store_group (info);
But the statements here are sorted primarily by bitpos and we emit statements
for the group at the location of the last statement (highest order) in the
merged store group.  So I think we need to check before adding another store if
it is not rhs_code INTEGER_CST, whether there is any overlap with following
stores.  Overlap is fine if the order of all the overlapping statements is
higher than MAX (merged_store->last_order, info->order), because then we know
we'll start a new group right after info and the merged stores of the current
group will come before any overlapping stores (whether merged successfully with
something or not), but otherwise we just shouldn't add info into the current
group.

Reply via email to