Hi! We miscompile the following testcase, because first we add a mem/v into the hash table (which should not happen), later on during merge_equiv_classes a new element for that mem/v is added and doesn't even have in_memory set (because HASH failed with do_not_record but nothing checked it) and later on this results in that memory not being properly invalidated.
The initial problem is that if SET_DEST (sets[i].rtl) is a volatile mem, but we have a known value at that memory, we compute initially sets[i].dest_hash as hash value of the known value. That doesn't result into do_not_record, and when we recompute actual hash value for the MEM, we ignore the do_not_record flag. I've tested it also with logging when did this trigger, and in both bootstraps it triggered only on the new testcase and in 64-bit build of libstdc++-v3/testsuite/29_atomics/atomic_flag/test_and_set/explicit-hle.cc. Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk? 2015-02-02 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/64756 * cse.c (cse_insn): If dest != SET_DEST (sets[i].rtl) and HASH (SET_DEST (sets[i].rtl), mode) computation sets do_not_record, invalidate and do not record it. * gcc.c-torture/execute/pr64756.c: New test. --- gcc/cse.c.jj 2015-01-23 20:49:11.000000000 +0100 +++ gcc/cse.c 2015-02-02 11:51:57.508084360 +0100 @@ -5521,7 +5521,22 @@ cse_insn (rtx_insn *insn) } if (sets[i].rtl != 0 && dest != SET_DEST (sets[i].rtl)) - sets[i].dest_hash = HASH (SET_DEST (sets[i].rtl), mode); + { + do_not_record = 0; + sets[i].dest_hash = HASH (SET_DEST (sets[i].rtl), mode); + if (do_not_record) + { + rtx dst = SET_DEST (sets[i].rtl); + if (REG_P (dst) || GET_CODE (dst) == SUBREG) + invalidate (dst, VOIDmode); + else if (MEM_P (dst)) + invalidate (dst, VOIDmode); + else if (GET_CODE (dst) == STRICT_LOW_PART + || GET_CODE (dst) == ZERO_EXTRACT) + invalidate (XEXP (dst, 0), GET_MODE (dst)); + sets[i].rtl = 0; + } + } #ifdef HAVE_cc0 /* If setting CC0, record what it was set to, or a constant, if it --- gcc/testsuite/gcc.c-torture/execute/pr64756.c.jj 2015-02-02 11:53:06.903882851 +0100 +++ gcc/testsuite/gcc.c-torture/execute/pr64756.c 2015-02-02 11:52:53.000000000 +0100 @@ -0,0 +1,30 @@ +/* PR rtl-optimization/64756 */ + +int a, *tmp, **c = &tmp; +volatile int d; +static int *volatile *e = &tmp; +unsigned int f; + +static void +fn1 (int *p) +{ + int g; + for (; f < 1; f++) + for (g = 1; g >= 0; g--) + { + d || d; + *c = p; + + if (tmp != &a) + __builtin_abort (); + + *e = 0; + } +} + +int +main () +{ + fn1 (&a); + return 0; +} Jakub