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

--- Comment #4 from Jeffrey A. Law <law at redhat dot com> ---
So the testcase has undefined behaviour, but obviously we shouldn't be
crashing.

The key insns are:

(insn 17 16 18 2 (set (mem:SI (plus:DI (mult:DI (reg:DI 98 [ c_lsm.5 ])
                    (const_int 4 [0x4]))
                (symbol_ref:DI ("a") [flags 0x2] <var_decl 0x7ffff7ff6cf0 a>))
[1 a S4 A32])
        (reg/v:SI 93 [ m ])) j.c:7 86 {*movsi_internal}
     (expr_list:REG_DEAD (reg:DI 98 [ c_lsm.5 ])
        (nil)))
(insn 18 17 20 2 (parallel [
            (set (reg/v:SI 93 [ m ])
                (plus:SI (reg/v:SI 93 [ m ])
                    (const_int -1 [0xffffffffffffffff])))
            (clobber (reg:CC 17 flags))
        ]) j.c:8 218 {*addsi_1}
     (expr_list:REG_UNUSED (reg:CC 17 flags)
        (nil)))

Note that insn 17 comes before insn 18.

We're in this code:

     /* If this sets a MEM to the contents of a REG that is only used
         in a single basic block, see if the register is always equivalent
         to that memory location and if moving the store from INSN to the
         insn that set REG is safe.  If so, put a REG_EQUIV note on the
         initializing insn.

         Don't add a REG_EQUIV note if the insn already has one.  The existing
         REG_EQUIV is likely more useful than the one we are adding.

         If one of the regs in the address has reg_equiv[REGNO].replace set,
         then we can't add this REG_EQUIV note.  The reg_equiv[REGNO].replace
         optimization may move the set of this register immediately before
         insn, which puts it after reg_equiv[REGNO].init_insns, and hence
         the mention in the REG_EQUIV note would be to an uninitialized
         pseudo.  */


We make the following call:   
           && ! memref_used_between_p (dest, init_insn, insn)

Where init_insn 18 and insn is 17.  memref_used_between_p is a forward walk, so
not surprisingly bad things happen when the 3rd argument comes before the 2nd
argument.  This situation is a direct result of the undefined behaviour in the
testcase.

From looking at the code, I think it's easiest to just bulletproof
memref_used_between_p.  Another approach would be to track the insns we've seen
in the enclosing loop and if INSN is one of them, then assume we can't create
the REG_EQUIV note.

Either should solve this problem.

Reply via email to