aboutsummaryrefslogtreecommitdiff
path: root/gcc/internal-fn.c
diff options
context:
space:
mode:
authorRichard Sandiford <richard.sandiford@arm.com>2019-11-08 08:32:19 +0000
committerRichard Sandiford <rsandifo@gcc.gnu.org>2019-11-08 08:32:19 +0000
commit09eb042a8a8ee16e8f23085a175be25c8ef68820 (patch)
tree3642ab9cc004670e3d3e8263db46861bfc11363d /gcc/internal-fn.c
parent47cc2d4917c7cb351e561dba5768deaa2d42bf8b (diff)
downloadgcc-09eb042a8a8ee16e8f23085a175be25c8ef68820.zip
gcc-09eb042a8a8ee16e8f23085a175be25c8ef68820.tar.gz
gcc-09eb042a8a8ee16e8f23085a175be25c8ef68820.tar.bz2
Generalise gather and scatter optabs
The gather and scatter optabs required the vector offset to be the integer equivalent of the vector mode being loaded or stored. This patch generalises them so that the two vectors can have different element sizes, although they still need to have the same number of elements. One consequence of this is that it's possible (if unlikely) for two IFN_GATHER_LOADs to have the same arguments but different return types. E.g. the same scalar base and vector of 32-bit offsets could be used to load 8-bit elements and to load 16-bit elements. From just looking at the arguments, we could wrongly deduce that they're equivalent. I know we saw this happen at one point with IFN_WHILE_ULT, and we dealt with it there by passing a zero of the return type as an extra argument. Doing the same here also makes the load and store functions have the same argument assignment. For now this patch should be a no-op, but later SVE patches take advantage of the new flexibility. 2019-11-08 Richard Sandiford <richard.sandiford@arm.com> gcc/ * optabs.def (gather_load_optab, mask_gather_load_optab) (scatter_store_optab, mask_scatter_store_optab): Turn into conversion optabs, with the offset mode given explicitly. * doc/md.texi: Update accordingly. * config/aarch64/aarch64-sve-builtins-base.cc (svld1_gather_impl::expand): Likewise. (svst1_scatter_impl::expand): Likewise. * internal-fn.c (gather_load_direct, scatter_store_direct): Likewise. (expand_scatter_store_optab_fn): Likewise. (direct_gather_load_optab_supported_p): Likewise. (direct_scatter_store_optab_supported_p): Likewise. (expand_gather_load_optab_fn): Likewise. Expect the mask argument to be argument 4. (internal_fn_mask_index): Return 4 for IFN_MASK_GATHER_LOAD. (internal_gather_scatter_fn_supported_p): Replace the offset sign argument with the offset vector type. Require the two vector types to have the same number of elements but allow their element sizes to be different. Treat the optabs as conversion optabs. * internal-fn.h (internal_gather_scatter_fn_supported_p): Update prototype accordingly. * optabs-query.c (supports_at_least_one_mode_p): Replace with... (supports_vec_convert_optab_p): ...this new function. (supports_vec_gather_load_p): Update accordingly. (supports_vec_scatter_store_p): Likewise. * tree-vectorizer.h (vect_gather_scatter_fn_p): Take a vec_info. Replace the offset sign and bits parameters with a scalar type tree. * tree-vect-data-refs.c (vect_gather_scatter_fn_p): Likewise. Pass back the offset vector type instead of the scalar element type. Allow the offset to be wider than the memory elements. Search for an offset type that the target supports, stopping once we've reached the maximum of the element size and pointer size. Update call to internal_gather_scatter_fn_supported_p. (vect_check_gather_scatter): Update calls accordingly. When testing a new scale before knowing the final offset type, check whether the scale is supported for any signed or unsigned offset type. Check whether the target supports the source and target types of a conversion before deciding whether to look through the conversion. Record the chosen offset_vectype. * tree-vect-patterns.c (vect_get_gather_scatter_offset_type): Delete. (vect_recog_gather_scatter_pattern): Get the scalar offset type directly from the gs_info's offset_vectype instead. Pass a zero of the result type to IFN_GATHER_LOAD and IFN_MASK_GATHER_LOAD. * tree-vect-stmts.c (check_load_store_masking): Update call to internal_gather_scatter_fn_supported_p, passing the offset vector type recorded in the gs_info. (vect_truncate_gather_scatter_offset): Update call to vect_check_gather_scatter, leaving it to search for a valid offset vector type. (vect_use_strided_gather_scatters_p): Convert the offset to the element type of the gs_info's offset_vectype. (vect_get_gather_scatter_ops): Get the offset vector type directly from the gs_info. (vect_get_strided_load_store_ops): Likewise. (vectorizable_load): Pass a zero of the result type to IFN_GATHER_LOAD and IFN_MASK_GATHER_LOAD. * config/aarch64/aarch64-sve.md (gather_load<mode>): Rename to... (gather_load<mode><v_int_equiv>): ...this. (mask_gather_load<mode>): Rename to... (mask_gather_load<mode><v_int_equiv>): ...this. (scatter_store<mode>): Rename to... (scatter_store<mode><v_int_equiv>): ...this. (mask_scatter_store<mode>): Rename to... (mask_scatter_store<mode><v_int_equiv>): ...this. From-SVN: r277949
Diffstat (limited to 'gcc/internal-fn.c')
-rw-r--r--gcc/internal-fn.c41
1 files changed, 22 insertions, 19 deletions
diff --git a/gcc/internal-fn.c b/gcc/internal-fn.c
index 549d6f1..6a878bd 100644
--- a/gcc/internal-fn.c
+++ b/gcc/internal-fn.c
@@ -103,11 +103,11 @@ init_internal_fns ()
#define mask_load_direct { -1, 2, false }
#define load_lanes_direct { -1, -1, false }
#define mask_load_lanes_direct { -1, -1, false }
-#define gather_load_direct { -1, -1, false }
+#define gather_load_direct { 3, 1, false }
#define mask_store_direct { 3, 2, false }
#define store_lanes_direct { 0, 0, false }
#define mask_store_lanes_direct { 0, 0, false }
-#define scatter_store_direct { 3, 3, false }
+#define scatter_store_direct { 3, 1, false }
#define unary_direct { 0, 0, true }
#define binary_direct { 0, 0, true }
#define ternary_direct { 0, 0, true }
@@ -2785,7 +2785,8 @@ expand_scatter_store_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
}
- insn_code icode = direct_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)));
+ insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (rhs)),
+ TYPE_MODE (TREE_TYPE (offset)));
expand_insn (icode, i, ops);
}
@@ -2813,11 +2814,12 @@ expand_gather_load_optab_fn (internal_fn, gcall *stmt, direct_optab optab)
create_integer_operand (&ops[i++], scale_int);
if (optab == mask_gather_load_optab)
{
- tree mask = gimple_call_arg (stmt, 3);
+ tree mask = gimple_call_arg (stmt, 4);
rtx mask_rtx = expand_normal (mask);
create_input_operand (&ops[i++], mask_rtx, TYPE_MODE (TREE_TYPE (mask)));
}
- insn_code icode = direct_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)));
+ insn_code icode = convert_optab_handler (optab, TYPE_MODE (TREE_TYPE (lhs)),
+ TYPE_MODE (TREE_TYPE (offset)));
expand_insn (icode, i, ops);
}
@@ -3084,11 +3086,11 @@ multi_vector_optab_supported_p (convert_optab optab, tree_pair types,
#define direct_mask_load_optab_supported_p direct_optab_supported_p
#define direct_load_lanes_optab_supported_p multi_vector_optab_supported_p
#define direct_mask_load_lanes_optab_supported_p multi_vector_optab_supported_p
-#define direct_gather_load_optab_supported_p direct_optab_supported_p
+#define direct_gather_load_optab_supported_p convert_optab_supported_p
#define direct_mask_store_optab_supported_p direct_optab_supported_p
#define direct_store_lanes_optab_supported_p multi_vector_optab_supported_p
#define direct_mask_store_lanes_optab_supported_p multi_vector_optab_supported_p
-#define direct_scatter_store_optab_supported_p direct_optab_supported_p
+#define direct_scatter_store_optab_supported_p convert_optab_supported_p
#define direct_while_optab_supported_p convert_optab_supported_p
#define direct_fold_extract_optab_supported_p direct_optab_supported_p
#define direct_fold_left_optab_supported_p direct_optab_supported_p
@@ -3513,8 +3515,6 @@ internal_fn_mask_index (internal_fn fn)
return 2;
case IFN_MASK_GATHER_LOAD:
- return 3;
-
case IFN_MASK_SCATTER_STORE:
return 4;
@@ -3546,27 +3546,30 @@ internal_fn_stored_value_index (internal_fn fn)
IFN. For loads, VECTOR_TYPE is the vector type of the load result,
while for stores it is the vector type of the stored data argument.
MEMORY_ELEMENT_TYPE is the type of the memory elements being loaded
- or stored. OFFSET_SIGN is the sign of the offset argument, which is
- only relevant when the offset is narrower than an address. SCALE is
- the amount by which the offset should be multiplied *after* it has
- been extended to address width. */
+ or stored. OFFSET_VECTOR_TYPE is the vector type that holds the
+ offset from the shared base address of each loaded or stored element.
+ SCALE is the amount by which these offsets should be multiplied
+ *after* they have been extended to address width. */
bool
internal_gather_scatter_fn_supported_p (internal_fn ifn, tree vector_type,
tree memory_element_type,
- signop offset_sign, int scale)
+ tree offset_vector_type, int scale)
{
if (!tree_int_cst_equal (TYPE_SIZE (TREE_TYPE (vector_type)),
TYPE_SIZE (memory_element_type)))
return false;
+ if (maybe_ne (TYPE_VECTOR_SUBPARTS (vector_type),
+ TYPE_VECTOR_SUBPARTS (offset_vector_type)))
+ return false;
optab optab = direct_internal_fn_optab (ifn);
- insn_code icode = direct_optab_handler (optab, TYPE_MODE (vector_type));
+ insn_code icode = convert_optab_handler (optab, TYPE_MODE (vector_type),
+ TYPE_MODE (offset_vector_type));
int output_ops = internal_load_fn_p (ifn) ? 1 : 0;
+ bool unsigned_p = TYPE_UNSIGNED (TREE_TYPE (offset_vector_type));
return (icode != CODE_FOR_nothing
- && insn_operand_matches (icode, 2 + output_ops,
- GEN_INT (offset_sign == UNSIGNED))
- && insn_operand_matches (icode, 3 + output_ops,
- GEN_INT (scale)));
+ && insn_operand_matches (icode, 2 + output_ops, GEN_INT (unsigned_p))
+ && insn_operand_matches (icode, 3 + output_ops, GEN_INT (scale)));
}
/* Expand STMT as though it were a call to internal function FN. */