@@ -3509,36 +3509,43 @@ try_combine (rtx i3, rtx i2, rtx i1, int
&& GET_CODE (XVECEXP (newpat, 0, 1)) == SET
&& GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != ZERO_EXTRACT
&& GET_CODE (SET_DEST (XVECEXP (newpat, 0, 1))) != STRICT_LOW_PART
- && ! use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)),
- DF_INSN_LUID (i2))
&& ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 1)),
XVECEXP (newpat, 0, 0))
&& ! reg_referenced_p (SET_DEST (XVECEXP (newpat, 0, 0)),
XVECEXP (newpat, 0, 1))
&& ! (contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 0)))
- && contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 1))))
-#ifdef HAVE_cc0
- /* We cannot split the parallel into two sets if both sets
- reference cc0. */
- && ! (reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0))
- && reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 1)))
-#endif
- )
+ && contains_muldiv (SET_SRC (XVECEXP (newpat, 0, 1)))))
{
/* Normally, it doesn't matter which of the two is done first,
- but it does if one references cc0. In that case, it has to
+ but the one that references cc0 can't be the second, and
+ one which uses any regs/memory set in between i2 and i3 can't
be first. */
+ bool pat0_in_i2_ok
+ = !use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 0)),
+ DF_INSN_LUID (i2));
+ bool pat1_in_i2_ok
+ = !use_crosses_set_p (SET_SRC (XVECEXP (newpat, 0, 1)),
+ DF_INSN_LUID (i2));
#ifdef HAVE_cc0
if (reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 0)))
+ pat1_in_i2_ok = false;
+ if (reg_referenced_p (cc0_rtx, XVECEXP (newpat, 0, 1)))
+ pat0_in_i2_ok = false;
+#endif
+ if (pat1_in_i2_ok)
+ {
+ newi2pat = XVECEXP (newpat, 0, 1);
+ newpat = XVECEXP (newpat, 0, 0);
+ }
+ else if (pat0_in_i2_ok)
{
newi2pat = XVECEXP (newpat, 0, 0);
newpat = XVECEXP (newpat, 0, 1);
}
else
-#endif
{
- newi2pat = XVECEXP (newpat, 0, 1);
- newpat = XVECEXP (newpat, 0, 0);
+ undo_all ();
+ return 0;
}
i2_code_number = recog_for_combine (&newi2pat, i2, &new_i2_notes);
@@ -3564,13 +3571,11 @@ try_combine (rtx i3, rtx i2, rtx i1, int
temp = newpat;
newpat = XVECEXP (newi2pat, 0, 0);
newi2pat = temp;
-#ifdef HAVE_cc0
- if (reg_referenced_p (cc0_rtx, newpat))
+ if (!pat0_in_i2_ok || !pat1_in_i2_ok)
{
undo_all ();
return 0;
}
-#endif
i2_code_number = recog_for_combine (&newi2pat, i2,
&new_i2_notes);
@@ -0,0 +1,32 @@
+/* PR rtl-optimization/45695 */
+
+extern void abort (void);
+
+__attribute__((noinline)) void
+g (int x)
+{
+ asm volatile ("" : "+r" (x));
+}
+
+__attribute__((noinline)) int
+f (int a, int b, int d)
+{
+ int r = -1;
+ b += d;
+ if (d == a)
+ r = b - d;
+ g (b);
+ return r;
+}
+
+int
+main (void)
+{
+ int l;
+ asm ("" : "=r" (l) : "0" (0));
+ if (f (l + 0, l + 1, l + 4) != -1)
+ abort ();
+ if (f (l + 4, l + 1, l + 4) != 1)
+ abort ();
+ return 0;
+}