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

            Bug ID: 86844
           Summary: wrong code generation cause by store merging pass
           Product: gcc
           Version: 8.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: tree-optimization
          Assignee: unassigned at gcc dot gnu.org
          Reporter: krebbel at gcc dot gnu.org
  Target Milestone: ---

Created attachment 44502
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=44502&action=edit
Reduced testcase

Compiling the attached testcase with -O2 results in the following code:

        movzbl  4(%rdi), %eax
        movl    $33024, 8(%rdi)
        movb    %al, 10(%rdi)

33024 -> 0  0 129 0

The store of 222 gets optimized away.

Without store merging:

        movzbl  4(%rdi), %eax
        movl    $0, 8(%rdi)
        movb    $-34, 11(%rdi)
        movb    $-127, 9(%rdi)
        movb    %al, 10(%rdi)

The original order of stores:

  a->b.wd0.u4i = 0;
  a->b.wd0.s2.w = 222;
  a->b.wd0.s2.y = 129;
  a->b.wd0.s2.z = a->f.wd1.s2.z;


coalesce_immediate_stores first reorders the stores according to its bit
positions:

  a->b.wd0.u4i = 0;
  a->b.wd0.s2.y = 129;
  a->b.wd0.s2.z = a->f.wd1.s2.z;
  a->b.wd0.s2.w = 222;

It then merges the first and the second and has to end the group seeing the
third. So the last ends up in its own group. Emitting the stores in the
original order makes the 222 store dead. The first two should not be merged.

coalesce_immediate_stores already tries to detect cases where stores later in
the chain might get invalidated by merging early stores but it also assumes
that if the later store also stores a constant it will be possible to merge it
as well.  However, in this case the non-constant store in between prevents
this.


Store merging pass output:

;; Function f (f, funcdef_no=0, decl_uid=1922, cgraph_uid=1, symbol_order=0)

Processing basic block <2>:
Starting new chain with statement:
a_3(D)->b.wd0.u4i = 0;
The base object is:
a_3(D)
Recording immediate store from stmt:
a_3(D)->b.wd0.s2.w = 222;
Recording immediate store from stmt:
a_3(D)->b.wd0.s2.y = 129;
Recording immediate store from stmt:
a_3(D)->b.wd0.s2.z = _1;
stmt causes chain termination:
return;
Attempting to coalesce 4 stores in chain
New store group
Store 0:
bitsize:32 bitpos:64 val:0
Store 1:
bitsize:8 bitpos:72 val:129
After writing 0 of size 32 at position 0
  the merged value contains 00 00 00 00 
  the merged mask contains  00 00 00 00 
After writing 129 of size 8 at position 8
  the merged value contains 00 81 00 00 
  the merged mask contains  00 00 00 00 
New store group
Store 2:
bitsize:8 bitpos:80 val:_1
New store group
Store 3:
bitsize:8 bitpos:88 val:222
Coalescing successful!
Merged into 1 stores
New sequence of 1 stores to replace old one of 2 stores
# .MEM_6 = VDEF <.MEM_5>
MEM[(union  *)a_3(D) + 8B] = 33024;
Merging successful!
f (struct bar * a)
{
  unsigned char _1;

  <bb 2> [local count: 1073741825]:
  a_3(D)->b.wd0.s2.w = 222;
  MEM[(union  *)a_3(D) + 8B] = 33024;
  _1 = a_3(D)->D.1919.f.wd1.s2.z;
  a_3(D)->b.wd0.s2.z = _1;
  return;

}

Reply via email to