diff options
-rw-r--r-- | gcc/doc/md.texi | 10 | ||||
-rw-r--r-- | gcc/gimple-isel.cc | 26 | ||||
-rw-r--r-- | gcc/internal-fn.def | 4 | ||||
-rw-r--r-- | gcc/optabs.def | 2 |
4 files changed, 42 insertions, 0 deletions
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi index 4fd7da0..7f4335e 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 60719ea..e4ab42a 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 915d329..0b45f32 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 a69af51..45e117a 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") |