https://gcc.gnu.org/g:6ced85903eb870fbc9710ed4675f5d668336722c
commit r17-4060-g6ced85903eb870fbc9710ed4675f5d668336722c Author: Kyrylo Tkachov <[email protected]> Date: Sun Sep 6 12:54:58 2026 +0200 ifcvt: factor the representable-difference check 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]> Diff: --- gcc/ifcvt.cc | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc index 49e5963ba108..ae1d432a01fd 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) @@ -2476,17 +2488,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);
