The following adds named patterns for reducing of vector masks with
AND, IOR and XOR to be used by the vectorizer.  A slight complication
will be targets using scalar integer modes as mask modes, as those
do not reliably know the actual number of mask bits.  A zero-extended
mask for IOR and a sign extended mask for AND works (and either for
XOR), but then I'm unsure who'd be supposed to ensure this.  I guess
the vectorizer?

        * doc/md.texi (reduc_mask_{and,ior,xor}_scal_<mode>): Document.
        * optabs.def (reduc_mask_and_scal_optab,
        reduc_mask_ior_scal_optab, reduc_mask_xor_scal_optab): New.
        * internal-fn.def (MASK_REDUC_AND, MASK_REDUC_IOR,
        MASK_REDUC_XOR): Likewise.
---
 gcc/doc/md.texi     | 11 +++++++++++
 gcc/internal-fn.def |  7 +++++++
 gcc/optabs.def      |  3 +++
 3 files changed, 21 insertions(+)

diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 44e1149bea8..77e44b24c7b 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -5736,6 +5736,17 @@ of a vector of mode @var{m}.  Operand 1 is the vector 
input and operand 0
 is the scalar result.  The mode of the scalar result is the same as one
 element of @var{m}.
 
+@cindex @code{reduc_mask_and_scal_@var{m}} instruction pattern
+@cindex @code{reduc_mask_ior_scal_@var{m}} instruction pattern
+@cindex @code{reduc_mask_xor_scal_@var{m}} instruction pattern
+@item @samp{reduc_mask_and_scal_@var{m}}
+@itemx @samp{reduc_mask_ior_scal_@var{m}}
+@itemx @samp{reduc_mask_xor_scal_@var{m}}
+Compute the bitwise @code{AND}/@code{IOR}/@code{XOR} reduction of the elements
+of a vector mask 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.
+
 @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
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 8434a805e28..97b518e56a8 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -330,6 +330,13 @@ DEF_INTERNAL_OPTAB_FN (REDUC_IOR, ECF_CONST | ECF_NOTHROW,
                       reduc_ior_scal, unary)
 DEF_INTERNAL_OPTAB_FN (REDUC_XOR, ECF_CONST | ECF_NOTHROW,
                       reduc_xor_scal, unary)
+DEF_INTERNAL_OPTAB_FN (MASK_REDUC_AND, ECF_CONST | ECF_NOTHROW,
+                      reduc_mask_and_scal, unary)
+DEF_INTERNAL_OPTAB_FN (MASK_REDUC_IOR, ECF_CONST | ECF_NOTHROW,
+                      reduc_mask_ior_scal, unary)
+DEF_INTERNAL_OPTAB_FN (MASK_REDUC_XOR, ECF_CONST | ECF_NOTHROW,
+                      reduc_mask_xor_scal, unary)
+
 
 /* Extract the last active element from a vector.  */
 DEF_INTERNAL_OPTAB_FN (EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 790e43f08f4..22284f775ac 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -401,6 +401,9 @@ OPTAB_D (reduc_umin_scal_optab, "reduc_umin_scal_$a")
 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_mask_and_scal_optab, "reduc_mask_and_scal_$a")
+OPTAB_D (reduc_mask_ior_scal_optab, "reduc_mask_ior_scal_$a")
+OPTAB_D (reduc_mask_xor_scal_optab, "reduc_mask_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")
-- 
2.51.0

Reply via email to