From: Kyrylo Tkachov <[email protected]>
noce_try_store_flag_constants and noce_try_cmove both compute the difference
between the two constant arms, reject it when it is not representable, and
truncate it to the mode. The overflow test is the same subtle expression in
both places.
Move it into noce_representable_diff_p. The callers keep their own failure
paths, which differ in whether a sequence has to be unwound. No functional
change.
gcc/ChangeLog:
* ifcvt.cc (noce_representable_diff_p): New function.
(noce_try_store_flag_constants): Use it.
(noce_try_cmove): Likewise.
Signed-off-by: Kyrylo Tkachov <[email protected]>
---
gcc/ifcvt.cc | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 026e0938e8f..79418c02491 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -1884,6 +1884,23 @@ noce_try_shifted_store_flag (struct noce_if_info
*if_info)
}
+/* Set *DIFF to ITRUE - IFALSE truncated to MODE and return true. Return
+ false, leaving *DIFF alone, when that difference is not representable and
+ so cannot be used to build a store-flag sequence. */
+
+static bool
+noce_representable_diff_p (HOST_WIDE_INT ifalse, HOST_WIDE_INT itrue,
+ machine_mode mode, HOST_WIDE_INT *diff)
+{
+ HOST_WIDE_INT d = (unsigned HOST_WIDE_INT) itrue - ifalse;
+
+ if ((d > 0) != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
+ return false;
+
+ *diff = trunc_int_for_mode (d, mode);
+ return true;
+}
+
/* Convert "if (test) x = a; else x = b", for A and B constant.
Also allow A = y + c1, B = y + c2, with a common y between A
and B. */
@@ -1930,14 +1947,9 @@ noce_try_store_flag_constants (struct noce_if_info
*if_info)
itrue = INTVAL (b);
bool subtract_flag_p = false;
- diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
- /* Make sure we can represent the difference between the two values. */
- if ((diff > 0)
- != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
+ if (!noce_representable_diff_p (ifalse, itrue, mode, &diff))
return false;
- diff = trunc_int_for_mode (diff, mode);
-
can_reverse = noce_reversed_cond_code (if_info) != UNKNOWN;
reversep = false;
if (diff == STORE_FLAG_VALUE || diff == -STORE_FLAG_VALUE)
@@ -2473,17 +2485,13 @@ noce_try_cmove (struct noce_if_info *if_info)
return false;
}
- HOST_WIDE_INT diff = (unsigned HOST_WIDE_INT) itrue - ifalse;
- /* Make sure we can represent the difference
- between the two values. */
- if ((diff > 0)
- != ((ifalse < 0) != (itrue < 0) ? ifalse < 0 : ifalse < itrue))
+ HOST_WIDE_INT diff;
+ if (!noce_representable_diff_p (ifalse, itrue, mode, &diff))
{
end_sequence ();
return false;
}
- diff = trunc_int_for_mode (diff, mode);
target = expand_simple_binop (mode, AND,
target, gen_int_mode (diff, mode),
if_info->x, 0, OPTAB_WIDEN);
--
2.50.1 (Apple Git-155)