Hi, in the testcase we die in post-reload cprop because updating one insn clobber actually affect other insn clobber. I actually introduced clobber sharing back in 2005 to save memory for (clobber cc0). This broke with introduction of post-reload code copying that is now done by shrink wrapping.
Fixed by unsharing those clobbers that originate from pseudos. Bootstrapped/regtested x86_64-linux, OK? PR middle-end/56571 * valtrack.c (cleanup_auto_inc_dec): Unshare clobbers originating from pseudos. * emit-rtl.c (verify_rtx_sharing): Likewise. (copy_insn_1): Likewise. * rtl.c (copy_rtx): Likewise. * gcc.c-torture/compile/pr56571.c: New testcase. Index: valtrack.c =================================================================== *** valtrack.c (revision 196596) --- valtrack.c (working copy) *************** cleanup_auto_inc_dec (rtx src, enum mach *** 71,77 **** /* SCRATCH must be shared because they represent distinct values. */ return x; case CLOBBER: ! if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER) return x; break; --- 71,78 ---- /* SCRATCH must be shared because they represent distinct values. */ return x; case CLOBBER: ! if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER ! && ORIGINAL_REGNO (XEXP (x, 0)) == REGNO (XEXP (x, 0))) return x; break; Index: testsuite/gcc.c-torture/compile/pr56571.c =================================================================== *** testsuite/gcc.c-torture/compile/pr56571.c (revision 0) --- testsuite/gcc.c-torture/compile/pr56571.c (revision 0) *************** *** 0 **** --- 1,8 ---- + /* { dg-options "-funroll-loops -ftracer" } */ + int a, b; + + int f(void) + { + (a % b) && f(); + a = (0 || a | (a ? : 1)); + } Index: emit-rtl.c =================================================================== *** emit-rtl.c (revision 196596) --- emit-rtl.c (working copy) *************** verify_rtx_sharing (rtx orig, rtx insn) *** 2583,2589 **** return; /* SCRATCH must be shared because they represent distinct values. */ case CLOBBER: ! if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER) return; break; --- 2583,2593 ---- return; /* SCRATCH must be shared because they represent distinct values. */ case CLOBBER: ! /* Share clobbers of hard registers (like cc0), but do not share pseudo reg ! clobbers or clobbers of hard registers that originated as pseudos. ! This is needed to allow safe register renaming. */ ! if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER ! && ORIGINAL_REGNO (XEXP (x, 0)) == REGNO (XEXP (x, 0))) return; break; *************** repeat: *** 2797,2803 **** /* SCRATCH must be shared because they represent distinct values. */ return; case CLOBBER: ! if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER) return; break; --- 2801,2811 ---- /* SCRATCH must be shared because they represent distinct values. */ return; case CLOBBER: ! /* Share clobbers of hard registers (like cc0), but do not share pseudo reg ! clobbers or clobbers of hard registers that originated as pseudos. ! This is needed to allow safe register renaming. */ ! if (REG_P (XEXP (x, 0)) && REGNO (XEXP (x, 0)) < FIRST_PSEUDO_REGISTER ! && ORIGINAL_REGNO (XEXP (x, 0)) == REGNO (XEXP (x, 0))) return; break; *************** copy_insn_1 (rtx orig) *** 5303,5309 **** case SIMPLE_RETURN: return orig; case CLOBBER: ! if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER) return orig; break; --- 5311,5318 ---- case SIMPLE_RETURN: return orig; case CLOBBER: ! if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER ! && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0))) return orig; break; Index: rtl.c =================================================================== *** rtl.c (revision 196596) --- rtl.c (working copy) *************** copy_rtx (rtx orig) *** 256,262 **** /* SCRATCH must be shared because they represent distinct values. */ return orig; case CLOBBER: ! if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER) return orig; break; --- 256,266 ---- /* SCRATCH must be shared because they represent distinct values. */ return orig; case CLOBBER: ! /* Share clobbers of hard registers (like cc0), but do not share pseudo reg ! clobbers or clobbers of hard registers that originated as pseudos. ! This is needed to allow safe register renaming. */ ! if (REG_P (XEXP (orig, 0)) && REGNO (XEXP (orig, 0)) < FIRST_PSEUDO_REGISTER ! && ORIGINAL_REGNO (XEXP (orig, 0)) == REGNO (XEXP (orig, 0))) return orig; break;