Define IFN_PREDICATED_INDEX_UPDATE and IFN_MASK_COMPRESS_SCATTER_STORE,
add scalar RTL expanders, and implement phase-2 pattern recognition for
the predicated-index PHI latch update and paired IFN_MASK_STORE.

During phase-1 detection, record the mask-store base and element scale in
loop_vec_info so compress-scatter recog can build
IFN_MASK_COMPRESS_SCATTER_STORE without re-walking the address chain.
---
 gcc/internal-fn.cc          |  58 +++++++++
 gcc/internal-fn.def         |   4 +
 gcc/tree-vect-loop.cc       |   7 +-
 gcc/tree-vect-patterns.cc   |   3 +
 gcc/tree-vect-vpcompress.cc | 229 ++++++++++++++++++++++++++++++------
 gcc/tree-vect-vpcompress.h  |   6 +
 gcc/tree-vectorizer.h       |   7 ++
 7 files changed, 279 insertions(+), 35 deletions(-)

diff --git a/gcc/internal-fn.cc b/gcc/internal-fn.cc
index 0138c6f7ef0..bf0f430ec7d 100644
--- a/gcc/internal-fn.cc
+++ b/gcc/internal-fn.cc
@@ -4777,6 +4777,56 @@ set_edom_supported_p (void)
   }
 #include "internal-fn.def"
 
+/* Expand IFN_PREDICATED_INDEX_UPDATE to mask ? idx + 1 : idx.  */
+
+static void
+expand_PREDICATED_INDEX_UPDATE (internal_fn, gcall *stmt)
+{
+  tree lhs = gimple_call_lhs (stmt);
+  gcc_assert (lhs != NULL_TREE);
+  tree idx = gimple_call_arg (stmt, 0);
+  tree mask = gimple_call_arg (stmt, 1);
+  tree type = TREE_TYPE (lhs);
+  tree one = build_int_cst (type, 1);
+  tree inc = fold_build2 (PLUS_EXPR, type, idx, one);
+  tree cond_expr;
+  if (VECTOR_TYPE_P (TREE_TYPE (mask)))
+    gcc_unreachable ();
+  if (TREE_CODE (TREE_TYPE (mask)) == BOOLEAN_TYPE)
+    cond_expr = fold_build3 (COND_EXPR, type, mask, inc, idx);
+  else
+    {
+      tree cmp = fold_build2 (NE_EXPR, boolean_type_node, mask,
+                             build_int_cst (TREE_TYPE (mask), 0));
+      cond_expr = fold_build3 (COND_EXPR, type, cmp, inc, idx);
+    }
+  rtx target = expand_expr (lhs, NULL_RTX, VOIDmode, EXPAND_WRITE);
+  rtx tmp = expand_expr (cond_expr, target, TYPE_MODE (type), EXPAND_NORMAL);
+  if (!rtx_equal_p (tmp, target))
+    emit_move_insn (target, tmp);
+}
+
+/* Lower IFN_MASK_COMPRESS_SCATTER_STORE to IFN_MASK_STORE for now.  */
+
+static void
+expand_MASK_COMPRESS_SCATTER_STORE (internal_fn, gcall *stmt)
+{
+  tree base = gimple_call_arg (stmt, 0);
+  tree align = gimple_call_arg (stmt, 1);
+  tree pack_idx = gimple_call_arg (stmt, 2);
+  tree scale = gimple_call_arg (stmt, 3);
+  tree value = gimple_call_arg (stmt, 4);
+  tree mask = gimple_call_arg (stmt, 5);
+  tree byte_off = fold_build2 (MULT_EXPR, sizetype, pack_idx,
+                              fold_convert (sizetype, scale));
+  tree ptr = fold_build2 (POINTER_PLUS_EXPR, TREE_TYPE (base), base,
+                         byte_off);
+  gcall *call
+    = gimple_build_call_internal (IFN_MASK_STORE, 4, ptr, align, mask, value);
+  gimple_set_location (call, gimple_location (stmt));
+  expand_internal_call (IFN_MASK_STORE, call);
+}
+
 /* Routines to expand each internal function, indexed by function number.
    Each routine has the prototype:
 
@@ -5104,6 +5154,7 @@ internal_store_fn_p (internal_fn fn)
     case IFN_MASK_LEN_SCATTER_STORE:
     case IFN_LEN_STORE:
     case IFN_MASK_LEN_STORE:
+    case IFN_MASK_COMPRESS_SCATTER_STORE:
       return true;
 
     default:
@@ -5124,6 +5175,7 @@ internal_gather_scatter_fn_p (internal_fn fn)
     case IFN_SCATTER_STORE:
     case IFN_MASK_SCATTER_STORE:
     case IFN_MASK_LEN_SCATTER_STORE:
+    case IFN_MASK_COMPRESS_SCATTER_STORE:
       return true;
 
     default:
@@ -5303,6 +5355,7 @@ internal_fn_mask_index (internal_fn fn)
     case IFN_MASK_SCATTER_STORE:
     case IFN_MASK_LEN_GATHER_LOAD:
     case IFN_MASK_LEN_SCATTER_STORE:
+    case IFN_MASK_COMPRESS_SCATTER_STORE:
       return 5;
 
     case IFN_VCOND_MASK:
@@ -5329,6 +5382,8 @@ internal_fn_stored_value_index (internal_fn fn)
     case IFN_MASK_STORE:
     case IFN_MASK_STORE_LANES:
       return 3;
+
+    case IFN_MASK_COMPRESS_SCATTER_STORE:
     case IFN_SCATTER_STORE:
     case IFN_MASK_SCATTER_STORE:
     case IFN_MASK_LEN_SCATTER_STORE:
@@ -5361,6 +5416,7 @@ internal_fn_alias_ptr_index (internal_fn fn)
     case IFN_SCATTER_STORE:
     case IFN_MASK_SCATTER_STORE:
     case IFN_MASK_LEN_SCATTER_STORE:
+    case IFN_MASK_COMPRESS_SCATTER_STORE:
       return 1;
 
     default:
@@ -5385,6 +5441,7 @@ internal_fn_offset_index (internal_fn fn)
     case IFN_SCATTER_STORE:
     case IFN_MASK_SCATTER_STORE:
     case IFN_MASK_LEN_SCATTER_STORE:
+    case IFN_MASK_COMPRESS_SCATTER_STORE:
       return 2;
 
     default:
@@ -5409,6 +5466,7 @@ internal_fn_scale_index (internal_fn fn)
     case IFN_SCATTER_STORE:
     case IFN_MASK_SCATTER_STORE:
     case IFN_MASK_LEN_SCATTER_STORE:
+    case IFN_MASK_COMPRESS_SCATTER_STORE:
       return 3;
 
     default:
diff --git a/gcc/internal-fn.def b/gcc/internal-fn.def
index af9f92950c7..7bb2ff37edd 100644
--- a/gcc/internal-fn.def
+++ b/gcc/internal-fn.def
@@ -639,6 +639,10 @@ DEF_INTERNAL_FN (ASSUME, ECF_CONST | ECF_LEAF | ECF_NOTHROW
 /* For if-conversion of inbranch SIMD clones.  */
 DEF_INTERNAL_FN (MASK_CALL, ECF_NOVOPS, NULL)
 
+/* For Predicated index PHI / compress-scatter .  */
+DEF_INTERNAL_FN (PREDICATED_INDEX_UPDATE, 0, NULL)
+DEF_INTERNAL_FN (MASK_COMPRESS_SCATTER_STORE, 0, NULL)
+
 /* _BitInt support.  */
 DEF_INTERNAL_FN (MULBITINT, ECF_LEAF | ECF_NOTHROW, ". O . R . R . ")
 DEF_INTERNAL_FN (DIVMODBITINT, ECF_LEAF, ". O . O . R . R . ")
diff --git a/gcc/tree-vect-loop.cc b/gcc/tree-vect-loop.cc
index 003f9565a2a..b93a6648acf 100644
--- a/gcc/tree-vect-loop.cc
+++ b/gcc/tree-vect-loop.cc
@@ -788,7 +788,12 @@ _loop_vec_info::_loop_vec_info (class loop *loop_in, 
vec_info_shared *shared)
     early_break_needs_epilogue (false),
     early_break_niters_var (NULL),
     predicated_index_phi (NULL),
-    predicated_index_mask_store (NULL)
+    predicated_index_mask_store (NULL),
+    predicated_index_store_base (NULL_TREE),
+    predicated_index_store_scale (NULL_TREE),
+    predicated_index_mask_compress_scatter_store (NULL),
+    predicated_index_update_ifn_p (false),
+    predicated_index_compress_scatter_ifn_p (false)
 {
   /* CHECKME: We want to visit all BBs before their successors (except for
      latch blocks, for which this assertion wouldn't hold).  In the simple
diff --git a/gcc/tree-vect-patterns.cc b/gcc/tree-vect-patterns.cc
index ab7892b6c7b..8aab8a6de1c 100644
--- a/gcc/tree-vect-patterns.cc
+++ b/gcc/tree-vect-patterns.cc
@@ -41,6 +41,7 @@ along with GCC; see the file COPYING3.  If not see
 #include "gimplify-me.h"
 #include "cfgloop.h"
 #include "tree-vectorizer.h"
+#include "tree-vect-vpcompress.h"
 #include "dumpfile.h"
 #include "builtins.h"
 #include "internal-fn.h"
@@ -7453,6 +7454,7 @@ static vect_recog_func vect_vect_recog_func_ptrs[] = {
      possible beforehand.  */
   { vect_recog_average_pattern, "average" },
   { vect_recog_cond_expr_convert_pattern, "cond_expr_convert" },
+  { vect_recog_predicated_index_update_pattern, "predicated_index_update" },
   { vect_recog_mulhs_pattern, "mult_high" },
   { vect_recog_cast_forwprop_pattern, "cast_forwprop" },
   { vect_recog_widen_mult_pattern, "widen_mult" },
@@ -7477,6 +7479,7 @@ static vect_recog_func vect_vect_recog_func_ptrs[] = {
      of mask conversion that are needed for gather and scatter
      internal functions.  */
   { vect_recog_gather_scatter_pattern, "gather_scatter" },
+  { vect_recog_compress_scatter_pattern, "compress_scatter" },
   { vect_recog_cond_store_pattern, "cond_store" },
   { vect_recog_mask_conversion_pattern, "mask_conversion" },
   { vect_recog_widen_plus_pattern, "widen_plus" },
diff --git a/gcc/tree-vect-vpcompress.cc b/gcc/tree-vect-vpcompress.cc
index c1a87405b94..0060ad5d780 100644
--- a/gcc/tree-vect-vpcompress.cc
+++ b/gcc/tree-vect-vpcompress.cc
@@ -164,27 +164,31 @@ predicated_index_plus_one (tree &pred_phi,
   return false;
 }
 
-/* Function pred_phi_in_mask_store_addr_computation.
+/* Function pred_phi_mask_store_base_and_scale.
 
-   Starting from the store pointer in MASK_STORE_CALL, this function tries to
-   check if the base + offset computation is done and offset finaly reaches
-   PRED_PHI.
+   Starting from the store pointer in MASK_STORE_CALL, check that the address
+   has the form base + pred_phi * element_size and return BASE_OUT and
+   SCALE_OUT on success.
 
      # n = PHI <n_1, ..>
      ...
      a_1 = (long unsigned int) n;
      a_2 = a_1 * 4;
      a_3 = base + a_2;
-     addr =  (int *) a_3;
+     addr = (int *) a_3;
      .MASK_STORE (addr, mask, ..)
      n_1 = n + 1;
      ...
-     n_2 = mask ? n_1 : n;  */
+     n_2 = mask ? n_1 : n;
+
+   On success BASE_OUT is base and SCALE_OUT is 4.  */
+
 static bool
-pred_phi_in_mask_store_addr_computation (class loop *loop,
-                                        gcall *mask_store_call, tree pred_phi)
+pred_phi_mask_store_base_and_scale (class loop *loop,
+                                   gcall *mask_store_call, tree pred_phi,
+                                   tree *base_out, tree *scale_out)
 {
-  /* Get the pointer operand of MASK_SLP_CALL. 'addr' in the example.  */
+  /* Get the pointer operand of MASK_STORE_CALL. 'addr' in the example.  */
   tree ptr = gimple_call_arg (mask_store_call, 0);
   if (TREE_CODE (ptr) != SSA_NAME)
     return false;
@@ -222,21 +226,21 @@ pred_phi_in_mask_store_addr_computation (class loop *loop,
   if (!add_stmt)
     return false;
 
-  /* Check if add_stmt is base + offset format. Note that it can be either
-     base + offset or offset + base.  We take the loop invariant pointer as
-     the base.  Example -  a_3 = base + a_2;  */
+  /* Identify the loop-invariant base and the varying offset.
+     a_3 = base + a_2;  */
   tree add_op0 = gimple_assign_rhs1 (add_stmt);
   tree add_op1 = gimple_assign_rhs2 (add_stmt);
-  tree offset;
+  tree base = add_op0;
+  tree offset = add_op1;
   if (expr_invariant_in_loop_p (loop, add_op1))
-    offset = add_op0;
-  else if (expr_invariant_in_loop_p (loop, add_op0))
-    offset = add_op1;
-  else
+    {
+      base = add_op1;
+      offset = add_op0;
+    }
+  else if (!expr_invariant_in_loop_p (loop, add_op0))
     return false;
 
-  /* Now offset can be a multiplication with the element size as in
-     a_2 = a_1 * 4;  */
+  /* Offset should be index * element size, as in a_2 = a_1 * 4.  */
   if (TREE_CODE (offset) != SSA_NAME)
     return false;
   gimple *def = SSA_NAME_DEF_STMT (offset);
@@ -245,7 +249,7 @@ pred_phi_in_mask_store_addr_computation (class loop *loop,
     return false;
   tree mul_op0 = gimple_assign_rhs1 (mul);
   tree mul_op1 = gimple_assign_rhs2 (mul);
-  tree index_op =  mul_op0;
+  tree index_op = mul_op0;
   tree size_op = mul_op1;
   if (TREE_CODE (mul_op0) == INTEGER_CST)
     {
@@ -254,10 +258,11 @@ pred_phi_in_mask_store_addr_computation (class loop *loop,
     }
   else if (TREE_CODE (mul_op1) != INTEGER_CST)
     return false;
-  /* The index_op should be an SSA_NAM. */
+  /* The index operand should be an SSA_NAME.  */
   if (TREE_CODE (index_op) != SSA_NAME)
-      return false;
-  /* The size_op should be the element size pointed by ptr.  */
+    return false;
+
+  /* SIZE_OP must match the element size of the store pointer type.  */
   tree eltype = TREE_TYPE (TREE_TYPE (ptr));
   tree elem_size_unit = TYPE_SIZE_UNIT (eltype);
   if (!elem_size_unit || TREE_CODE (elem_size_unit) != INTEGER_CST)
@@ -265,12 +270,16 @@ pred_phi_in_mask_store_addr_computation (class loop *loop,
   if (!operand_equal_p (size_op, elem_size_unit, OEP_ONLY_CONST))
     return false;
 
-  /* No the index_op can be a casted one. So strip off that cast as in
-     a_1 = (long unsigned int) n;  */
+  /* Index may be cast, as in a_1 = (long unsigned int) n.  */
   pred_phi_strip_conversion (&index_op);
+  if (index_op != pred_phi)
+    return false;
 
-  /* Finally index_op should be PRED_PHI.  */
-  return index_op == pred_phi;
+  if (base_out)
+    *base_out = base;
+  if (scale_out)
+    *scale_out = elem_size_unit;
+  return true;
 }
 
 /* Function vect_find_predicated_index_mask_store.
@@ -295,7 +304,8 @@ pred_phi_in_mask_store_addr_computation (class loop *loop,
      n_2 = mask ? n_1 : n;  */
 static gcall *
 vect_find_predicated_index_mask_store (class loop *loop, gphi *phi,
-                                      tree pred_phi, tree pred_phi_mask)
+                                      tree pred_phi, tree pred_phi_mask,
+                                      tree *base_out, tree *scale_out)
 {
   /* Search only the basic block that holds PHI; TODO: to scan other blocks
      when generalizing.  */
@@ -317,9 +327,8 @@ vect_find_predicated_index_mask_store (class loop *loop, 
gphi *phi,
        continue;
 
       /* Check if PRED_PHI is used to compute mask_store_call address.  */
-      /* TODO: Can use any match operator (as in instcombine)??  */
-      if (!pred_phi_in_mask_store_addr_computation(loop, mask_store_call,
-                                                  pred_phi))
+      if (!pred_phi_mask_store_base_and_scale (loop, mask_store_call, pred_phi,
+                                              base_out, scale_out))
        continue;
 
       if (dump_enabled_p ())
@@ -349,8 +358,8 @@ vect_find_predicated_index_mask_store (class loop *loop, 
gphi *phi,
      ...
      n_2 = mask ? n_1 : n;  */
 bool
-vect_vpcompress_analyze_predicated_index_phi (loop_vec_info loop_vinfo,
-                                             class loop *loop, gphi *phi)
+vect_vpcompress_analyze_predicated_index_phi (loop_vec_info loop_vinfo, class 
loop *loop,
+                                             gphi *phi)
 {
   /* Require a loop-header PHI.  */
   if (gimple_bb (phi) != loop->header)
@@ -397,8 +406,11 @@ vect_vpcompress_analyze_predicated_index_phi 
(loop_vec_info loop_vinfo,
    * computed based on pred-phi and it should use the same mask as that of
    * COND_EXPR.  */
   tree mask = gimple_assign_rhs1 (pred_phi_back_edge_asgn_stmt);
+  tree store_base;
+  tree store_scale;
   gcall *mask_store =
-    vect_find_predicated_index_mask_store (loop, phi, pred_phi, mask);
+    vect_find_predicated_index_mask_store (loop, phi, pred_phi, mask,
+                                          &store_base, &store_scale);
 
   if (dump_enabled_p ())
     dump_printf_loc (MSG_NOTE, vect_location,
@@ -415,7 +427,156 @@ vect_vpcompress_analyze_predicated_index_phi 
(loop_vec_info loop_vinfo,
 
   loop_vinfo->predicated_index_phi = phi;
   loop_vinfo->predicated_index_mask_store = mask_store;
+  loop_vinfo->predicated_index_store_base = store_base;
+  loop_vinfo->predicated_index_store_scale = store_scale;
 
   /* All requirements satisfiled.  */
   return true;
 }
+
+/* Function vect_recog_predicated_index_update_pattern.
+
+   After phase-1 detection, rewrite the predicated-index PHI latch update
+   from a COND_EXPR into IFN_PREDICATED_INDEX_UPDATE.  The statement must be
+   the latch definition of the predicated-index PHI and use the same mask as
+   the paired IFN_MASK_STORE.
+
+     # n = PHI <n_1, 0>
+     ...
+     .MASK_STORE (addr, mask, ..)
+     ...
+     n_2 = mask ? n_1 : n;
+
+   is rewritten to:
+
+     n_2 = IFN_PREDICATED_INDEX_UPDATE (n, mask);  */
+
+gimple *
+vect_recog_predicated_index_update_pattern (vec_info *vinfo,
+                                           stmt_vec_info stmt_info,
+                                           tree *type_out)
+{
+  loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
+  /* Require a loop that already matched the predicated-index PHI pattern.  */
+  if (!loop_vinfo
+      || !loop_vinfo->predicated_index_phi
+      || !loop_vinfo->predicated_index_mask_store)
+    return NULL;
+
+  gphi *phi = loop_vinfo->predicated_index_phi;
+  class loop *loop = LOOP_VINFO_LOOP (loop_vinfo);
+  tree pred_phi = PHI_RESULT (phi);
+  /* STMT_INFO must be the latch-edge definition of the predicated-index PHI,
+     e.g. n_2 = mask ? n_1 : n.  */
+  tree latch_val = PHI_ARG_DEF_FROM_EDGE (phi, loop_latch_edge (loop));
+  if (TREE_CODE (latch_val) != SSA_NAME
+      || SSA_NAME_DEF_STMT (latch_val) != stmt_info->stmt)
+    return NULL;
+
+  gassign *asg = dyn_cast <gassign *> (stmt_info->stmt);
+  if (!asg || gimple_assign_rhs_code (asg) != COND_EXPR)
+    return NULL;
+
+  /* The COND_EXPR condition must be the same mask used by the mask store.  */
+  tree mask = gimple_assign_rhs1 (asg);
+  if (TREE_CODE (mask) != SSA_NAME)
+    return NULL;
+
+  gcall *mask_store = loop_vinfo->predicated_index_mask_store;
+  if (gimple_call_arg (mask_store, 2) != mask)
+    return NULL;
+
+  /* Build IFN_PREDICATED_INDEX_UPDATE (pred_phi, mask).  */
+  gcall *call
+    = gimple_build_call_internal (IFN_PREDICATED_INDEX_UPDATE, 2, pred_phi,
+                                 mask);
+  gimple_call_set_lhs (call, gimple_assign_lhs (asg));
+  gimple_set_location (call, gimple_location (asg));
+  gimple_call_set_nothrow (call, true);
+
+  /* pred_phi stays scalar even in the vector loop (idx + popcount (mask) per
+     vector iteration).  No vector SSA is produced here, so leave type_out
+     unset for the generic pattern machinery.  */
+  *type_out = NULL_TREE;
+  loop_vinfo->predicated_index_update_ifn_p = true;
+
+  if (dump_enabled_p ())
+    dump_printf_loc (MSG_NOTE, vect_location, "%s: detected: %G",
+                    "predicated_index_update", stmt_info->stmt);
+
+  return call;
+}
+
+/* Function vect_recog_compress_scatter_pattern.
+
+   After phase-1 detection, replace the paired IFN_MASK_STORE with
+   IFN_MASK_COMPRESS_SCATTER_STORE.  Base and scale were recorded during
+   phase-1 address analysis.
+
+     # n = PHI <n_1, ..>
+     ...
+     a_1 = (long unsigned int) n;
+     a_2 = a_1 * 4;
+     a_3 = base + a_2;
+     addr = (int *) a_3;
+     .MASK_STORE (addr, mask, ..);
+
+   is rewritten to:
+
+     IFN_MASK_COMPRESS_SCATTER_STORE (base, align, n, 4, .., mask);  */
+
+gimple *
+vect_recog_compress_scatter_pattern (vec_info *vinfo,
+                                    stmt_vec_info stmt_info,
+                                    tree *type_out)
+{
+  loop_vec_info loop_vinfo = dyn_cast <loop_vec_info> (vinfo);
+  /* Require a loop that already matched the predicated-index PHI pattern.  */
+  if (!loop_vinfo
+      || !loop_vinfo->predicated_index_phi
+      || !loop_vinfo->predicated_index_mask_store)
+    return NULL;
+
+  /* STMT_INFO must be the IFN_MASK_STORE recorded during phase-1.  */
+  gcall *orig = dyn_cast <gcall *> (stmt_info->stmt);
+  if (!orig || orig != loop_vinfo->predicated_index_mask_store)
+    return NULL;
+  if (!gimple_call_internal_p (orig, IFN_MASK_STORE))
+    return NULL;
+
+  tree pred_phi = PHI_RESULT (loop_vinfo->predicated_index_phi);
+  tree mask = gimple_call_arg (orig, 2);
+  tree value = gimple_call_arg (orig, 3);
+  tree pack_idx = pred_phi;
+  tree base = loop_vinfo->predicated_index_store_base;
+  tree scale = loop_vinfo->predicated_index_store_scale;
+  if (!base || !scale)
+    return NULL;
+
+  tree align = gimple_call_arg (orig, 1);
+
+  /* Build IFN_MASK_COMPRESS_SCATTER_STORE (base, align, pack_idx, scale,
+     value, mask).  */
+  gcall *call
+    = gimple_build_call_internal (IFN_MASK_COMPRESS_SCATTER_STORE, 6,
+                                 base, align, pack_idx, scale, value, mask);
+  gimple_set_location (call, gimple_location (orig));
+  gimple_call_set_nothrow (call, true);
+
+  tree scalar_type = TREE_TYPE (value);
+  tree vectype = get_vectype_for_scalar_type (vinfo, scalar_type);
+  if (vectype == NULL_TREE)
+    return NULL;
+
+  stmt_vec_info pattern_stmt_info = loop_vinfo->add_stmt (call);
+  loop_vinfo->move_dr (pattern_stmt_info, stmt_info);
+
+  loop_vinfo->predicated_index_mask_compress_scatter_store = call;
+  loop_vinfo->predicated_index_compress_scatter_ifn_p = true;
+
+  *type_out = vectype;
+  if (dump_enabled_p ())
+    dump_printf_loc (MSG_NOTE, vect_location, "%s: detected: %G",
+                    "compress_scatter", stmt_info->stmt);
+  return call;
+}
diff --git a/gcc/tree-vect-vpcompress.h b/gcc/tree-vect-vpcompress.h
index b8d0093831f..0df8bf95ce1 100644
--- a/gcc/tree-vect-vpcompress.h
+++ b/gcc/tree-vect-vpcompress.h
@@ -24,4 +24,10 @@ along with GCC; see the file COPYING3.  If not see
 extern bool vect_vpcompress_analyze_predicated_index_phi (loop_vec_info,
                                                          class loop *, gphi *);
 
+extern gimple *vect_recog_predicated_index_update_pattern (vec_info *,
+                                                          stmt_vec_info,
+                                                          tree *);
+extern gimple *vect_recog_compress_scatter_pattern (vec_info *,
+                                                   stmt_vec_info,
+                                                   tree *);
 #endif /* GCC_TREE_VECT_VPCOMPRESS_H */
diff --git a/gcc/tree-vectorizer.h b/gcc/tree-vectorizer.h
index 82c79e101d7..90d9e723ed0 100644
--- a/gcc/tree-vectorizer.h
+++ b/gcc/tree-vectorizer.h
@@ -1278,6 +1278,13 @@ public:
   /* Predicated-index PHI and matching IFN_MASK_STORE.  */
   gphi *predicated_index_phi;
   gcall *predicated_index_mask_store;
+  tree predicated_index_store_base;
+  tree predicated_index_store_scale;
+  /* Non-NULL after compress-scatter pattern installs 
IFN_MASK_COMPRESS_SCATTER_STORE.  */
+  gcall *predicated_index_mask_compress_scatter_store;
+  /* Set when pattern recog rewrites the idiom to internal functions.  */
+  bool predicated_index_update_ifn_p;
+  bool predicated_index_compress_scatter_ifn_p;
 } *loop_vec_info;
 
 /* Access Functions.  */
-- 
2.34.1

Reply via email to