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

--- Comment #5 from Uroš Bizjak <ubizjak at gmail dot com> ---
The cc1 gem from comment #2 actually comes from libz's deflate.c, function
deflate_stores:

        /* Replace the lengths in the dummy stored block with len. */
        s->pending_buf[s->pending - 4] = len;
        s->pending_buf[s->pending - 3] = len >> 8;
        s->pending_buf[s->pending - 2] = ~len;
        s->pending_buf[s->pending - 1] = ~len >> 8;

The compiler, patched with both patches, does not merge stores there.

Please consider following testcase:

--cut here--
typedef __SIZE_TYPE__ size_t;

struct s
{
  char *buf;
  size_t cnt;
};

void foo (struct s *state, unsigned int data)
{
  state->buf[state->cnt - 4] = data;
  state->buf[state->cnt - 3] = data >> 8;
  state->buf[state->cnt - 2] = ~data;
  state->buf[state->cnt - 1] = ~data >> 8;
}

void bar (char *buf, size_t *cnt, unsigned int data)
{
  buf[*cnt - 4] = data;
  buf[*cnt - 3] = data >> 8;
  buf[*cnt - 2] = ~data;
  buf[*cnt - 1] = ~data >> 8;
}

void baz (char *buf, size_t cnt, unsigned int data)
{
  buf[cnt - 4] = data;
  buf[cnt - 3] = data >> 8;
  buf[cnt - 2] = ~data;
  buf[cnt - 1] = ~data >> 8;
}
--cut here--

None of the stores in the above functions are merged.

The simplest function (baz) results in:

[*]     movl    %edx, %eax
        movb    %dl, -4(%rdi,%rsi)
        movb    %dh, -3(%rdi,%rsi)
        notl    %eax
[**]    notl    %edx
        movb    %al, -2(%rdi,%rsi)
        movb    %dh, -1(%rdi,%rsi)

In addition to a merge opportunity, there is a redundant move [*], that results
in redundant operation [**]. The whole function could be just:

        movw    %dx, -4(%rdi,%rsi)
        notl    %edx
        movw    %dx, -2(%rdi,%rsi)

Reply via email to