/* We have something like:
if (x > y)
- { i = a; j = b; k = c; }
+ { i = EXPR_A; j = EXPR_B; k = EXPR_C; }
Make it:
- tmp_i = (x > y) ? a : i;
- tmp_j = (x > y) ? b : j;
- tmp_k = (x > y) ? c : k;
+ tmp_i = (x > y) ? EXPR_A : i;
+ tmp_j = (x > y) ? EXPR_B : j;
+ tmp_k = (x > y) ? EXPR_C : k;
i = tmp_i;
j = tmp_j;
k = tmp_k;
-/* Return true iff basic block TEST_BB is comprised of only
- (SET (REG) (REG)) insns suitable for conversion to a series
- of conditional moves. Also check that we have more than one set
- (other routines can handle a single set better than we would), and
- fewer than PARAM_MAX_RTL_IF_CONVERSION_INSNS sets. While going
+/* Return true iff basic block TEST_BB is suitable for conversion to a
+ series of conditional moves. Also check that we have more than one
+ set (other routines can handle a single set better than we would),
+ and fewer than PARAM_MAX_RTL_IF_CONVERSION_INSNS sets. While going
through the insns store the sum of their potential costs in COST. */
static bool
rtx dest = SET_DEST (set);
rtx src = SET_SRC (set);
- /* We can possibly relax this, but for now only handle REG to REG
- (including subreg) moves. This avoids any issues that might come
- from introducing loads/stores that might violate data-race-freedom
- guarantees. */
- if (!REG_P (dest))
- return false;
-
- if (!((REG_P (src) || CONSTANT_P (src))
- || (GET_CODE (src) == SUBREG && REG_P (SUBREG_REG (src))
- && subreg_lowpart_p (src))))
+ /* Do not handle anything involving memory loads/stores since it might
+ violate data-race-freedom guarantees. */
+ if (!REG_P (dest) || contains_mem_rtx_p (src))
return false;
- /* Destination must be appropriate for a conditional write. */
- if (!noce_operand_ok (dest))
+ /* Destination and source must be appropriate. */
+ if (!noce_operand_ok (dest) || !noce_operand_ok (src))
return false;
/* We must be able to conditionally move in this mode. */
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-rtl-ce1" } */
+
+void sink2(int, int);
+void sink3(int, int, int);
+
+void cond1(int cond, int x, int y)
+{
+ if (cond)
+ {
+ x = x << 4;
+ y = 1;
+ }
+
+ sink2(x, y);
+}
+
+void cond2(int cond, int x, int y)
+{
+ if (cond)
+ {
+ x++;
+ y++;
+ }
+
+ sink2(x, y);
+}
+
+void cond3(int cond, int x1, int x2, int x3)
+{
+ if (cond)
+ {
+ x1++;
+ x2++;
+ x3++;
+ }
+
+ sink3(x1, x2, x3);
+}
+
+void cond4(int cond, int x, int y)
+{
+ if (cond)
+ {
+ x += 2;
+ y += 3;
+ }
+
+ sink2(x, y);
+}
+
+void cond5(int cond, int x, int y, int r1, int r2)
+{
+ if (cond)
+ {
+ x = r1 + 2;
+ y = r2 - 34;
+ }
+
+ sink2(x, y);
+}
+
+void cond6(int cond, int x, int y)
+{
+ if (cond)
+ {
+ x = -x;
+ y = ~y;
+ }
+
+ sink2(x, y);
+}
+
+/* { dg-final { scan-assembler-times "cinc\t" 5 } } */
+/* { dg-final { scan-assembler-times "csneg\t" 1 } } */
+/* { dg-final { scan-assembler-times "csinv\t" 1 } } */
+/* { dg-final { scan-assembler "csel\t" } } */
+
+/* { dg-final { scan-rtl-dump-times "if-conversion succeeded through noce_convert_multiple_sets" 6 "ce1" } } */