https://gcc.gnu.org/g:35b6620f18df4864fd01642512eb5c985d10fe06

commit r16-6329-g35b6620f18df4864fd01642512eb5c985d10fe06
Author: Vineet Gupta <[email protected]>
Date:   Mon Dec 22 08:52:07 2025 -0800

    ifcvt: cond zero arith: opencode helper noce_bbs_ok_for_cond_zero_arith 
[NFC]
    
    This makes the code more readable by eliminating a bunch of pointer
    intermediaries which obfuscate if_info items needed later in
    noce_try_cond_zero_arith (). And while here add some top level comments
    about what cond zero arith actually does.
    
    gcc/ChangeLog:
    
            * ifcvt.cc (noce_bbs_ok_for_cond_zero_arith): Move logic out.
            (noce_try_cond_zero_arith): Into here.
    
    Signed-off-by: Vineet Gupta <[email protected]>

Diff:
---
 gcc/ifcvt.cc | 165 +++++++++++++++++++++++++----------------------------------
 1 file changed, 70 insertions(+), 95 deletions(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index 97ef09a7a680..b1fb27e2331d 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -3145,30 +3145,35 @@ get_base_reg (rtx exp)
   return NULL_RTX;
 }
 
-/*  Check if IF-BB and THEN-BB satisfy the condition for conditional zero
-    based if conversion, returning TRUE if satisfied otherwise FALSE.
-
+/*  Try to covert if-then-else with conditional zero,
+    returning TURE on success or FALSE on failure.
     IF_INFO describes the if-conversion scenario under consideration.
-    COMMON_PTR points to the common REG of canonicalized IF_INFO->A and
-    IF_INFO->B.
-    CZERO_CODE_PTR points to the comparison code to use in czero RTX.
-    A_PTR points to the A expression of canonicalized IF_INFO->A.
-    TO_REPLACE points to the RTX to be replaced by czero RTX destnation.  */
 
-static bool
-noce_bbs_ok_for_cond_zero_arith (struct noce_if_info *if_info, rtx *common_ptr,
-                                rtx *bin_exp_ptr,
-                                enum rtx_code *czero_code_ptr, rtx *a_ptr,
-                                rtx **to_replace)
+    It verifies the branch structure on left and transforms it into branchless
+    sequence on the right, with a backend provided conditional zero or orig for
+    operand z. If true, tmp is z, 0 otherwise (y op 0 is same as y for most 
op).
+
+      if (cond)                |  tmp = cond ? z : 0
+       x = y op z      |    x = y op tmp
+      else             |
+       x = y           |
+
+    AND is special as it needs to be handled differently.
+
+      tmp = !cond ? y : 0
+       x = (y & z) | tmp
+  */
+
+static int
+noce_try_cond_zero_arith (struct noce_if_info *if_info)
 {
-  rtx common = NULL_RTX;
+  rtx target, a, b, a_op0, a_op1;
   rtx cond = if_info->cond;
-  rtx a = copy_rtx (if_info->a);
-  rtx b = copy_rtx (if_info->b);
-  rtx bin_op1 = NULL_RTX;
+  rtx_insn *seq;
+  rtx_code op;
+  machine_mode mode = GET_MODE (if_info->x);
   enum rtx_code czero_code = UNKNOWN;
   bool reverse = false;
-  rtx op0, op1, bin_exp;
 
   if (!noce_simple_bbs (if_info))
     return false;
@@ -3176,131 +3181,101 @@ noce_bbs_ok_for_cond_zero_arith (struct noce_if_info 
*if_info, rtx *common_ptr,
   /* COND must be EQ or NE comparision of a reg and 0.  */
   if (GET_CODE (cond) != NE && GET_CODE (cond) != EQ)
     return false;
+
   if (!REG_P (XEXP (cond, 0)) || !rtx_equal_p (XEXP (cond, 1), const0_rtx))
     return false;
 
+  a = copy_rtx (if_info->a);
+  b = copy_rtx (if_info->b);
+
   /* Canonicalize x = y : (y op z) to x = (y op z) : y.  */
   if (REG_P (a) && noce_cond_zero_binary_op_supported (b))
     {
       std::swap (a, b);
-      reverse = !reverse;
+      reverse = true;
     }
 
   /* Check if x = (y op z) : y is supported by czero based ifcvt.  */
-  if (!(noce_cond_zero_binary_op_supported (a) && REG_P (b)))
-    return false;
+  else if (!(noce_cond_zero_binary_op_supported (a) && REG_P (b)))
+    goto fail;
 
-  bin_exp = a;
+  op = GET_CODE (a);
 
   /* Canonicalize x = (z op y) : y to x = (y op z) : y */
-  op1 = get_base_reg (XEXP (bin_exp, 1));
-  if (op1 && rtx_equal_p (op1, b) && COMMUTATIVE_ARITH_P (bin_exp))
-    std::swap (XEXP (bin_exp, 0), XEXP (bin_exp, 1));
+  a_op1 = get_base_reg (XEXP (a, 1));
+  if (a_op1 && rtx_equal_p (a_op1, b) && COMMUTATIVE_ARITH_P (a))
+    {
+      std::swap (XEXP (a, 0), XEXP (a, 1));
+      a_op1 = get_base_reg (XEXP (a, 1));
+    }
+
+  if (a_op1 == NULL_RTX)
+    goto fail;
 
-  op0 = get_base_reg (XEXP (bin_exp, 0));
-  if (op0 && rtx_equal_p (op0, b))
+  /* Ensure the cond is of form: x = (y op z) : y */
+  a_op0 = get_base_reg (XEXP (a, 0));
+  if (a_op0 && rtx_equal_p (a_op0, b))
     {
-      common = b;
-      bin_op1 = XEXP (bin_exp, 1);
-      czero_code = (reverse ^ (GET_CODE (bin_exp) == AND))
+      czero_code = (reverse ^ (op == AND))
                     ? noce_reversed_cond_code (if_info)
                     : GET_CODE (cond);
-    }
-  else
-    return false;
-
-  if (czero_code == UNKNOWN)
-    return false;
 
-  if (REG_P (bin_op1))
-    *to_replace = &XEXP (bin_exp, 1);
+      if (czero_code == UNKNOWN)
+       goto fail;
+    }
   else
-    return false;
-
-  *common_ptr = common;
-  *bin_exp_ptr = bin_exp;
-  *czero_code_ptr = czero_code;
-  *a_ptr = a;
-
-  return true;
-}
-
-/*  Try to covert if-then-else with conditional zero,
-    returning TURE on success or FALSE on failure.
-    IF_INFO describes the if-conversion scenario under consideration.  */
-
-static int
-noce_try_cond_zero_arith (struct noce_if_info *if_info)
-{
-  rtx target, rtmp, a;
-  rtx_insn *seq;
-  machine_mode mode = GET_MODE (if_info->x);
-  rtx common = NULL_RTX;
-  enum rtx_code czero_code = UNKNOWN;
-  rtx bin_exp = NULL_RTX;
-  enum rtx_code bin_code = UNKNOWN;
-  rtx non_zero_op = NULL_RTX;
-  rtx *to_replace = NULL;
-
-  if (!noce_bbs_ok_for_cond_zero_arith (if_info, &common, &bin_exp, 
&czero_code,
-                                       &a, &to_replace))
-    return false;
+    goto fail;
 
   start_sequence ();
 
-  bin_code = GET_CODE (bin_exp);
-
-  if (bin_code == AND)
+  if (op == AND)
     {
-      rtmp = gen_reg_rtx (mode);
-      noce_emit_move_insn (rtmp, a);
+      rtx a_bin = gen_reg_rtx (mode);
+      noce_emit_move_insn (a_bin, a);
 
-      target = noce_emit_czero (if_info, czero_code, common, if_info->x);
-      if (!target)
-       {
-         end_sequence ();
-         return false;
-       }
+      target = noce_emit_czero (if_info, czero_code, b, if_info->x);
+      if (target)
+       target = expand_simple_binop (mode, IOR, a_bin, target, if_info->x, 0,
+                                     OPTAB_WIDEN);
 
-      target = expand_simple_binop (mode, IOR, rtmp, target, if_info->x, 0,
-                                   OPTAB_WIDEN);
       if (!target)
-       {
-         end_sequence ();
-         return false;
-       }
+       goto end_seq_n_fail;
 
       if (target != if_info->x)
        noce_emit_move_insn (if_info->x, target);
     }
   else
     {
-      non_zero_op = *to_replace;
       /* If x is used in both input and out like x = c ? x + z : x,
         use a new reg to avoid modifying x  */
-      if (common && rtx_equal_p (common, if_info->x))
+      if (rtx_equal_p (b, if_info->x))
        target = gen_reg_rtx (mode);
       else
        target = if_info->x;
 
-      target = noce_emit_czero (if_info, czero_code, non_zero_op, target);
-      if (!target || !to_replace)
-       {
-         end_sequence ();
-         return false;
-       }
+      target = noce_emit_czero (if_info, czero_code, a_op1, target);
+      if (!target)
+       goto end_seq_n_fail;
+
+      if (REG_P (XEXP (a, 1)))
+       XEXP (a, 1) = target;
 
-      *to_replace = target;
       noce_emit_move_insn (if_info->x, a);
     }
 
   seq = end_ifcvt_sequence (if_info);
   if (!seq || !targetm.noce_conversion_profitable_p (seq, if_info))
-    return false;
+    goto fail;
 
   emit_insn_before_setloc (seq, if_info->jump, INSN_LOCATION 
(if_info->insn_a));
   if_info->transform_name = "noce_try_cond_zero_arith";
   return true;
+
+end_seq_n_fail:
+  end_sequence ();
+
+fail:
+  return false;
 }
 
 /* Optimize away "if (x & C) x |= C" and similar bit manipulation

Reply via email to