Hi! As shown on the testcase below, if REE modifies some sign/zero extension insn, which is on the candidate vector, as a def_insn of some other extension, before combine_reaching_defs is called on that insn, we might ignore the changes done to that insn and just assume it is only an extension to the recorded mode. It might be an extension to a wider mode though.
Fixed thusly, bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk/4.7? 2012-04-30 Jakub Jelinek <ja...@redhat.com> PR rtl-optimization/53160 * ree.c (combine_reaching_defs): Handle the case where cand->insn has been modified by ree pass already. * gcc.c-torture/execute/pr53160.c: New test. --- gcc/ree.c.jj 2012-01-31 11:04:34.000000000 +0100 +++ gcc/ree.c 2012-04-30 11:24:02.682520157 +0200 @@ -667,6 +667,24 @@ combine_reaching_defs (ext_cand *cand, c if (!outcome) return false; + /* If cand->insn has been already modified, update cand->mode to a wider + mode if possible, or punt. */ + if (state->modified[INSN_UID (cand->insn)].kind != EXT_MODIFIED_NONE) + { + enum machine_mode mode; + rtx set; + + if (state->modified[INSN_UID (cand->insn)].kind + != (cand->code == ZERO_EXTEND + ? EXT_MODIFIED_ZEXT : EXT_MODIFIED_SEXT) + || state->modified[INSN_UID (cand->insn)].mode != cand->mode + || (set = single_set (cand->insn)) == NULL_RTX) + return false; + mode = GET_MODE (SET_DEST (set)); + gcc_assert (GET_MODE_SIZE (mode) >= GET_MODE_SIZE (cand->mode)); + cand->mode = mode; + } + merge_successful = true; /* Go through the defs vector and try to merge all the definitions --- gcc/testsuite/gcc.c-torture/execute/pr53160.c.jj 2012-04-30 11:34:33.807798084 +0200 +++ gcc/testsuite/gcc.c-torture/execute/pr53160.c 2012-04-30 11:34:18.000000000 +0200 @@ -0,0 +1,35 @@ +/* PR rtl-optimization/53160 */ + +extern void abort (void); + +int a, c = 1, d, e, g; +volatile int b; +volatile char f; +long h; +short i; + +void +foo (void) +{ + for (e = 0; e; ++e) + ; +} + +int +main () +{ + if (g) + (void) b; + foo (); + for (d = 0; d >= 0; d--) + { + short j = f; + int k = 0; + i = j ? j : j << k; + } + h = c == 0 ? 0 : i; + a = h; + if (a != 0) + abort (); + return 0; +} Jakub