This came up when investigating PR62151. In that PR combine messes up a four-insn combination. It should really have done the combination of the first three insns in that. The second of those instructions sets a register; the third clobbers the same. Substituting the source of the set into the clobber usually results in invalid RTL so that the combination will not be valid; also, it confuses the undobuf machinery. can_combine_p rejects the combination for this reason.
But we can simply make subst not substitute into clobbers of registers. Any unnecessary clobbers will be removed later anyway. With this patch, the three-insn combination in PR62151 is successful. It does likely not really solve the problem there though, it just hides it. Bootstrapped and regression checked on powerpc64-linux, options -m64,-m32,-m32/-mpowerpc64. Is this okay for mainline? Segher 2014-09-03 Segher Boessenkool <seg...@kernel.crashing.org> PR rtl-optimization/62151 * combine.c (can_combine_p): Allow the destination register of INSN to be clobbered in I3. (subst): Do not substitute into clobbers of registers. --- gcc/combine.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gcc/combine.c b/gcc/combine.c index 60524b5..6a5dfbb 100644 --- a/gcc/combine.c +++ b/gcc/combine.c @@ -1950,11 +1950,7 @@ can_combine_p (rtx_insn *insn, rtx_insn *i3, rtx_insn *pred ATTRIBUTE_UNUSED, for (i = XVECLEN (PATTERN (i3), 0) - 1; i >= 0; i--) if (GET_CODE (XVECEXP (PATTERN (i3), 0, i)) == CLOBBER) { - /* Don't substitute for a register intended as a clobberable - operand. */ rtx reg = XEXP (XVECEXP (PATTERN (i3), 0, i), 0); - if (rtx_equal_p (reg, dest)) - return 0; /* If the clobber represents an earlyclobber operand, we must not substitute an expression containing the clobbered register. @@ -4964,6 +4960,11 @@ subst (rtx x, rtx from, rtx to, int in_dest, int in_cond, int unique_copy) || (REG_P (X) && REG_P (Y) \ && REGNO (X) == REGNO (Y) && GET_MODE (X) == GET_MODE (Y))) + /* Do not substitute into clobbers of regs -- this will never result in + valid RTL. */ + if (GET_CODE (x) == CLOBBER && REG_P (XEXP (x, 0))) + return x; + if (! in_dest && COMBINE_RTX_EQUAL_P (x, from)) { n_occurrences++; -- 1.8.1.4