https://gcc.gnu.org/g:2a84a753afcf376a5fc0339c5ce228c130000cd7

commit r16-6332-g2a84a753afcf376a5fc0339c5ce228c130000cd7
Author: Vineet Gupta <[email protected]>
Date:   Mon Dec 22 08:54:06 2025 -0800

    ifcvt: cond zero arith: elide short forward branch for signed GE 0 
comparison [PR122769]
    
                 Before            After
          ---------------------+----------------------
            bge a0,zero,.L2    | slti      a0,a0,0
                               | czero.eqz a0,a0,a0
            xor a1,a1,a3       | xor       a0,a0,a0
          .L2                  |
            mv  a0,a1          |
            ret                | ret
    
    This is what all the prev NFC patches have been preparing to get to.
    
    Currently the cond arith code only handles EQ/NE zero conditions missing
    ifcvt optimization for cases such as GE zero, as show in example above.
    This is due to the limitation of noce_emit_czero () so switch to
    noce_emit_cmove () which can handle conditions other than EQ/NE and
    if needed generate additional supporting insns such as SLT.
    
    This also allows us to remove the constraint at the entry to limit to EQ/NE
    conditions, improving ifcvt outcomes in general.
    
            PR target/122769
    
    gcc/ChangeLog:
    
            * ifcvt.cc (noce_try_cond_zero_arith): Use noce_emit_cmove.
            Delete noce_emit_czero () no longer used.
    
    gcc/testsuite/ChangeLog:
    
            * gcc.target/riscv/pr122769.c: New test.
    
    Co-authored-by: Philipp Tomsich <[email protected]>
    Signed-off-by: Vineet Gupta <[email protected]>

Diff:
---
 gcc/ifcvt.cc                              | 40 ++++---------------------------
 gcc/testsuite/gcc.target/riscv/pr122769.c | 17 +++++++++++++
 2 files changed, 21 insertions(+), 36 deletions(-)

diff --git a/gcc/ifcvt.cc b/gcc/ifcvt.cc
index ef59a93e987e..280f398cee6c 100644
--- a/gcc/ifcvt.cc
+++ b/gcc/ifcvt.cc
@@ -2037,35 +2037,6 @@ noce_emit_cmove (struct noce_if_info *if_info, rtx x, 
enum rtx_code code,
     return NULL_RTX;
 }
 
-/*  Emit a conditional zero, returning TARGET or NULL_RTX upon failure.
-    IF_INFO describes the if-conversion scenario under consideration.
-    CZERO_CODE selects the condition (EQ/NE).
-    NON_ZERO_OP is the nonzero operand of the conditional move
-    TARGET is the desired output register.  */
-
-static rtx
-noce_emit_czero (struct noce_if_info *if_info, enum rtx_code czero_code,
-                rtx non_zero_op, rtx target)
-{
-  machine_mode mode = GET_MODE (target);
-  rtx cond_op0 = XEXP (if_info->cond, 0);
-  rtx czero_cond
-    = gen_rtx_fmt_ee (czero_code, GET_MODE (cond_op0), cond_op0, const0_rtx);
-  rtx if_then_else
-    = gen_rtx_IF_THEN_ELSE (mode, czero_cond, const0_rtx, non_zero_op);
-  rtx set = gen_rtx_SET (target, if_then_else);
-
-  rtx_insn *insn = make_insn_raw (set);
-
-  if (recog_memoized (insn) >= 0)
-    {
-      add_insn (insn);
-      return target;
-    }
-
-  return NULL_RTX;
-}
-
 /* Try only simple constants and registers here.  More complex cases
    are handled in noce_try_cmove_arith after noce_try_store_flag_arith
    has had a go at it.  */
@@ -3177,10 +3148,6 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info)
   if (!noce_simple_bbs (if_info))
     return false;
 
-  /* 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;
 
@@ -3222,9 +3189,10 @@ noce_try_cond_zero_arith (struct noce_if_info *if_info)
   target = gen_reg_rtx (mode);
 
   /* AND requires !cond, instead we swap ops around.  */
-  target = noce_emit_czero (if_info, GET_CODE (if_info->cond),
-                           op != AND ? a_op1 : a_op0, target);
-
+  target = noce_emit_cmove (if_info, target, GET_CODE (if_info->cond),
+                           XEXP (if_info->cond, 0), XEXP (if_info->cond, 1),
+                           op != AND ? a_op1 : const0_rtx,
+                           op != AND ? const0_rtx : a_op0);
   if (!target)
     goto end_seq_n_fail;
 
diff --git a/gcc/testsuite/gcc.target/riscv/pr122769.c 
b/gcc/testsuite/gcc.target/riscv/pr122769.c
new file mode 100644
index 000000000000..0f7e19ca5045
--- /dev/null
+++ b/gcc/testsuite/gcc.target/riscv/pr122769.c
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -march=rv64gc_zbs_zicond -mabi=lp64d" { target rv64} } */
+
+/* Elide a short forward branch and generate a czero instead.  */
+
+#include <stdint.h>
+
+uint64_t updateLSB63 (uint64_t val, uint64_t val2, int bits, int n)
+{
+  if (val & (1ULL << 63))
+    val2 ^= n;
+  return val2;
+}
+
+/* { dg-final { scan-assembler-times {\tczero} 1 } } */
+/* { dg-final { scan-assembler-not {\tbge} } } */
+

Reply via email to