@@ -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.
@@ -4963,6 +4959,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++;
new file mode 100644
@@ -0,0 +1,22 @@
+/* { dg-do compile { target i?86-*-* x86_64-*-* } } */
+/* { dg-options "-O2 -fdump-rtl-combine-all" } */
+
+/* This testcase checks if combine tries to combine sequences where the last
+ insn has a clobber of a reg, and a previous insn sets that reg.
+
+ In this case, we have three insns
+
+ (set flags (compare a b))
+ (set tmp (eq flags 0))
+ (parallel [(set dst (neg tmp))
+ (clobber flags)])
+
+ Previously, combine would not try the three-insn combination because of
+ the set and clobber of flags. Now it does. Test that. */
+
+
+int f(int a, int b) { return -(a == b); }
+
+/* This regexp works for reg parameters as well as mem parameters. */
+/* { dg-final { scan-rtl-dump {neg:SI[^:]*eq:SI[^:]*:SI} "combine" } } */
+/* { dg-final { cleanup-rtl-dump "combine" } } */