https://gcc.gnu.org/g:f379596e0ba99df249d6e8b3f2e66edfcea916fe

commit r15-1890-gf379596e0ba99df249d6e8b3f2e66edfcea916fe
Author: Kewen Lin <li...@linux.ibm.com>
Date:   Mon Jul 8 00:14:59 2024 -0500

    isel: Fold more in gimple_expand_vec_cond_expr with andc and iorc [PR115659]
    
    As PR115659 shows, assuming c = x CMP y, there are some
    folding chances for patterns r = c ? 0/z : z/-1:
      - for r = c ? 0 : z, it can be folded into r = ~c & z.
      - for r = c ? z : -1, it can be folded into r = ~c | z.
    
    But BIT_AND/BIT_IOR applied on one BIT_NOT operand is a
    compound operation, it's arguable to consider it beats
    vector selection.  So this patch is to introduce new
    optabs andc, iorc and its corresponding internal functions
    BIT_{ANDC,IORC}, and if targets defines such optabs for
    vector modes, it means targets support these hardware
    insns and should be not worse than vector selection.
    
            PR tree-optimization/115659
    
    gcc/ChangeLog:
    
            * doc/md.texi: Document andcm3 and iorcm3.
            * gimple-isel.cc (gimple_expand_vec_cond_expr): Add more foldings 
for
            patterns x CMP y ? 0 : z and x CMP y ? z : -1.
            * internal-fn.def (BIT_ANDC): New internal function.
            (BIT_IORC): Likewise.
            * optabs.def (andc, iorc): New optab.

Diff:
---
 gcc/doc/md.texi     | 10 ++++++++++
 gcc/gimple-isel.cc  | 26 ++++++++++++++++++++++++++
 gcc/internal-fn.def |  4 ++++
 gcc/optabs.def      |  2 ++
 4 files changed, 42 insertions(+)

diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 4fd7da095feb..7f4335e0aac1 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -5543,6 +5543,16 @@ means of constraints requiring operands 1 and 0 to be 
the same location.
 @itemx @samp{and@var{m}3}, @samp{ior@var{m}3}, @samp{xor@var{m}3}
 Similar, for other arithmetic operations.
 
+@cindex @code{andc@var{m}3} instruction pattern
+@item @samp{andc@var{m}3}
+Like @code{and@var{m}3}, but it uses bitwise-complement of operand 2
+rather than operand 2 itself.
+
+@cindex @code{iorc@var{m}3} instruction pattern
+@item @samp{iorc@var{m}3}
+Like @code{ior@var{m}3}, but it uses bitwise-complement of operand 2
+rather than operand 2 itself.
+
 @cindex @code{addv@var{m}4} instruction pattern
 @item @samp{addv@var{m}4}
 Like @code{add@var{m}3} but takes a @code{code_label} as operand 3 and
diff --git a/gcc/gimple-isel.cc b/gcc/gimple-isel.cc
index 60719eafc651..e4ab42ad05ba 100644
--- a/gcc/gimple-isel.cc
+++ b/gcc/gimple-isel.cc
@@ -284,6 +284,32 @@ gimple_expand_vec_cond_expr (struct function *fun, 
gimple_stmt_iterator *gsi,
                  /* r = c ? z : c */
                  op2 = new_op2;
                }
+             bool op1_zerop = integer_zerop (op1);
+             bool op2_minus_onep = integer_minus_onep (op2);
+             /* Try to fold r = c ? 0 : z to r = .BIT_ANDC (z, c).  */
+             if (op1_zerop
+                 && (direct_internal_fn_supported_p (IFN_BIT_ANDC, vtype,
+                                                     OPTIMIZE_FOR_BOTH)))
+               {
+                 tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
+                 tree new_op = make_ssa_name (vtype);
+                 gassign *new_stmt = gimple_build_assign (new_op, conv_op);
+                 gsi_insert_seq_before (gsi, new_stmt, GSI_SAME_STMT);
+                 return gimple_build_call_internal (IFN_BIT_ANDC, 2, op2,
+                                                    new_op);
+               }
+             /* Try to fold r = c ? z : -1 to r = .BIT_IORC (z, c).  */
+             else if (op2_minus_onep
+                      && (direct_internal_fn_supported_p (IFN_BIT_IORC, vtype,
+                                                          OPTIMIZE_FOR_BOTH)))
+               {
+                 tree conv_op = build1 (VIEW_CONVERT_EXPR, vtype, op0);
+                 tree new_op = make_ssa_name (vtype);
+                 gassign *new_stmt = gimple_build_assign (new_op, conv_op);
+                 gsi_insert_seq_before (gsi, new_stmt, GSI_SAME_STMT);
+                 return gimple_build_call_internal (IFN_BIT_IORC, 2, op1,
+                                                    new_op);
+               }
            }
 
          /* When the compare has EH we do not want to forward it when
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 915d329c05a0..0b45f322f0db 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -595,6 +595,10 @@ DEF_INTERNAL_FN (DIVMODBITINT, ECF_LEAF, ". O . O . R . R 
. ")
 DEF_INTERNAL_FN (FLOATTOBITINT, ECF_LEAF | ECF_NOTHROW, ". O . . ")
 DEF_INTERNAL_FN (BITINTTOFLOAT, ECF_PURE | ECF_LEAF, ". R . ")
 
+/* Bitwise functions.  */
+DEF_INTERNAL_OPTAB_FN (BIT_ANDC, ECF_CONST, andc, binary)
+DEF_INTERNAL_OPTAB_FN (BIT_IORC, ECF_CONST, iorc, binary)
+
 #undef DEF_INTERNAL_WIDENING_OPTAB_FN
 #undef DEF_INTERNAL_SIGNED_COND_FN
 #undef DEF_INTERNAL_COND_FN
diff --git a/gcc/optabs.def b/gcc/optabs.def
index a69af51d6012..45e117a7f508 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -545,3 +545,5 @@ OPTAB_D (vec_shl_insert_optab, "vec_shl_insert_$a")
 OPTAB_D (len_load_optab, "len_load_$a")
 OPTAB_D (len_store_optab, "len_store_$a")
 OPTAB_D (select_vl_optab, "select_vl$a")
+OPTAB_D (andc_optab, "andc$a3")
+OPTAB_D (iorc_optab, "iorc$a3")

Reply via email to