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)