This patch adds the IFN and optabs needed by the later no-epilogue early-break
patches.  The vectorizer can already build predicates that describe the active
lanes of a vector iteration, but it did not have a common IFN/optab interface
for asking a target to count those lanes, find the first active lane, build
inclusive or exclusive prefixes, or extract the selected scalar value.

The new IFNs are grouped as follows:

  Unconditional forms:
    COUNT_ACTIVE, INDEX_FIRST_ACTIVE, TAKE_INCL_ACTIVE,
    TAKE_EXCL_ACTIVE and EXTRACT_FIRST operate on the full predicate.  On
    Adv.SIMD these enable ADDHN/UMOV compression followed by RBIT/CLZ and TBL
    extraction.  On SVE they enable CNTP, BRK*, FIRSTP/PFIRST and LASTB-style
    extraction.

  Conditional forms:
    COND_COUNT_ACTIVE, COND_INDEX_FIRST_ACTIVE, COND_TAKE_INCL_ACTIVE and
    COND_TAKE_EXCL_ACTIVE apply the same operations under an existing mask.
    These are used when an early exit is governed by a loop mask or a previous
    vector predicate.

  Length-limited forms:
    COND_LEN_COUNT_ACTIVE, COND_LEN_INDEX_FIRST_ACTIVE,
    COND_LEN_TAKE_INCL_ACTIVE and COND_LEN_TAKE_EXCL_ACTIVE add the length
    and bias operands used by partial-vector loops.  These let targets account
    for both the governing predicate and the active vector length in one
    operation.

For example, consider:

  unsigned char a[1008], b[1008];

  unsigned char f1 (void)
  {
    unsigned char res = 0;
    for (unsigned int i = 0; i < 1008; ++i)
      {
        unsigned char x = a[i] & b[i];
        res = x;
        if (x > 5)
          break;
      }
    return res;
  }

Used to generate on GCC trunk using -O3 -march=armv8-a

  cmhi    v30.16b, v31.16b, v29.16b
  umaxp   v30.4s, v30.4s, v30.4s
  fmov    x0, d30
  cbz     x0, .L2
  ldrb    w0, [x2, w1, uxtw]
  cmp     w0, 5
  bhi     .L3
  ... repeated scalar lane checks ...

which branches to scalar to find the element. With this branch we get
with Adv.SIMD:

  cmhi    v31.16b, v30.16b, v29.16b
  addhn   v31.8b, v31.8h, v31.8h
  umov    x0, v31.d[0]
  cbz     x0, .L8
  rbit    x0, x0
  clz     x0, x0
  ... construction of tbl index from x0 
  tbl     v30.16b, {v30.16b}, v31.16b
  fmov    w0, s30

Or with SVE2:

  cmphi   p6.b, p7/z, z31.b, #5
  b.none  .L8
  splice  z31.b, p6, z31.b, z31.b
  fmov    w0, s31
  ret

Bootstrapped Regtested on aarch64-none-linux-gnu,
arm-none-linux-gnueabihf, x86_64-pc-linux-gnu
-m32, -m64 and no issues.

-O3, profiled, profiled -O3 and -O3 -LTO bootstrap tested and no issues.

 Also SPECCPU 2017 and SPECCPU 2026 tested.

OK for master?

Thanks,
Tamar

gcc/ChangeLog:

        * doc/ifn.texi: Document the IFNs.
        * doc/md.texi: Document the optabs..
        * internal-fn.cc (cond_mask_unary_direct): Add conditional
        active-predicate direct optab descriptors.
        (cond_len_mask_unary_direct): Add length-limited descriptors.
        (expand_cond_mask_unary_optab_fn): Expand conditional unary IFNs.
        (expand_cond_len_mask_unary_optab_fn): Expand length forms.
        (direct_cond_mask_unary_optab_supported_p): Query optab support.
        (direct_cond_len_mask_unary_optab_supported_p): Likewise.
        (FOR_EACH_COND_FN_PAIR): Add active-predicate IFN mappings.
        (get_conditional_internal_fn): Handle active-predicate IFNs.
        (get_len_internal_fn): Likewise.
        (get_unconditional_internal_fn): Likewise.
        (internal_fn_len_index): Return length operand positions.
        (internal_fn_else_index): Return else operand positions.
        * internal-fn.def (COUNT_ACTIVE): New internal function.
        (COND_COUNT_ACTIVE): Likewise.
        (COND_LEN_COUNT_ACTIVE): Likewise.
        (INDEX_FIRST_ACTIVE): Likewise.
        (COND_INDEX_FIRST_ACTIVE): Likewise.
        (COND_LEN_INDEX_FIRST_ACTIVE): Likewise.
        (TAKE_INCL_ACTIVE): Likewise.
        (COND_TAKE_INCL_ACTIVE): Likewise.
        (COND_LEN_TAKE_INCL_ACTIVE): Likewise.
        (TAKE_EXCL_ACTIVE): Likewise.
        (COND_TAKE_EXCL_ACTIVE): Likewise.
        (COND_LEN_TAKE_EXCL_ACTIVE): Likewise.
        (EXTRACT_FIRST): Likewise.
        * optabs.def (extract_first_optab, count_active_optab,
        cond_count_active_optab, cond_len_count_active_optab,
        index_first_active_optab, cond_index_first_active_optab,
        cond_len_index_first_active_optab, take_incl_active_optab,
        take_excl_active_optab, cond_take_incl_active_optab,
        cond_take_excl_active_optab, cond_len_take_incl_active_optab,
        cond_len_take_excl_active_optab): New.

---
diff --git a/gcc/doc/ifn.texi b/gcc/doc/ifn.texi
index 
7cfc80eecf262db33b62e02d3d2d2552c69e5e82..9f130998ec7351f9820576cc309a6eec8798372f
 100644
--- a/gcc/doc/ifn.texi
+++ b/gcc/doc/ifn.texi
@@ -457,6 +457,107 @@ The @code{IFN_COND_NOT} internal function directly maps 
to the
 The @code{IFN_COND_LEN_NOT} internal function directly maps to the
 @code{cond_len_one_cmpl} instruction pattern.
 
+@cindex @code{IFN_COUNT_ACTIVE} internal function
+@item @samp{IFN_COUNT_ACTIVE}
+The @code{IFN_COUNT_ACTIVE} internal function directly maps to the
+@code{count_active} instruction pattern.  It returns the number of active
+elements in its argument.
+
+@cindex @code{IFN_COND_COUNT_ACTIVE} internal function
+@item @samp{IFN_COND_COUNT_ACTIVE}
+The @code{IFN_COND_COUNT_ACTIVE} internal function directly maps to the
+@code{cond_count_active} instruction pattern.  It returns the number of
+active elements in its second argument under the mask in its first
+argument.
+
+@cindex @code{IFN_COND_LEN_COUNT_ACTIVE} internal function
+@item @samp{IFN_COND_LEN_COUNT_ACTIVE}
+The @code{IFN_COND_LEN_COUNT_ACTIVE} internal function directly maps to the
+@code{cond_len_count_active} instruction pattern.  It is like
+@code{IFN_COND_COUNT_ACTIVE}, but also ignores elements whose index is
+greater than or equal to the sum of the length and bias arguments.
+
+@cindex @code{IFN_INDEX_FIRST_ACTIVE} internal function
+@item @samp{IFN_INDEX_FIRST_ACTIVE}
+The @code{IFN_INDEX_FIRST_ACTIVE} internal function directly maps to the
+@code{index_first_active} instruction pattern.  It returns the index of the
+first active element in its argument.  The result is undefined if the
+predicate has no active elements.
+
+@cindex @code{IFN_COND_INDEX_FIRST_ACTIVE} internal function
+@item @samp{IFN_COND_INDEX_FIRST_ACTIVE}
+The @code{IFN_COND_INDEX_FIRST_ACTIVE} internal function directly maps to the
+@code{cond_index_first_active} instruction pattern.  It returns the index of
+the first active element in its second argument under the mask in its first
+argument.  The result is undefined if the selected predicate has no active
+elements.
+
+@cindex @code{IFN_COND_LEN_INDEX_FIRST_ACTIVE} internal function
+@item @samp{IFN_COND_LEN_INDEX_FIRST_ACTIVE}
+The @code{IFN_COND_LEN_INDEX_FIRST_ACTIVE} internal function directly maps to
+the @code{cond_len_index_first_active} instruction pattern.  It is like
+@code{IFN_COND_INDEX_FIRST_ACTIVE}, but also ignores elements whose index is
+greater than or equal to the sum of the length and bias arguments.
+
+@cindex @code{IFN_TAKE_INCL_ACTIVE} internal function
+@item @samp{IFN_TAKE_INCL_ACTIVE}
+The @code{IFN_TAKE_INCL_ACTIVE} internal function directly maps to the
+@code{take_incl_active} instruction pattern.  It returns a predicate
+containing the active elements up to and including the first active element
+of its argument.
+
+@cindex @code{IFN_COND_TAKE_INCL_ACTIVE} internal function
+@item @samp{IFN_COND_TAKE_INCL_ACTIVE}
+The @code{IFN_COND_TAKE_INCL_ACTIVE} internal function directly maps to the
+@code{cond_take_incl_active} instruction pattern.  It returns a predicate
+containing the active elements up to and including the first active element
+of the predicate formed by selecting its second argument under the mask in
+its first argument, and its third argument elsewhere.
+
+@cindex @code{IFN_COND_LEN_TAKE_INCL_ACTIVE} internal function
+@item @samp{IFN_COND_LEN_TAKE_INCL_ACTIVE}
+The @code{IFN_COND_LEN_TAKE_INCL_ACTIVE} internal function directly maps to
+the @code{cond_len_take_incl_active} instruction pattern.  It is like
+@code{IFN_COND_TAKE_INCL_ACTIVE}, but also ignores elements whose index is
+greater than or equal to the sum of the length and bias arguments.
+
+@cindex @code{IFN_TAKE_EXCL_ACTIVE} internal function
+@item @samp{IFN_TAKE_EXCL_ACTIVE}
+The @code{IFN_TAKE_EXCL_ACTIVE} internal function directly maps to the
+@code{take_excl_active} instruction pattern.  It returns a predicate
+containing the active elements before, but excluding, the first active
+element of its argument.
+
+@cindex @code{IFN_COND_TAKE_EXCL_ACTIVE} internal function
+@item @samp{IFN_COND_TAKE_EXCL_ACTIVE}
+The @code{IFN_COND_TAKE_EXCL_ACTIVE} internal function directly maps to the
+@code{cond_take_excl_active} instruction pattern.  It returns a predicate
+containing the active elements before, but excluding, the first active element
+of the predicate formed by selecting its second argument under the mask in
+its first argument, and its third argument elsewhere.
+
+@cindex @code{IFN_COND_LEN_TAKE_EXCL_ACTIVE} internal function
+@item @samp{IFN_COND_LEN_TAKE_EXCL_ACTIVE}
+The @code{IFN_COND_LEN_TAKE_EXCL_ACTIVE} internal function directly maps to
+the @code{cond_len_take_excl_active} instruction pattern.  It is like
+@code{IFN_COND_TAKE_EXCL_ACTIVE}, but also ignores elements whose index is
+greater than or equal to the sum of the length and bias arguments.
+
+@cindex @code{IFN_COND_VEC_CMP} internal function
+@item @samp{IFN_COND_VEC_CMP}
+The @code{IFN_COND_VEC_CMP} internal function directly maps to the
+@code{cond_vec_cmp} instruction pattern.  It performs the comparison
+identified by its first argument on its third and fourth arguments, then
+returns the comparison result after applying the predicate mask in its
+second argument.
+
+@cindex @code{IFN_COND_LEN_VEC_CMP} internal function
+@item @samp{IFN_COND_LEN_VEC_CMP}
+The @code{IFN_COND_LEN_VEC_CMP} internal function directly maps to the
+@code{cond_len_vec_cmp} instruction pattern.  It is like
+@code{IFN_COND_VEC_CMP}, but also ignores elements whose index is greater
+than or equal to the sum of the length and bias arguments.
+
 @cindex @code{IFN_RSQRT} internal function
 @item @samp{IFN_RSQRT}
 The @code{IFN_RSQRT} internal function directly maps to the @code{rsqrt}
@@ -512,6 +613,11 @@ The @code{IFN_REDUC_SBOOL_XOR} internal function directly 
maps to the
 The @code{IFN_EXTRACT_LAST} internal function directly maps to the
 @code{extract_last} instruction pattern.
 
+@cindex @code{IFN_EXTRACT_FIRST} internal function
+@item @samp{IFN_EXTRACT_FIRST}
+The @code{IFN_EXTRACT_FIRST} internal function directly maps to the
+@code{extract_first} instruction pattern.
+
 @cindex @code{IFN_FOLD_EXTRACT_LAST} internal function
 @item @samp{IFN_FOLD_EXTRACT_LAST}
 The @code{IFN_FOLD_EXTRACT_LAST} internal function directly maps to the
@@ -1553,4 +1659,3 @@ definition is still being built by the current pass.  The 
pass that creates
 it must replace it before finishing; the verifier rejects any remaining calls.
 
 @end table
-
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index 
f86fa8038e8a0a4498325ea12e041b9622b4e7d5..629fb18b362770a74347441f178d865983dd4e4a
 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -7905,6 +7905,34 @@ has vector mode @var{m} while operand 0 has the mode 
appropriate for one
 element of @var{m}.  Operand 1 has the usual mask mode for vectors of mode
 @var{m}; see @code{TARGET_VECTORIZE_GET_MASK_MODE}.
 
+@mdindex extract_first_@var{m}
+@item @code{extract_first_@var{m}}
+Find the first set bit in mask operand 1 and extract the associated element
+of vector operand 2.  Store the result in scalar operand 0.  Operand 2
+has vector mode @var{m} while operand 0 has the mode appropriate for one
+element of @var{m}.  Operand 1 has the usual mask mode for vectors of mode
+@var{m}; see @code{TARGET_VECTORIZE_GET_MASK_MODE}.
+
+@mdindex count_active_@var{m}
+@item @code{count_active_@var{m}}
+Count the set bits in mask operand 1 and store the result in scalar
+operand 0.
+
+@mdindex index_first_active_@var{m}
+@item @code{index_first_active_@var{m}}
+Find the first set bit in mask operand 1 and store the zero-based element
+index in scalar operand 0.  The result is undefined if no bits are set.
+
+@mdindex take_incl_active_@var{m}
+@item @code{take_incl_active_@var{m}}
+Set mask operand 0 to the active elements of mask operand 1 up to and
+including the first active element of operand 1.
+
+@mdindex take_excl_active_@var{m}
+@item @code{take_excl_active_@var{m}}
+Set mask operand 0 to the active elements of mask operand 1 before, but
+excluding, the first active element of operand 1.
+
 @mdindex fold_extract_last_@var{m}
 @item @code{fold_extract_last_@var{m}}
 If any bits of mask operand 2 are set, find the last set bit, extract
@@ -8675,6 +8703,76 @@ for (i = 0; i < GET_MODE_NUNITS (@var{m}); i++)
             : op5[i]);
 @end smallexample
 
+@mdindex cond_count_active_@var{mode}
+@item @samp{cond_count_active_@var{mode}}
+Set operand 0 to the number of active elements in operand 2 under the mask
+in operand 1.  Operand 0 has a scalar integer mode.  Operands 1 and 2 have
+mode @var{mode}.
+
+@mdindex cond_len_count_active_@var{mode}
+@item @samp{cond_len_count_active_@var{mode}}
+Like @samp{cond_count_active_@var{mode}}, but additionally ignore elements
+whose index is greater than or equal to the sum of operands 3 and 4.
+Operand 3 has whichever integer mode the target prefers, and operand 4 is
+a bias.
+
+@mdindex cond_index_first_active_@var{mode}
+@item @samp{cond_index_first_active_@var{mode}}
+Set operand 0 to the index of the first active element in operand 2 under
+the mask in operand 1.  Operand 0 has a scalar integer mode.  Operands 1
+and 2 have mode @var{mode}.  The result is undefined if the selected
+predicate has no
+active elements.
+
+@mdindex cond_len_index_first_active_@var{mode}
+@item @samp{cond_len_index_first_active_@var{mode}}
+Like @samp{cond_index_first_active_@var{mode}}, but additionally ignore
+elements whose index is greater than or equal to the sum of operands 3
+and 4.  Operand 3 has whichever integer mode the target prefers, and
+operand 4 is a bias.
+
+@mdindex cond_take_incl_active_@var{mode}
+@item @samp{cond_take_incl_active_@var{mode}}
+Set operand 0 to a predicate that contains the active elements up to and
+including the first active element in the predicate formed by selecting
+operand 2 under operand 1, and operand 3 elsewhere.  Operands 0, 1, 2
+and 3 have mode @var{mode}.
+
+@mdindex cond_len_take_incl_active_@var{mode}
+@item @samp{cond_len_take_incl_active_@var{mode}}
+Like @samp{cond_take_incl_active_@var{mode}}, but additionally ignore
+elements whose index is greater than or equal to the sum of operands 4
+and 5.  Operand 4 has whichever integer mode the target prefers, and
+operand 5 is a bias.
+
+@mdindex cond_take_excl_active_@var{mode}
+@item @samp{cond_take_excl_active_@var{mode}}
+Set operand 0 to a predicate that contains the active elements before,
+but excluding, the first active element in the predicate formed by selecting
+operand 2 under operand 1, and operand 3 elsewhere.  Operands 0, 1, 2
+and 3 have mode @var{mode}.
+
+@mdindex cond_len_take_excl_active_@var{mode}
+@item @samp{cond_len_take_excl_active_@var{mode}}
+Like @samp{cond_take_excl_active_@var{mode}}, but additionally ignore
+elements whose index is greater than or equal to the sum of operands 4
+and 5.  Operand 4 has whichever integer mode the target prefers, and
+operand 5 is a bias.
+
+@mdindex cond_vec_cmp@var{m}@var{n}
+@item @samp{cond_vec_cmp@var{m}@var{n}}
+Set operand 0 to the result of applying comparison operand 1 to operands
+3 and 4, after applying predicate mask operand 2.  Operand 0 has mode
+@var{n}; operands 3 and 4 have mode @var{m}.  Operand 2 has the mode
+returned by @code{TARGET_VECTORIZE_GET_MASK_MODE} for @var{m}.
+
+@mdindex cond_len_vec_cmp@var{m}@var{n}
+@item @samp{cond_len_vec_cmp@var{m}@var{n}}
+Like @samp{cond_vec_cmp@var{m}@var{n}}, but additionally ignore elements
+whose index is greater than or equal to the sum of operands 5 and 6.
+Operand 5 has whichever integer mode the target prefers, and operand 6 is
+a bias.
+
 @mdindex cbranch@var{mode}4
 @item @samp{cbranch@var{mode}4}
 Conditional branch instruction combined with a compare instruction.
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index 
0138c6f7ef0117f43afa5c81406a6564a425d304..0030db0c29bf62c4cb4aebb250be9fb5e598dbfa
 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -186,6 +186,8 @@ init_internal_fns ()
 #define cond_len_unary_direct { 1, 1, true }
 #define cond_len_binary_direct { 1, 1, true }
 #define cond_len_ternary_direct { 1, 1, true }
+#define cond_mask_unary_direct { 0, 0, true }
+#define cond_len_mask_unary_direct { 0, 0, true }
 #define while_direct { 0, 2, false }
 #define fold_extract_direct { 2, 2, false }
 #define fold_len_extract_direct { 2, 2, false }
@@ -4294,6 +4296,12 @@ expand_reduc_sbool_optab_fn (internal_fn fn, gcall 
*stmt, direct_optab optab)
 #define expand_cond_len_ternary_optab_fn(FN, STMT, OPTAB) \
   expand_direct_optab_fn (FN, STMT, OPTAB, 7)
 
+#define expand_cond_mask_unary_optab_fn(FN, STMT, OPTAB) \
+  expand_direct_optab_fn (FN, STMT, OPTAB, 2)
+
+#define expand_cond_len_mask_unary_optab_fn(FN, STMT, OPTAB) \
+  expand_direct_optab_fn (FN, STMT, OPTAB, 4)
+
 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
 
@@ -4404,6 +4412,8 @@ multi_vector_optab_supported_p (convert_optab optab, 
tree_pair types,
 #define direct_cond_len_unary_optab_supported_p direct_optab_supported_p
 #define direct_cond_len_binary_optab_supported_p direct_optab_supported_p
 #define direct_cond_len_ternary_optab_supported_p direct_optab_supported_p
+#define direct_cond_mask_unary_optab_supported_p direct_optab_supported_p
+#define direct_cond_len_mask_unary_optab_supported_p direct_optab_supported_p
 #define direct_crc_optab_supported_p convert_optab_supported_p
 #define direct_mask_load_optab_supported_p convert_optab_supported_p
 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
@@ -4892,6 +4902,8 @@ get_conditional_len_internal_fn (tree_code code)
 /* Invoke T(IFN) for each internal function IFN that also has an
    IFN_COND_* form.  */
 #define FOR_EACH_COND_FN_PAIR(T) \
+  T (TAKE_INCL_ACTIVE) \
+  T (TAKE_EXCL_ACTIVE) \
   T (FMAX) \
   T (FMIN) \
   T (FMA) \
@@ -4923,6 +4935,10 @@ get_conditional_internal_fn (internal_fn fn)
 {
   switch (fn)
     {
+    case IFN_COUNT_ACTIVE:
+      return IFN_COND_COUNT_ACTIVE;
+    case IFN_INDEX_FIRST_ACTIVE:
+      return IFN_COND_INDEX_FIRST_ACTIVE;
 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
       FOR_EACH_COND_FN_PAIR(CASE)
 #undef CASE
@@ -4958,6 +4974,14 @@ get_len_internal_fn (internal_fn fn)
       return IFN_MASK_LEN_LOAD_LANES;
     case IFN_MASK_GATHER_LOAD:
       return IFN_MASK_LEN_GATHER_LOAD;
+    case IFN_COND_COUNT_ACTIVE:
+      return IFN_COND_LEN_COUNT_ACTIVE;
+    case IFN_COND_INDEX_FIRST_ACTIVE:
+      return IFN_COND_LEN_INDEX_FIRST_ACTIVE;
+    case IFN_COND_TAKE_INCL_ACTIVE:
+      return IFN_COND_LEN_TAKE_INCL_ACTIVE;
+    case IFN_COND_TAKE_EXCL_ACTIVE:
+      return IFN_COND_LEN_TAKE_EXCL_ACTIVE;
     default:
       return IFN_LAST;
     }
@@ -4971,6 +4995,12 @@ get_unconditional_internal_fn (internal_fn ifn)
 {
   switch (ifn)
     {
+    case IFN_COND_COUNT_ACTIVE:
+    case IFN_COND_LEN_COUNT_ACTIVE:
+      return IFN_COUNT_ACTIVE;
+    case IFN_COND_INDEX_FIRST_ACTIVE:
+    case IFN_COND_LEN_INDEX_FIRST_ACTIVE:
+      return IFN_INDEX_FIRST_ACTIVE;
 #define CASE(NAME)                                                             
\
     case IFN_COND_##NAME:                                                      
\
     case IFN_COND_LEN_##NAME:                                                  
\
@@ -5177,6 +5207,17 @@ internal_fn_len_index (internal_fn fn)
     case IFN_MASK_LEN_STRIDED_STORE:
       return 4;
 
+    case IFN_COND_LEN_COUNT_ACTIVE:
+    case IFN_COND_LEN_INDEX_FIRST_ACTIVE:
+      return 2;
+
+    case IFN_COND_LEN_TAKE_INCL_ACTIVE:
+    case IFN_COND_LEN_TAKE_EXCL_ACTIVE:
+      return 3;
+
+    case IFN_COND_LEN_VEC_CMP:
+      return 4;
+
     case IFN_COND_LEN_NEG:
     case IFN_MASK_LEN_STORE:
     case IFN_MASK_LEN_STORE_LANES:
@@ -5214,6 +5255,10 @@ internal_fn_else_index (internal_fn fn)
     case IFN_COND_LEN_FLOOR:
     case IFN_COND_LEN_ROUND:
     case IFN_COND_LEN_RINT:
+    case IFN_COND_TAKE_INCL_ACTIVE:
+    case IFN_COND_TAKE_EXCL_ACTIVE:
+    case IFN_COND_LEN_TAKE_INCL_ACTIVE:
+    case IFN_COND_LEN_TAKE_EXCL_ACTIVE:
       return 2;
 
     case IFN_LEN_LOAD:
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index 
af9f92950c73dd09356a625cf2fd60a5abbde321..8ec060415e60dfb6d073a7041c866a1fdf05e800
 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -89,6 +89,10 @@ along with GCC; see the file COPYING3.  If not see
    - cond_len_binary: a conditional binary optab, such as cond_len_add<mode>
    - cond_len_ternary: a conditional ternary optab, such as
    cond_len_fma_rev<mode>
+   - cond_mask_unary: a unary optab that takes a mask and a predicate operand,
+     such as cond_count_active<mode>
+   - cond_len_mask_unary: a unary optab that takes a mask, a predicate
+     operand, a length and a bias, such as cond_len_count_active<mode>
 
    DEF_INTERNAL_SIGNED_OPTAB_FN defines an internal function that
    maps to one of two optabs, depending on the signedness of an input.
@@ -337,6 +341,28 @@ DEF_INTERNAL_COND_FN (FNMS, ECF_CONST, fnms, ternary)
 DEF_INTERNAL_COND_FN (NEG, ECF_CONST, neg, unary)
 DEF_INTERNAL_COND_FN (NOT, ECF_CONST, one_cmpl, unary)
 
+DEF_INTERNAL_OPTAB_FN (COUNT_ACTIVE, ECF_CONST, count_active, unary)
+DEF_INTERNAL_OPTAB_FN (COND_COUNT_ACTIVE, ECF_CONST, cond_count_active,
+                      cond_mask_unary)
+DEF_INTERNAL_OPTAB_FN (COND_LEN_COUNT_ACTIVE, ECF_CONST,
+                      cond_len_count_active, cond_len_mask_unary)
+DEF_INTERNAL_OPTAB_FN (INDEX_FIRST_ACTIVE, ECF_CONST, index_first_active,
+                      unary)
+DEF_INTERNAL_OPTAB_FN (COND_INDEX_FIRST_ACTIVE, ECF_CONST,
+                      cond_index_first_active, cond_mask_unary)
+DEF_INTERNAL_OPTAB_FN (COND_LEN_INDEX_FIRST_ACTIVE, ECF_CONST,
+                      cond_len_index_first_active, cond_len_mask_unary)
+DEF_INTERNAL_OPTAB_FN (TAKE_INCL_ACTIVE, ECF_CONST, take_incl_active, unary)
+DEF_INTERNAL_OPTAB_FN (COND_TAKE_INCL_ACTIVE, ECF_CONST,
+                      cond_take_incl_active, cond_unary)
+DEF_INTERNAL_OPTAB_FN (COND_LEN_TAKE_INCL_ACTIVE, ECF_CONST,
+                      cond_len_take_incl_active, cond_len_unary)
+DEF_INTERNAL_OPTAB_FN (TAKE_EXCL_ACTIVE, ECF_CONST, take_excl_active, unary)
+DEF_INTERNAL_OPTAB_FN (COND_TAKE_EXCL_ACTIVE, ECF_CONST,
+                      cond_take_excl_active, cond_unary)
+DEF_INTERNAL_OPTAB_FN (COND_LEN_TAKE_EXCL_ACTIVE, ECF_CONST,
+                      cond_len_take_excl_active, cond_len_unary)
+
 DEF_INTERNAL_OPTAB_FN (RSQRT, ECF_CONST, rsqrt, unary)
 
 DEF_INTERNAL_OPTAB_FN (REDUC_PLUS, ECF_CONST | ECF_NOTHROW,
@@ -363,9 +389,11 @@ 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.  */
+/* Extract the first or last active element from a vector.  */
 DEF_INTERNAL_OPTAB_FN (EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
                       extract_last, fold_left)
+DEF_INTERNAL_OPTAB_FN (EXTRACT_FIRST, ECF_CONST | ECF_NOTHROW,
+                      extract_first, fold_left)
 
 /* Same, but return the first argument if no elements are active.  */
 DEF_INTERNAL_OPTAB_FN (FOLD_EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 
327e3efaf8a9eb217db7276848fee1676de02e80..73571fe700c6cb73b35f7f25796bb1b2d090d244
 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -427,8 +427,21 @@ 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")
 
 OPTAB_D (extract_last_optab, "extract_last_$a")
+OPTAB_D (extract_first_optab, "extract_first_$a")
+OPTAB_D (count_active_optab, "count_active_$a")
+OPTAB_D (cond_count_active_optab, "cond_count_active_$a")
+OPTAB_D (cond_len_count_active_optab, "cond_len_count_active_$a")
+OPTAB_D (index_first_active_optab, "index_first_active_$a")
+OPTAB_D (cond_index_first_active_optab, "cond_index_first_active_$a")
+OPTAB_D (cond_len_index_first_active_optab, "cond_len_index_first_active_$a")
 OPTAB_D (fold_extract_last_optab, "fold_extract_last_$a")
 OPTAB_D (len_fold_extract_last_optab, "len_fold_extract_last_$a")
+OPTAB_D (take_incl_active_optab, "take_incl_active_$a")
+OPTAB_D (take_excl_active_optab, "take_excl_active_$a")
+OPTAB_D (cond_take_incl_active_optab, "cond_take_incl_active_$a")
+OPTAB_D (cond_take_excl_active_optab, "cond_take_excl_active_$a")
+OPTAB_D (cond_len_take_incl_active_optab, "cond_len_take_incl_active_$a")
+OPTAB_D (cond_len_take_excl_active_optab, "cond_len_take_excl_active_$a")
 
 OPTAB_D (uabd_optab, "uabd$a3")
 OPTAB_D (sabd_optab, "sabd$a3")


-- 
diff --git a/gcc/doc/ifn.texi b/gcc/doc/ifn.texi
index 7cfc80eecf262db33b62e02d3d2d2552c69e5e82..9f130998ec7351f9820576cc309a6eec8798372f 100644
--- a/gcc/doc/ifn.texi
+++ b/gcc/doc/ifn.texi
@@ -457,6 +457,107 @@ The @code{IFN_COND_NOT} internal function directly maps to the
 The @code{IFN_COND_LEN_NOT} internal function directly maps to the
 @code{cond_len_one_cmpl} instruction pattern.
 
+@cindex @code{IFN_COUNT_ACTIVE} internal function
+@item @samp{IFN_COUNT_ACTIVE}
+The @code{IFN_COUNT_ACTIVE} internal function directly maps to the
+@code{count_active} instruction pattern.  It returns the number of active
+elements in its argument.
+
+@cindex @code{IFN_COND_COUNT_ACTIVE} internal function
+@item @samp{IFN_COND_COUNT_ACTIVE}
+The @code{IFN_COND_COUNT_ACTIVE} internal function directly maps to the
+@code{cond_count_active} instruction pattern.  It returns the number of
+active elements in its second argument under the mask in its first
+argument.
+
+@cindex @code{IFN_COND_LEN_COUNT_ACTIVE} internal function
+@item @samp{IFN_COND_LEN_COUNT_ACTIVE}
+The @code{IFN_COND_LEN_COUNT_ACTIVE} internal function directly maps to the
+@code{cond_len_count_active} instruction pattern.  It is like
+@code{IFN_COND_COUNT_ACTIVE}, but also ignores elements whose index is
+greater than or equal to the sum of the length and bias arguments.
+
+@cindex @code{IFN_INDEX_FIRST_ACTIVE} internal function
+@item @samp{IFN_INDEX_FIRST_ACTIVE}
+The @code{IFN_INDEX_FIRST_ACTIVE} internal function directly maps to the
+@code{index_first_active} instruction pattern.  It returns the index of the
+first active element in its argument.  The result is undefined if the
+predicate has no active elements.
+
+@cindex @code{IFN_COND_INDEX_FIRST_ACTIVE} internal function
+@item @samp{IFN_COND_INDEX_FIRST_ACTIVE}
+The @code{IFN_COND_INDEX_FIRST_ACTIVE} internal function directly maps to the
+@code{cond_index_first_active} instruction pattern.  It returns the index of
+the first active element in its second argument under the mask in its first
+argument.  The result is undefined if the selected predicate has no active
+elements.
+
+@cindex @code{IFN_COND_LEN_INDEX_FIRST_ACTIVE} internal function
+@item @samp{IFN_COND_LEN_INDEX_FIRST_ACTIVE}
+The @code{IFN_COND_LEN_INDEX_FIRST_ACTIVE} internal function directly maps to
+the @code{cond_len_index_first_active} instruction pattern.  It is like
+@code{IFN_COND_INDEX_FIRST_ACTIVE}, but also ignores elements whose index is
+greater than or equal to the sum of the length and bias arguments.
+
+@cindex @code{IFN_TAKE_INCL_ACTIVE} internal function
+@item @samp{IFN_TAKE_INCL_ACTIVE}
+The @code{IFN_TAKE_INCL_ACTIVE} internal function directly maps to the
+@code{take_incl_active} instruction pattern.  It returns a predicate
+containing the active elements up to and including the first active element
+of its argument.
+
+@cindex @code{IFN_COND_TAKE_INCL_ACTIVE} internal function
+@item @samp{IFN_COND_TAKE_INCL_ACTIVE}
+The @code{IFN_COND_TAKE_INCL_ACTIVE} internal function directly maps to the
+@code{cond_take_incl_active} instruction pattern.  It returns a predicate
+containing the active elements up to and including the first active element
+of the predicate formed by selecting its second argument under the mask in
+its first argument, and its third argument elsewhere.
+
+@cindex @code{IFN_COND_LEN_TAKE_INCL_ACTIVE} internal function
+@item @samp{IFN_COND_LEN_TAKE_INCL_ACTIVE}
+The @code{IFN_COND_LEN_TAKE_INCL_ACTIVE} internal function directly maps to
+the @code{cond_len_take_incl_active} instruction pattern.  It is like
+@code{IFN_COND_TAKE_INCL_ACTIVE}, but also ignores elements whose index is
+greater than or equal to the sum of the length and bias arguments.
+
+@cindex @code{IFN_TAKE_EXCL_ACTIVE} internal function
+@item @samp{IFN_TAKE_EXCL_ACTIVE}
+The @code{IFN_TAKE_EXCL_ACTIVE} internal function directly maps to the
+@code{take_excl_active} instruction pattern.  It returns a predicate
+containing the active elements before, but excluding, the first active
+element of its argument.
+
+@cindex @code{IFN_COND_TAKE_EXCL_ACTIVE} internal function
+@item @samp{IFN_COND_TAKE_EXCL_ACTIVE}
+The @code{IFN_COND_TAKE_EXCL_ACTIVE} internal function directly maps to the
+@code{cond_take_excl_active} instruction pattern.  It returns a predicate
+containing the active elements before, but excluding, the first active element
+of the predicate formed by selecting its second argument under the mask in
+its first argument, and its third argument elsewhere.
+
+@cindex @code{IFN_COND_LEN_TAKE_EXCL_ACTIVE} internal function
+@item @samp{IFN_COND_LEN_TAKE_EXCL_ACTIVE}
+The @code{IFN_COND_LEN_TAKE_EXCL_ACTIVE} internal function directly maps to
+the @code{cond_len_take_excl_active} instruction pattern.  It is like
+@code{IFN_COND_TAKE_EXCL_ACTIVE}, but also ignores elements whose index is
+greater than or equal to the sum of the length and bias arguments.
+
+@cindex @code{IFN_COND_VEC_CMP} internal function
+@item @samp{IFN_COND_VEC_CMP}
+The @code{IFN_COND_VEC_CMP} internal function directly maps to the
+@code{cond_vec_cmp} instruction pattern.  It performs the comparison
+identified by its first argument on its third and fourth arguments, then
+returns the comparison result after applying the predicate mask in its
+second argument.
+
+@cindex @code{IFN_COND_LEN_VEC_CMP} internal function
+@item @samp{IFN_COND_LEN_VEC_CMP}
+The @code{IFN_COND_LEN_VEC_CMP} internal function directly maps to the
+@code{cond_len_vec_cmp} instruction pattern.  It is like
+@code{IFN_COND_VEC_CMP}, but also ignores elements whose index is greater
+than or equal to the sum of the length and bias arguments.
+
 @cindex @code{IFN_RSQRT} internal function
 @item @samp{IFN_RSQRT}
 The @code{IFN_RSQRT} internal function directly maps to the @code{rsqrt}
@@ -512,6 +613,11 @@ The @code{IFN_REDUC_SBOOL_XOR} internal function directly maps to the
 The @code{IFN_EXTRACT_LAST} internal function directly maps to the
 @code{extract_last} instruction pattern.
 
+@cindex @code{IFN_EXTRACT_FIRST} internal function
+@item @samp{IFN_EXTRACT_FIRST}
+The @code{IFN_EXTRACT_FIRST} internal function directly maps to the
+@code{extract_first} instruction pattern.
+
 @cindex @code{IFN_FOLD_EXTRACT_LAST} internal function
 @item @samp{IFN_FOLD_EXTRACT_LAST}
 The @code{IFN_FOLD_EXTRACT_LAST} internal function directly maps to the
@@ -1553,4 +1659,3 @@ definition is still being built by the current pass.  The pass that creates
 it must replace it before finishing; the verifier rejects any remaining calls.
 
 @end table
-
diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
index f86fa8038e8a0a4498325ea12e041b9622b4e7d5..629fb18b362770a74347441f178d865983dd4e4a 100644
--- a/gcc/doc/md.texi
+++ b/gcc/doc/md.texi
@@ -7905,6 +7905,34 @@ has vector mode @var{m} while operand 0 has the mode appropriate for one
 element of @var{m}.  Operand 1 has the usual mask mode for vectors of mode
 @var{m}; see @code{TARGET_VECTORIZE_GET_MASK_MODE}.
 
+@mdindex extract_first_@var{m}
+@item @code{extract_first_@var{m}}
+Find the first set bit in mask operand 1 and extract the associated element
+of vector operand 2.  Store the result in scalar operand 0.  Operand 2
+has vector mode @var{m} while operand 0 has the mode appropriate for one
+element of @var{m}.  Operand 1 has the usual mask mode for vectors of mode
+@var{m}; see @code{TARGET_VECTORIZE_GET_MASK_MODE}.
+
+@mdindex count_active_@var{m}
+@item @code{count_active_@var{m}}
+Count the set bits in mask operand 1 and store the result in scalar
+operand 0.
+
+@mdindex index_first_active_@var{m}
+@item @code{index_first_active_@var{m}}
+Find the first set bit in mask operand 1 and store the zero-based element
+index in scalar operand 0.  The result is undefined if no bits are set.
+
+@mdindex take_incl_active_@var{m}
+@item @code{take_incl_active_@var{m}}
+Set mask operand 0 to the active elements of mask operand 1 up to and
+including the first active element of operand 1.
+
+@mdindex take_excl_active_@var{m}
+@item @code{take_excl_active_@var{m}}
+Set mask operand 0 to the active elements of mask operand 1 before, but
+excluding, the first active element of operand 1.
+
 @mdindex fold_extract_last_@var{m}
 @item @code{fold_extract_last_@var{m}}
 If any bits of mask operand 2 are set, find the last set bit, extract
@@ -8675,6 +8703,76 @@ for (i = 0; i < GET_MODE_NUNITS (@var{m}); i++)
             : op5[i]);
 @end smallexample
 
+@mdindex cond_count_active_@var{mode}
+@item @samp{cond_count_active_@var{mode}}
+Set operand 0 to the number of active elements in operand 2 under the mask
+in operand 1.  Operand 0 has a scalar integer mode.  Operands 1 and 2 have
+mode @var{mode}.
+
+@mdindex cond_len_count_active_@var{mode}
+@item @samp{cond_len_count_active_@var{mode}}
+Like @samp{cond_count_active_@var{mode}}, but additionally ignore elements
+whose index is greater than or equal to the sum of operands 3 and 4.
+Operand 3 has whichever integer mode the target prefers, and operand 4 is
+a bias.
+
+@mdindex cond_index_first_active_@var{mode}
+@item @samp{cond_index_first_active_@var{mode}}
+Set operand 0 to the index of the first active element in operand 2 under
+the mask in operand 1.  Operand 0 has a scalar integer mode.  Operands 1
+and 2 have mode @var{mode}.  The result is undefined if the selected
+predicate has no
+active elements.
+
+@mdindex cond_len_index_first_active_@var{mode}
+@item @samp{cond_len_index_first_active_@var{mode}}
+Like @samp{cond_index_first_active_@var{mode}}, but additionally ignore
+elements whose index is greater than or equal to the sum of operands 3
+and 4.  Operand 3 has whichever integer mode the target prefers, and
+operand 4 is a bias.
+
+@mdindex cond_take_incl_active_@var{mode}
+@item @samp{cond_take_incl_active_@var{mode}}
+Set operand 0 to a predicate that contains the active elements up to and
+including the first active element in the predicate formed by selecting
+operand 2 under operand 1, and operand 3 elsewhere.  Operands 0, 1, 2
+and 3 have mode @var{mode}.
+
+@mdindex cond_len_take_incl_active_@var{mode}
+@item @samp{cond_len_take_incl_active_@var{mode}}
+Like @samp{cond_take_incl_active_@var{mode}}, but additionally ignore
+elements whose index is greater than or equal to the sum of operands 4
+and 5.  Operand 4 has whichever integer mode the target prefers, and
+operand 5 is a bias.
+
+@mdindex cond_take_excl_active_@var{mode}
+@item @samp{cond_take_excl_active_@var{mode}}
+Set operand 0 to a predicate that contains the active elements before,
+but excluding, the first active element in the predicate formed by selecting
+operand 2 under operand 1, and operand 3 elsewhere.  Operands 0, 1, 2
+and 3 have mode @var{mode}.
+
+@mdindex cond_len_take_excl_active_@var{mode}
+@item @samp{cond_len_take_excl_active_@var{mode}}
+Like @samp{cond_take_excl_active_@var{mode}}, but additionally ignore
+elements whose index is greater than or equal to the sum of operands 4
+and 5.  Operand 4 has whichever integer mode the target prefers, and
+operand 5 is a bias.
+
+@mdindex cond_vec_cmp@var{m}@var{n}
+@item @samp{cond_vec_cmp@var{m}@var{n}}
+Set operand 0 to the result of applying comparison operand 1 to operands
+3 and 4, after applying predicate mask operand 2.  Operand 0 has mode
+@var{n}; operands 3 and 4 have mode @var{m}.  Operand 2 has the mode
+returned by @code{TARGET_VECTORIZE_GET_MASK_MODE} for @var{m}.
+
+@mdindex cond_len_vec_cmp@var{m}@var{n}
+@item @samp{cond_len_vec_cmp@var{m}@var{n}}
+Like @samp{cond_vec_cmp@var{m}@var{n}}, but additionally ignore elements
+whose index is greater than or equal to the sum of operands 5 and 6.
+Operand 5 has whichever integer mode the target prefers, and operand 6 is
+a bias.
+
 @mdindex cbranch@var{mode}4
 @item @samp{cbranch@var{mode}4}
 Conditional branch instruction combined with a compare instruction.
diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index 0138c6f7ef0117f43afa5c81406a6564a425d304..0030db0c29bf62c4cb4aebb250be9fb5e598dbfa 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -186,6 +186,8 @@ init_internal_fns ()
 #define cond_len_unary_direct { 1, 1, true }
 #define cond_len_binary_direct { 1, 1, true }
 #define cond_len_ternary_direct { 1, 1, true }
+#define cond_mask_unary_direct { 0, 0, true }
+#define cond_len_mask_unary_direct { 0, 0, true }
 #define while_direct { 0, 2, false }
 #define fold_extract_direct { 2, 2, false }
 #define fold_len_extract_direct { 2, 2, false }
@@ -4294,6 +4296,12 @@ expand_reduc_sbool_optab_fn (internal_fn fn, gcall *stmt, direct_optab optab)
 #define expand_cond_len_ternary_optab_fn(FN, STMT, OPTAB) \
   expand_direct_optab_fn (FN, STMT, OPTAB, 7)
 
+#define expand_cond_mask_unary_optab_fn(FN, STMT, OPTAB) \
+  expand_direct_optab_fn (FN, STMT, OPTAB, 2)
+
+#define expand_cond_len_mask_unary_optab_fn(FN, STMT, OPTAB) \
+  expand_direct_optab_fn (FN, STMT, OPTAB, 4)
+
 #define expand_fold_extract_optab_fn(FN, STMT, OPTAB) \
   expand_direct_optab_fn (FN, STMT, OPTAB, 3)
 
@@ -4404,6 +4412,8 @@ multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
 #define direct_cond_len_unary_optab_supported_p direct_optab_supported_p
 #define direct_cond_len_binary_optab_supported_p direct_optab_supported_p
 #define direct_cond_len_ternary_optab_supported_p direct_optab_supported_p
+#define direct_cond_mask_unary_optab_supported_p direct_optab_supported_p
+#define direct_cond_len_mask_unary_optab_supported_p direct_optab_supported_p
 #define direct_crc_optab_supported_p convert_optab_supported_p
 #define direct_mask_load_optab_supported_p convert_optab_supported_p
 #define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
@@ -4892,6 +4902,8 @@ get_conditional_len_internal_fn (tree_code code)
 /* Invoke T(IFN) for each internal function IFN that also has an
    IFN_COND_* form.  */
 #define FOR_EACH_COND_FN_PAIR(T) \
+  T (TAKE_INCL_ACTIVE) \
+  T (TAKE_EXCL_ACTIVE) \
   T (FMAX) \
   T (FMIN) \
   T (FMA) \
@@ -4923,6 +4935,10 @@ get_conditional_internal_fn (internal_fn fn)
 {
   switch (fn)
     {
+    case IFN_COUNT_ACTIVE:
+      return IFN_COND_COUNT_ACTIVE;
+    case IFN_INDEX_FIRST_ACTIVE:
+      return IFN_COND_INDEX_FIRST_ACTIVE;
 #define CASE(NAME) case IFN_##NAME: return IFN_COND_##NAME;
       FOR_EACH_COND_FN_PAIR(CASE)
 #undef CASE
@@ -4958,6 +4974,14 @@ get_len_internal_fn (internal_fn fn)
       return IFN_MASK_LEN_LOAD_LANES;
     case IFN_MASK_GATHER_LOAD:
       return IFN_MASK_LEN_GATHER_LOAD;
+    case IFN_COND_COUNT_ACTIVE:
+      return IFN_COND_LEN_COUNT_ACTIVE;
+    case IFN_COND_INDEX_FIRST_ACTIVE:
+      return IFN_COND_LEN_INDEX_FIRST_ACTIVE;
+    case IFN_COND_TAKE_INCL_ACTIVE:
+      return IFN_COND_LEN_TAKE_INCL_ACTIVE;
+    case IFN_COND_TAKE_EXCL_ACTIVE:
+      return IFN_COND_LEN_TAKE_EXCL_ACTIVE;
     default:
       return IFN_LAST;
     }
@@ -4971,6 +4995,12 @@ get_unconditional_internal_fn (internal_fn ifn)
 {
   switch (ifn)
     {
+    case IFN_COND_COUNT_ACTIVE:
+    case IFN_COND_LEN_COUNT_ACTIVE:
+      return IFN_COUNT_ACTIVE;
+    case IFN_COND_INDEX_FIRST_ACTIVE:
+    case IFN_COND_LEN_INDEX_FIRST_ACTIVE:
+      return IFN_INDEX_FIRST_ACTIVE;
 #define CASE(NAME)                                                             \
     case IFN_COND_##NAME:                                                      \
     case IFN_COND_LEN_##NAME:                                                  \
@@ -5177,6 +5207,17 @@ internal_fn_len_index (internal_fn fn)
     case IFN_MASK_LEN_STRIDED_STORE:
       return 4;
 
+    case IFN_COND_LEN_COUNT_ACTIVE:
+    case IFN_COND_LEN_INDEX_FIRST_ACTIVE:
+      return 2;
+
+    case IFN_COND_LEN_TAKE_INCL_ACTIVE:
+    case IFN_COND_LEN_TAKE_EXCL_ACTIVE:
+      return 3;
+
+    case IFN_COND_LEN_VEC_CMP:
+      return 4;
+
     case IFN_COND_LEN_NEG:
     case IFN_MASK_LEN_STORE:
     case IFN_MASK_LEN_STORE_LANES:
@@ -5214,6 +5255,10 @@ internal_fn_else_index (internal_fn fn)
     case IFN_COND_LEN_FLOOR:
     case IFN_COND_LEN_ROUND:
     case IFN_COND_LEN_RINT:
+    case IFN_COND_TAKE_INCL_ACTIVE:
+    case IFN_COND_TAKE_EXCL_ACTIVE:
+    case IFN_COND_LEN_TAKE_INCL_ACTIVE:
+    case IFN_COND_LEN_TAKE_EXCL_ACTIVE:
       return 2;
 
     case IFN_LEN_LOAD:
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index af9f92950c73dd09356a625cf2fd60a5abbde321..8ec060415e60dfb6d073a7041c866a1fdf05e800 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -89,6 +89,10 @@ along with GCC; see the file COPYING3.  If not see
    - cond_len_binary: a conditional binary optab, such as cond_len_add<mode>
    - cond_len_ternary: a conditional ternary optab, such as
    cond_len_fma_rev<mode>
+   - cond_mask_unary: a unary optab that takes a mask and a predicate operand,
+     such as cond_count_active<mode>
+   - cond_len_mask_unary: a unary optab that takes a mask, a predicate
+     operand, a length and a bias, such as cond_len_count_active<mode>
 
    DEF_INTERNAL_SIGNED_OPTAB_FN defines an internal function that
    maps to one of two optabs, depending on the signedness of an input.
@@ -337,6 +341,28 @@ DEF_INTERNAL_COND_FN (FNMS, ECF_CONST, fnms, ternary)
 DEF_INTERNAL_COND_FN (NEG, ECF_CONST, neg, unary)
 DEF_INTERNAL_COND_FN (NOT, ECF_CONST, one_cmpl, unary)
 
+DEF_INTERNAL_OPTAB_FN (COUNT_ACTIVE, ECF_CONST, count_active, unary)
+DEF_INTERNAL_OPTAB_FN (COND_COUNT_ACTIVE, ECF_CONST, cond_count_active,
+		       cond_mask_unary)
+DEF_INTERNAL_OPTAB_FN (COND_LEN_COUNT_ACTIVE, ECF_CONST,
+		       cond_len_count_active, cond_len_mask_unary)
+DEF_INTERNAL_OPTAB_FN (INDEX_FIRST_ACTIVE, ECF_CONST, index_first_active,
+		       unary)
+DEF_INTERNAL_OPTAB_FN (COND_INDEX_FIRST_ACTIVE, ECF_CONST,
+		       cond_index_first_active, cond_mask_unary)
+DEF_INTERNAL_OPTAB_FN (COND_LEN_INDEX_FIRST_ACTIVE, ECF_CONST,
+		       cond_len_index_first_active, cond_len_mask_unary)
+DEF_INTERNAL_OPTAB_FN (TAKE_INCL_ACTIVE, ECF_CONST, take_incl_active, unary)
+DEF_INTERNAL_OPTAB_FN (COND_TAKE_INCL_ACTIVE, ECF_CONST,
+		       cond_take_incl_active, cond_unary)
+DEF_INTERNAL_OPTAB_FN (COND_LEN_TAKE_INCL_ACTIVE, ECF_CONST,
+		       cond_len_take_incl_active, cond_len_unary)
+DEF_INTERNAL_OPTAB_FN (TAKE_EXCL_ACTIVE, ECF_CONST, take_excl_active, unary)
+DEF_INTERNAL_OPTAB_FN (COND_TAKE_EXCL_ACTIVE, ECF_CONST,
+		       cond_take_excl_active, cond_unary)
+DEF_INTERNAL_OPTAB_FN (COND_LEN_TAKE_EXCL_ACTIVE, ECF_CONST,
+		       cond_len_take_excl_active, cond_len_unary)
+
 DEF_INTERNAL_OPTAB_FN (RSQRT, ECF_CONST, rsqrt, unary)
 
 DEF_INTERNAL_OPTAB_FN (REDUC_PLUS, ECF_CONST | ECF_NOTHROW,
@@ -363,9 +389,11 @@ 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.  */
+/* Extract the first or last active element from a vector.  */
 DEF_INTERNAL_OPTAB_FN (EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
 		       extract_last, fold_left)
+DEF_INTERNAL_OPTAB_FN (EXTRACT_FIRST, ECF_CONST | ECF_NOTHROW,
+		       extract_first, fold_left)
 
 /* Same, but return the first argument if no elements are active.  */
 DEF_INTERNAL_OPTAB_FN (FOLD_EXTRACT_LAST, ECF_CONST | ECF_NOTHROW,
diff --git a/gcc/optabs.def b/gcc/optabs.def
index 327e3efaf8a9eb217db7276848fee1676de02e80..73571fe700c6cb73b35f7f25796bb1b2d090d244 100644
--- a/gcc/optabs.def
+++ b/gcc/optabs.def
@@ -427,8 +427,21 @@ 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")
 
 OPTAB_D (extract_last_optab, "extract_last_$a")
+OPTAB_D (extract_first_optab, "extract_first_$a")
+OPTAB_D (count_active_optab, "count_active_$a")
+OPTAB_D (cond_count_active_optab, "cond_count_active_$a")
+OPTAB_D (cond_len_count_active_optab, "cond_len_count_active_$a")
+OPTAB_D (index_first_active_optab, "index_first_active_$a")
+OPTAB_D (cond_index_first_active_optab, "cond_index_first_active_$a")
+OPTAB_D (cond_len_index_first_active_optab, "cond_len_index_first_active_$a")
 OPTAB_D (fold_extract_last_optab, "fold_extract_last_$a")
 OPTAB_D (len_fold_extract_last_optab, "len_fold_extract_last_$a")
+OPTAB_D (take_incl_active_optab, "take_incl_active_$a")
+OPTAB_D (take_excl_active_optab, "take_excl_active_$a")
+OPTAB_D (cond_take_incl_active_optab, "cond_take_incl_active_$a")
+OPTAB_D (cond_take_excl_active_optab, "cond_take_excl_active_$a")
+OPTAB_D (cond_len_take_incl_active_optab, "cond_len_take_incl_active_$a")
+OPTAB_D (cond_len_take_excl_active_optab, "cond_len_take_excl_active_$a")
 
 OPTAB_D (uabd_optab, "uabd$a3")
 OPTAB_D (sabd_optab, "sabd$a3")

Reply via email to