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

Jakub Jelinek <jakub at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |ebotcazou at gcc dot gnu.org,
                   |                            |jakub at gcc dot gnu.org,
                   |                            |law at gcc dot gnu.org

--- Comment #3 from Jakub Jelinek <jakub at gcc dot gnu.org> ---
No idea what this has to do with wide_int, I don't see any relation
(unfortunately my r210112 and r210113 copies are without debug info at this
point).
But, it really seems to be a CSE bug to me (during cse2).
The thing is, in insn 29 tmp is stored to using volatile store:
(insn 29 27 30 7 (set (mem/v/f/c:SI (symbol_ref:SI ("tmp")  <var_decl
0x7f0ea7350cf0 tmp>) [1 MEM[(int * volatile *)&tmp]+0 S4 A32])
        (const_int 0 [0])) pr64756.c:19 90 {*movsi_internal}
     (nil))
but when the hash of dest is computed, we actually use:
      if (MEM_P (dest))
        {
#ifdef PUSH_ROUNDING
          /* Stack pushes invalidate the stack pointer.  */
          rtx addr = XEXP (dest, 0);
          if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC
              && XEXP (addr, 0) == stack_pointer_rtx)
            invalidate (stack_pointer_rtx, VOIDmode);
#endif
          dest = fold_rtx (dest, insn);
        }

      /* Compute the hash code of the destination now,
         before the effects of this instruction are recorded,
         since the register values used in the address computation
         are those before this instruction.  */
      sets[i].dest_hash = HASH (dest, mode);
and so dest is folded first into symbol_ref ("a").  That means when computing
hash we do not get do_not_record flag set, which we would otherwise get because
the memory is volatile, nor we do get the hash_arg_in_memory flag set.
Next we recompute the hash, but do not look at do_not_record anymore:
      if (sets[i].rtl != 0 && dest != SET_DEST (sets[i].rtl))
        sets[i].dest_hash = HASH (SET_DEST (sets[i].rtl), mode);
Later on we insert this mem/v/f/c into the hash table and set the in_memory
flag (correctly):
        elt->in_memory = (MEM_P (sets[i].inner_dest)
                          && !MEM_READONLY_P (sets[i].inner_dest));
Later on merge_equiv_classes is called, and that one obviously doesn't count
with the option that do_not_record might be true, and when we set
do_not_record, we don't set hash_arg_in_memory, so we end up with a new elt
that for the MEM
at this time doesn't even have in_memory flag set, so when we later in insn 36
store into memory that aliases with this, we do not even invalidate it.

Reply via email to