is the scalar result. The mode of the scalar result is the same as one
element of @var{m}.
+@cindex @code{reduc_sbool_and_scal_@var{m}} instruction pattern
+@cindex @code{reduc_sbool_ior_scal_@var{m}} instruction pattern
+@cindex @code{reduc_sbool_xor_scal_@var{m}} instruction pattern
+@item @samp{reduc_sbool_and_scal_@var{m}}
+@itemx @samp{reduc_sbool_ior_scal_@var{m}}
+@itemx @samp{reduc_sbool_xor_scal_@var{m}}
+Compute the bitwise @code{AND}/@code{IOR}/@code{XOR} reduction of the elements
+of a vector boolean of mode @var{m}. Operand 1 is the vector input and
+operand 0 is the scalar result. The mode of the scalar result is @var{QImode}
+with its value either zero or one. If mode @var{m} is a scalar integer mode
+then operand 2 is the number of elements in the input vector to provide
+disambiguation for the case @var{m} is ambiguous.
+
@cindex @code{extract_last_@var{m}} instruction pattern
@item @code{extract_last_@var{m}}
Find the last set bit in mask operand 1 and extract the associated element
#define mask_len_fold_left_direct { 1, 1, false }
#define check_ptrs_direct { 0, 0, false }
#define crc_direct { 1, -1, true }
+#define reduc_sbool_direct { 0, 0, true }
const direct_internal_fn_info direct_internal_fn_array[IFN_LAST + 1] = {
#define DEF_INTERNAL_FN(CODE, FLAGS, FNSPEC) not_direct,
}
}
+/* Expand .REDUC_SBOOL_{AND,IOR,XOR}. */
+
+static void
+expand_reduc_sbool_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab)
+{
+ tree_pair types = direct_internal_fn_types (fn, stmt);
+ insn_code icode = direct_optab_handler (optab, TYPE_MODE (types.first));
+
+ /* Below copied from expand_fn_using_insn. */
+
+ gcc_assert (icode != CODE_FOR_nothing);
+
+ expand_operand *ops = XALLOCAVEC (expand_operand, 3);
+ rtx lhs_rtx = NULL_RTX;
+ tree lhs = gimple_call_lhs (stmt);
+ if (lhs)
+ lhs_rtx = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
+ create_call_lhs_operand (&ops[0], lhs_rtx,
+ insn_data[icode].operand[0].mode);
+
+ tree rhs = gimple_call_arg (stmt, 0);
+ tree rhs_type = TREE_TYPE (rhs);
+ rtx rhs_rtx = expand_normal (rhs);
+ gcc_assert (VECTOR_BOOLEAN_TYPE_P (rhs_type));
+ create_input_operand (&ops[1], rhs_rtx, TYPE_MODE (rhs_type));
+ if (SCALAR_INT_MODE_P (TYPE_MODE (rhs_type)))
+ {
+ rtx nunits = GEN_INT (TYPE_VECTOR_SUBPARTS (rhs_type).to_constant ());
+ gcc_assert (insn_operand_matches (icode, 2, nunits));
+ create_input_operand (&ops[2], nunits, SImode);
+ }
+ expand_insn (icode, SCALAR_INT_MODE_P (TYPE_MODE (rhs_type)) ? 3 : 2, ops);
+ if (lhs_rtx)
+ assign_call_lhs (lhs, lhs_rtx, &ops[0]);
+}
+
/* Expanders for optabs that can use expand_direct_optab_fn. */
#define expand_unary_optab_fn(FN, STMT, OPTAB) \
#define direct_check_ptrs_optab_supported_p direct_optab_supported_p
#define direct_vec_set_optab_supported_p direct_optab_supported_p
#define direct_vec_extract_optab_supported_p convert_optab_supported_p
+#define direct_reduc_sbool_optab_supported_p direct_optab_supported_p
/* Return the optab used by internal function FN. */
reduc_ior_scal, unary)
DEF_INTERNAL_OPTAB_FN (REDUC_XOR, ECF_CONST | ECF_NOTHROW,
reduc_xor_scal, unary)
+DEF_INTERNAL_OPTAB_FN (REDUC_SBOOL_AND, ECF_CONST | ECF_NOTHROW,
+ reduc_sbool_and_scal, reduc_sbool)
+DEF_INTERNAL_OPTAB_FN (REDUC_SBOOL_IOR, ECF_CONST | ECF_NOTHROW,
+ reduc_sbool_ior_scal, reduc_sbool)
+DEF_INTERNAL_OPTAB_FN (REDUC_SBOOL_XOR, ECF_CONST | ECF_NOTHROW,
+ reduc_sbool_xor_scal, reduc_sbool)
+
/* Extract the last active element from a vector. */
DEF_INTERNAL_OPTAB_FN (EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
OPTAB_D (reduc_and_scal_optab, "reduc_and_scal_$a")
OPTAB_D (reduc_ior_scal_optab, "reduc_ior_scal_$a")
OPTAB_D (reduc_xor_scal_optab, "reduc_xor_scal_$a")
+OPTAB_D (reduc_sbool_and_scal_optab, "reduc_sbool_and_scal_$a")
+OPTAB_D (reduc_sbool_ior_scal_optab, "reduc_sbool_ior_scal_$a")
+OPTAB_D (reduc_sbool_xor_scal_optab, "reduc_sbool_xor_scal_$a")
OPTAB_D (fold_left_plus_optab, "fold_left_plus_$a")
OPTAB_D (mask_fold_left_plus_optab, "mask_fold_left_plus_$a")
OPTAB_D (mask_len_fold_left_plus_optab, "mask_len_fold_left_plus_$a")