https://gcc.gnu.org/bugzilla/show_bug.cgi?id=78821
--- Comment #6 from rguenther at suse dot de <rguenther at suse dot de> --- On Thu, 9 Nov 2017, ubizjak at gmail dot com wrote: > 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) or xorl $0xffff0000, %edx movl %edx, -4(%rdi,%rsi) ?