On Tue, 30 Jun 2026, Raghesh Aloor wrote:
> 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.
IFNs need documenting in ifns.texi, I suppose you want corresponding
optabs as well. I assume the IFN expanders will go away or be
direct optab expanders.
> ---
> 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. */
>
--
Richard Biener <[email protected]>
SUSE Software Solutions Germany GmbH,
Frankenstrasse 146, 90461 Nuernberg, Germany;
GF: Jochen Jaser, Andrew McDonald; (HRB 36809, AG Nuernberg)