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);

Reply via email to