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

--- Comment #10 from Dominik Vogt <vogt at linux dot vnet.ibm.com> ---
This is what's happening:

Before the dse2 pass, there is a store instruction (25) followed by a read
instruction later (29):

---
# store first byte
(insn 25 135 136 4 (set (mem/j:QI (reg/v/f:DI 2 %r2 [orig:47 ps ] [47]) [2
ps_7\
->f1+0 S1 A32]) 
        (reg:QI 1 %r1 [orig:51 D.2017+3 ] [51])) t67443.cxx:17 74 {*movqi} 
     (nil))

(insn 136 25 137 4 (set (reg/v/f:DI 1 %r1 [orig:47 ps ] [47]) 
        (reg/v/f:DI 3 %r3 [orig:47 ps ] [47])) t67443.cxx:18 63 {*movdi_64} 
     (nil)) 

# overwrites r2
(insn 137 136 29 4 (set (reg:SI 2 %r2 [68]) 
        (mem/u/c:SI (unspec:DI [ 
                    (symbol_ref/u:DI ("*.LC0") [flags 0x2]) 
                    (reg:DI 13 %r13) 
                ] UNSPEC_LTREF) [3  S4 A32])) t67443.cxx:18 67 {*movsi_zarch} 
     (nil)) 

# write three bytes
(insn 29 137 139 4 (parallel [ 
            (set (reg:SI 2 %r2 [68]) 
                (and:SI (reg:SI 2 %r2 [68]) 
                    (mem/j:SI (reg/v/f:DI 1 %r1 [orig:47 ps ] [47]) [2
ps_7->f2\
+-1 S4 A32]))) 
            (clobber (reg:CC 33 %cc)) 
        ]) t67443.cxx:18 454 {*andsi3_zarch} 
     (nil)) 
---

With the unpatched code, the a "value" expression is put in the mem_addr field
of the store_info for the "set" (similar for the read in insn 29):

store (value:DI 3:3 @0xb7049598/0xb70516a8) 
read  (value:DI 3:3 @0xb7049598/0xb70516a8) 

With the patched code, the mem_addr is resolved to a register expression r2 for
the store and r1 for the read:

store (reg/v/f:DI 2 %r2 [orig:47 ps ] [47])
read  (reg/v/f:DI 1 %r1 [orig:47 ps ] [47])

Then, canon_true_dependence is called with these terms and calls get_addr on
them again.  In the unpatched case, the same address value is resolved to the
same register expression:

(reg/v/f:DI 1 %r1 [orig:47 ps ] [47])

With the patched code, there's nothing left to do for get_addr, so there are
two different register expressions that describe the same address.  In the end,
memrefs_conflict_p() gets called with the two different register expressions
and fails to detect that they refer to the same address (which they do *not* at
insn 29 because r2 has been overwritten in between).

So, I'd say the new call of get_addr() in record_store() is too early because
it may replace the address value by an expression that is no longer valid when
the memory is read later.

Reply via email to