aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/doc/md.texi10
-rw-r--r--gcc/gimple-isel.cc26
-rw-r--r--gcc/internal-fn.def4
-rw-r--r--gcc/optabs.def2
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")