[AArch64] Add support for arm_sve.h
authorRichard Sandiford <richard.sandiford@arm.com>
Tue, 29 Oct 2019 08:58:41 +0000 (08:58 +0000)
committerRichard Sandiford <rsandifo@gcc.gnu.org>
Tue, 29 Oct 2019 08:58:41 +0000 (08:58 +0000)
This patch adds support for arm_sve.h.  I've tried to split all the
groundwork out into separate patches, so this is mostly adding new code
rather than changing existing code.

The C++ frontend seems to handle correct ACLE code without modification,
even in length-agnostic mode.  The C frontend is close; the only correct
construct I know it doesn't handle is initialisation.  E.g.:

  svbool_t pg = svptrue_b8 ();

produces:

  variable-sized object may not be initialized

although:

  svbool_t pg; pg = svptrue_b8 ();

works fine.  This can be fixed by changing:

    {
      /* A complete type is ok if size is fixed.  */

-     if (TREE_CODE (TYPE_SIZE (TREE_TYPE (decl))) != INTEGER_CST
+     if (!poly_int_tree_p (TYPE_SIZE (TREE_TYPE (decl)))
  || C_DECL_VARIABLE_SIZE (decl))
        {
  error ("variable-sized object may not be initialized");

in c/c-decl.c:start_decl.

Invalid code is likely to trigger ICEs, so this isn't ready for general
use yet.  However, it seemed better to apply the patch now and deal with
diagnosing invalid code as a follow-up.  For one thing, it means that
we'll be able to provide testcases for middle-end changes related
to SVE vectors, which has been a problem until now.  (I already have
a series of such patches lined up.)

The patch includes some tests, but the main ones need to wait until the
PCS support has been applied.

2019-10-29  Richard Sandiford  <richard.sandiford@arm.com>
    Kugan Vivekanandarajah  <kugan.vivekanandarajah@linaro.org>
    Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>

gcc/
* config.gcc (aarch64*-*-*): Add arm_sve.h to extra_headers.
Add aarch64-sve-builtins.o, aarch64-sve-builtins-shapes.o and
aarch64-sve-builtins-base.o to extra_objs.  Add
aarch64-sve-builtins.h and aarch64-sve-builtins.cc to target_gtfiles.
* config/aarch64/t-aarch64 (aarch64-sve-builtins.o): New rule.
(aarch64-sve-builtins-shapes.o): Likewise.
(aarch64-sve-builtins-base.o): New rules.
* config/aarch64/aarch64-c.c (aarch64_pragma_aarch64): New function.
(aarch64_resolve_overloaded_builtin): Likewise.
(aarch64_check_builtin_call): Likewise.
(aarch64_register_pragmas): Install aarch64_resolve_overloaded_builtin
and aarch64_check_builtin_call in targetm.  Register the GCC aarch64
pragma.
* config/aarch64/aarch64-protos.h (AARCH64_FOR_SVPRFOP): New macro.
(aarch64_svprfop): New enum.
(AARCH64_BUILTIN_SVE): New aarch64_builtin_class enum value.
(aarch64_sve_int_mode, aarch64_sve_data_mode): Declare.
(aarch64_fold_sve_cnt_pat, aarch64_output_sve_prefetch): Likewise.
(aarch64_output_sve_cnt_pat_immediate): Likewise.
(aarch64_output_sve_ptrues, aarch64_sve_ptrue_svpattern_p): Likewise.
(aarch64_sve_sqadd_sqsub_immediate_p, aarch64_sve_ldff1_operand_p)
(aarch64_sve_ldnf1_operand_p, aarch64_sve_prefetch_operand_p)
(aarch64_ptrue_all_mode, aarch64_convert_sve_data_to_pred): Likewise.
(aarch64_expand_sve_dupq, aarch64_replace_reg_mode): Likewise.
(aarch64_sve::init_builtins, aarch64_sve::handle_arm_sve_h): Likewise.
(aarch64_sve::builtin_decl, aarch64_sve::builtin_type_p): Likewise.
(aarch64_sve::mangle_builtin_type): Likewise.
(aarch64_sve::resolve_overloaded_builtin): Likewise.
(aarch64_sve::check_builtin_call, aarch64_sve::gimple_fold_builtin)
(aarch64_sve::expand_builtin): Likewise.
* config/aarch64/aarch64.c (aarch64_sve_data_mode): Make public.
(aarch64_sve_int_mode): Likewise.
(aarch64_ptrue_all_mode): New function.
(aarch64_convert_sve_data_to_pred): Make public.
(svprfop_token): New function.
(aarch64_output_sve_prefetch): Likewise.
(aarch64_fold_sve_cnt_pat): Likewise.
(aarch64_output_sve_cnt_pat_immediate): Likewise.
(aarch64_sve_move_pred_via_while): Use gen_while with UNSPEC_WHILE_LO
instead of gen_while_ult.
(aarch64_replace_reg_mode): Make public.
(aarch64_init_builtins): Call aarch64_sve::init_builtins.
(aarch64_fold_builtin): Handle AARCH64_BUILTIN_SVE.
(aarch64_gimple_fold_builtin, aarch64_expand_builtin): Likewise.
(aarch64_builtin_decl, aarch64_builtin_reciprocal): Likewise.
(aarch64_mangle_type): Call aarch64_sve::mangle_type.
(aarch64_sve_sqadd_sqsub_immediate_p): New function.
(aarch64_sve_ptrue_svpattern_p): Likewise.
(aarch64_sve_pred_valid_immediate): Check
aarch64_sve_ptrue_svpattern_p.
(aarch64_sve_ldff1_operand_p, aarch64_sve_ldnf1_operand_p)
(aarch64_sve_prefetch_operand_p, aarch64_output_sve_ptrues): New
functions.
* config/aarch64/aarch64.md (UNSPEC_LDNT1_SVE, UNSPEC_STNT1_SVE)
(UNSPEC_LDFF1_GATHER, UNSPEC_PTRUE, UNSPEC_WHILE_LE, UNSPEC_WHILE_LS)
(UNSPEC_WHILE_LT, UNSPEC_CLASTA, UNSPEC_UPDATE_FFR)
(UNSPEC_UPDATE_FFRT, UNSPEC_RDFFR, UNSPEC_WRFFR)
(UNSPEC_SVE_LANE_SELECT, UNSPEC_SVE_CNT_PAT, UNSPEC_SVE_PREFETCH)
(UNSPEC_SVE_PREFETCH_GATHER, UNSPEC_SVE_COMPACT, UNSPEC_SVE_SPLICE):
New unspecs.
* config/aarch64/iterators.md (SI_ONLY, DI_ONLY, VNx8HI_ONLY)
(VNx2DI_ONLY, SVE_PARTIAL, VNx8_NARROW, VNx8_WIDE, VNx4_NARROW)
(VNx4_WIDE, VNx2_NARROW, VNx2_WIDE, PRED_HSD): New mode iterators.
(UNSPEC_ADR, UNSPEC_BRKA, UNSPEC_BRKB, UNSPEC_BRKN, UNSPEC_BRKPA)
(UNSPEC_BRKPB, UNSPEC_PFIRST, UNSPEC_PNEXT, UNSPEC_CNTP, UNSPEC_SADDV)
(UNSPEC_UADDV, UNSPEC_FMLA, UNSPEC_FMLS, UNSPEC_FEXPA, UNSPEC_FTMAD)
(UNSPEC_FTSMUL, UNSPEC_FTSSEL, UNSPEC_COND_CMPEQ_WIDE): New unspecs.
(UNSPEC_COND_CMPGE_WIDE, UNSPEC_COND_CMPGT_WIDE): Likewise.
(UNSPEC_COND_CMPHI_WIDE, UNSPEC_COND_CMPHS_WIDE): Likewise.
(UNSPEC_COND_CMPLE_WIDE, UNSPEC_COND_CMPLO_WIDE): Likewise.
(UNSPEC_COND_CMPLS_WIDE, UNSPEC_COND_CMPLT_WIDE): Likewise.
(UNSPEC_COND_CMPNE_WIDE, UNSPEC_COND_FCADD90, UNSPEC_COND_FCADD270)
(UNSPEC_COND_FCMLA, UNSPEC_COND_FCMLA90, UNSPEC_COND_FCMLA180)
(UNSPEC_COND_FCMLA270, UNSPEC_COND_FMAX, UNSPEC_COND_FMIN): Likewise.
(UNSPEC_COND_FMULX, UNSPEC_COND_FRECPX, UNSPEC_COND_FSCALE): Likewise.
(UNSPEC_LASTA, UNSPEC_ASHIFT_WIDE, UNSPEC_ASHIFTRT_WIDE): Likewise.
(UNSPEC_LSHIFTRT_WIDE, UNSPEC_LDFF1, UNSPEC_LDNF1): Likewise.
(Vesize): Handle partial vector modes.
(self_mask, narrower_mask, sve_lane_con, sve_lane_pair_con): New
mode attributes.
(UBINQOPS, ANY_PLUS, SAT_PLUS, ANY_MINUS, SAT_MINUS): New code
iterators.
(s, paired_extend, inc_dec): New code attributes.
(SVE_INT_ADDV, CLAST, LAST): New int iterators.
(SVE_INT_UNARY): Add UNSPEC_RBIT.
(SVE_FP_UNARY, SVE_FP_UNARY_INT): New int iterators.
(SVE_FP_BINARY, SVE_FP_BINARY_INT): Likewise.
(SVE_COND_FP_UNARY): Add UNSPEC_COND_FRECPX.
(SVE_COND_FP_BINARY): Add UNSPEC_COND_FMAX, UNSPEC_COND_FMIN and
UNSPEC_COND_FMULX.
(SVE_COND_FP_BINARY_INT, SVE_COND_FP_ADD): New int iterators.
(SVE_COND_FP_SUB, SVE_COND_FP_MUL): Likewise.
(SVE_COND_FP_BINARY_I1): Add UNSPEC_COND_FMAX and UNSPEC_COND_FMIN.
(SVE_COND_FP_BINARY_REG): Add UNSPEC_COND_FMULX.
(SVE_COND_FCADD, SVE_COND_FP_MAXMIN, SVE_COND_FCMLA)
(SVE_COND_INT_CMP_WIDE, SVE_FP_TERNARY_LANE, SVE_CFP_TERNARY_LANE)
(SVE_WHILE, SVE_SHIFT_WIDE, SVE_LDFF1_LDNF1, SVE_BRK_UNARY)
(SVE_BRK_BINARY, SVE_PITER): New int iterators.
(optab): Handle UNSPEC_SADDV, UNSPEC_UADDV, UNSPEC_FRECPE,
UNSPEC_FRECPS, UNSPEC_RSQRTE, UNSPEC_RSQRTS, UNSPEC_RBIT,
UNSPEC_SMUL_HIGHPART, UNSPEC_UMUL_HIGHPART, UNSPEC_FMLA, UNSPEC_FMLS,
UNSPEC_FCMLA, UNSPEC_FCMLA90, UNSPEC_FCMLA180, UNSPEC_FCMLA270,
UNSPEC_FEXPA, UNSPEC_FTSMUL, UNSPEC_FTSSEL, UNSPEC_COND_FCADD90,
UNSPEC_COND_FCADD270, UNSPEC_COND_FCMLA, UNSPEC_COND_FCMLA90,
UNSPEC_COND_FCMLA180, UNSPEC_COND_FCMLA270, UNSPEC_COND_FMAX,
UNSPEC_COND_FMIN, UNSPEC_COND_FMULX, UNSPEC_COND_FRECPX and
UNSPEC_COND_FSCALE.
(maxmin_uns): Handle UNSPEC_COND_FMAX and UNSPEC_COND_FMIN.
(binqops_op, binqops_op_rev, last_op): New int attributes.
(su): Handle UNSPEC_SADDV and UNSPEC_UADDV.
(fn, ab): New int attributes.
(cmp_op): Handle UNSPEC_COND_CMP*_WIDE and UNSPEC_WHILE_*.
(while_optab_cmp, brk_op, sve_pred_op): New int attributes.
(sve_int_op): Handle UNSPEC_SMUL_HIGHPART, UNSPEC_UMUL_HIGHPART,
UNSPEC_ASHIFT_WIDE, UNSPEC_ASHIFTRT_WIDE, UNSPEC_LSHIFTRT_WIDE and
UNSPEC_RBIT.
(sve_fp_op): Handle UNSPEC_FRECPE, UNSPEC_FRECPS, UNSPEC_RSQRTE,
UNSPEC_RSQRTS, UNSPEC_FMLA, UNSPEC_FMLS, UNSPEC_FEXPA, UNSPEC_FTSMUL,
UNSPEC_FTSSEL, UNSPEC_COND_FMAX, UNSPEC_COND_FMIN, UNSPEC_COND_FMULX,
UNSPEC_COND_FRECPX and UNSPEC_COND_FSCALE.
(sve_fp_op_rev): Handle UNSPEC_COND_FMAX, UNSPEC_COND_FMIN and
UNSPEC_COND_FMULX.
(rot): Handle UNSPEC_COND_FCADD* and UNSPEC_COND_FCMLA*.
(brk_reg_con, brk_reg_opno): New int attributes.
(sve_pred_fp_rhs1_operand, sve_pred_fp_rhs2_operand): Handle
UNSPEC_COND_FMAX, UNSPEC_COND_FMIN and UNSPEC_COND_FMULX.
(sve_pred_fp_rhs2_immediate): Handle UNSPEC_COND_FMAX and
UNSPEC_COND_FMIN.
(max_elem_bits): New int attribute.
(min_elem_bits): Handle UNSPEC_RBIT.
* config/aarch64/predicates.md (subreg_lowpart_operator): Handle
TRUNCATE as well as SUBREG.
(ascending_int_parallel, aarch64_simd_reg_or_minus_one)
(aarch64_sve_ldff1_operand, aarch64_sve_ldnf1_operand)
(aarch64_sve_prefetch_operand, aarch64_sve_ptrue_svpattern_immediate)
(aarch64_sve_qadd_immediate, aarch64_sve_qsub_immediate)
(aarch64_sve_gather_immediate_b, aarch64_sve_gather_immediate_h)
(aarch64_sve_gather_immediate_w, aarch64_sve_gather_immediate_d)
(aarch64_sve_sqadd_operand, aarch64_sve_gather_offset_b)
(aarch64_sve_gather_offset_h, aarch64_sve_gather_offset_w)
(aarch64_sve_gather_offset_d, aarch64_gather_scale_operand_b)
(aarch64_gather_scale_operand_h): New predicates.
* config/aarch64/constraints.md (UPb, UPd, UPh, UPw, Utf, Utn, vgb)
(vgd, vgh, vgw, vsQ, vsS): New constraints.
* config/aarch64/aarch64-sve.md: Add a note on the FFR handling.
(*aarch64_sve_reinterpret<mode>): Allow any source register
instead of requiring an exact match.
(*aarch64_sve_ptruevnx16bi_cc, *aarch64_sve_ptrue<mode>_cc)
(*aarch64_sve_ptruevnx16bi_ptest, *aarch64_sve_ptrue<mode>_ptest)
(aarch64_wrffr, aarch64_update_ffr_for_load, aarch64_copy_ffr_to_ffrt)
(aarch64_rdffr, aarch64_rdffr_z, *aarch64_rdffr_z_ptest)
(*aarch64_rdffr_ptest, *aarch64_rdffr_z_cc, *aarch64_rdffr_cc)
(aarch64_update_ffrt): New patterns.
(@aarch64_load_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>)
(@aarch64_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
(@aarch64_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
(@aarch64_ld<fn>f1<mode>): New patterns.
(@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>)
(@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
(@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
(@aarch64_ldnt1<mode>): New patterns.
(gather_load<mode>): Use aarch64_sve_gather_offset_<Vesize> for
the scalar part of the address.
(mask_gather_load<SVE_S:mode>): Use aarch64_sve_gather_offset_w for the
scalar part of the addresse and add an alternative for handling
nonzero offsets.
(mask_gather_load<SVE_D:mode>): Likewise aarch64_sve_gather_offset_d.
(*mask_gather_load<mode>_sxtw, *mask_gather_load<mode>_uxtw)
(@aarch64_gather_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
(@aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
(*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw)
(*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw)
(@aarch64_ldff1_gather<SVE_S:mode>, @aarch64_ldff1_gather<SVE_D:mode>)
(*aarch64_ldff1_gather<mode>_sxtw, *aarch64_ldff1_gather<mode>_uxtw)
(@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
(@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
(*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw)
(*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw)
(@aarch64_sve_prefetch<mode>): New patterns.
(@aarch64_sve_gather_prefetch<SVE_I:mode><VNx4SI_ONLY:mode>)
(@aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>)
(*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_sxtw)
(*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_uxtw)
(@aarch64_store_trunc<VNx8_NARROW:mode><VNx8_WIDE:mode>)
(@aarch64_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>)
(@aarch64_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>)
(@aarch64_stnt1<mode>): New patterns.
(scatter_store<mode>): Use aarch64_sve_gather_offset_<Vesize> for
the scalar part of the address.
(mask_scatter_store<SVE_S:mode>): Use aarch64_sve_gather_offset_w for
the scalar part of the addresse and add an alternative for handling
nonzero offsets.
(mask_scatter_store<SVE_D:mode>): Likewise aarch64_sve_gather_offset_d.
(*mask_scatter_store<mode>_sxtw, *mask_scatter_store<mode>_uxtw)
(@aarch64_scatter_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>)
(@aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>)
(*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_sxtw)
(*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_uxtw):
New patterns.
(vec_duplicate<mode>): Use QI as the mode of the input operand.
(extract_last_<mode>): Generalize to...
(@extract_<LAST:last_op>_<mode>): ...this.
(*<SVE_INT_UNARY:optab><mode>2): Rename to...
(@aarch64_pred_<SVE_INT_UNARY:optab><mode>): ...this.
(@cond_<SVE_INT_UNARY:optab><mode>): New expander.
(@aarch64_pred_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>): New pattern.
(@aarch64_cond_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>): Likewise.
(@aarch64_pred_cnot<mode>, @cond_cnot<mode>): New expanders.
(@aarch64_sve_<SVE_FP_UNARY_INT:optab><mode>): New pattern.
(@aarch64_sve_<SVE_FP_UNARY:optab><mode>): Likewise.
(*<SVE_COND_FP_UNARY:optab><mode>2): Rename to...
(@aarch64_pred_<SVE_COND_FP_UNARY:optab><mode>): ...this.
(@cond_<SVE_COND_FP_UNARY:optab><mode>): New expander.
(*<SVE_INT_BINARY_IMM:optab><mode>3): Rename to...
(@aarch64_pred_<SVE_INT_BINARY_IMM:optab><mode>): ...this.
(@aarch64_adr<mode>, *aarch64_adr_sxtw): New patterns.
(*aarch64_adr_uxtw_unspec): Likewise.
(*aarch64_adr_uxtw): Rename to...
(*aarch64_adr_uxtw_and): ...this.
(@aarch64_adr<mode>_shift): New expander.
(*aarch64_adr_shift_sxtw): New pattern.
(aarch64_<su>abd<mode>_3): Rename to...
(@aarch64_pred_<su>abd<mode>): ...this.
(<su>abd<mode>_3): Update accordingly.
(@aarch64_cond_<su>abd<mode>): New expander.
(@aarch64_<SBINQOPS:su_optab><optab><mode>): New pattern.
(@aarch64_<UBINQOPS:su_optab><optab><mode>): Likewise.
(*<su>mul<mode>3_highpart): Rename to...
(@aarch64_pred_<optab><mode>): ...this.
(@cond_<MUL_HIGHPART:optab><mode>): New expander.
(*cond_<MUL_HIGHPART:optab><mode>_2): New pattern.
(*cond_<MUL_HIGHPART:optab><mode>_z): Likewise.
(*<SVE_INT_BINARY_SD:optab><mode>3): Rename to...
(@aarch64_pred_<SVE_INT_BINARY_SD:optab><mode>): ...this.
(cond_<SVE_INT_BINARY_SD:optab><mode>): Add a "@" marker.
(@aarch64_bic<mode>, @cond_bic<mode>): New expanders.
(*v<ASHIFT:optab><mode>3): Rename to...
(@aarch64_pred_<ASHIFT:optab><mode>): ...this.
(@aarch64_sve_<SVE_SHIFT_WIDE:sve_int_op><mode>): New pattern.
(@cond_<SVE_SHIFT_WIDE:sve_int_op><mode>): New expander.
(*cond_<SVE_SHIFT_WIDE:sve_int_op><mode>_m): New pattern.
(*cond_<SVE_SHIFT_WIDE:sve_int_op><mode>_z): Likewise.
(@cond_asrd<mode>): New expander.
(*cond_asrd<mode>_2, *cond_asrd<mode>_z): New patterns.
(sdiv_pow2<mode>3): Expand to *cond_asrd<mode>_2.
(*sdiv_pow2<mode>3): Delete.
(@cond_<SVE_COND_FP_BINARY_INT:optab><mode>): New expander.
(*cond_<SVE_COND_FP_BINARY_INT:optab><mode>_2): New pattern.
(*cond_<SVE_COND_FP_BINARY_INT:optab><mode>_any): Likewise.
(@aarch64_sve_<SVE_FP_BINARY:optab><mode>): New pattern.
(@aarch64_sve_<SVE_FP_BINARY_INT:optab><mode>): Likewise.
(*<SVE_COND_FP_BINARY_REG:optab><mode>3): Rename to...
(@aarch64_pred_<SVE_COND_FP_BINARY_REG:optab><mode>): ...this.
(@aarch64_pred_<SVE_COND_FP_BINARY_INT:optab><mode>): New pattern.
(cond_<SVE_COND_FP_BINARY:optab><mode>): Add a "@" marker.
(*add<SVE_F:mode>3): Rename to...
(@aarch64_pred_add<SVE_F:mode>): ...this and add alternatives
for SVE_STRICT_GP.
(@aarch64_pred_<SVE_COND_FCADD:optab><mode>): New pattern.
(@cond_<SVE_COND_FCADD:optab><mode>): New expander.
(*cond_<SVE_COND_FCADD:optab><mode>_2): New pattern.
(*cond_<SVE_COND_FCADD:optab><mode>_any): Likewise.
(*sub<SVE_F:mode>3): Rename to...
(@aarch64_pred_sub<SVE_F:mode>): ...this and add alternatives
for SVE_STRICT_GP.
(@aarch64_pred_abd<SVE_F:mode>): New expander.
(*fabd<SVE_F:mode>3): Rename to...
(*aarch64_pred_abd<SVE_F:mode>): ...this.
(@aarch64_cond_abd<SVE_F:mode>): New expander.
(*mul<SVE_F:mode>3): Rename to...
(@aarch64_pred_<SVE_F:optab><mode>): ...this and add alternatives
for SVE_STRICT_GP.
(@aarch64_mul_lane_<SVE_F:mode>): New pattern.
(*<SVE_COND_FP_MAXMIN_PUBLIC:optab><mode>3): Rename and generalize
to...
(@aarch64_pred_<SVE_COND_FP_MAXMIN:optab><mode>): ...this.
(*<LOGICAL:optab><PRED_ALL:mode>3_ptest): New pattern.
(*<nlogical><PRED_ALL:mode>3): Rename to...
(aarch64_pred_<nlogical><PRED_ALL:mode>_z): ...this.
(*<nlogical><PRED_ALL:mode>3_cc): New pattern.
(*<nlogical><PRED_ALL:mode>3_ptest): Likewise.
(*<logical_nn><PRED_ALL:mode>3): Rename to...
(aarch64_pred_<logical_nn><mode>_z): ...this.
(*<logical_nn><PRED_ALL:mode>3_cc): New pattern.
(*<logical_nn><PRED_ALL:mode>3_ptest): Likewise.
(*fma<SVE_I:mode>4): Rename to...
(@aarch64_pred_fma<SVE_I:mode>): ...this.
(*fnma<SVE_I:mode>4): Rename to...
(@aarch64_pred_fnma<SVE_I:mode>): ...this.
(@aarch64_<sur>dot_prod_lane<vsi2qi>): New pattern.
(*<SVE_FP_TERNARY:optab><mode>4): Rename to...
(@aarch64_pred_<SVE_FP_TERNARY:optab><mode>): ...this.
(cond_<SVE_FP_TERNARY:optab><mode>): Add a "@" marker.
(@aarch64_<SVE_FP_TERNARY_LANE:optab>_lane_<mode>): New pattern.
(@aarch64_pred_<SVE_COND_FCMLA:optab><mode>): Likewise.
(@cond_<SVE_COND_FCMLA:optab><mode>): New expander.
(*cond_<SVE_COND_FCMLA:optab><mode>_4): New pattern.
(*cond_<SVE_COND_FCMLA:optab><mode>_any): Likewise.
(@aarch64_<FCMLA:optab>_lane_<mode>): Likewise.
(@aarch64_sve_tmad<mode>): Likewise.
(vcond_mask_<SVE_ALL:mode><vpred>): Add a "@" marker.
(*aarch64_sel_dup<mode>): Rename to...
(@aarch64_sel_dup<mode>): ...this.
(@aarch64_pred_cmp<cmp_op><SVE_I:mode>_wide): New pattern.
(*aarch64_pred_cmp<cmp_op><SVE_I:mode>_wide_cc): Likewise.
(*aarch64_pred_cmp<cmp_op><SVE_I:mode>_wide_ptest): Likewise.
(@while_ult<GPI:mode><PRED_ALL:mode>): Generalize to...
(@while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>): ...this.
(*while_ult<GPI:mode><PRED_ALL:mode>_cc): Generalize to.
(*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_cc): ...this.
(*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_ptest): New pattern.
(*fcm<cmp_op><mode>): Rename to...
(@aarch64_pred_fcm<cmp_op><mode>): ...this.  Make operand order
match @aarch64_pred_cmp<cmp_op><SVE_I:mode>.
(*fcmuo<mode>): Rename to...
(@aarch64_pred_fcmuo<mode>): ...this.  Make operand order
match @aarch64_pred_cmp<cmp_op><SVE_I:mode>.
(@aarch64_pred_fac<cmp_op><mode>): New expander.
(@vcond_mask_<PRED_ALL:mode><mode>): New pattern.
(fold_extract_last_<mode>): Generalize to...
(@fold_extract_<last_op>_<mode>): ...this.
(@aarch64_fold_extract_vector_<last_op>_<mode>): New pattern.
(*reduc_plus_scal_<SVE_I:mode>): Replace with...
(@aarch64_pred_reduc_<optab>_<mode>): ...this pattern, making the
DImode result explicit.
(reduc_plus_scal_<mode>): Update accordingly.
(*reduc_<optab>_scal_<SVE_I:mode>): Rename to...
(@aarch64_pred_reduc_<optab>_<SVE_I:mode>): ...this.
(*reduc_<optab>_scal_<SVE_F:mode>): Rename to...
(@aarch64_pred_reduc_<optab>_<SVE_F:mode>): ...this.
(*aarch64_sve_tbl<mode>): Rename to...
(@aarch64_sve_tbl<mode>): ...this.
(@aarch64_sve_compact<mode>): New pattern.
(*aarch64_sve_dup_lane<mode>): Rename to...
(@aarch64_sve_dup_lane<mode>): ...this.
(@aarch64_sve_dupq_lane<mode>): New pattern.
(@aarch64_sve_splice<mode>): Likewise.
(aarch64_sve_<perm_insn><mode>): Rename to...
(@aarch64_sve_<perm_insn><mode>): ...this.
(*aarch64_sve_ext<mode>): Rename to...
(@aarch64_sve_ext<mode>): ...this.
(aarch64_sve_<su>unpk<perm_hilo>_<SVE_BHSI:mode>): Add a "@" marker.
(*aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>): Rename
to...
(@aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>): ...this.
(*aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>):
Rename to...
(@aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>):
...this.
(@cond_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>): New expander.
(@cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>): Likewise.
(*cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>): New pattern.
(*aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>): Rename
to...
(@aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>): ...this.
(aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>): Add
a "@" marker.
(@cond_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>): New expander.
(@cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>): Likewise.
(*cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>): New
pattern.
(*aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): Rename to...
(@aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): ...this.
(@cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): New expander.
(*cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): New pattern.
(aarch64_sve_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>): Add a
"@" marker.
(@cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>): New expander.
(*cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>): New pattern.
(aarch64_sve_punpk<perm_hilo>_<mode>): Add a "@" marker.
(@aarch64_brk<SVE_BRK_UNARY:brk_op>): New pattern.
(*aarch64_brk<SVE_BRK_UNARY:brk_op>_cc): Likewise.
(*aarch64_brk<SVE_BRK_UNARY:brk_op>_ptest): Likewise.
(@aarch64_brk<SVE_BRK_BINARY:brk_op>): Likewise.
(*aarch64_brk<SVE_BRK_BINARY:brk_op>_cc): Likewise.
(*aarch64_brk<SVE_BRK_BINARY:brk_op>_ptest): Likewise.
(@aarch64_sve_<SVE_PITER:sve_pred_op><mode>): Likewise.
(*aarch64_sve_<SVE_PITER:sve_pred_op><mode>_cc): Likewise.
(*aarch64_sve_<SVE_PITER:sve_pred_op><mode>_ptest): Likewise.
(aarch64_sve_cnt_pat): Likewise.
(@aarch64_sve_<ANY_PLUS:inc_dec><DI_ONLY:mode>_pat): Likewise.
(*aarch64_sve_incsi_pat): Likewise.
(@aarch64_sve_<SAT_PLUS:inc_dec><SI_ONLY:mode>_pat): Likewise.
(@aarch64_sve_<ANY_PLUS:inc_dec><VNx2DI_ONLY:mode>_pat): Likewise.
(@aarch64_sve_<ANY_PLUS:inc_dec><VNx4SI_ONLY:mode>_pat): Likewise.
(@aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_pat): New expander.
(*aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_pat): New pattern.
(@aarch64_sve_<ANY_MINUS:inc_dec><DI_ONLY:mode>_pat): Likewise.
(*aarch64_sve_decsi_pat): Likewise.
(@aarch64_sve_<SAT_MINUS:inc_dec><SI_ONLY:mode>_pat): Likewise.
(@aarch64_sve_<ANY_MINUS:inc_dec><VNx2DI_ONLY:mode>_pat): Likewise.
(@aarch64_sve_<ANY_MINUS:inc_dec><VNx4SI_ONLY:mode>_pat): Likewise.
(@aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_pat): New expander.
(*aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_pat): New pattern.
(@aarch64_pred_cntp<mode>): Likewise.
(@aarch64_sve_<ANY_PLUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp):
New expander.
(*aarch64_sve_<ANY_PLUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp)
(*aarch64_incsi<PRED_ALL:mode>_cntp): New patterns.
(@aarch64_sve_<SAT_PLUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
New expander.
(*aarch64_sve_<SAT_PLUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
New pattern.
(@aarch64_sve_<ANY_PLUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New expander.
(*aarch64_sve_<ANY_PLUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New pattern.
(@aarch64_sve_<ANY_PLUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New expander.
(*aarch64_sve_<ANY_PLUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New pattern.
(@aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New expander.
(*aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New pattern.
(@aarch64_sve_<ANY_MINUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp):
New expander.
(*aarch64_sve_<ANY_MINUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp)
(*aarch64_incsi<PRED_ALL:mode>_cntp): New patterns.
(@aarch64_sve_<SAT_MINUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
New expander.
(*aarch64_sve_<SAT_MINUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
New pattern.
(@aarch64_sve_<ANY_MINUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New
expander.
(*aarch64_sve_<ANY_MINUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New pattern.
(@aarch64_sve_<ANY_MINUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New
expander.
(*aarch64_sve_<ANY_MINUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New pattern.
(@aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New
expander.
(*aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New pattern.
* config/aarch64/arm_sve.h: New file.
* config/aarch64/aarch64-sve-builtins.h: Likewise.
* config/aarch64/aarch64-sve-builtins.cc: Likewise.
* config/aarch64/aarch64-sve-builtins.def: Likewise.
* config/aarch64/aarch64-sve-builtins-base.h: Likewise.
* config/aarch64/aarch64-sve-builtins-base.cc: Likewise.
* config/aarch64/aarch64-sve-builtins-base.def: Likewise.
* config/aarch64/aarch64-sve-builtins-functions.h: Likewise.
* config/aarch64/aarch64-sve-builtins-shapes.h: Likewise.
* config/aarch64/aarch64-sve-builtins-shapes.cc: Likewise.

gcc/testsuite/
* g++.target/aarch64/sve/acle/aarch64-sve-acle.exp: New file.
* g++.target/aarch64/sve/acle/general-c++: New test directory.
* gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp: New file.
* gcc.target/aarch64/sve/acle/general: New test directory.
* gcc.target/aarch64/sve/acle/general-c: Likewise.

Co-Authored-By: Kugan Vivekanandarajah <kuganv@linaro.org>
Co-Authored-By: Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org>
From-SVN: r277563

296 files changed:
gcc/ChangeLog
gcc/config.gcc
gcc/config/aarch64/aarch64-c.c
gcc/config/aarch64/aarch64-protos.h
gcc/config/aarch64/aarch64-sve-builtins-base.cc [new file with mode: 0644]
gcc/config/aarch64/aarch64-sve-builtins-base.def [new file with mode: 0644]
gcc/config/aarch64/aarch64-sve-builtins-base.h [new file with mode: 0644]
gcc/config/aarch64/aarch64-sve-builtins-functions.h [new file with mode: 0644]
gcc/config/aarch64/aarch64-sve-builtins-shapes.cc [new file with mode: 0644]
gcc/config/aarch64/aarch64-sve-builtins-shapes.h [new file with mode: 0644]
gcc/config/aarch64/aarch64-sve-builtins.cc [new file with mode: 0644]
gcc/config/aarch64/aarch64-sve-builtins.def [new file with mode: 0644]
gcc/config/aarch64/aarch64-sve-builtins.h [new file with mode: 0644]
gcc/config/aarch64/aarch64-sve.md
gcc/config/aarch64/aarch64.c
gcc/config/aarch64/aarch64.md
gcc/config/aarch64/arm_sve.h [new file with mode: 0644]
gcc/config/aarch64/constraints.md
gcc/config/aarch64/iterators.md
gcc/config/aarch64/predicates.md
gcc/config/aarch64/t-aarch64
gcc/testsuite/ChangeLog
gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle.exp [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_1.h [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_2.h [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_3.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/asrd_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/asrd_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/asrd_3.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/cntb_pat.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/conversion_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create2_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create2_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create3_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create3_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create4_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create4_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_1.h [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_2.h [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_1.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_2.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_3.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_4.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_5.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_6.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_7.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get2_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get2_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get3_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get3_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get4_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get4_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/lsl_wide_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/lsl_wide_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_3.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_4.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set2_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set2_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set3_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set3_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set4_1.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set4_2.C [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_1.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_10.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_11.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_12.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_13.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_14.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_15.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_16.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_17.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_18.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_19.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_2.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_20.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_3.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_4.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_5.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_6.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_7.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_8.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_9.c [new file with mode: 0644]
gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/whilele_1.C [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_index_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_offset_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_int_opt_n.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_opt_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_scalar_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_wide_opt_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_pat_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_vector_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ext_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/fold_left_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_scalar_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ld1sh_gather_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_index_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_gather_sv_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_gather_sv_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_replicate_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pattern_pred_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_index_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_index_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_wide_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_index_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_11.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_12.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_13.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_14.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_15.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_16.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_17.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_18.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_19.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_20.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_9.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_count_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_count_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_count_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_uint_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_widen_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/add_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/and_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/bic_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/brka_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/brka_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkb_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkb_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkn_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkpa_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkpb_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntb_pat_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntd_pat_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/cnth_pat_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntw_pat_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/debug_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/debug_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/debug_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/double_pragma_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_9.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_8.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/eor_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ld1_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/nand_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/nor_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/orn_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/orr_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/pfirst_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/qincb_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/struct_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_10.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_3.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_4.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_5.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_6.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_7.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_9.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_1.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_2.c [new file with mode: 0644]
gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_3.c [new file with mode: 0644]

index d0c9ac2a8a01fcdcacc60d9a12689f3c10761a75..937a179ec72b3bbd336759e51aa9fe8f3a29b3c9 100644 (file)
@@ -1,3 +1,444 @@
+2019-10-29  Richard Sandiford  <richard.sandiford@arm.com>
+           Kugan Vivekanandarajah  <kugan.vivekanandarajah@linaro.org>
+           Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>
+
+       * config.gcc (aarch64*-*-*): Add arm_sve.h to extra_headers.
+       Add aarch64-sve-builtins.o, aarch64-sve-builtins-shapes.o and
+       aarch64-sve-builtins-base.o to extra_objs.  Add
+       aarch64-sve-builtins.h and aarch64-sve-builtins.cc to target_gtfiles.
+       * config/aarch64/t-aarch64 (aarch64-sve-builtins.o): New rule.
+       (aarch64-sve-builtins-shapes.o): Likewise.
+       (aarch64-sve-builtins-base.o): New rules.
+       * config/aarch64/aarch64-c.c (aarch64_pragma_aarch64): New function.
+       (aarch64_resolve_overloaded_builtin): Likewise.
+       (aarch64_check_builtin_call): Likewise.
+       (aarch64_register_pragmas): Install aarch64_resolve_overloaded_builtin
+       and aarch64_check_builtin_call in targetm.  Register the GCC aarch64
+       pragma.
+       * config/aarch64/aarch64-protos.h (AARCH64_FOR_SVPRFOP): New macro.
+       (aarch64_svprfop): New enum.
+       (AARCH64_BUILTIN_SVE): New aarch64_builtin_class enum value.
+       (aarch64_sve_int_mode, aarch64_sve_data_mode): Declare.
+       (aarch64_fold_sve_cnt_pat, aarch64_output_sve_prefetch): Likewise.
+       (aarch64_output_sve_cnt_pat_immediate): Likewise.
+       (aarch64_output_sve_ptrues, aarch64_sve_ptrue_svpattern_p): Likewise.
+       (aarch64_sve_sqadd_sqsub_immediate_p, aarch64_sve_ldff1_operand_p)
+       (aarch64_sve_ldnf1_operand_p, aarch64_sve_prefetch_operand_p)
+       (aarch64_ptrue_all_mode, aarch64_convert_sve_data_to_pred): Likewise.
+       (aarch64_expand_sve_dupq, aarch64_replace_reg_mode): Likewise.
+       (aarch64_sve::init_builtins, aarch64_sve::handle_arm_sve_h): Likewise.
+       (aarch64_sve::builtin_decl, aarch64_sve::builtin_type_p): Likewise.
+       (aarch64_sve::mangle_builtin_type): Likewise.
+       (aarch64_sve::resolve_overloaded_builtin): Likewise.
+       (aarch64_sve::check_builtin_call, aarch64_sve::gimple_fold_builtin)
+       (aarch64_sve::expand_builtin): Likewise.
+       * config/aarch64/aarch64.c (aarch64_sve_data_mode): Make public.
+       (aarch64_sve_int_mode): Likewise.
+       (aarch64_ptrue_all_mode): New function.
+       (aarch64_convert_sve_data_to_pred): Make public.
+       (svprfop_token): New function.
+       (aarch64_output_sve_prefetch): Likewise.
+       (aarch64_fold_sve_cnt_pat): Likewise.
+       (aarch64_output_sve_cnt_pat_immediate): Likewise.
+       (aarch64_sve_move_pred_via_while): Use gen_while with UNSPEC_WHILE_LO
+       instead of gen_while_ult.
+       (aarch64_replace_reg_mode): Make public.
+       (aarch64_init_builtins): Call aarch64_sve::init_builtins.
+       (aarch64_fold_builtin): Handle AARCH64_BUILTIN_SVE.
+       (aarch64_gimple_fold_builtin, aarch64_expand_builtin): Likewise.
+       (aarch64_builtin_decl, aarch64_builtin_reciprocal): Likewise.
+       (aarch64_mangle_type): Call aarch64_sve::mangle_type.
+       (aarch64_sve_sqadd_sqsub_immediate_p): New function.
+       (aarch64_sve_ptrue_svpattern_p): Likewise.
+       (aarch64_sve_pred_valid_immediate): Check
+       aarch64_sve_ptrue_svpattern_p.
+       (aarch64_sve_ldff1_operand_p, aarch64_sve_ldnf1_operand_p)
+       (aarch64_sve_prefetch_operand_p, aarch64_output_sve_ptrues): New
+       functions.
+       * config/aarch64/aarch64.md (UNSPEC_LDNT1_SVE, UNSPEC_STNT1_SVE)
+       (UNSPEC_LDFF1_GATHER, UNSPEC_PTRUE, UNSPEC_WHILE_LE, UNSPEC_WHILE_LS)
+       (UNSPEC_WHILE_LT, UNSPEC_CLASTA, UNSPEC_UPDATE_FFR)
+       (UNSPEC_UPDATE_FFRT, UNSPEC_RDFFR, UNSPEC_WRFFR)
+       (UNSPEC_SVE_LANE_SELECT, UNSPEC_SVE_CNT_PAT, UNSPEC_SVE_PREFETCH)
+       (UNSPEC_SVE_PREFETCH_GATHER, UNSPEC_SVE_COMPACT, UNSPEC_SVE_SPLICE):
+       New unspecs.
+       * config/aarch64/iterators.md (SI_ONLY, DI_ONLY, VNx8HI_ONLY)
+       (VNx2DI_ONLY, SVE_PARTIAL, VNx8_NARROW, VNx8_WIDE, VNx4_NARROW)
+       (VNx4_WIDE, VNx2_NARROW, VNx2_WIDE, PRED_HSD): New mode iterators.
+       (UNSPEC_ADR, UNSPEC_BRKA, UNSPEC_BRKB, UNSPEC_BRKN, UNSPEC_BRKPA)
+       (UNSPEC_BRKPB, UNSPEC_PFIRST, UNSPEC_PNEXT, UNSPEC_CNTP, UNSPEC_SADDV)
+       (UNSPEC_UADDV, UNSPEC_FMLA, UNSPEC_FMLS, UNSPEC_FEXPA, UNSPEC_FTMAD)
+       (UNSPEC_FTSMUL, UNSPEC_FTSSEL, UNSPEC_COND_CMPEQ_WIDE): New unspecs.
+       (UNSPEC_COND_CMPGE_WIDE, UNSPEC_COND_CMPGT_WIDE): Likewise.
+       (UNSPEC_COND_CMPHI_WIDE, UNSPEC_COND_CMPHS_WIDE): Likewise.
+       (UNSPEC_COND_CMPLE_WIDE, UNSPEC_COND_CMPLO_WIDE): Likewise.
+       (UNSPEC_COND_CMPLS_WIDE, UNSPEC_COND_CMPLT_WIDE): Likewise.
+       (UNSPEC_COND_CMPNE_WIDE, UNSPEC_COND_FCADD90, UNSPEC_COND_FCADD270)
+       (UNSPEC_COND_FCMLA, UNSPEC_COND_FCMLA90, UNSPEC_COND_FCMLA180)
+       (UNSPEC_COND_FCMLA270, UNSPEC_COND_FMAX, UNSPEC_COND_FMIN): Likewise.
+       (UNSPEC_COND_FMULX, UNSPEC_COND_FRECPX, UNSPEC_COND_FSCALE): Likewise.
+       (UNSPEC_LASTA, UNSPEC_ASHIFT_WIDE, UNSPEC_ASHIFTRT_WIDE): Likewise.
+       (UNSPEC_LSHIFTRT_WIDE, UNSPEC_LDFF1, UNSPEC_LDNF1): Likewise.
+       (Vesize): Handle partial vector modes.
+       (self_mask, narrower_mask, sve_lane_con, sve_lane_pair_con): New
+       mode attributes.
+       (UBINQOPS, ANY_PLUS, SAT_PLUS, ANY_MINUS, SAT_MINUS): New code
+       iterators.
+       (s, paired_extend, inc_dec): New code attributes.
+       (SVE_INT_ADDV, CLAST, LAST): New int iterators.
+       (SVE_INT_UNARY): Add UNSPEC_RBIT.
+       (SVE_FP_UNARY, SVE_FP_UNARY_INT): New int iterators.
+       (SVE_FP_BINARY, SVE_FP_BINARY_INT): Likewise.
+       (SVE_COND_FP_UNARY): Add UNSPEC_COND_FRECPX.
+       (SVE_COND_FP_BINARY): Add UNSPEC_COND_FMAX, UNSPEC_COND_FMIN and
+       UNSPEC_COND_FMULX.
+       (SVE_COND_FP_BINARY_INT, SVE_COND_FP_ADD): New int iterators.
+       (SVE_COND_FP_SUB, SVE_COND_FP_MUL): Likewise.
+       (SVE_COND_FP_BINARY_I1): Add UNSPEC_COND_FMAX and UNSPEC_COND_FMIN.
+       (SVE_COND_FP_BINARY_REG): Add UNSPEC_COND_FMULX.
+       (SVE_COND_FCADD, SVE_COND_FP_MAXMIN, SVE_COND_FCMLA)
+       (SVE_COND_INT_CMP_WIDE, SVE_FP_TERNARY_LANE, SVE_CFP_TERNARY_LANE)
+       (SVE_WHILE, SVE_SHIFT_WIDE, SVE_LDFF1_LDNF1, SVE_BRK_UNARY)
+       (SVE_BRK_BINARY, SVE_PITER): New int iterators.
+       (optab): Handle UNSPEC_SADDV, UNSPEC_UADDV, UNSPEC_FRECPE,
+       UNSPEC_FRECPS, UNSPEC_RSQRTE, UNSPEC_RSQRTS, UNSPEC_RBIT,
+       UNSPEC_SMUL_HIGHPART, UNSPEC_UMUL_HIGHPART, UNSPEC_FMLA, UNSPEC_FMLS,
+       UNSPEC_FCMLA, UNSPEC_FCMLA90, UNSPEC_FCMLA180, UNSPEC_FCMLA270,
+       UNSPEC_FEXPA, UNSPEC_FTSMUL, UNSPEC_FTSSEL, UNSPEC_COND_FCADD90,
+       UNSPEC_COND_FCADD270, UNSPEC_COND_FCMLA, UNSPEC_COND_FCMLA90,
+       UNSPEC_COND_FCMLA180, UNSPEC_COND_FCMLA270, UNSPEC_COND_FMAX,
+       UNSPEC_COND_FMIN, UNSPEC_COND_FMULX, UNSPEC_COND_FRECPX and
+       UNSPEC_COND_FSCALE.
+       (maxmin_uns): Handle UNSPEC_COND_FMAX and UNSPEC_COND_FMIN.
+       (binqops_op, binqops_op_rev, last_op): New int attributes.
+       (su): Handle UNSPEC_SADDV and UNSPEC_UADDV.
+       (fn, ab): New int attributes.
+       (cmp_op): Handle UNSPEC_COND_CMP*_WIDE and UNSPEC_WHILE_*.
+       (while_optab_cmp, brk_op, sve_pred_op): New int attributes.
+       (sve_int_op): Handle UNSPEC_SMUL_HIGHPART, UNSPEC_UMUL_HIGHPART,
+       UNSPEC_ASHIFT_WIDE, UNSPEC_ASHIFTRT_WIDE, UNSPEC_LSHIFTRT_WIDE and
+       UNSPEC_RBIT.
+       (sve_fp_op): Handle UNSPEC_FRECPE, UNSPEC_FRECPS, UNSPEC_RSQRTE,
+       UNSPEC_RSQRTS, UNSPEC_FMLA, UNSPEC_FMLS, UNSPEC_FEXPA, UNSPEC_FTSMUL,
+       UNSPEC_FTSSEL, UNSPEC_COND_FMAX, UNSPEC_COND_FMIN, UNSPEC_COND_FMULX,
+       UNSPEC_COND_FRECPX and UNSPEC_COND_FSCALE.
+       (sve_fp_op_rev): Handle UNSPEC_COND_FMAX, UNSPEC_COND_FMIN and
+       UNSPEC_COND_FMULX.
+       (rot): Handle UNSPEC_COND_FCADD* and UNSPEC_COND_FCMLA*.
+       (brk_reg_con, brk_reg_opno): New int attributes.
+       (sve_pred_fp_rhs1_operand, sve_pred_fp_rhs2_operand): Handle
+       UNSPEC_COND_FMAX, UNSPEC_COND_FMIN and UNSPEC_COND_FMULX.
+       (sve_pred_fp_rhs2_immediate): Handle UNSPEC_COND_FMAX and
+       UNSPEC_COND_FMIN.
+       (max_elem_bits): New int attribute.
+       (min_elem_bits): Handle UNSPEC_RBIT.
+       * config/aarch64/predicates.md (subreg_lowpart_operator): Handle
+       TRUNCATE as well as SUBREG.
+       (ascending_int_parallel, aarch64_simd_reg_or_minus_one)
+       (aarch64_sve_ldff1_operand, aarch64_sve_ldnf1_operand)
+       (aarch64_sve_prefetch_operand, aarch64_sve_ptrue_svpattern_immediate)
+       (aarch64_sve_qadd_immediate, aarch64_sve_qsub_immediate)
+       (aarch64_sve_gather_immediate_b, aarch64_sve_gather_immediate_h)
+       (aarch64_sve_gather_immediate_w, aarch64_sve_gather_immediate_d)
+       (aarch64_sve_sqadd_operand, aarch64_sve_gather_offset_b)
+       (aarch64_sve_gather_offset_h, aarch64_sve_gather_offset_w)
+       (aarch64_sve_gather_offset_d, aarch64_gather_scale_operand_b)
+       (aarch64_gather_scale_operand_h): New predicates.
+       * config/aarch64/constraints.md (UPb, UPd, UPh, UPw, Utf, Utn, vgb)
+       (vgd, vgh, vgw, vsQ, vsS): New constraints.
+       * config/aarch64/aarch64-sve.md: Add a note on the FFR handling.
+       (*aarch64_sve_reinterpret<mode>): Allow any source register
+       instead of requiring an exact match.
+       (*aarch64_sve_ptruevnx16bi_cc, *aarch64_sve_ptrue<mode>_cc)
+       (*aarch64_sve_ptruevnx16bi_ptest, *aarch64_sve_ptrue<mode>_ptest)
+       (aarch64_wrffr, aarch64_update_ffr_for_load, aarch64_copy_ffr_to_ffrt)
+       (aarch64_rdffr, aarch64_rdffr_z, *aarch64_rdffr_z_ptest)
+       (*aarch64_rdffr_ptest, *aarch64_rdffr_z_cc, *aarch64_rdffr_cc)
+       (aarch64_update_ffrt): New patterns.
+       (@aarch64_load_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>)
+       (@aarch64_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
+       (@aarch64_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
+       (@aarch64_ld<fn>f1<mode>): New patterns.
+       (@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>)
+       (@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
+       (@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
+       (@aarch64_ldnt1<mode>): New patterns.
+       (gather_load<mode>): Use aarch64_sve_gather_offset_<Vesize> for
+       the scalar part of the address.
+       (mask_gather_load<SVE_S:mode>): Use aarch64_sve_gather_offset_w for the
+       scalar part of the addresse and add an alternative for handling
+       nonzero offsets.
+       (mask_gather_load<SVE_D:mode>): Likewise aarch64_sve_gather_offset_d.
+       (*mask_gather_load<mode>_sxtw, *mask_gather_load<mode>_uxtw)
+       (@aarch64_gather_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
+       (@aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
+       (*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw)
+       (*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw)
+       (@aarch64_ldff1_gather<SVE_S:mode>, @aarch64_ldff1_gather<SVE_D:mode>)
+       (*aarch64_ldff1_gather<mode>_sxtw, *aarch64_ldff1_gather<mode>_uxtw)
+       (@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>)
+       (@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>)
+       (*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw)
+       (*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw)
+       (@aarch64_sve_prefetch<mode>): New patterns.
+       (@aarch64_sve_gather_prefetch<SVE_I:mode><VNx4SI_ONLY:mode>)
+       (@aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>)
+       (*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_sxtw)
+       (*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_uxtw)
+       (@aarch64_store_trunc<VNx8_NARROW:mode><VNx8_WIDE:mode>)
+       (@aarch64_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>)
+       (@aarch64_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>)
+       (@aarch64_stnt1<mode>): New patterns.
+       (scatter_store<mode>): Use aarch64_sve_gather_offset_<Vesize> for
+       the scalar part of the address.
+       (mask_scatter_store<SVE_S:mode>): Use aarch64_sve_gather_offset_w for
+       the scalar part of the addresse and add an alternative for handling
+       nonzero offsets.
+       (mask_scatter_store<SVE_D:mode>): Likewise aarch64_sve_gather_offset_d.
+       (*mask_scatter_store<mode>_sxtw, *mask_scatter_store<mode>_uxtw)
+       (@aarch64_scatter_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>)
+       (@aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>)
+       (*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_sxtw)
+       (*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_uxtw):
+       New patterns.
+       (vec_duplicate<mode>): Use QI as the mode of the input operand.
+       (extract_last_<mode>): Generalize to...
+       (@extract_<LAST:last_op>_<mode>): ...this.
+       (*<SVE_INT_UNARY:optab><mode>2): Rename to...
+       (@aarch64_pred_<SVE_INT_UNARY:optab><mode>): ...this.
+       (@cond_<SVE_INT_UNARY:optab><mode>): New expander.
+       (@aarch64_pred_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>): New pattern.
+       (@aarch64_cond_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>): Likewise.
+       (@aarch64_pred_cnot<mode>, @cond_cnot<mode>): New expanders.
+       (@aarch64_sve_<SVE_FP_UNARY_INT:optab><mode>): New pattern.
+       (@aarch64_sve_<SVE_FP_UNARY:optab><mode>): Likewise.
+       (*<SVE_COND_FP_UNARY:optab><mode>2): Rename to...
+       (@aarch64_pred_<SVE_COND_FP_UNARY:optab><mode>): ...this.
+       (@cond_<SVE_COND_FP_UNARY:optab><mode>): New expander.
+       (*<SVE_INT_BINARY_IMM:optab><mode>3): Rename to...
+       (@aarch64_pred_<SVE_INT_BINARY_IMM:optab><mode>): ...this.
+       (@aarch64_adr<mode>, *aarch64_adr_sxtw): New patterns.
+       (*aarch64_adr_uxtw_unspec): Likewise.
+       (*aarch64_adr_uxtw): Rename to...
+       (*aarch64_adr_uxtw_and): ...this.
+       (@aarch64_adr<mode>_shift): New expander.
+       (*aarch64_adr_shift_sxtw): New pattern.
+       (aarch64_<su>abd<mode>_3): Rename to...
+       (@aarch64_pred_<su>abd<mode>): ...this.
+       (<su>abd<mode>_3): Update accordingly.
+       (@aarch64_cond_<su>abd<mode>): New expander.
+       (@aarch64_<SBINQOPS:su_optab><optab><mode>): New pattern.
+       (@aarch64_<UBINQOPS:su_optab><optab><mode>): Likewise.
+       (*<su>mul<mode>3_highpart): Rename to...
+       (@aarch64_pred_<optab><mode>): ...this.
+       (@cond_<MUL_HIGHPART:optab><mode>): New expander.
+       (*cond_<MUL_HIGHPART:optab><mode>_2): New pattern.
+       (*cond_<MUL_HIGHPART:optab><mode>_z): Likewise.
+       (*<SVE_INT_BINARY_SD:optab><mode>3): Rename to...
+       (@aarch64_pred_<SVE_INT_BINARY_SD:optab><mode>): ...this.
+       (cond_<SVE_INT_BINARY_SD:optab><mode>): Add a "@" marker.
+       (@aarch64_bic<mode>, @cond_bic<mode>): New expanders.
+       (*v<ASHIFT:optab><mode>3): Rename to...
+       (@aarch64_pred_<ASHIFT:optab><mode>): ...this.
+       (@aarch64_sve_<SVE_SHIFT_WIDE:sve_int_op><mode>): New pattern.
+       (@cond_<SVE_SHIFT_WIDE:sve_int_op><mode>): New expander.
+       (*cond_<SVE_SHIFT_WIDE:sve_int_op><mode>_m): New pattern.
+       (*cond_<SVE_SHIFT_WIDE:sve_int_op><mode>_z): Likewise.
+       (@cond_asrd<mode>): New expander.
+       (*cond_asrd<mode>_2, *cond_asrd<mode>_z): New patterns.
+       (sdiv_pow2<mode>3): Expand to *cond_asrd<mode>_2.
+       (*sdiv_pow2<mode>3): Delete.
+       (@cond_<SVE_COND_FP_BINARY_INT:optab><mode>): New expander.
+       (*cond_<SVE_COND_FP_BINARY_INT:optab><mode>_2): New pattern.
+       (*cond_<SVE_COND_FP_BINARY_INT:optab><mode>_any): Likewise.
+       (@aarch64_sve_<SVE_FP_BINARY:optab><mode>): New pattern.
+       (@aarch64_sve_<SVE_FP_BINARY_INT:optab><mode>): Likewise.
+       (*<SVE_COND_FP_BINARY_REG:optab><mode>3): Rename to...
+       (@aarch64_pred_<SVE_COND_FP_BINARY_REG:optab><mode>): ...this.
+       (@aarch64_pred_<SVE_COND_FP_BINARY_INT:optab><mode>): New pattern.
+       (cond_<SVE_COND_FP_BINARY:optab><mode>): Add a "@" marker.
+       (*add<SVE_F:mode>3): Rename to...
+       (@aarch64_pred_add<SVE_F:mode>): ...this and add alternatives
+       for SVE_STRICT_GP.
+       (@aarch64_pred_<SVE_COND_FCADD:optab><mode>): New pattern.
+       (@cond_<SVE_COND_FCADD:optab><mode>): New expander.
+       (*cond_<SVE_COND_FCADD:optab><mode>_2): New pattern.
+       (*cond_<SVE_COND_FCADD:optab><mode>_any): Likewise.
+       (*sub<SVE_F:mode>3): Rename to...
+       (@aarch64_pred_sub<SVE_F:mode>): ...this and add alternatives
+       for SVE_STRICT_GP.
+       (@aarch64_pred_abd<SVE_F:mode>): New expander.
+       (*fabd<SVE_F:mode>3): Rename to...
+       (*aarch64_pred_abd<SVE_F:mode>): ...this.
+       (@aarch64_cond_abd<SVE_F:mode>): New expander.
+       (*mul<SVE_F:mode>3): Rename to...
+       (@aarch64_pred_<SVE_F:optab><mode>): ...this and add alternatives
+       for SVE_STRICT_GP.
+       (@aarch64_mul_lane_<SVE_F:mode>): New pattern.
+       (*<SVE_COND_FP_MAXMIN_PUBLIC:optab><mode>3): Rename and generalize
+       to...
+       (@aarch64_pred_<SVE_COND_FP_MAXMIN:optab><mode>): ...this.
+       (*<LOGICAL:optab><PRED_ALL:mode>3_ptest): New pattern.
+       (*<nlogical><PRED_ALL:mode>3): Rename to...
+       (aarch64_pred_<nlogical><PRED_ALL:mode>_z): ...this.
+       (*<nlogical><PRED_ALL:mode>3_cc): New pattern.
+       (*<nlogical><PRED_ALL:mode>3_ptest): Likewise.
+       (*<logical_nn><PRED_ALL:mode>3): Rename to...
+       (aarch64_pred_<logical_nn><mode>_z): ...this.
+       (*<logical_nn><PRED_ALL:mode>3_cc): New pattern.
+       (*<logical_nn><PRED_ALL:mode>3_ptest): Likewise.
+       (*fma<SVE_I:mode>4): Rename to...
+       (@aarch64_pred_fma<SVE_I:mode>): ...this.
+       (*fnma<SVE_I:mode>4): Rename to...
+       (@aarch64_pred_fnma<SVE_I:mode>): ...this.
+       (@aarch64_<sur>dot_prod_lane<vsi2qi>): New pattern.
+       (*<SVE_FP_TERNARY:optab><mode>4): Rename to...
+       (@aarch64_pred_<SVE_FP_TERNARY:optab><mode>): ...this.
+       (cond_<SVE_FP_TERNARY:optab><mode>): Add a "@" marker.
+       (@aarch64_<SVE_FP_TERNARY_LANE:optab>_lane_<mode>): New pattern.
+       (@aarch64_pred_<SVE_COND_FCMLA:optab><mode>): Likewise.
+       (@cond_<SVE_COND_FCMLA:optab><mode>): New expander.
+       (*cond_<SVE_COND_FCMLA:optab><mode>_4): New pattern.
+       (*cond_<SVE_COND_FCMLA:optab><mode>_any): Likewise.
+       (@aarch64_<FCMLA:optab>_lane_<mode>): Likewise.
+       (@aarch64_sve_tmad<mode>): Likewise.
+       (vcond_mask_<SVE_ALL:mode><vpred>): Add a "@" marker.
+       (*aarch64_sel_dup<mode>): Rename to...
+       (@aarch64_sel_dup<mode>): ...this.
+       (@aarch64_pred_cmp<cmp_op><SVE_I:mode>_wide): New pattern.
+       (*aarch64_pred_cmp<cmp_op><SVE_I:mode>_wide_cc): Likewise.
+       (*aarch64_pred_cmp<cmp_op><SVE_I:mode>_wide_ptest): Likewise.
+       (@while_ult<GPI:mode><PRED_ALL:mode>): Generalize to...
+       (@while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>): ...this.
+       (*while_ult<GPI:mode><PRED_ALL:mode>_cc): Generalize to.
+       (*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_cc): ...this.
+       (*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_ptest): New pattern.
+       (*fcm<cmp_op><mode>): Rename to...
+       (@aarch64_pred_fcm<cmp_op><mode>): ...this.  Make operand order
+       match @aarch64_pred_cmp<cmp_op><SVE_I:mode>.
+       (*fcmuo<mode>): Rename to...
+       (@aarch64_pred_fcmuo<mode>): ...this.  Make operand order
+       match @aarch64_pred_cmp<cmp_op><SVE_I:mode>.
+       (@aarch64_pred_fac<cmp_op><mode>): New expander.
+       (@vcond_mask_<PRED_ALL:mode><mode>): New pattern.
+       (fold_extract_last_<mode>): Generalize to...
+       (@fold_extract_<last_op>_<mode>): ...this.
+       (@aarch64_fold_extract_vector_<last_op>_<mode>): New pattern.
+       (*reduc_plus_scal_<SVE_I:mode>): Replace with...
+       (@aarch64_pred_reduc_<optab>_<mode>): ...this pattern, making the
+       DImode result explicit.
+       (reduc_plus_scal_<mode>): Update accordingly.
+       (*reduc_<optab>_scal_<SVE_I:mode>): Rename to...
+       (@aarch64_pred_reduc_<optab>_<SVE_I:mode>): ...this.
+       (*reduc_<optab>_scal_<SVE_F:mode>): Rename to...
+       (@aarch64_pred_reduc_<optab>_<SVE_F:mode>): ...this.
+       (*aarch64_sve_tbl<mode>): Rename to...
+       (@aarch64_sve_tbl<mode>): ...this.
+       (@aarch64_sve_compact<mode>): New pattern.
+       (*aarch64_sve_dup_lane<mode>): Rename to...
+       (@aarch64_sve_dup_lane<mode>): ...this.
+       (@aarch64_sve_dupq_lane<mode>): New pattern.
+       (@aarch64_sve_splice<mode>): Likewise.
+       (aarch64_sve_<perm_insn><mode>): Rename to...
+       (@aarch64_sve_<perm_insn><mode>): ...this.
+       (*aarch64_sve_ext<mode>): Rename to...
+       (@aarch64_sve_ext<mode>): ...this.
+       (aarch64_sve_<su>unpk<perm_hilo>_<SVE_BHSI:mode>): Add a "@" marker.
+       (*aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>): Rename
+       to...
+       (@aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>): ...this.
+       (*aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>):
+       Rename to...
+       (@aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>):
+       ...this.
+       (@cond_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>): New expander.
+       (@cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>): Likewise.
+       (*cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>): New pattern.
+       (*aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>): Rename
+       to...
+       (@aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>): ...this.
+       (aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>): Add
+       a "@" marker.
+       (@cond_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>): New expander.
+       (@cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>): Likewise.
+       (*cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>): New
+       pattern.
+       (*aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): Rename to...
+       (@aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): ...this.
+       (@cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): New expander.
+       (*cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>): New pattern.
+       (aarch64_sve_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>): Add a
+       "@" marker.
+       (@cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>): New expander.
+       (*cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>): New pattern.
+       (aarch64_sve_punpk<perm_hilo>_<mode>): Add a "@" marker.
+       (@aarch64_brk<SVE_BRK_UNARY:brk_op>): New pattern.
+       (*aarch64_brk<SVE_BRK_UNARY:brk_op>_cc): Likewise.
+       (*aarch64_brk<SVE_BRK_UNARY:brk_op>_ptest): Likewise.
+       (@aarch64_brk<SVE_BRK_BINARY:brk_op>): Likewise.
+       (*aarch64_brk<SVE_BRK_BINARY:brk_op>_cc): Likewise.
+       (*aarch64_brk<SVE_BRK_BINARY:brk_op>_ptest): Likewise.
+       (@aarch64_sve_<SVE_PITER:sve_pred_op><mode>): Likewise.
+       (*aarch64_sve_<SVE_PITER:sve_pred_op><mode>_cc): Likewise.
+       (*aarch64_sve_<SVE_PITER:sve_pred_op><mode>_ptest): Likewise.
+       (aarch64_sve_cnt_pat): Likewise.
+       (@aarch64_sve_<ANY_PLUS:inc_dec><DI_ONLY:mode>_pat): Likewise.
+       (*aarch64_sve_incsi_pat): Likewise.
+       (@aarch64_sve_<SAT_PLUS:inc_dec><SI_ONLY:mode>_pat): Likewise.
+       (@aarch64_sve_<ANY_PLUS:inc_dec><VNx2DI_ONLY:mode>_pat): Likewise.
+       (@aarch64_sve_<ANY_PLUS:inc_dec><VNx4SI_ONLY:mode>_pat): Likewise.
+       (@aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_pat): New expander.
+       (*aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_pat): New pattern.
+       (@aarch64_sve_<ANY_MINUS:inc_dec><DI_ONLY:mode>_pat): Likewise.
+       (*aarch64_sve_decsi_pat): Likewise.
+       (@aarch64_sve_<SAT_MINUS:inc_dec><SI_ONLY:mode>_pat): Likewise.
+       (@aarch64_sve_<ANY_MINUS:inc_dec><VNx2DI_ONLY:mode>_pat): Likewise.
+       (@aarch64_sve_<ANY_MINUS:inc_dec><VNx4SI_ONLY:mode>_pat): Likewise.
+       (@aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_pat): New expander.
+       (*aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_pat): New pattern.
+       (@aarch64_pred_cntp<mode>): Likewise.
+       (@aarch64_sve_<ANY_PLUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp):
+       New expander.
+       (*aarch64_sve_<ANY_PLUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp)
+       (*aarch64_incsi<PRED_ALL:mode>_cntp): New patterns.
+       (@aarch64_sve_<SAT_PLUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
+       New expander.
+       (*aarch64_sve_<SAT_PLUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
+       New pattern.
+       (@aarch64_sve_<ANY_PLUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New expander.
+       (*aarch64_sve_<ANY_PLUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New pattern.
+       (@aarch64_sve_<ANY_PLUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New expander.
+       (*aarch64_sve_<ANY_PLUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New pattern.
+       (@aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New expander.
+       (*aarch64_sve_<ANY_PLUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New pattern.
+       (@aarch64_sve_<ANY_MINUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp):
+       New expander.
+       (*aarch64_sve_<ANY_MINUS:inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp)
+       (*aarch64_incsi<PRED_ALL:mode>_cntp): New patterns.
+       (@aarch64_sve_<SAT_MINUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
+       New expander.
+       (*aarch64_sve_<SAT_MINUS:inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp):
+       New pattern.
+       (@aarch64_sve_<ANY_MINUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New
+       expander.
+       (*aarch64_sve_<ANY_MINUS:inc_dec><VNx2DI_ONLY:mode>_cntp): New pattern.
+       (@aarch64_sve_<ANY_MINUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New
+       expander.
+       (*aarch64_sve_<ANY_MINUS:inc_dec><VNx4SI_ONLY:mode>_cntp): New pattern.
+       (@aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New
+       expander.
+       (*aarch64_sve_<ANY_MINUS:inc_dec><VNx8HI_ONLY:mode>_cntp): New pattern.
+       * config/aarch64/arm_sve.h: New file.
+       * config/aarch64/aarch64-sve-builtins.h: Likewise.
+       * config/aarch64/aarch64-sve-builtins.cc: Likewise.
+       * config/aarch64/aarch64-sve-builtins.def: Likewise.
+       * config/aarch64/aarch64-sve-builtins-base.h: Likewise.
+       * config/aarch64/aarch64-sve-builtins-base.cc: Likewise.
+       * config/aarch64/aarch64-sve-builtins-base.def: Likewise.
+       * config/aarch64/aarch64-sve-builtins-functions.h: Likewise.
+       * config/aarch64/aarch64-sve-builtins-shapes.h: Likewise.
+       * config/aarch64/aarch64-sve-builtins-shapes.cc: Likewise.
+
 2019-10-29  Richard Sandiford  <richard.sandiford@arm.com>
 
        * config/aarch64/aarch64-sve.md (@aarch64_sve_rev<PRED_ALL:mode>):
index b4440877e99f15d4351bff0b58214d5e9d6aee9d..d74bcbb9856922a930c1318703d14916cfc159a0 100644 (file)
@@ -315,12 +315,12 @@ m32c*-*-*)
         ;;
 aarch64*-*-*)
        cpu_type=aarch64
-       extra_headers="arm_fp16.h arm_neon.h arm_acle.h"
+       extra_headers="arm_fp16.h arm_neon.h arm_acle.h arm_sve.h"
        c_target_objs="aarch64-c.o"
        cxx_target_objs="aarch64-c.o"
        d_target_objs="aarch64-d.o"
-       extra_objs="aarch64-builtins.o aarch-common.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o"
-       target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c"
+       extra_objs="aarch64-builtins.o aarch-common.o aarch64-sve-builtins.o aarch64-sve-builtins-shapes.o aarch64-sve-builtins-base.o cortex-a57-fma-steering.o aarch64-speculation.o falkor-tag-collision-avoidance.o aarch64-bti-insert.o"
+       target_gtfiles="\$(srcdir)/config/aarch64/aarch64-builtins.c \$(srcdir)/config/aarch64/aarch64-sve-builtins.h \$(srcdir)/config/aarch64/aarch64-sve-builtins.cc"
        target_has_targetm_common=yes
        ;;
 alpha*-*-*)
index 85b68317b938a37090ec401618b7f540fc243fde..7c322ca0813caea8894abd0106dec04a75e714dc 100644 (file)
@@ -243,6 +243,73 @@ aarch64_pragma_target_parse (tree args, tree pop_target)
   return true;
 }
 
+/* Implement "#pragma GCC aarch64".  */
+static void
+aarch64_pragma_aarch64 (cpp_reader *)
+{
+  tree x;
+  if (pragma_lex (&x) != CPP_STRING)
+    {
+      error ("%<#pragma GCC aarch64%> requires a string parameter");
+      return;
+    }
+
+  const char *name = TREE_STRING_POINTER (x);
+  if (strcmp (name, "arm_sve.h") == 0)
+    aarch64_sve::handle_arm_sve_h ();
+  else
+    error ("unknown %<#pragma GCC aarch64%> option %qs", name);
+}
+
+/* Implement TARGET_RESOLVE_OVERLOADED_BUILTIN.  */
+static tree
+aarch64_resolve_overloaded_builtin (unsigned int uncast_location,
+                                   tree fndecl, void *uncast_arglist)
+{
+  vec<tree, va_gc> empty = {};
+  location_t location = (location_t) uncast_location;
+  vec<tree, va_gc> *arglist = (uncast_arglist
+                              ? (vec<tree, va_gc> *) uncast_arglist
+                              : &empty);
+  unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
+  unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
+  tree new_fndecl;
+  switch (code & AARCH64_BUILTIN_CLASS)
+    {
+    case AARCH64_BUILTIN_GENERAL:
+      return NULL_TREE;
+
+    case AARCH64_BUILTIN_SVE:
+      new_fndecl = aarch64_sve::resolve_overloaded_builtin (location, subcode,
+                                                           arglist);
+      break;
+    }
+  if (new_fndecl == NULL_TREE || new_fndecl == error_mark_node)
+    return new_fndecl;
+  return build_function_call_vec (location, vNULL, new_fndecl, arglist,
+                                 NULL, fndecl);
+}
+
+/* Implement TARGET_CHECK_BUILTIN_CALL.  */
+static bool
+aarch64_check_builtin_call (location_t loc, vec<location_t> arg_loc,
+                           tree fndecl, tree orig_fndecl,
+                           unsigned int nargs, tree *args)
+{
+  unsigned int code = DECL_MD_FUNCTION_CODE (fndecl);
+  unsigned int subcode = code >> AARCH64_BUILTIN_SHIFT;
+  switch (code & AARCH64_BUILTIN_CLASS)
+    {
+    case AARCH64_BUILTIN_GENERAL:
+      return true;
+
+    case AARCH64_BUILTIN_SVE:
+      return aarch64_sve::check_builtin_call (loc, arg_loc, subcode,
+                                             orig_fndecl, nargs, args);
+    }
+  gcc_unreachable ();
+}
+
 /* Implement REGISTER_TARGET_PRAGMAS.  */
 
 void
@@ -250,4 +317,9 @@ aarch64_register_pragmas (void)
 {
   /* Update pragma hook to allow parsing #pragma GCC target.  */
   targetm.target_option.pragma_parse = aarch64_pragma_target_parse;
+
+  targetm.resolve_overloaded_builtin = aarch64_resolve_overloaded_builtin;
+  targetm.check_builtin_call = aarch64_check_builtin_call;
+
+  c_register_pragma ("GCC", "aarch64", aarch64_pragma_aarch64);
 }
index ca235085bfbc7560cdfb8a6f767f0bd634067d24..15f288b9ee33fb1c7300888284eb7f80b1e82f66 100644 (file)
@@ -426,11 +426,31 @@ extern struct tune_params aarch64_tune_params;
   T (MUL3, mul3, 30) \
   T (ALL, all, 31)
 
+/* The available SVE prefetch operations, known in the ACLE as "svprfop".  */
+#define AARCH64_FOR_SVPRFOP(T) \
+  T (PLDL1KEEP, pldl1keep, 0) \
+  T (PLDL1STRM, pldl1strm, 1) \
+  T (PLDL2KEEP, pldl2keep, 2) \
+  T (PLDL2STRM, pldl2strm, 3) \
+  T (PLDL3KEEP, pldl3keep, 4) \
+  T (PLDL3STRM, pldl3strm, 5) \
+  T (PSTL1KEEP, pstl1keep, 8) \
+  T (PSTL1STRM, pstl1strm, 9) \
+  T (PSTL2KEEP, pstl2keep, 10) \
+  T (PSTL2STRM, pstl2strm, 11) \
+  T (PSTL3KEEP, pstl3keep, 12) \
+  T (PSTL3STRM, pstl3strm, 13)
+
 #define AARCH64_SVENUM(UPPER, LOWER, VALUE) AARCH64_SV_##UPPER = VALUE,
 enum aarch64_svpattern {
   AARCH64_FOR_SVPATTERN (AARCH64_SVENUM)
   AARCH64_NUM_SVPATTERNS
 };
+
+enum aarch64_svprfop {
+  AARCH64_FOR_SVPRFOP (AARCH64_SVENUM)
+  AARCH64_NUM_SVPRFOPS
+};
 #undef AARCH64_SVENUM
 
 /* It's convenient to divide the built-in function codes into groups,
@@ -438,7 +458,8 @@ enum aarch64_svpattern {
    those groups.  */
 enum aarch64_builtin_class
 {
-  AARCH64_BUILTIN_GENERAL
+  AARCH64_BUILTIN_GENERAL,
+  AARCH64_BUILTIN_SVE
 };
 
 /* Built-in function codes are structured so that the low
@@ -489,8 +510,11 @@ bool aarch64_masks_and_shift_for_bfi_p (scalar_int_mode, unsigned HOST_WIDE_INT,
                                        unsigned HOST_WIDE_INT);
 bool aarch64_zero_extend_const_eq (machine_mode, rtx, machine_mode, rtx);
 bool aarch64_move_imm (HOST_WIDE_INT, machine_mode);
+machine_mode aarch64_sve_int_mode (machine_mode);
 opt_machine_mode aarch64_sve_pred_mode (unsigned int);
+opt_machine_mode aarch64_sve_data_mode (scalar_mode, poly_uint64);
 bool aarch64_sve_mode_p (machine_mode);
+HOST_WIDE_INT aarch64_fold_sve_cnt_pat (aarch64_svpattern, unsigned int);
 bool aarch64_sve_cnt_immediate_p (rtx);
 bool aarch64_sve_scalar_inc_dec_immediate_p (rtx);
 bool aarch64_sve_addvl_addpl_immediate_p (rtx);
@@ -501,7 +525,9 @@ bool aarch64_mov_operand_p (rtx, machine_mode);
 rtx aarch64_reverse_mask (machine_mode, unsigned int);
 bool aarch64_offset_7bit_signed_scaled_p (machine_mode, poly_int64);
 bool aarch64_offset_9bit_signed_unscaled_p (machine_mode, poly_int64);
+char *aarch64_output_sve_prefetch (const char *, rtx, const char *);
 char *aarch64_output_sve_cnt_immediate (const char *, const char *, rtx);
+char *aarch64_output_sve_cnt_pat_immediate (const char *, const char *, rtx *);
 char *aarch64_output_sve_scalar_inc_dec (rtx);
 char *aarch64_output_sve_addvl_addpl (rtx);
 char *aarch64_output_sve_vector_inc_dec (const char *, rtx);
@@ -509,6 +535,7 @@ char *aarch64_output_scalar_simd_mov_immediate (rtx, scalar_int_mode);
 char *aarch64_output_simd_mov_immediate (rtx, unsigned,
                        enum simd_immediate_check w = AARCH64_CHECK_MOV);
 char *aarch64_output_sve_mov_immediate (rtx);
+char *aarch64_output_sve_ptrues (rtx);
 bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
 bool aarch64_regno_ok_for_base_p (int, bool);
 bool aarch64_regno_ok_for_index_p (int, bool);
@@ -517,11 +544,13 @@ bool aarch64_simd_check_vect_par_cnst_half (rtx op, machine_mode mode,
                                            bool high);
 bool aarch64_simd_scalar_immediate_valid_for_move (rtx, scalar_int_mode);
 bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool);
+bool aarch64_sve_ptrue_svpattern_p (rtx, struct simd_immediate_info *);
 bool aarch64_simd_valid_immediate (rtx, struct simd_immediate_info *,
                        enum simd_immediate_check w = AARCH64_CHECK_MOV);
 rtx aarch64_check_zero_based_sve_index_immediate (rtx);
 bool aarch64_sve_index_immediate_p (rtx);
 bool aarch64_sve_arith_immediate_p (rtx, bool);
+bool aarch64_sve_sqadd_sqsub_immediate_p (rtx, bool);
 bool aarch64_sve_bitmask_immediate_p (rtx);
 bool aarch64_sve_dup_immediate_p (rtx);
 bool aarch64_sve_cmp_immediate_p (rtx, bool);
@@ -552,7 +581,10 @@ rtx aarch64_simd_gen_const_vector_dup (machine_mode, HOST_WIDE_INT);
 bool aarch64_simd_mem_operand_p (rtx);
 bool aarch64_sve_ld1r_operand_p (rtx);
 bool aarch64_sve_ld1rq_operand_p (rtx);
+bool aarch64_sve_ldff1_operand_p (rtx);
+bool aarch64_sve_ldnf1_operand_p (rtx);
 bool aarch64_sve_ldr_operand_p (rtx);
+bool aarch64_sve_prefetch_operand_p (rtx, machine_mode);
 bool aarch64_sve_struct_memory_operand_p (rtx);
 rtx aarch64_simd_vect_par_cnst_half (machine_mode, int, bool);
 rtx aarch64_gen_stepped_int_parallel (unsigned int, int, int);
@@ -568,6 +600,9 @@ const char * aarch64_output_probe_sve_stack_clash (rtx, rtx, rtx, rtx);
 void aarch64_err_no_fpadvsimd (machine_mode);
 void aarch64_expand_epilogue (bool);
 rtx aarch64_ptrue_all (unsigned int);
+opt_machine_mode aarch64_ptrue_all_mode (rtx);
+rtx aarch64_convert_sve_data_to_pred (rtx, machine_mode, rtx);
+rtx aarch64_expand_sve_dupq (rtx, machine_mode, rtx);
 void aarch64_expand_mov_immediate (rtx, rtx);
 rtx aarch64_ptrue_reg (machine_mode);
 rtx aarch64_pfalse_reg (machine_mode);
@@ -576,6 +611,7 @@ bool aarch64_sve_same_pred_for_ptest_p (rtx *, rtx *);
 void aarch64_emit_sve_pred_move (rtx, rtx, rtx);
 void aarch64_expand_sve_mem_move (rtx, rtx, machine_mode);
 bool aarch64_maybe_expand_sve_subreg_move (rtx, rtx);
+rtx aarch64_replace_reg_mode (rtx, machine_mode);
 void aarch64_split_sve_subreg_move (rtx, rtx, rtx);
 void aarch64_expand_prologue (void);
 void aarch64_expand_vector_init (rtx, rtx);
@@ -664,6 +700,20 @@ tree aarch64_general_builtin_decl (unsigned, bool);
 tree aarch64_general_builtin_rsqrt (unsigned int);
 tree aarch64_builtin_vectorized_function (unsigned int, tree, tree);
 
+namespace aarch64_sve {
+  void init_builtins ();
+  void handle_arm_sve_h ();
+  tree builtin_decl (unsigned, bool);
+  bool builtin_type_p (const_tree);
+  const char *mangle_builtin_type (const_tree);
+  tree resolve_overloaded_builtin (location_t, unsigned int,
+                                  vec<tree, va_gc> *);
+  bool check_builtin_call (location_t, vec<location_t>, unsigned int,
+                          tree, unsigned int, tree *);
+  gimple *gimple_fold_builtin (unsigned int, gimple_stmt_iterator *, gcall *);
+  rtx expand_builtin (unsigned int, tree, rtx);
+}
+
 extern void aarch64_split_combinev16qi (rtx operands[3]);
 extern void aarch64_expand_vec_perm (rtx, rtx, rtx, rtx, unsigned int);
 extern void aarch64_expand_sve_vec_perm (rtx, rtx, rtx, rtx);
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.cc b/gcc/config/aarch64/aarch64-sve-builtins-base.cc
new file mode 100644 (file)
index 0000000..ce70f80
--- /dev/null
@@ -0,0 +1,2704 @@
+/* ACLE support for AArch64 SVE (__ARM_FEATURE_SVE intrinsics)
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "memmodel.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "recog.h"
+#include "expr.h"
+#include "basic-block.h"
+#include "function.h"
+#include "fold-const.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimplify.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "tree-vector-builder.h"
+#include "rtx-vector-builder.h"
+#include "vec-perm-indices.h"
+#include "aarch64-sve-builtins.h"
+#include "aarch64-sve-builtins-shapes.h"
+#include "aarch64-sve-builtins-base.h"
+#include "aarch64-sve-builtins-functions.h"
+
+using namespace aarch64_sve;
+
+namespace {
+
+/* Expand a call to svmad, or svmla after reordering its operands.
+   Make _m forms merge with argument MERGE_ARGNO.  */
+static rtx
+expand_mad (function_expander &e,
+           unsigned int merge_argno = DEFAULT_MERGE_ARGNO)
+{
+  if (e.pred == PRED_x)
+    {
+      insn_code icode;
+      if (e.type_suffix (0).integer_p)
+       icode = code_for_aarch64_pred_fma (e.vector_mode (0));
+      else
+       icode = code_for_aarch64_pred (UNSPEC_COND_FMLA, e.vector_mode (0));
+      return e.use_pred_x_insn (icode);
+    }
+
+  insn_code icode = e.direct_optab_handler (cond_fma_optab);
+  return e.use_cond_insn (icode, merge_argno);
+}
+
+/* Expand a call to svmsb, or svmls after reordering its operands.
+   Make _m forms merge with argument MERGE_ARGNO.  */
+static rtx
+expand_msb (function_expander &e,
+           unsigned int merge_argno = DEFAULT_MERGE_ARGNO)
+{
+  if (e.pred == PRED_x)
+    {
+      insn_code icode;
+      if (e.type_suffix (0).integer_p)
+       icode = code_for_aarch64_pred_fnma (e.vector_mode (0));
+      else
+       icode = code_for_aarch64_pred (UNSPEC_COND_FMLS, e.vector_mode (0));
+      return e.use_pred_x_insn (icode);
+    }
+
+  insn_code icode = e.direct_optab_handler (cond_fnma_optab);
+  return e.use_cond_insn (icode, merge_argno);
+}
+
+class svabd_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* The integer operations are represented as the subtraction of the
+       minimum from the maximum, with the signedness of the instruction
+       keyed off the signedness of the maximum operation.  */
+    rtx_code max_code = e.type_suffix (0).unsigned_p ? UMAX : SMAX;
+    insn_code icode;
+    if (e.pred == PRED_x)
+      {
+       if (e.type_suffix (0).integer_p)
+         icode = code_for_aarch64_pred_abd (max_code, e.vector_mode (0));
+       else
+         icode = code_for_aarch64_pred_abd (e.vector_mode (0));
+       return e.use_pred_x_insn (icode);
+      }
+
+    if (e.type_suffix (0).integer_p)
+      icode = code_for_aarch64_cond_abd (max_code, e.vector_mode (0));
+    else
+      icode = code_for_aarch64_cond_abd (e.vector_mode (0));
+    return e.use_cond_insn (icode);
+  }
+};
+
+/* Implements svacge, svacgt, svacle and svaclt.  */
+class svac_impl : public function_base
+{
+public:
+  CONSTEXPR svac_impl (int unspec) : m_unspec (unspec) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    e.add_ptrue_hint (0, e.gp_mode (0));
+    insn_code icode = code_for_aarch64_pred_fac (m_unspec, e.vector_mode (0));
+    return e.use_exact_insn (icode);
+  }
+
+  /* The unspec code for the underlying comparison.  */
+  int m_unspec;
+};
+
+class svadda_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Put the predicate last, as required by mask_fold_left_plus_optab.  */
+    e.rotate_inputs_left (0, 3);
+    machine_mode mode = e.vector_mode (0);
+    insn_code icode = direct_optab_handler (mask_fold_left_plus_optab, mode);
+    return e.use_exact_insn (icode);
+  }
+};
+
+/* Implements svadr[bhwd].  */
+class svadr_bhwd_impl : public function_base
+{
+public:
+  CONSTEXPR svadr_bhwd_impl (unsigned int shift) : m_shift (shift) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = GET_MODE (e.args[0]);
+    if (m_shift == 0)
+      return e.use_exact_insn (code_for_aarch64_adr (mode));
+
+    /* Turn the access size into an extra shift argument.  */
+    rtx shift = gen_int_mode (m_shift, GET_MODE_INNER (mode));
+    e.args.quick_push (expand_vector_broadcast (mode, shift));
+    return e.use_exact_insn (code_for_aarch64_adr_shift (mode));
+  }
+
+  /* How many bits left to shift the vector displacement.  */
+  unsigned int m_shift;
+};
+
+class svasrd_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_cond_insn (code_for_cond_asrd (e.vector_mode (0)));
+  }
+};
+
+class svbic_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Convert svbic of a constant into svand of its inverse.  */
+    if (CONST_INT_P (e.args[2]))
+      {
+       machine_mode mode = GET_MODE_INNER (e.vector_mode (0));
+       e.args[2] = simplify_unary_operation (NOT, mode, e.args[2], mode);
+       return e.map_to_rtx_codes (AND, AND, -1);
+      }
+
+    if (e.type_suffix_ids[0] == TYPE_SUFFIX_b)
+      {
+       gcc_assert (e.pred == PRED_z);
+       return e.use_exact_insn (CODE_FOR_aarch64_pred_bicvnx16bi_z);
+      }
+
+    if (e.pred == PRED_x)
+      return e.use_unpred_insn (code_for_aarch64_bic (e.vector_mode (0)));
+
+    return e.use_cond_insn (code_for_cond_bic (e.vector_mode (0)));
+  }
+};
+
+/* Implements svbrkn, svbrkpa and svbrkpb.  */
+class svbrk_binary_impl : public function_base
+{
+public:
+  CONSTEXPR svbrk_binary_impl (int unspec) : m_unspec (unspec) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (code_for_aarch64_brk (m_unspec));
+  }
+
+  /* The unspec code associated with the operation.  */
+  int m_unspec;
+};
+
+/* Implements svbrka and svbrkb.  */
+class svbrk_unary_impl : public function_base
+{
+public:
+  CONSTEXPR svbrk_unary_impl (int unspec) : m_unspec (unspec) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_cond_insn (code_for_aarch64_brk (m_unspec));
+  }
+
+  /* The unspec code associated with the operation.  */
+  int m_unspec;
+};
+
+class svcadd_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Convert the rotation amount into a specific unspec.  */
+    int rot = INTVAL (e.args[3]);
+    e.args.ordered_remove (3);
+    int unspec = (rot == 90 ? UNSPEC_COND_FCADD90
+                 : rot == 270 ? UNSPEC_COND_FCADD270
+                 : (gcc_unreachable (), 0));
+    return e.map_to_unspecs (-1, -1, unspec);
+  }
+};
+
+/* Implements svclasta and svclastb.  */
+class svclast_impl : public quiet<function_base>
+{
+public:
+  CONSTEXPR svclast_impl (int unspec) : m_unspec (unspec) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Match the fold_extract_optab order.  */
+    std::swap (e.args[0], e.args[1]);
+    machine_mode mode = e.vector_mode (0);
+    insn_code icode;
+    if (e.mode_suffix_id == MODE_n)
+      icode = code_for_fold_extract (m_unspec, mode);
+    else
+      icode = code_for_aarch64_fold_extract_vector (m_unspec, mode);
+    return e.use_exact_insn (icode);
+  }
+
+  /* The unspec code associated with the operation.  */
+  int m_unspec;
+};
+
+class svcmla_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Convert the rotation amount into a specific unspec.  */
+    int rot = INTVAL (e.args[4]);
+    e.args.ordered_remove (4);
+    int unspec = (rot == 0 ? UNSPEC_COND_FCMLA
+                 : rot == 90 ? UNSPEC_COND_FCMLA90
+                 : rot == 180 ? UNSPEC_COND_FCMLA180
+                 : rot == 270 ? UNSPEC_COND_FCMLA270
+                 : (gcc_unreachable (), 0));
+
+    /* Make the operand order the same as the one used by the fma optabs,
+       with the accumulator last.  */
+    e.rotate_inputs_left (1, 4);
+    return e.map_to_unspecs (-1, -1, unspec, 3);
+  }
+};
+
+class svcmla_lane_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Convert the rotation amount into a specific unspec.  */
+    int rot = INTVAL (e.args[4]);
+    e.args.ordered_remove (4);
+    int unspec = (rot == 0 ? UNSPEC_FCMLA
+                 : rot == 90 ? UNSPEC_FCMLA90
+                 : rot == 180 ? UNSPEC_FCMLA180
+                 : rot == 270 ? UNSPEC_FCMLA270
+                 : (gcc_unreachable (), 0));
+
+    /* Make the operand order the same as the one used by the fma optabs,
+       with the accumulator last.  */
+    e.rotate_inputs_left (0, 4);
+    insn_code icode = code_for_aarch64_lane (unspec, e.vector_mode (0));
+    return e.use_exact_insn (icode);
+  }
+};
+
+/* Implements svcmp<cc> (except svcmpuo, which is handled separately).  */
+class svcmp_impl : public function_base
+{
+public:
+  CONSTEXPR svcmp_impl (tree_code code, int unspec_for_fp)
+    : m_code (code), m_unspec_for_fp (unspec_for_fp) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+
+    /* Comparisons are UNSPEC_PRED_Z operations and so need a hint
+       operand.  */
+    e.add_ptrue_hint (0, e.gp_mode (0));
+
+    if (e.type_suffix (0).integer_p)
+      {
+       bool unsigned_p = e.type_suffix (0).unsigned_p;
+       rtx_code code = get_rtx_code (m_code, unsigned_p);
+       return e.use_exact_insn (code_for_aarch64_pred_cmp (code, mode));
+      }
+
+    insn_code icode = code_for_aarch64_pred_fcm (m_unspec_for_fp, mode);
+    return e.use_exact_insn (icode);
+  }
+
+  /* The tree code associated with the comparison.  */
+  tree_code m_code;
+
+  /* The unspec code to use for floating-point comparisons.  */
+  int m_unspec_for_fp;
+};
+
+/* Implements svcmp<cc>_wide.  */
+class svcmp_wide_impl : public function_base
+{
+public:
+  CONSTEXPR svcmp_wide_impl (tree_code code, int unspec_for_sint,
+                            int unspec_for_uint)
+    : m_code (code), m_unspec_for_sint (unspec_for_sint),
+      m_unspec_for_uint (unspec_for_uint) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+    bool unsigned_p = e.type_suffix (0).unsigned_p;
+    rtx_code code = get_rtx_code (m_code, unsigned_p);
+
+    /* Comparisons are UNSPEC_PRED_Z operations and so need a hint
+       operand.  */
+    e.add_ptrue_hint (0, e.gp_mode (0));
+
+    /* If the argument is a constant that the unwidened comparisons
+       can handle directly, use them instead.  */
+    insn_code icode = code_for_aarch64_pred_cmp (code, mode);
+    rtx op2 = unwrap_const_vec_duplicate (e.args[3]);
+    if (CONSTANT_P (op2)
+       && insn_data[icode].operand[4].predicate (op2, DImode))
+      {
+       e.args[3] = op2;
+       return e.use_exact_insn (icode);
+      }
+
+    int unspec = (unsigned_p ? m_unspec_for_uint : m_unspec_for_sint);
+    return e.use_exact_insn (code_for_aarch64_pred_cmp_wide (unspec, mode));
+  }
+
+  /* The tree code associated with the comparison.  */
+  tree_code m_code;
+
+  /* The unspec codes for signed and unsigned wide comparisons
+     respectively.  */
+  int m_unspec_for_sint;
+  int m_unspec_for_uint;
+};
+
+class svcmpuo_impl : public quiet<function_base>
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    e.add_ptrue_hint (0, e.gp_mode (0));
+    return e.use_exact_insn (code_for_aarch64_pred_fcmuo (e.vector_mode (0)));
+  }
+};
+
+class svcnot_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+    if (e.pred == PRED_x)
+      {
+       /* The pattern for CNOT includes an UNSPEC_PRED_Z, so needs
+          a ptrue hint.  */
+       e.add_ptrue_hint (0, e.gp_mode (0));
+       return e.use_pred_x_insn (code_for_aarch64_pred_cnot (mode));
+      }
+
+    return e.use_cond_insn (code_for_cond_cnot (mode), 0);
+  }
+};
+
+/* Implements svcnt[bhwd], which count the number of elements
+   in a particular vector mode.  */
+class svcnt_bhwd_impl : public function_base
+{
+public:
+  CONSTEXPR svcnt_bhwd_impl (machine_mode ref_mode) : m_ref_mode (ref_mode) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree count = build_int_cstu (TREE_TYPE (f.lhs),
+                                GET_MODE_NUNITS (m_ref_mode));
+    return gimple_build_assign (f.lhs, count);
+  }
+
+  rtx
+  expand (function_expander &) const OVERRIDE
+  {
+    return gen_int_mode (GET_MODE_NUNITS (m_ref_mode), DImode);
+  }
+
+  /* The mode of the vector associated with the [bhwd] suffix.  */
+  machine_mode m_ref_mode;
+};
+
+/* Implements svcnt[bhwd]_pat.  */
+class svcnt_bhwd_pat_impl : public svcnt_bhwd_impl
+{
+public:
+  CONSTEXPR svcnt_bhwd_pat_impl (machine_mode ref_mode)
+    : svcnt_bhwd_impl (ref_mode) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree pattern_arg = gimple_call_arg (f.call, 0);
+    aarch64_svpattern pattern = (aarch64_svpattern) tree_to_shwi (pattern_arg);
+
+    if (pattern == AARCH64_SV_ALL)
+      /* svcvnt[bwhd]_pat (SV_ALL) == svcnt[bwhd] ().  */
+      return svcnt_bhwd_impl::fold (f);
+
+    /* See whether we can count the number of elements in the pattern
+       at compile time.  */
+    unsigned int elements_per_vq = 128 / GET_MODE_UNIT_BITSIZE (m_ref_mode);
+    HOST_WIDE_INT value = aarch64_fold_sve_cnt_pat (pattern, elements_per_vq);
+    if (value >= 0)
+      {
+       tree count = build_int_cstu (TREE_TYPE (f.lhs), value);
+       return gimple_build_assign (f.lhs, count);
+      }
+
+    return NULL;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    unsigned int elements_per_vq = 128 / GET_MODE_UNIT_BITSIZE (m_ref_mode);
+    e.args.quick_push (gen_int_mode (elements_per_vq, DImode));
+    e.args.quick_push (const1_rtx);
+    return e.use_exact_insn (CODE_FOR_aarch64_sve_cnt_pat);
+  }
+};
+
+class svcntp_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+    e.add_ptrue_hint (0, mode);
+    return e.use_exact_insn (code_for_aarch64_pred_cntp (mode));
+  }
+};
+
+class svcompact_impl : public quiet<function_base>
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (code_for_aarch64_sve_compact (e.vector_mode (0)));
+  }
+};
+
+/* Implements svcreate2, svcreate3 and svcreate4.  */
+class svcreate_impl : public quiet<multi_vector_function>
+{
+public:
+  CONSTEXPR svcreate_impl (unsigned int vectors_per_tuple)
+    : quiet<multi_vector_function> (vectors_per_tuple) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    unsigned int nargs = gimple_call_num_args (f.call);
+    tree lhs_type = TREE_TYPE (f.lhs);
+
+    /* Replace the call with a clobber of the result (to prevent it from
+       becoming upwards exposed) followed by stores into each individual
+       vector of tuple.
+
+       The fold routines expect the replacement statement to have the
+       same lhs as the original call, so return the clobber statement
+       rather than the final vector store.  */
+    gassign *clobber = gimple_build_assign (f.lhs, build_clobber (lhs_type));
+
+    for (unsigned int i = nargs; i-- > 0; )
+      {
+       tree rhs_vector = gimple_call_arg (f.call, i);
+       tree field = tuple_type_field (TREE_TYPE (f.lhs));
+       tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
+                                unshare_expr (f.lhs), field, NULL_TREE);
+       tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector),
+                                 lhs_array, size_int (i),
+                                 NULL_TREE, NULL_TREE);
+       gassign *assign = gimple_build_assign (lhs_vector, rhs_vector);
+       gsi_insert_after (f.gsi, assign, GSI_SAME_STMT);
+      }
+    return clobber;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    rtx lhs_tuple = e.get_nonoverlapping_reg_target ();
+
+    /* Record that LHS_TUPLE is dead before the first store.  */
+    emit_clobber (lhs_tuple);
+    for (unsigned int i = 0; i < e.args.length (); ++i)
+      {
+       /* Use an lvalue subreg to refer to vector I in LHS_TUPLE.  */
+       rtx lhs_vector = simplify_gen_subreg (GET_MODE (e.args[i]),
+                                             lhs_tuple, GET_MODE (lhs_tuple),
+                                             i * BYTES_PER_SVE_VECTOR);
+       emit_move_insn (lhs_vector, e.args[i]);
+      }
+    return lhs_tuple;
+  }
+};
+
+class svcvt_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode0 = e.vector_mode (0);
+    machine_mode mode1 = e.vector_mode (1);
+    insn_code icode;
+    /* All this complication comes from the need to select four things
+       simultaneously:
+
+       (1) the kind of conversion (int<-float, float<-int, float<-float)
+       (2) signed vs. unsigned integers, where relevant
+       (3) the predication mode, which must be the wider of the predication
+          modes for MODE0 and MODE1
+       (4) the predication type (m, x or z)
+
+       The only supported int<->float conversions for which the integer is
+       narrower than the float are SI<->DF.  It's therefore more convenient
+       to handle (3) by defining two patterns for int<->float conversions:
+       one in which the integer is at least as wide as the float and so
+       determines the predication mode, and another single SI<->DF pattern
+       in which the float's mode determines the predication mode (which is
+       always VNx2BI in that case).
+
+       The names of the patterns follow the optab convention of giving
+       the source mode before the destination mode.  */
+    if (e.type_suffix (1).integer_p)
+      {
+       int unspec = (e.type_suffix (1).unsigned_p
+                     ? UNSPEC_COND_UCVTF
+                     : UNSPEC_COND_SCVTF);
+       if (e.type_suffix (0).element_bytes <= e.type_suffix (1).element_bytes)
+         icode = (e.pred == PRED_x
+                  ? code_for_aarch64_sve_nonextend (unspec, mode1, mode0)
+                  : code_for_cond_nonextend (unspec, mode1, mode0));
+       else
+         icode = (e.pred == PRED_x
+                  ? code_for_aarch64_sve_extend (unspec, mode1, mode0)
+                  : code_for_cond_extend (unspec, mode1, mode0));
+      }
+    else
+      {
+       int unspec = (!e.type_suffix (0).integer_p ? UNSPEC_COND_FCVT
+                     : e.type_suffix (0).unsigned_p ? UNSPEC_COND_FCVTZU
+                     : UNSPEC_COND_FCVTZS);
+       if (e.type_suffix (0).element_bytes >= e.type_suffix (1).element_bytes)
+         icode = (e.pred == PRED_x
+                  ? code_for_aarch64_sve_nontrunc (unspec, mode1, mode0)
+                  : code_for_cond_nontrunc (unspec, mode1, mode0));
+       else
+         icode = (e.pred == PRED_x
+                  ? code_for_aarch64_sve_trunc (unspec, mode1, mode0)
+                  : code_for_cond_trunc (unspec, mode1, mode0));
+      }
+
+    if (e.pred == PRED_x)
+      return e.use_pred_x_insn (icode);
+    return e.use_cond_insn (icode);
+  }
+};
+
+class svdot_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* In the optab, the multiplication operands come before the accumulator
+       operand.  The optab is keyed off the multiplication mode.  */
+    e.rotate_inputs_left (0, 3);
+    insn_code icode
+      = e.direct_optab_handler_for_sign (sdot_prod_optab, udot_prod_optab,
+                                        0, GET_MODE (e.args[0]));
+    return e.use_unpred_insn (icode);
+  }
+};
+
+class svdot_lane_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Use the same ordering as the dot_prod_optab, with the
+       accumulator last.  */
+    e.rotate_inputs_left (0, 4);
+    int unspec = (e.type_suffix (0).unsigned_p ? UNSPEC_UDOT : UNSPEC_SDOT);
+    machine_mode mode = e.vector_mode (0);
+    return e.use_exact_insn (code_for_aarch64_dot_prod_lane (unspec, mode));
+  }
+};
+
+class svdup_impl : public quiet<function_base>
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree vec_type = TREE_TYPE (f.lhs);
+    tree rhs = gimple_call_arg (f.call, f.pred == PRED_none ? 0 : 1);
+
+    if (f.pred == PRED_none || f.pred == PRED_x)
+      {
+       if (CONSTANT_CLASS_P (rhs))
+         {
+           if (f.type_suffix (0).bool_p)
+             return (tree_to_shwi (rhs)
+                     ? f.fold_to_ptrue ()
+                     : f.fold_to_pfalse ());
+
+           tree rhs_vector = build_vector_from_val (vec_type, rhs);
+           return gimple_build_assign (f.lhs, rhs_vector);
+         }
+
+       /* Avoid folding _b to a VEC_DUPLICATE_EXPR, since to do that we
+          would need to introduce an extra and unwanted conversion to
+          the truth vector element type.  */
+       if (!f.type_suffix (0).bool_p)
+         return gimple_build_assign (f.lhs, VEC_DUPLICATE_EXPR, rhs);
+      }
+
+    return NULL;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    if (e.pred == PRED_none || e.pred == PRED_x)
+      /* There's no benefit to using predicated instructions for _x here.  */
+      return e.use_unpred_insn (e.direct_optab_handler (vec_duplicate_optab));
+
+    /* Model predicated svdups as a SEL in which the "true" value is
+       the duplicate of the function argument and the "false" value
+       is the value of inactive lanes.  */
+    insn_code icode;
+    machine_mode mode = e.vector_mode (0);
+    if (valid_for_const_vector_p (GET_MODE_INNER (mode), e.args.last ()))
+      /* Duplicate the constant to fill a vector.  The pattern optimizes
+        various cases involving constant operands, falling back to SEL
+        if necessary.  */
+      icode = code_for_vcond_mask (mode, mode);
+    else
+      /* Use the pattern for selecting between a duplicated scalar
+        variable and a vector fallback.  */
+      icode = code_for_aarch64_sel_dup (mode);
+    return e.use_vcond_mask_insn (icode);
+  }
+};
+
+class svdup_lane_impl : public quiet<function_base>
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* The native DUP lane has an index range of 64 bytes.  */
+    machine_mode mode = e.vector_mode (0);
+    if (CONST_INT_P (e.args[1])
+       && IN_RANGE (INTVAL (e.args[1]) * GET_MODE_UNIT_SIZE (mode), 0, 63))
+      return e.use_exact_insn (code_for_aarch64_sve_dup_lane (mode));
+
+    /* Treat svdup_lane as if it were svtbl_n.  */
+    return e.use_exact_insn (code_for_aarch64_sve_tbl (e.vector_mode (0)));
+  }
+};
+
+class svdupq_impl : public quiet<function_base>
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree vec_type = TREE_TYPE (f.lhs);
+    unsigned int nargs = gimple_call_num_args (f.call);
+    /* For predicates, pad out each argument so that we have one element
+       per bit.  */
+    unsigned int factor = (f.type_suffix (0).bool_p
+                          ? f.type_suffix (0).element_bytes : 1);
+    tree_vector_builder builder (vec_type, nargs * factor, 1);
+    for (unsigned int i = 0; i < nargs; ++i)
+      {
+       tree elt = gimple_call_arg (f.call, i);
+       if (!CONSTANT_CLASS_P (elt))
+         return NULL;
+       builder.quick_push (elt);
+       for (unsigned int j = 1; j < factor; ++j)
+         builder.quick_push (build_zero_cst (TREE_TYPE (vec_type)));
+      }
+    return gimple_build_assign (f.lhs, builder.build ());
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+    unsigned int elements_per_vq = e.args.length ();
+    if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+      {
+       /* Construct a vector of integers so that we can compare them against
+          zero below.  Zero vs. nonzero is the only distinction that
+          matters.  */
+       mode = aarch64_sve_int_mode (mode);
+       for (unsigned int i = 0; i < elements_per_vq; ++i)
+         e.args[i] = simplify_gen_unary (ZERO_EXTEND, GET_MODE_INNER (mode),
+                                         e.args[i], QImode);
+      }
+
+    /* Get the 128-bit Advanced SIMD vector for this data size.  */
+    scalar_mode element_mode = GET_MODE_INNER (mode);
+    machine_mode vq_mode = aarch64_vq_mode (element_mode).require ();
+    gcc_assert (known_eq (elements_per_vq, GET_MODE_NUNITS (vq_mode)));
+
+    /* Put the arguments into a 128-bit Advanced SIMD vector.  We want
+       argument N to go into architectural lane N, whereas Advanced SIMD
+       vectors are loaded memory lsb to register lsb.  We therefore need
+       to reverse the elements for big-endian targets.  */
+    rtx vq_reg = gen_reg_rtx (vq_mode);
+    rtvec vec = rtvec_alloc (elements_per_vq);
+    for (unsigned int i = 0; i < elements_per_vq; ++i)
+      {
+       unsigned int argno = BYTES_BIG_ENDIAN ? elements_per_vq - i - 1 : i;
+       RTVEC_ELT (vec, i) = e.args[argno];
+      }
+    aarch64_expand_vector_init (vq_reg, gen_rtx_PARALLEL (vq_mode, vec));
+
+    /* If the result is a boolean, compare the data vector against zero.  */
+    if (mode != e.vector_mode (0))
+      {
+       rtx data_dupq = aarch64_expand_sve_dupq (NULL, mode, vq_reg);
+       return aarch64_convert_sve_data_to_pred (e.possible_target,
+                                                e.vector_mode (0), data_dupq);
+      }
+
+    return aarch64_expand_sve_dupq (e.possible_target, mode, vq_reg);
+  }
+};
+
+class svdupq_lane_impl : public quiet<function_base>
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+    rtx index = e.args[1];
+    if (CONST_INT_P (index) && IN_RANGE (INTVAL (index), 0, 3))
+      {
+       /* Use the .Q form of DUP, which is the native instruction for
+          this function.  */
+       insn_code icode = code_for_aarch64_sve_dupq_lane (mode);
+       unsigned int num_indices = e.elements_per_vq (0);
+       rtx indices = aarch64_gen_stepped_int_parallel
+         (num_indices, INTVAL (index) * num_indices, 1);
+
+       e.add_output_operand (icode);
+       e.add_input_operand (icode, e.args[0]);
+       e.add_fixed_operand (indices);
+       return e.generate_insn (icode);
+      }
+
+    /* Build a .D TBL index for the pairs of doublewords that we want to
+       duplicate.  */
+    if (CONST_INT_P (index))
+      {
+       /* The index vector is a constant.  */
+       rtx_vector_builder builder (VNx2DImode, 2, 1);
+       builder.quick_push (gen_int_mode (INTVAL (index) * 2, DImode));
+       builder.quick_push (gen_int_mode (INTVAL (index) * 2 + 1, DImode));
+       index = builder.build ();
+      }
+    else
+      {
+       /* Duplicate INDEX * 2 to fill a DImode vector.  The ACLE spec
+          explicitly allows the top of the index to be dropped.  */
+       index = force_reg (DImode, simplify_gen_binary (ASHIFT, DImode,
+                                                       index, const1_rtx));
+       index = expand_vector_broadcast (VNx2DImode, index);
+
+       /* Get an alternating 0, 1 predicate.  */
+       rtx_vector_builder builder (VNx2BImode, 2, 1);
+       builder.quick_push (const0_rtx);
+       builder.quick_push (constm1_rtx);
+       rtx pg = force_reg (VNx2BImode, builder.build ());
+
+       /* Add one to the odd elements of the index.  */
+       rtx one = force_reg (VNx2DImode, CONST1_RTX (VNx2DImode));
+       rtx target = gen_reg_rtx (VNx2DImode);
+       emit_insn (gen_cond_addvnx2di (target, pg, index, one, index));
+       index = target;
+      }
+
+    e.args[0] = gen_lowpart (VNx2DImode, e.args[0]);
+    e.args[1] = index;
+    return e.use_exact_insn (CODE_FOR_aarch64_sve_tblvnx2di);
+  }
+};
+
+class svext_impl : public quiet<function_base>
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (code_for_aarch64_sve_ext (e.vector_mode (0)));
+  }
+};
+
+/* Implements svextb, svexth and svextw.  */
+class svext_bhw_impl : public function_base
+{
+public:
+  CONSTEXPR svext_bhw_impl (scalar_int_mode from_mode)
+    : m_from_mode (from_mode) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    if (e.type_suffix (0).unsigned_p)
+      {
+       /* Convert to an AND.  The widest we go is 0xffffffff, which fits
+          in a CONST_INT.  */
+       e.args.quick_push (GEN_INT (GET_MODE_MASK (m_from_mode)));
+       if (e.pred == PRED_m)
+         /* We now have arguments "(inactive, pg, op, mask)".  Convert this
+            to "(pg, op, mask, inactive)" so that the order matches svand_m
+            with an extra argument on the end.  Take the inactive elements
+            from this extra argument.  */
+         e.rotate_inputs_left (0, 4);
+       return e.map_to_rtx_codes (AND, AND, -1, 3);
+      }
+
+    machine_mode wide_mode = e.vector_mode (0);
+    poly_uint64 nunits = GET_MODE_NUNITS (wide_mode);
+    machine_mode narrow_mode
+      = aarch64_sve_data_mode (m_from_mode, nunits).require ();
+    if (e.pred == PRED_x)
+      {
+       insn_code icode = code_for_aarch64_pred_sxt (wide_mode, narrow_mode);
+       return e.use_pred_x_insn (icode);
+      }
+
+    insn_code icode = code_for_aarch64_cond_sxt (wide_mode, narrow_mode);
+    return e.use_cond_insn (icode);
+  }
+
+  /* The element mode that we're extending from.  */
+  scalar_int_mode m_from_mode;
+};
+
+/* Implements svget2, svget3 and svget4.  */
+class svget_impl : public quiet<multi_vector_function>
+{
+public:
+  CONSTEXPR svget_impl (unsigned int vectors_per_tuple)
+    : quiet<multi_vector_function> (vectors_per_tuple) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* Fold into a normal gimple component access.  */
+    tree rhs_tuple = gimple_call_arg (f.call, 0);
+    tree index = gimple_call_arg (f.call, 1);
+    tree field = tuple_type_field (TREE_TYPE (rhs_tuple));
+    tree rhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
+                            rhs_tuple, field, NULL_TREE);
+    tree rhs_vector = build4 (ARRAY_REF, TREE_TYPE (f.lhs),
+                             rhs_array, index, NULL_TREE, NULL_TREE);
+    return gimple_build_assign (f.lhs, rhs_vector);
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Fold the access into a subreg rvalue.  */
+    return simplify_gen_subreg (e.vector_mode (0), e.args[0],
+                               GET_MODE (e.args[0]),
+                               INTVAL (e.args[1]) * BYTES_PER_SVE_VECTOR);
+  }
+};
+
+class svindex_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (e.direct_optab_handler (vec_series_optab));
+  }
+};
+
+class svinsr_impl : public quiet<function_base>
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    gcall *new_call = gimple_build_call_internal (IFN_VEC_SHL_INSERT, 2,
+                                                 gimple_call_arg (f.call, 0),
+                                                 gimple_call_arg (f.call, 1));
+    gimple_call_set_lhs (new_call, f.lhs);
+    return new_call;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    insn_code icode = direct_optab_handler (vec_shl_insert_optab,
+                                           e.vector_mode (0));
+    return e.use_exact_insn (icode);
+  }
+};
+
+/* Implements svlasta and svlastb.  */
+class svlast_impl : public quiet<function_base>
+{
+public:
+  CONSTEXPR svlast_impl (int unspec) : m_unspec (unspec) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (code_for_extract (m_unspec, e.vector_mode (0)));
+  }
+
+  /* The unspec code associated with the operation.  */
+  int m_unspec;
+};
+
+class svld1_impl : public full_width_access
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_MEMORY;
+  }
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree vectype = f.vector_type (0);
+
+    /* Get the predicate and base pointer.  */
+    gimple_seq stmts = NULL;
+    tree pred = f.convert_pred (stmts, vectype, 0);
+    tree base = f.fold_contiguous_base (stmts, vectype);
+    gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+
+    tree cookie = f.load_store_cookie (TREE_TYPE (vectype));
+    gcall *new_call = gimple_build_call_internal (IFN_MASK_LOAD, 3,
+                                                 base, cookie, pred);
+    gimple_call_set_lhs (new_call, f.lhs);
+    return new_call;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    insn_code icode = convert_optab_handler (maskload_optab,
+                                            e.vector_mode (0), e.gp_mode (0));
+    return e.use_contiguous_load_insn (icode);
+  }
+};
+
+/* Implements extending contiguous forms of svld1.  */
+class svld1_extend_impl : public extending_load
+{
+public:
+  CONSTEXPR svld1_extend_impl (type_suffix_index memory_type)
+    : extending_load (memory_type) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    insn_code icode = code_for_aarch64_load (extend_rtx_code (),
+                                            e.vector_mode (0),
+                                            e.memory_vector_mode ());
+    return e.use_contiguous_load_insn (icode);
+  }
+};
+
+class svld1_gather_impl : public full_width_access
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_MEMORY;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    e.prepare_gather_address_operands (1);
+    /* Put the predicate last, as required by mask_gather_load_optab.  */
+    e.rotate_inputs_left (0, 5);
+    machine_mode mem_mode = e.memory_vector_mode ();
+    insn_code icode = direct_optab_handler (mask_gather_load_optab, mem_mode);
+    return e.use_exact_insn (icode);
+  }
+};
+
+/* Implements extending forms of svld1_gather.  */
+class svld1_gather_extend_impl : public extending_load
+{
+public:
+  CONSTEXPR svld1_gather_extend_impl (type_suffix_index memory_type)
+    : extending_load (memory_type) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    e.prepare_gather_address_operands (1);
+    /* Put the predicate last, since the extending gathers use the same
+       operand order as mask_gather_load_optab.  */
+    e.rotate_inputs_left (0, 5);
+    insn_code icode = code_for_aarch64_gather_load (extend_rtx_code (),
+                                                   e.vector_mode (0),
+                                                   e.memory_vector_mode ());
+    return e.use_exact_insn (icode);
+  }
+};
+
+class svld1rq_impl : public function_base
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_MEMORY;
+  }
+
+  tree
+  memory_scalar_type (const function_instance &fi) const OVERRIDE
+  {
+    return fi.scalar_type (0);
+  }
+
+  machine_mode
+  memory_vector_mode (const function_instance &fi) const OVERRIDE
+  {
+    return aarch64_vq_mode (GET_MODE_INNER (fi.vector_mode (0))).require ();
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    insn_code icode = code_for_aarch64_sve_ld1rq (e.vector_mode (0));
+    return e.use_contiguous_load_insn (icode);
+  }
+};
+
+/* Implements svld2, svld3 and svld4.  */
+class svld234_impl : public full_width_access
+{
+public:
+  CONSTEXPR svld234_impl (unsigned int vectors_per_tuple)
+    : full_width_access (vectors_per_tuple) {}
+
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_MEMORY;
+  }
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree tuple_type = TREE_TYPE (f.lhs);
+    tree vectype = f.vector_type (0);
+
+    /* Get the predicate and base pointer.  */
+    gimple_seq stmts = NULL;
+    tree pred = f.convert_pred (stmts, vectype, 0);
+    tree base = f.fold_contiguous_base (stmts, vectype);
+    gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+
+    /* Emit two statements: a clobber of the lhs, so that it isn't
+       upwards exposed, and then the load itself.
+
+       The fold routines expect the replacement statement to have the
+       same lhs as the original call, so return the clobber statement
+       rather than the load.  */
+    gimple *clobber = gimple_build_assign (f.lhs, build_clobber (tuple_type));
+
+    /* View the loaded data as an array of vectors.  */
+    tree field = tuple_type_field (tuple_type);
+    tree lhs_array = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (field),
+                            unshare_expr (f.lhs));
+
+    /* Emit the load itself.  */
+    tree cookie = f.load_store_cookie (TREE_TYPE (vectype));
+    gcall *new_call = gimple_build_call_internal (IFN_MASK_LOAD_LANES, 3,
+                                                 base, cookie, pred);
+    gimple_call_set_lhs (new_call, lhs_array);
+    gsi_insert_after (f.gsi, new_call, GSI_SAME_STMT);
+
+    return clobber;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode tuple_mode = TYPE_MODE (TREE_TYPE (e.call_expr));
+    insn_code icode = convert_optab_handler (vec_mask_load_lanes_optab,
+                                            tuple_mode, e.vector_mode (0));
+    return e.use_contiguous_load_insn (icode);
+  }
+};
+
+class svldff1_gather_impl : public full_width_access
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_MEMORY | CP_READ_FFR | CP_WRITE_FFR;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* See the block comment in aarch64-sve.md for details about the
+       FFR handling.  */
+    emit_insn (gen_aarch64_update_ffr_for_load ());
+
+    e.prepare_gather_address_operands (1);
+    /* Put the predicate last, since ldff1_gather uses the same operand
+       order as mask_gather_load_optab.  */
+    e.rotate_inputs_left (0, 5);
+    machine_mode mem_mode = e.memory_vector_mode ();
+    return e.use_exact_insn (code_for_aarch64_ldff1_gather (mem_mode));
+  }
+};
+
+/* Implements extending forms of svldff1_gather.  */
+class svldff1_gather_extend : public extending_load
+{
+public:
+  CONSTEXPR svldff1_gather_extend (type_suffix_index memory_type)
+    : extending_load (memory_type) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* See the block comment in aarch64-sve.md for details about the
+       FFR handling.  */
+    emit_insn (gen_aarch64_update_ffr_for_load ());
+
+    e.prepare_gather_address_operands (1);
+    /* Put the predicate last, since ldff1_gather uses the same operand
+       order as mask_gather_load_optab.  */
+    e.rotate_inputs_left (0, 5);
+    insn_code icode = code_for_aarch64_ldff1_gather (extend_rtx_code (),
+                                                    e.vector_mode (0),
+                                                    e.memory_vector_mode ());
+    return e.use_exact_insn (icode);
+  }
+};
+
+class svldnt1_impl : public full_width_access
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_MEMORY;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    insn_code icode = code_for_aarch64_ldnt1 (e.vector_mode (0));
+    return e.use_contiguous_load_insn (icode);
+  }
+};
+
+/* Implements svldff1 and svldnf1.  */
+class svldxf1_impl : public full_width_access
+{
+public:
+  CONSTEXPR svldxf1_impl (int unspec) : m_unspec (unspec) {}
+
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_MEMORY | CP_READ_FFR | CP_WRITE_FFR;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* See the block comment in aarch64-sve.md for details about the
+       FFR handling.  */
+    emit_insn (gen_aarch64_update_ffr_for_load ());
+
+    machine_mode mode = e.vector_mode (0);
+    return e.use_contiguous_load_insn (code_for_aarch64_ldf1 (m_unspec, mode));
+  }
+
+  /* The unspec associated with the load.  */
+  int m_unspec;
+};
+
+/* Implements extending contiguous forms of svldff1 and svldnf1.  */
+class svldxf1_extend_impl : public extending_load
+{
+public:
+  CONSTEXPR svldxf1_extend_impl (type_suffix_index memory_type, int unspec)
+    : extending_load (memory_type), m_unspec (unspec) {}
+
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_MEMORY | CP_READ_FFR | CP_WRITE_FFR;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* See the block comment in aarch64-sve.md for details about the
+       FFR handling.  */
+    emit_insn (gen_aarch64_update_ffr_for_load ());
+
+    insn_code icode = code_for_aarch64_ldf1 (m_unspec, extend_rtx_code (),
+                                            e.vector_mode (0),
+                                            e.memory_vector_mode ());
+    return e.use_contiguous_load_insn (icode);
+  }
+
+  /* The unspec associated with the load.  */
+  int m_unspec;
+};
+
+class svlen_impl : public quiet<function_base>
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* The argument only exists for its type.  */
+    tree rhs_type = TREE_TYPE (gimple_call_arg (f.call, 0));
+    tree count = build_int_cstu (TREE_TYPE (f.lhs),
+                                TYPE_VECTOR_SUBPARTS (rhs_type));
+    return gimple_build_assign (f.lhs, count);
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* The argument only exists for its type.  */
+    return gen_int_mode (GET_MODE_NUNITS (e.vector_mode (0)), DImode);
+  }
+};
+
+class svmad_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return expand_mad (e);
+  }
+};
+
+class svmla_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Put the accumulator at the end (argument 3), but keep it as the
+       merge input for _m functions.  */
+    e.rotate_inputs_left (1, 4);
+    return expand_mad (e, 3);
+  }
+};
+
+/* Base class for svmla_lane and svmls_lane.  */
+class svmla_svmls_lane_impl : public function_base
+{
+public:
+  CONSTEXPR svmla_svmls_lane_impl (int unspec)
+    : m_unspec (unspec) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Put the operands in the normal (fma ...) order, with the accumulator
+       last.  This fits naturally since that's also the unprinted operand
+       in the asm output.  */
+    e.rotate_inputs_left (0, 4);
+    insn_code icode = code_for_aarch64_lane (m_unspec, e.vector_mode (0));
+    return e.use_exact_insn (icode);
+  }
+
+  /* The unspec code associated with the operation.  */
+  int m_unspec;
+};
+
+class svmls_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Put the accumulator at the end (argument 3), but keep it as the
+       merge input for _m functions.  */
+    e.rotate_inputs_left (1, 4);
+    return expand_msb (e, 3);
+  }
+};
+
+class svmov_impl : public function_base
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    return gimple_build_assign (f.lhs, BIT_AND_EXPR,
+                               gimple_call_arg (f.call, 0),
+                               gimple_call_arg (f.call, 1));
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* The canonical form for the assembler alias "MOV Pa.B, Pb/Z, Pc.B"
+       is "AND Pa.B, Pb/Z, Pc.B, Pc.B".  */
+    gcc_assert (e.pred == PRED_z);
+    e.args.quick_push (e.args[1]);
+    return e.use_exact_insn (CODE_FOR_aarch64_pred_andvnx16bi_z);
+  }
+};
+
+class svmsb_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return expand_msb (e);
+  }
+};
+
+class svmul_lane_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (code_for_aarch64_mul_lane (e.vector_mode (0)));
+  }
+};
+
+class svnand_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    gcc_assert (e.pred == PRED_z);
+    return e.use_exact_insn (CODE_FOR_aarch64_pred_nandvnx16bi_z);
+  }
+};
+
+class svnor_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    gcc_assert (e.pred == PRED_z);
+    return e.use_exact_insn (CODE_FOR_aarch64_pred_norvnx16bi_z);
+  }
+};
+
+class svnot_impl : public rtx_code_function
+{
+public:
+  CONSTEXPR svnot_impl () : rtx_code_function (NOT, NOT, -1) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    if (e.type_suffix_ids[0] == TYPE_SUFFIX_b)
+      {
+       /* The canonical form for the assembler alias "NOT Pa.B, Pb/Z, Pc.B"
+          is "EOR Pa.B, Pb/Z, Pb.B, Pc.B".  */
+       gcc_assert (e.pred == PRED_z);
+       e.args.quick_insert (1, e.args[0]);
+       return e.use_exact_insn (CODE_FOR_aarch64_pred_xorvnx16bi_z);
+      }
+    return rtx_code_function::expand (e);
+  }
+};
+
+class svorn_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    gcc_assert (e.pred == PRED_z);
+    return e.use_exact_insn (CODE_FOR_aarch64_pred_ornvnx16bi_z);
+  }
+};
+
+class svpfalse_impl : public function_base
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    return f.fold_to_pfalse ();
+  }
+
+  rtx
+  expand (function_expander &) const OVERRIDE
+  {
+    return CONST0_RTX (VNx16BImode);
+  }
+};
+
+/* Implements svpfirst and svpnext, which share the same .md patterns.  */
+class svpfirst_svpnext_impl : public function_base
+{
+public:
+  CONSTEXPR svpfirst_svpnext_impl (int unspec) : m_unspec (unspec) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+    e.add_ptrue_hint (0, mode);
+    return e.use_exact_insn (code_for_aarch64_sve (m_unspec, mode));
+  }
+
+  /* The unspec associated with the operation.  */
+  int m_unspec;
+};
+
+/* Implements contiguous forms of svprf[bhwd].  */
+class svprf_bhwd_impl : public function_base
+{
+public:
+  CONSTEXPR svprf_bhwd_impl (machine_mode mode) : m_mode (mode) {}
+
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_PREFETCH_MEMORY;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    e.prepare_prefetch_operands ();
+    insn_code icode = code_for_aarch64_sve_prefetch (m_mode);
+    return e.use_contiguous_prefetch_insn (icode);
+  }
+
+  /* The mode that we'd use to hold one vector of prefetched data.  */
+  machine_mode m_mode;
+};
+
+/* Implements svprf[bhwd]_gather.  */
+class svprf_bhwd_gather_impl : public function_base
+{
+public:
+  CONSTEXPR svprf_bhwd_gather_impl (machine_mode mode) : m_mode (mode) {}
+
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_PREFETCH_MEMORY;
+  }
+
+  machine_mode
+  memory_vector_mode (const function_instance &) const OVERRIDE
+  {
+    return m_mode;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    e.prepare_prefetch_operands ();
+    e.prepare_gather_address_operands (1);
+
+    /* Insert a zero operand to identify the mode of the memory being
+       accessed.  This goes between the gather operands and prefetch
+       operands created above.  */
+    e.args.quick_insert (5, CONST0_RTX (m_mode));
+
+    machine_mode reg_mode = GET_MODE (e.args[2]);
+    insn_code icode = code_for_aarch64_sve_gather_prefetch (m_mode, reg_mode);
+    return e.use_exact_insn (icode);
+  }
+
+  /* The mode that we'd use to hold one vector of prefetched data.  */
+  machine_mode m_mode;
+};
+
+/* Implements svptest_any, svptest_first and svptest_last.  */
+class svptest_impl : public function_base
+{
+public:
+  CONSTEXPR svptest_impl (rtx_code compare) : m_compare (compare) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* See whether GP is an exact ptrue for some predicate mode;
+       i.e. whether converting the GP to that mode will not drop
+       set bits and will leave all significant bits set.  */
+    machine_mode wide_mode;
+    int hint;
+    if (aarch64_ptrue_all_mode (e.args[0]).exists (&wide_mode))
+      hint = SVE_KNOWN_PTRUE;
+    else
+      {
+       hint = SVE_MAYBE_NOT_PTRUE;
+       wide_mode = VNx16BImode;
+      }
+
+    /* Generate the PTEST itself.  */
+    rtx pg = force_reg (VNx16BImode, e.args[0]);
+    rtx wide_pg = gen_lowpart (wide_mode, pg);
+    rtx hint_rtx = gen_int_mode (hint, DImode);
+    rtx op = force_reg (wide_mode, gen_lowpart (wide_mode, e.args[1]));
+    emit_insn (gen_aarch64_ptestvnx16bi (pg, wide_pg, hint_rtx, op));
+
+    /* Get the location of the boolean result.  We can provide SImode and
+       DImode values directly; rely on generic code to convert others.  */
+    rtx target = e.possible_target;
+    if (!target
+       || !REG_P (target)
+       || (GET_MODE (target) != SImode && GET_MODE (target) != DImode))
+      target = gen_reg_rtx (DImode);
+
+    /* Generate a CSET to convert the CC result of the PTEST to a boolean.  */
+    rtx cc_reg = gen_rtx_REG (CC_NZCmode, CC_REGNUM);
+    rtx compare = gen_rtx_fmt_ee (m_compare, GET_MODE (target),
+                                 cc_reg, const0_rtx);
+    emit_insn (gen_rtx_SET (target, compare));
+    return target;
+  }
+
+  /* The comparison code associated with ptest condition.  */
+  rtx_code m_compare;
+};
+
+class svptrue_impl : public function_base
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    return f.fold_to_ptrue ();
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return aarch64_ptrue_all (e.type_suffix (0).element_bytes);
+  }
+};
+
+class svptrue_pat_impl : public function_base
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree pattern_arg = gimple_call_arg (f.call, 0);
+    aarch64_svpattern pattern = (aarch64_svpattern) tree_to_shwi (pattern_arg);
+
+    if (pattern == AARCH64_SV_ALL)
+      /* svptrue_pat_bN (SV_ALL) == svptrue_bN ().  */
+      return f.fold_to_ptrue ();
+
+    /* See whether we can count the number of elements in the pattern
+       at compile time.  If so, construct a predicate with that number
+       of 1s followed by all 0s.  */
+    int nelts_per_vq = f.elements_per_vq (0);
+    HOST_WIDE_INT value = aarch64_fold_sve_cnt_pat (pattern, nelts_per_vq);
+    if (value >= 0)
+      return f.fold_to_vl_pred (value);
+
+    return NULL;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* In rtl, the predicate is represented as the constant:
+
+         (const:V16BI (unspec:V16BI [(const_int PATTERN)
+                                    (const_vector:VnnBI [zeros])]
+                                   UNSPEC_PTRUE))
+
+       where nn determines the element size.  */
+    rtvec vec = gen_rtvec (2, e.args[0], CONST0_RTX (e.vector_mode (0)));
+    return gen_rtx_CONST (VNx16BImode,
+                         gen_rtx_UNSPEC (VNx16BImode, vec, UNSPEC_PTRUE));
+  }
+};
+
+class svqadd_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.expand_signed_unpred_op (SS_PLUS, US_PLUS);
+  }
+};
+
+/* Implements svqdec[bhwd]{,_pat} and svqinc[bhwd]{,_pat}.  */
+class svqdec_svqinc_bhwd_impl : public function_base
+{
+public:
+  CONSTEXPR svqdec_svqinc_bhwd_impl (rtx_code code_for_sint,
+                                    rtx_code code_for_uint,
+                                    scalar_int_mode elem_mode)
+    : m_code_for_sint (code_for_sint),
+      m_code_for_uint (code_for_uint),
+      m_elem_mode (elem_mode)
+  {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Treat non-_pat functions in the same way as _pat functions with
+       an SV_ALL argument.  */
+    if (e.args.length () == 2)
+      e.args.quick_insert (1, gen_int_mode (AARCH64_SV_ALL, DImode));
+
+    /* Insert the number of elements per 128-bit block as a fake argument,
+       between the pattern and the multiplier.  Arguments 1, 2 and 3 then
+       correspond exactly with the 3 UNSPEC_SVE_CNT_PAT operands; see
+       aarch64_sve_cnt_pat for details.  */
+    unsigned int elements_per_vq = 128 / GET_MODE_BITSIZE (m_elem_mode);
+    e.args.quick_insert (2, gen_int_mode (elements_per_vq, DImode));
+
+    rtx_code code = (e.type_suffix (0).unsigned_p
+                    ? m_code_for_uint
+                    : m_code_for_sint);
+
+    /* Choose between operating on integer scalars or integer vectors.  */
+    machine_mode mode = e.vector_mode (0);
+    if (e.mode_suffix_id == MODE_n)
+      mode = GET_MODE_INNER (mode);
+    return e.use_exact_insn (code_for_aarch64_sve_pat (code, mode));
+  }
+
+  /* The saturating addition or subtraction codes to use for signed and
+     unsigned values respectively.  */
+  rtx_code m_code_for_sint;
+  rtx_code m_code_for_uint;
+
+  /* The integer mode associated with the [bhwd] suffix.  */
+  scalar_int_mode m_elem_mode;
+};
+
+/* Implements svqdec[bhwd]{,_pat}.  */
+class svqdec_bhwd_impl : public svqdec_svqinc_bhwd_impl
+{
+public:
+  CONSTEXPR svqdec_bhwd_impl (scalar_int_mode elem_mode)
+    : svqdec_svqinc_bhwd_impl (SS_MINUS, US_MINUS, elem_mode) {}
+};
+
+/* Implements svqinc[bhwd]{,_pat}.  */
+class svqinc_bhwd_impl : public svqdec_svqinc_bhwd_impl
+{
+public:
+  CONSTEXPR svqinc_bhwd_impl (scalar_int_mode elem_mode)
+    : svqdec_svqinc_bhwd_impl (SS_PLUS, US_PLUS, elem_mode) {}
+};
+
+/* Implements svqdecp and svqincp.  */
+class svqdecp_svqincp_impl : public function_base
+{
+public:
+  CONSTEXPR svqdecp_svqincp_impl (rtx_code code_for_sint,
+                                 rtx_code code_for_uint)
+    : m_code_for_sint (code_for_sint),
+      m_code_for_uint (code_for_uint)
+  {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    rtx_code code = (e.type_suffix (0).unsigned_p
+                    ? m_code_for_uint
+                    : m_code_for_sint);
+    insn_code icode;
+    if (e.mode_suffix_id == MODE_n)
+      {
+       /* Increment or decrement a scalar (whose mode is given by the first
+          type suffix) by the number of active elements in a predicate
+          (whose mode is given by the second type suffix).  */
+       machine_mode mode = GET_MODE_INNER (e.vector_mode (0));
+       icode = code_for_aarch64_sve_cntp (code, mode, e.vector_mode (1));
+      }
+    else
+      /* Increment a vector by the number of active elements in a predicate,
+        with the vector mode determining the predicate mode.  */
+      icode = code_for_aarch64_sve_cntp (code, e.vector_mode (0));
+    return e.use_exact_insn (icode);
+  }
+
+  /* The saturating addition or subtraction codes to use for signed and
+     unsigned values respectively.  */
+  rtx_code m_code_for_sint;
+  rtx_code m_code_for_uint;
+};
+
+class svqsub_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.expand_signed_unpred_op (SS_MINUS, US_MINUS);
+  }
+};
+
+class svrdffr_impl : public function_base
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_FFR;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* See the block comment in aarch64-sve.md for details about the
+       FFR handling.  */
+    emit_insn (gen_aarch64_copy_ffr_to_ffrt ());
+    rtx result = e.use_exact_insn (e.pred == PRED_z
+                                  ? CODE_FOR_aarch64_rdffr_z
+                                  : CODE_FOR_aarch64_rdffr);
+    emit_insn (gen_aarch64_update_ffrt ());
+    return result;
+  }
+};
+
+class svreinterpret_impl : public quiet<function_base>
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* Punt to rtl if the effect of the reinterpret on registers does not
+       conform to GCC's endianness model.  */
+    if (!targetm.can_change_mode_class (f.vector_mode (0),
+                                       f.vector_mode (1), FP_REGS))
+      return NULL;
+
+    /* Otherwise svreinterpret corresponds directly to a VIEW_CONVERT_EXPR
+       reinterpretation.  */
+    tree rhs = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (f.lhs),
+                      gimple_call_arg (f.call, 0));
+    return gimple_build_assign (f.lhs, VIEW_CONVERT_EXPR, rhs);
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+    return e.use_exact_insn (code_for_aarch64_sve_reinterpret (mode));
+  }
+};
+
+class svrev_impl : public permute
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* Punt for now on _b16 and wider; we'd need more complex evpc logic
+       to rerecognize the result.  */
+    if (f.type_suffix (0).bool_p && f.type_suffix (0).element_bits > 8)
+      return NULL;
+
+    /* Permute as { nelts - 1, nelts - 2, nelts - 3, ... }.  */
+    poly_int64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+    vec_perm_builder builder (nelts, 1, 3);
+    for (int i = 0; i < 3; ++i)
+      builder.quick_push (nelts - i - 1);
+    return fold_permute (f, builder);
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (code_for_aarch64_sve_rev (e.vector_mode (0)));
+  }
+};
+
+class svsel_impl : public quiet<function_base>
+{
+public:
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* svsel corresponds exactly to VEC_COND_EXPR.  */
+    gimple_seq stmts = NULL;
+    tree pred = f.convert_pred (stmts, f.vector_type (0), 0);
+    gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+    return gimple_build_assign (f.lhs, VEC_COND_EXPR, pred,
+                               gimple_call_arg (f.call, 1),
+                               gimple_call_arg (f.call, 2));
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* svsel (cond, truev, falsev) is vcond_mask (truev, falsev, cond).  */
+    e.rotate_inputs_left (0, 3);
+    insn_code icode = convert_optab_handler (vcond_mask_optab,
+                                            e.vector_mode (0),
+                                            e.gp_mode (0));
+    return e.use_exact_insn (icode);
+  }
+};
+
+/* Implements svset2, svset3 and svset4.  */
+class svset_impl : public quiet<multi_vector_function>
+{
+public:
+  CONSTEXPR svset_impl (unsigned int vectors_per_tuple)
+    : quiet<multi_vector_function> (vectors_per_tuple) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree rhs_tuple = gimple_call_arg (f.call, 0);
+    tree index = gimple_call_arg (f.call, 1);
+    tree rhs_vector = gimple_call_arg (f.call, 2);
+
+    /* Replace the call with two statements: a copy of the full tuple
+       to the call result, followed by an update of the individual vector.
+
+       The fold routines expect the replacement statement to have the
+       same lhs as the original call, so return the copy statement
+       rather than the field update.  */
+    gassign *copy = gimple_build_assign (unshare_expr (f.lhs), rhs_tuple);
+
+    /* Get a reference to the individual vector.  */
+    tree field = tuple_type_field (TREE_TYPE (f.lhs));
+    tree lhs_array = build3 (COMPONENT_REF, TREE_TYPE (field),
+                            f.lhs, field, NULL_TREE);
+    tree lhs_vector = build4 (ARRAY_REF, TREE_TYPE (rhs_vector),
+                             lhs_array, index, NULL_TREE, NULL_TREE);
+    gassign *update = gimple_build_assign (lhs_vector, rhs_vector);
+    gsi_insert_after (f.gsi, update, GSI_SAME_STMT);
+
+    return copy;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    rtx rhs_tuple = e.args[0];
+    unsigned int index = INTVAL (e.args[1]);
+    rtx rhs_vector = e.args[2];
+
+    /* First copy the full tuple to the target register.  */
+    rtx lhs_tuple = e.get_nonoverlapping_reg_target ();
+    emit_move_insn (lhs_tuple, rhs_tuple);
+
+    /* ...then update the individual vector.  */
+    rtx lhs_vector = simplify_gen_subreg (GET_MODE (rhs_vector),
+                                         lhs_tuple, GET_MODE (lhs_tuple),
+                                         index * BYTES_PER_SVE_VECTOR);
+    emit_move_insn (lhs_vector, rhs_vector);
+    return lhs_vector;
+  }
+};
+
+class svsetffr_impl : public function_base
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_WRITE_FFR;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    e.args.quick_push (CONSTM1_RTX (VNx16BImode));
+    return e.use_exact_insn (CODE_FOR_aarch64_wrffr);
+  }
+};
+
+class svsplice_impl : public quiet<function_base>
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (code_for_aarch64_sve_splice (e.vector_mode (0)));
+  }
+};
+
+class svst1_impl : public full_width_access
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_WRITE_MEMORY;
+  }
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree vectype = f.vector_type (0);
+
+    /* Get the predicate and base pointer.  */
+    gimple_seq stmts = NULL;
+    tree pred = f.convert_pred (stmts, vectype, 0);
+    tree base = f.fold_contiguous_base (stmts, vectype);
+    gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+
+    tree cookie = f.load_store_cookie (TREE_TYPE (vectype));
+    tree rhs = gimple_call_arg (f.call, gimple_call_num_args (f.call) - 1);
+    return gimple_build_call_internal (IFN_MASK_STORE, 4,
+                                      base, cookie, pred, rhs);
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    insn_code icode = convert_optab_handler (maskstore_optab,
+                                            e.vector_mode (0), e.gp_mode (0));
+    return e.use_contiguous_store_insn (icode);
+  }
+};
+
+class svst1_scatter_impl : public full_width_access
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_WRITE_MEMORY;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    e.prepare_gather_address_operands (1);
+    /* Put the predicate last, as required by mask_scatter_store_optab.  */
+    e.rotate_inputs_left (0, 6);
+    insn_code icode = direct_optab_handler (mask_scatter_store_optab,
+                                           e.memory_vector_mode ());
+    return e.use_exact_insn (icode);
+  }
+};
+
+/* Implements truncating forms of svst1_scatter.  */
+class svst1_scatter_truncate_impl : public truncating_store
+{
+public:
+  CONSTEXPR svst1_scatter_truncate_impl (scalar_int_mode to_mode)
+    : truncating_store (to_mode) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    e.prepare_gather_address_operands (1);
+    /* Put the predicate last, since the truncating scatters use the same
+       operand order as mask_scatter_store_optab.  */
+    e.rotate_inputs_left (0, 6);
+    insn_code icode = code_for_aarch64_scatter_store_trunc
+      (e.memory_vector_mode (), e.vector_mode (0));
+    return e.use_exact_insn (icode);
+  }
+};
+
+/* Implements truncating contiguous forms of svst1.  */
+class svst1_truncate_impl : public truncating_store
+{
+public:
+  CONSTEXPR svst1_truncate_impl (scalar_int_mode to_mode)
+    : truncating_store (to_mode) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    insn_code icode = code_for_aarch64_store_trunc (e.memory_vector_mode (),
+                                                   e.vector_mode (0));
+    return e.use_contiguous_store_insn (icode);
+  }
+};
+
+/* Implements svst2, svst3 and svst4.  */
+class svst234_impl : public full_width_access
+{
+public:
+  CONSTEXPR svst234_impl (unsigned int vectors_per_tuple)
+    : full_width_access (vectors_per_tuple) {}
+
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_WRITE_MEMORY;
+  }
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    tree vectype = f.vector_type (0);
+
+    /* Get the predicate and base pointer.  */
+    gimple_seq stmts = NULL;
+    tree pred = f.convert_pred (stmts, vectype, 0);
+    tree base = f.fold_contiguous_base (stmts, vectype);
+    gsi_insert_seq_before (f.gsi, stmts, GSI_SAME_STMT);
+
+    /* View the stored data as an array of vectors.  */
+    unsigned int num_args = gimple_call_num_args (f.call);
+    tree rhs_tuple = gimple_call_arg (f.call, num_args - 1);
+    tree field = tuple_type_field (TREE_TYPE (rhs_tuple));
+    tree rhs_array = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (field), rhs_tuple);
+
+    tree cookie = f.load_store_cookie (TREE_TYPE (vectype));
+    return gimple_build_call_internal (IFN_MASK_STORE_LANES, 4,
+                                      base, cookie, pred, rhs_array);
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode tuple_mode = GET_MODE (e.args.last ());
+    insn_code icode = convert_optab_handler (vec_mask_store_lanes_optab,
+                                            tuple_mode, e.vector_mode (0));
+    return e.use_contiguous_store_insn (icode);
+  }
+};
+
+class svstnt1_impl : public full_width_access
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_WRITE_MEMORY;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    insn_code icode = code_for_aarch64_stnt1 (e.vector_mode (0));
+    return e.use_contiguous_store_insn (icode);
+  }
+};
+
+class svsub_impl : public rtx_code_function
+{
+public:
+  CONSTEXPR svsub_impl ()
+    : rtx_code_function (MINUS, MINUS, UNSPEC_COND_FSUB) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Canonicalize subtractions of constants to additions.  */
+    machine_mode mode = e.vector_mode (0);
+    if (e.try_negating_argument (2, mode))
+      return e.map_to_rtx_codes (PLUS, PLUS, UNSPEC_COND_FADD);
+
+    return rtx_code_function::expand (e);
+  }
+};
+
+class svtbl_impl : public permute
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (code_for_aarch64_sve_tbl (e.vector_mode (0)));
+  }
+};
+
+class svtmad_impl : public function_base
+{
+public:
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (code_for_aarch64_sve_tmad (e.vector_mode (0)));
+  }
+};
+
+/* Implements svtrn1 and svtrn2.  */
+class svtrn_impl : public binary_permute
+{
+public:
+  CONSTEXPR svtrn_impl (int base)
+    : binary_permute (base ? UNSPEC_TRN2 : UNSPEC_TRN1), m_base (base) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* svtrn1: { 0, nelts, 2, nelts + 2, 4, nelts + 4, ... }
+       svtrn2: as for svtrn1, but with 1 added to each index.  */
+    poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+    vec_perm_builder builder (nelts, 2, 3);
+    for (unsigned int i = 0; i < 3; ++i)
+      {
+       builder.quick_push (m_base + i * 2);
+       builder.quick_push (m_base + i * 2 + nelts);
+      }
+    return fold_permute (f, builder);
+  }
+
+  /* 0 for svtrn1, 1 for svtrn2.  */
+  unsigned int m_base;
+};
+
+/* Base class for svundef{,2,3,4}.  */
+class svundef_impl : public quiet<multi_vector_function>
+{
+public:
+  CONSTEXPR svundef_impl (unsigned int vectors_per_tuple)
+    : quiet<multi_vector_function> (vectors_per_tuple) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* Don't fold svundef at the gimple level.  There's no exact
+       correspondence for SSA_NAMEs, and we explicitly don't want
+       to generate a specific value (like an all-zeros vector).  */
+    if (vectors_per_tuple () == 1)
+      return NULL;
+    return gimple_build_assign (f.lhs, build_clobber (TREE_TYPE (f.lhs)));
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    rtx target = e.get_reg_target ();
+    emit_clobber (copy_rtx (target));
+    return target;
+  }
+};
+
+/* Implements svunpklo and svunpkhi.  */
+class svunpk_impl : public quiet<function_base>
+{
+public:
+  CONSTEXPR svunpk_impl (bool high_p) : m_high_p (high_p) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* Don't fold the predicate ops, since every bit of the svbool_t
+       result is significant.  */
+    if (f.type_suffix_ids[0] == TYPE_SUFFIX_b)
+      return NULL;
+
+    /* The first half in memory is VEC_UNPACK_LO_EXPR for little-endian
+       and VEC_UNPACK_HI_EXPR for big-endian.  */
+    bool high_p = BYTES_BIG_ENDIAN ? !m_high_p : m_high_p;
+    tree_code code = high_p ? VEC_UNPACK_HI_EXPR : VEC_UNPACK_LO_EXPR;
+    return gimple_build_assign (f.lhs, code, gimple_call_arg (f.call, 0));
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = GET_MODE (e.args[0]);
+    unsigned int unpacku = m_high_p ? UNSPEC_UNPACKUHI : UNSPEC_UNPACKULO;
+    unsigned int unpacks = m_high_p ? UNSPEC_UNPACKSHI : UNSPEC_UNPACKSLO;
+    insn_code icode;
+    if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+      icode = code_for_aarch64_sve_punpk (unpacku, mode);
+    else
+      {
+       int unspec = e.type_suffix (0).unsigned_p ? unpacku : unpacks;
+       icode = code_for_aarch64_sve_unpk (unspec, unspec, mode);
+      }
+    return e.use_exact_insn (icode);
+  }
+
+  /* True for svunpkhi, false for svunpklo.  */
+  bool m_high_p;
+};
+
+/* Implements svuzp1 and svuzp2.  */
+class svuzp_impl : public binary_permute
+{
+public:
+  CONSTEXPR svuzp_impl (unsigned int base)
+    : binary_permute (base ? UNSPEC_UZP2 : UNSPEC_UZP1), m_base (base) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* svuzp1: { 0, 2, 4, 6, ... }
+       svuzp2: { 1, 3, 5, 7, ... }.  */
+    poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+    vec_perm_builder builder (nelts, 1, 3);
+    for (unsigned int i = 0; i < 3; ++i)
+      builder.quick_push (m_base + i * 2);
+    return fold_permute (f, builder);
+  }
+
+  /* 0 for svuzp1, 1 for svuzp2.  */
+  unsigned int m_base;
+};
+
+/* A function_base for svwhilele and svwhilelt functions.  */
+class svwhile_impl : public function_base
+{
+public:
+  CONSTEXPR svwhile_impl (int unspec_for_sint, int unspec_for_uint, bool eq_p)
+    : m_unspec_for_sint (unspec_for_sint),
+      m_unspec_for_uint (unspec_for_uint), m_eq_p (eq_p)
+  {}
+
+  /* Try to fold a call by treating its arguments as constants of type T.  */
+  template<typename T>
+  gimple *
+  fold_type (gimple_folder &f) const
+  {
+    /* Only handle cases in which both operands are constant.  */
+    T arg0, arg1;
+    if (!poly_int_tree_p (gimple_call_arg (f.call, 0), &arg0)
+       || !poly_int_tree_p (gimple_call_arg (f.call, 1), &arg1))
+      return NULL;
+
+    /* Check whether the result is known to be all-false.  */
+    if (m_eq_p ? known_gt (arg0, arg1) : known_ge (arg0, arg1))
+      return f.fold_to_pfalse ();
+
+    /* Punt if we can't tell at compile time whether the result
+       is all-false.  */
+    if (m_eq_p ? maybe_gt (arg0, arg1) : maybe_ge (arg0, arg1))
+      return NULL;
+
+    /* At this point we know the result has at least one set element.  */
+    poly_uint64 diff = arg1 - arg0;
+    poly_uint64 nelts = GET_MODE_NUNITS (f.vector_mode (0));
+
+    /* Canonicalize the svwhilele form to the svwhilelt form.  Subtract
+       from NELTS rather than adding to DIFF, to prevent overflow.  */
+    if (m_eq_p)
+      nelts -= 1;
+
+    /* Check whether the result is known to be all-true.  */
+    if (known_ge (diff, nelts))
+      return f.fold_to_ptrue ();
+
+    /* Punt if DIFF might not be the actual number of set elements
+       in the result.  Conditional equality is fine.  */
+    if (maybe_gt (diff, nelts))
+      return NULL;
+
+    /* At this point we know that the predicate will have DIFF set elements
+       for svwhilelt and DIFF + 1 set elements for svwhilele (which stops
+       after rather than before ARG1 is reached).  See if we can create
+       the predicate at compile time.  */
+    unsigned HOST_WIDE_INT vl;
+    if (diff.is_constant (&vl))
+      /* Overflow is no longer possible after the checks above.  */
+      return f.fold_to_vl_pred (m_eq_p ? vl + 1 : vl);
+
+    return NULL;
+  }
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    if (f.type_suffix (1).unsigned_p)
+      return fold_type<poly_uint64> (f);
+    else
+      return fold_type<poly_int64> (f);
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Suffix 0 determines the predicate mode, suffix 1 determines the
+       scalar mode and signedness.  */
+    int unspec = (e.type_suffix (1).unsigned_p
+                 ? m_unspec_for_uint
+                 : m_unspec_for_sint);
+    machine_mode pred_mode = e.vector_mode (0);
+    scalar_mode reg_mode = GET_MODE_INNER (e.vector_mode (1));
+    return e.use_exact_insn (code_for_while (unspec, reg_mode, pred_mode));
+  }
+
+  /* The unspec codes associated with signed and unsigned operations
+     respectively.  */
+  int m_unspec_for_sint;
+  int m_unspec_for_uint;
+
+  /* True svwhilele, false for svwhilelt.  */
+  bool m_eq_p;
+};
+
+class svwrffr_impl : public function_base
+{
+public:
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_WRITE_FFR;
+  }
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.use_exact_insn (CODE_FOR_aarch64_wrffr);
+  }
+};
+
+/* Implements svzip1 and svzip2.  */
+class svzip_impl : public binary_permute
+{
+public:
+  CONSTEXPR svzip_impl (unsigned int base)
+    : binary_permute (base ? UNSPEC_ZIP2 : UNSPEC_ZIP1), m_base (base) {}
+
+  gimple *
+  fold (gimple_folder &f) const OVERRIDE
+  {
+    /* svzip1: { 0, nelts, 1, nelts + 1, 2, nelts + 2, ... }
+       svzip2: as for svzip1, but with nelts / 2 added to each index.  */
+    poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+    poly_uint64 base = m_base * exact_div (nelts, 2);
+    vec_perm_builder builder (nelts, 2, 3);
+    for (unsigned int i = 0; i < 3; ++i)
+      {
+       builder.quick_push (base + i);
+       builder.quick_push (base + i + nelts);
+      }
+    return fold_permute (f, builder);
+  }
+
+  /* 0 for svzip1, 1 for svzip2.  */
+  unsigned int m_base;
+};
+
+} /* end anonymous namespace */
+
+namespace aarch64_sve {
+
+FUNCTION (svabd, svabd_impl,)
+FUNCTION (svabs, quiet<rtx_code_function>, (ABS, ABS, UNSPEC_COND_FABS))
+FUNCTION (svacge, svac_impl, (UNSPEC_COND_FCMGE))
+FUNCTION (svacgt, svac_impl, (UNSPEC_COND_FCMGT))
+FUNCTION (svacle, svac_impl, (UNSPEC_COND_FCMLE))
+FUNCTION (svaclt, svac_impl, (UNSPEC_COND_FCMLT))
+FUNCTION (svadd, rtx_code_function, (PLUS, PLUS, UNSPEC_COND_FADD))
+FUNCTION (svadda, svadda_impl,)
+FUNCTION (svaddv, reduction, (UNSPEC_SADDV, UNSPEC_UADDV, UNSPEC_FADDV))
+FUNCTION (svadrb, svadr_bhwd_impl, (0))
+FUNCTION (svadrd, svadr_bhwd_impl, (3))
+FUNCTION (svadrh, svadr_bhwd_impl, (1))
+FUNCTION (svadrw, svadr_bhwd_impl, (2))
+FUNCTION (svand, rtx_code_function, (AND, AND))
+FUNCTION (svandv, reduction, (UNSPEC_ANDV))
+FUNCTION (svasr, rtx_code_function, (ASHIFTRT, ASHIFTRT))
+FUNCTION (svasr_wide, shift_wide, (ASHIFTRT, UNSPEC_ASHIFTRT_WIDE))
+FUNCTION (svasrd, svasrd_impl,)
+FUNCTION (svbic, svbic_impl,)
+FUNCTION (svbrka, svbrk_unary_impl, (UNSPEC_BRKA))
+FUNCTION (svbrkb, svbrk_unary_impl, (UNSPEC_BRKB))
+FUNCTION (svbrkn, svbrk_binary_impl, (UNSPEC_BRKN))
+FUNCTION (svbrkpa, svbrk_binary_impl, (UNSPEC_BRKPA))
+FUNCTION (svbrkpb, svbrk_binary_impl, (UNSPEC_BRKPB))
+FUNCTION (svcadd, svcadd_impl,)
+FUNCTION (svclasta, svclast_impl, (UNSPEC_CLASTA))
+FUNCTION (svclastb, svclast_impl, (UNSPEC_CLASTB))
+FUNCTION (svcls, unary_count, (CLRSB))
+FUNCTION (svclz, unary_count, (CLZ))
+FUNCTION (svcmla, svcmla_impl,)
+FUNCTION (svcmla_lane, svcmla_lane_impl,)
+FUNCTION (svcmpeq, svcmp_impl, (EQ_EXPR, UNSPEC_COND_FCMEQ))
+FUNCTION (svcmpeq_wide, svcmp_wide_impl, (EQ_EXPR, UNSPEC_COND_CMPEQ_WIDE,
+                                         UNSPEC_COND_CMPEQ_WIDE))
+FUNCTION (svcmpge, svcmp_impl, (GE_EXPR, UNSPEC_COND_FCMGE))
+FUNCTION (svcmpge_wide, svcmp_wide_impl, (GE_EXPR, UNSPEC_COND_CMPGE_WIDE,
+                                         UNSPEC_COND_CMPHS_WIDE))
+FUNCTION (svcmpgt, svcmp_impl, (GT_EXPR, UNSPEC_COND_FCMGT))
+FUNCTION (svcmpgt_wide, svcmp_wide_impl, (GT_EXPR, UNSPEC_COND_CMPGT_WIDE,
+                                         UNSPEC_COND_CMPHI_WIDE))
+FUNCTION (svcmple, svcmp_impl, (LE_EXPR, UNSPEC_COND_FCMLE))
+FUNCTION (svcmple_wide, svcmp_wide_impl, (LE_EXPR, UNSPEC_COND_CMPLE_WIDE,
+                                         UNSPEC_COND_CMPLS_WIDE))
+FUNCTION (svcmplt, svcmp_impl, (LT_EXPR, UNSPEC_COND_FCMLT))
+FUNCTION (svcmplt_wide, svcmp_wide_impl, (LT_EXPR, UNSPEC_COND_CMPLT_WIDE,
+                                         UNSPEC_COND_CMPLO_WIDE))
+FUNCTION (svcmpne, svcmp_impl, (NE_EXPR, UNSPEC_COND_FCMNE))
+FUNCTION (svcmpne_wide, svcmp_wide_impl, (NE_EXPR, UNSPEC_COND_CMPNE_WIDE,
+                                         UNSPEC_COND_CMPNE_WIDE))
+FUNCTION (svcmpuo, svcmpuo_impl,)
+FUNCTION (svcnot, svcnot_impl,)
+FUNCTION (svcnt, unary_count, (POPCOUNT))
+FUNCTION (svcntb, svcnt_bhwd_impl, (VNx16QImode))
+FUNCTION (svcntb_pat, svcnt_bhwd_pat_impl, (VNx16QImode))
+FUNCTION (svcntd, svcnt_bhwd_impl, (VNx2DImode))
+FUNCTION (svcntd_pat, svcnt_bhwd_pat_impl, (VNx2DImode))
+FUNCTION (svcnth, svcnt_bhwd_impl, (VNx8HImode))
+FUNCTION (svcnth_pat, svcnt_bhwd_pat_impl, (VNx8HImode))
+FUNCTION (svcntp, svcntp_impl,)
+FUNCTION (svcntw, svcnt_bhwd_impl, (VNx4SImode))
+FUNCTION (svcntw_pat, svcnt_bhwd_pat_impl, (VNx4SImode))
+FUNCTION (svcompact, svcompact_impl,)
+FUNCTION (svcreate2, svcreate_impl, (2))
+FUNCTION (svcreate3, svcreate_impl, (3))
+FUNCTION (svcreate4, svcreate_impl, (4))
+FUNCTION (svcvt, svcvt_impl,)
+FUNCTION (svdiv, rtx_code_function, (DIV, UDIV, UNSPEC_COND_FDIV))
+FUNCTION (svdivr, rtx_code_function_rotated, (DIV, UDIV, UNSPEC_COND_FDIV))
+FUNCTION (svdot, svdot_impl,)
+FUNCTION (svdot_lane, svdot_lane_impl,)
+FUNCTION (svdup, svdup_impl,)
+FUNCTION (svdup_lane, svdup_lane_impl,)
+FUNCTION (svdupq, svdupq_impl,)
+FUNCTION (svdupq_lane, svdupq_lane_impl,)
+FUNCTION (sveor, rtx_code_function, (XOR, XOR, -1))
+FUNCTION (sveorv, reduction, (UNSPEC_XORV))
+FUNCTION (svexpa, unspec_based_function, (-1, -1, UNSPEC_FEXPA))
+FUNCTION (svext, svext_impl,)
+FUNCTION (svextb, svext_bhw_impl, (QImode))
+FUNCTION (svexth, svext_bhw_impl, (HImode))
+FUNCTION (svextw, svext_bhw_impl, (SImode))
+FUNCTION (svget2, svget_impl, (2))
+FUNCTION (svget3, svget_impl, (3))
+FUNCTION (svget4, svget_impl, (4))
+FUNCTION (svindex, svindex_impl,)
+FUNCTION (svinsr, svinsr_impl,)
+FUNCTION (svlasta, svlast_impl, (UNSPEC_LASTA))
+FUNCTION (svlastb, svlast_impl, (UNSPEC_LASTB))
+FUNCTION (svld1, svld1_impl,)
+FUNCTION (svld1_gather, svld1_gather_impl,)
+FUNCTION (svld1rq, svld1rq_impl,)
+FUNCTION (svld1sb, svld1_extend_impl, (TYPE_SUFFIX_s8))
+FUNCTION (svld1sb_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_s8))
+FUNCTION (svld1sh, svld1_extend_impl, (TYPE_SUFFIX_s16))
+FUNCTION (svld1sh_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_s16))
+FUNCTION (svld1sw, svld1_extend_impl, (TYPE_SUFFIX_s32))
+FUNCTION (svld1sw_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_s32))
+FUNCTION (svld1ub, svld1_extend_impl, (TYPE_SUFFIX_u8))
+FUNCTION (svld1ub_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_u8))
+FUNCTION (svld1uh, svld1_extend_impl, (TYPE_SUFFIX_u16))
+FUNCTION (svld1uh_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_u16))
+FUNCTION (svld1uw, svld1_extend_impl, (TYPE_SUFFIX_u32))
+FUNCTION (svld1uw_gather, svld1_gather_extend_impl, (TYPE_SUFFIX_u32))
+FUNCTION (svld2, svld234_impl, (2))
+FUNCTION (svld3, svld234_impl, (3))
+FUNCTION (svld4, svld234_impl, (4))
+FUNCTION (svldff1, svldxf1_impl, (UNSPEC_LDFF1))
+FUNCTION (svldff1_gather, svldff1_gather_impl,)
+FUNCTION (svldff1sb, svldxf1_extend_impl, (TYPE_SUFFIX_s8, UNSPEC_LDFF1))
+FUNCTION (svldff1sb_gather, svldff1_gather_extend, (TYPE_SUFFIX_s8))
+FUNCTION (svldff1sh, svldxf1_extend_impl, (TYPE_SUFFIX_s16, UNSPEC_LDFF1))
+FUNCTION (svldff1sh_gather, svldff1_gather_extend, (TYPE_SUFFIX_s16))
+FUNCTION (svldff1sw, svldxf1_extend_impl, (TYPE_SUFFIX_s32, UNSPEC_LDFF1))
+FUNCTION (svldff1sw_gather, svldff1_gather_extend, (TYPE_SUFFIX_s32))
+FUNCTION (svldff1ub, svldxf1_extend_impl, (TYPE_SUFFIX_u8, UNSPEC_LDFF1))
+FUNCTION (svldff1ub_gather, svldff1_gather_extend, (TYPE_SUFFIX_u8))
+FUNCTION (svldff1uh, svldxf1_extend_impl, (TYPE_SUFFIX_u16, UNSPEC_LDFF1))
+FUNCTION (svldff1uh_gather, svldff1_gather_extend, (TYPE_SUFFIX_u16))
+FUNCTION (svldff1uw, svldxf1_extend_impl, (TYPE_SUFFIX_u32, UNSPEC_LDFF1))
+FUNCTION (svldff1uw_gather, svldff1_gather_extend, (TYPE_SUFFIX_u32))
+FUNCTION (svldnf1, svldxf1_impl, (UNSPEC_LDNF1))
+FUNCTION (svldnf1sb, svldxf1_extend_impl, (TYPE_SUFFIX_s8, UNSPEC_LDNF1))
+FUNCTION (svldnf1sh, svldxf1_extend_impl, (TYPE_SUFFIX_s16, UNSPEC_LDNF1))
+FUNCTION (svldnf1sw, svldxf1_extend_impl, (TYPE_SUFFIX_s32, UNSPEC_LDNF1))
+FUNCTION (svldnf1ub, svldxf1_extend_impl, (TYPE_SUFFIX_u8, UNSPEC_LDNF1))
+FUNCTION (svldnf1uh, svldxf1_extend_impl, (TYPE_SUFFIX_u16, UNSPEC_LDNF1))
+FUNCTION (svldnf1uw, svldxf1_extend_impl, (TYPE_SUFFIX_u32, UNSPEC_LDNF1))
+FUNCTION (svldnt1, svldnt1_impl,)
+FUNCTION (svlen, svlen_impl,)
+FUNCTION (svlsl, rtx_code_function, (ASHIFT, ASHIFT))
+FUNCTION (svlsl_wide, shift_wide, (ASHIFT, UNSPEC_ASHIFT_WIDE))
+FUNCTION (svlsr, rtx_code_function, (LSHIFTRT, LSHIFTRT))
+FUNCTION (svlsr_wide, shift_wide, (LSHIFTRT, UNSPEC_LSHIFTRT_WIDE))
+FUNCTION (svmad, svmad_impl,)
+FUNCTION (svmax, rtx_code_function, (SMAX, UMAX, UNSPEC_COND_FMAX))
+FUNCTION (svmaxnm, unspec_based_function, (-1, -1, UNSPEC_COND_FMAXNM))
+FUNCTION (svmaxnmv, reduction, (UNSPEC_FMAXNMV))
+FUNCTION (svmaxv, reduction, (UNSPEC_SMAXV, UNSPEC_UMAXV, UNSPEC_FMAXV))
+FUNCTION (svmin, rtx_code_function, (SMIN, UMIN, UNSPEC_COND_FMIN))
+FUNCTION (svminnm, unspec_based_function, (-1, -1, UNSPEC_COND_FMINNM))
+FUNCTION (svminnmv, reduction, (UNSPEC_FMINNMV))
+FUNCTION (svminv, reduction, (UNSPEC_SMINV, UNSPEC_UMINV, UNSPEC_FMINV))
+FUNCTION (svmla, svmla_impl,)
+FUNCTION (svmla_lane, svmla_svmls_lane_impl, (UNSPEC_FMLA))
+FUNCTION (svmls, svmls_impl,)
+FUNCTION (svmls_lane, svmla_svmls_lane_impl, (UNSPEC_FMLS))
+FUNCTION (svmov, svmov_impl,)
+FUNCTION (svmsb, svmsb_impl,)
+FUNCTION (svmul, rtx_code_function, (MULT, MULT, UNSPEC_COND_FMUL))
+FUNCTION (svmul_lane, svmul_lane_impl,)
+FUNCTION (svmulh, unspec_based_function, (UNSPEC_SMUL_HIGHPART,
+                                         UNSPEC_UMUL_HIGHPART, -1))
+FUNCTION (svmulx, unspec_based_function, (-1, -1, UNSPEC_COND_FMULX))
+FUNCTION (svnand, svnand_impl,)
+FUNCTION (svneg, quiet<rtx_code_function>, (NEG, NEG, UNSPEC_COND_FNEG))
+FUNCTION (svnmad, unspec_based_function, (-1, -1, UNSPEC_COND_FNMLA))
+FUNCTION (svnmla, unspec_based_function_rotated, (-1, -1, UNSPEC_COND_FNMLA))
+FUNCTION (svnmls, unspec_based_function_rotated, (-1, -1, UNSPEC_COND_FNMLS))
+FUNCTION (svnmsb, unspec_based_function, (-1, -1, UNSPEC_COND_FNMLS))
+FUNCTION (svnor, svnor_impl,)
+FUNCTION (svnot, svnot_impl,)
+FUNCTION (svorn, svorn_impl,)
+FUNCTION (svorr, rtx_code_function, (IOR, IOR))
+FUNCTION (svorv, reduction, (UNSPEC_IORV))
+FUNCTION (svpfalse, svpfalse_impl,)
+FUNCTION (svpfirst, svpfirst_svpnext_impl, (UNSPEC_PFIRST))
+FUNCTION (svpnext, svpfirst_svpnext_impl, (UNSPEC_PNEXT))
+FUNCTION (svprfb, svprf_bhwd_impl, (VNx16QImode))
+FUNCTION (svprfb_gather, svprf_bhwd_gather_impl, (VNx16QImode))
+FUNCTION (svprfd, svprf_bhwd_impl, (VNx2DImode))
+FUNCTION (svprfd_gather, svprf_bhwd_gather_impl, (VNx2DImode))
+FUNCTION (svprfh, svprf_bhwd_impl, (VNx8HImode))
+FUNCTION (svprfh_gather, svprf_bhwd_gather_impl, (VNx8HImode))
+FUNCTION (svprfw, svprf_bhwd_impl, (VNx4SImode))
+FUNCTION (svprfw_gather, svprf_bhwd_gather_impl, (VNx4SImode))
+FUNCTION (svptest_any, svptest_impl, (NE))
+FUNCTION (svptest_first, svptest_impl, (LT))
+FUNCTION (svptest_last, svptest_impl, (LTU))
+FUNCTION (svptrue, svptrue_impl,)
+FUNCTION (svptrue_pat, svptrue_pat_impl,)
+FUNCTION (svqadd, svqadd_impl,)
+FUNCTION (svqdecb, svqdec_bhwd_impl, (QImode))
+FUNCTION (svqdecb_pat, svqdec_bhwd_impl, (QImode))
+FUNCTION (svqdecd, svqdec_bhwd_impl, (DImode))
+FUNCTION (svqdecd_pat, svqdec_bhwd_impl, (DImode))
+FUNCTION (svqdech, svqdec_bhwd_impl, (HImode))
+FUNCTION (svqdech_pat, svqdec_bhwd_impl, (HImode))
+FUNCTION (svqdecp, svqdecp_svqincp_impl, (SS_MINUS, US_MINUS))
+FUNCTION (svqdecw, svqdec_bhwd_impl, (SImode))
+FUNCTION (svqdecw_pat, svqdec_bhwd_impl, (SImode))
+FUNCTION (svqincb, svqinc_bhwd_impl, (QImode))
+FUNCTION (svqincb_pat, svqinc_bhwd_impl, (QImode))
+FUNCTION (svqincd, svqinc_bhwd_impl, (DImode))
+FUNCTION (svqincd_pat, svqinc_bhwd_impl, (DImode))
+FUNCTION (svqinch, svqinc_bhwd_impl, (HImode))
+FUNCTION (svqinch_pat, svqinc_bhwd_impl, (HImode))
+FUNCTION (svqincp, svqdecp_svqincp_impl, (SS_PLUS, US_PLUS))
+FUNCTION (svqincw, svqinc_bhwd_impl, (SImode))
+FUNCTION (svqincw_pat, svqinc_bhwd_impl, (SImode))
+FUNCTION (svqsub, svqsub_impl,)
+FUNCTION (svrbit, unspec_based_function, (UNSPEC_RBIT, UNSPEC_RBIT, -1))
+FUNCTION (svrdffr, svrdffr_impl,)
+FUNCTION (svrecpe, unspec_based_function, (-1, -1, UNSPEC_FRECPE))
+FUNCTION (svrecps, unspec_based_function, (-1, -1, UNSPEC_FRECPS))
+FUNCTION (svrecpx, unspec_based_function, (-1, -1, UNSPEC_COND_FRECPX))
+FUNCTION (svreinterpret, svreinterpret_impl,)
+FUNCTION (svrev, svrev_impl,)
+FUNCTION (svrevb, unspec_based_function, (UNSPEC_REVB, UNSPEC_REVB, -1))
+FUNCTION (svrevh, unspec_based_function, (UNSPEC_REVH, UNSPEC_REVH, -1))
+FUNCTION (svrevw, unspec_based_function, (UNSPEC_REVW, UNSPEC_REVW, -1))
+FUNCTION (svrinta, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTA))
+FUNCTION (svrinti, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTI))
+FUNCTION (svrintm, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTM))
+FUNCTION (svrintn, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTN))
+FUNCTION (svrintp, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTP))
+FUNCTION (svrintx, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTX))
+FUNCTION (svrintz, unspec_based_function, (-1, -1, UNSPEC_COND_FRINTZ))
+FUNCTION (svrsqrte, unspec_based_function, (-1, -1, UNSPEC_RSQRTE))
+FUNCTION (svrsqrts, unspec_based_function, (-1, -1, UNSPEC_RSQRTS))
+FUNCTION (svscale, unspec_based_function, (-1, -1, UNSPEC_COND_FSCALE))
+FUNCTION (svsel, svsel_impl,)
+FUNCTION (svset2, svset_impl, (2))
+FUNCTION (svset3, svset_impl, (3))
+FUNCTION (svset4, svset_impl, (4))
+FUNCTION (svsetffr, svsetffr_impl,)
+FUNCTION (svsplice, svsplice_impl,)
+FUNCTION (svsqrt, rtx_code_function, (SQRT, SQRT, UNSPEC_COND_FSQRT))
+FUNCTION (svst1, svst1_impl,)
+FUNCTION (svst1_scatter, svst1_scatter_impl,)
+FUNCTION (svst1b, svst1_truncate_impl, (QImode))
+FUNCTION (svst1b_scatter, svst1_scatter_truncate_impl, (QImode))
+FUNCTION (svst1h, svst1_truncate_impl, (HImode))
+FUNCTION (svst1h_scatter, svst1_scatter_truncate_impl, (HImode))
+FUNCTION (svst1w, svst1_truncate_impl, (SImode))
+FUNCTION (svst1w_scatter, svst1_scatter_truncate_impl, (SImode))
+FUNCTION (svst2, svst234_impl, (2))
+FUNCTION (svst3, svst234_impl, (3))
+FUNCTION (svst4, svst234_impl, (4))
+FUNCTION (svstnt1, svstnt1_impl,)
+FUNCTION (svsub, svsub_impl,)
+FUNCTION (svsubr, rtx_code_function_rotated, (MINUS, MINUS, UNSPEC_COND_FSUB))
+FUNCTION (svtbl, svtbl_impl,)
+FUNCTION (svtmad, svtmad_impl,)
+FUNCTION (svtrn1, svtrn_impl, (0))
+FUNCTION (svtrn2, svtrn_impl, (1))
+FUNCTION (svtsmul, unspec_based_function, (-1, -1, UNSPEC_FTSMUL))
+FUNCTION (svtssel, unspec_based_function, (-1, -1, UNSPEC_FTSSEL))
+FUNCTION (svundef, svundef_impl, (1))
+FUNCTION (svundef2, svundef_impl, (2))
+FUNCTION (svundef3, svundef_impl, (3))
+FUNCTION (svundef4, svundef_impl, (4))
+FUNCTION (svunpkhi, svunpk_impl, (true))
+FUNCTION (svunpklo, svunpk_impl, (false))
+FUNCTION (svuzp1, svuzp_impl, (0))
+FUNCTION (svuzp2, svuzp_impl, (1))
+FUNCTION (svwhilele, svwhile_impl, (UNSPEC_WHILE_LE, UNSPEC_WHILE_LS, true))
+FUNCTION (svwhilelt, svwhile_impl, (UNSPEC_WHILE_LT, UNSPEC_WHILE_LO, false))
+FUNCTION (svwrffr, svwrffr_impl,)
+FUNCTION (svzip1, svzip_impl, (0))
+FUNCTION (svzip2, svzip_impl, (1))
+
+} /* end namespace aarch64_sve */
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.def b/gcc/config/aarch64/aarch64-sve-builtins-base.def
new file mode 100644 (file)
index 0000000..a678ee8
--- /dev/null
@@ -0,0 +1,318 @@
+/* ACLE support for AArch64 SVE (__ARM_FEATURE_SVE intrinsics)
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#define REQUIRED_EXTENSIONS 0
+DEF_SVE_FUNCTION (svabd, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svabs, unary, all_float_and_signed, mxz)
+DEF_SVE_FUNCTION (svacge, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svacgt, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svacle, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svaclt, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svadd, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svadda, fold_left, all_float, implicit)
+DEF_SVE_FUNCTION (svaddv, reduction_wide, all_data, implicit)
+DEF_SVE_FUNCTION (svadrb, adr_offset, none, none)
+DEF_SVE_FUNCTION (svadrd, adr_index, none, none)
+DEF_SVE_FUNCTION (svadrh, adr_index, none, none)
+DEF_SVE_FUNCTION (svadrw, adr_index, none, none)
+DEF_SVE_FUNCTION (svand, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svand, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svandv, reduction, all_integer, implicit)
+DEF_SVE_FUNCTION (svasr, binary_uint_opt_n, all_signed, mxz)
+DEF_SVE_FUNCTION (svasr_wide, binary_uint64_opt_n, bhs_signed, mxz)
+DEF_SVE_FUNCTION (svasrd, shift_right_imm, all_signed, mxz)
+DEF_SVE_FUNCTION (svbic, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svbic, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svbrka, unary, b, mz)
+DEF_SVE_FUNCTION (svbrkb, unary, b, mz)
+DEF_SVE_FUNCTION (svbrkn, binary, b, z)
+DEF_SVE_FUNCTION (svbrkpa, binary, b, z)
+DEF_SVE_FUNCTION (svbrkpb, binary, b, z)
+DEF_SVE_FUNCTION (svcadd, binary_rotate, all_float, mxz)
+DEF_SVE_FUNCTION (svclasta, clast, all_data, implicit)
+DEF_SVE_FUNCTION (svclastb, clast, all_data, implicit)
+DEF_SVE_FUNCTION (svcls, unary_count, all_signed, mxz)
+DEF_SVE_FUNCTION (svclz, unary_count, all_integer, mxz)
+DEF_SVE_FUNCTION (svcmla, ternary_rotate, all_float, mxz)
+DEF_SVE_FUNCTION (svcmla_lane, ternary_lane_rotate, hs_float, none)
+DEF_SVE_FUNCTION (svcmpeq, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmpeq_wide, compare_wide_opt_n, bhs_signed, implicit)
+DEF_SVE_FUNCTION (svcmpge, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmpge_wide, compare_wide_opt_n, bhs_integer, implicit)
+DEF_SVE_FUNCTION (svcmpgt, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmpgt_wide, compare_wide_opt_n, bhs_integer, implicit)
+DEF_SVE_FUNCTION (svcmple, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmple_wide, compare_wide_opt_n, bhs_integer, implicit)
+DEF_SVE_FUNCTION (svcmplt, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmplt_wide, compare_wide_opt_n, bhs_integer, implicit)
+DEF_SVE_FUNCTION (svcmpne, compare_opt_n, all_data, implicit)
+DEF_SVE_FUNCTION (svcmpne_wide, compare_wide_opt_n, bhs_signed, implicit)
+DEF_SVE_FUNCTION (svcmpuo, compare_opt_n, all_float, implicit)
+DEF_SVE_FUNCTION (svcnot, unary, all_integer, mxz)
+DEF_SVE_FUNCTION (svcnt, unary_count, all_data, mxz)
+DEF_SVE_FUNCTION (svcntb, count_inherent, none, none)
+DEF_SVE_FUNCTION (svcntb_pat, count_pat, none, none)
+DEF_SVE_FUNCTION (svcntd, count_inherent, none, none)
+DEF_SVE_FUNCTION (svcntd_pat, count_pat, none, none)
+DEF_SVE_FUNCTION (svcnth, count_inherent, none, none)
+DEF_SVE_FUNCTION (svcnth_pat, count_pat, none, none)
+DEF_SVE_FUNCTION (svcntp, count_pred, all_pred, implicit)
+DEF_SVE_FUNCTION (svcntw, count_inherent, none, none)
+DEF_SVE_FUNCTION (svcntw_pat, count_pat, none, none)
+DEF_SVE_FUNCTION (svcompact, unary, sd_data, implicit)
+DEF_SVE_FUNCTION (svcreate2, create, all_data, none)
+DEF_SVE_FUNCTION (svcreate3, create, all_data, none)
+DEF_SVE_FUNCTION (svcreate4, create, all_data, none)
+DEF_SVE_FUNCTION (svcvt, unary_convert, cvt, mxz)
+DEF_SVE_FUNCTION (svdiv, binary_opt_n, all_float_and_sd_integer, mxz)
+DEF_SVE_FUNCTION (svdivr, binary_opt_n, all_float_and_sd_integer, mxz)
+DEF_SVE_FUNCTION (svdot, ternary_qq_opt_n, sd_integer, none)
+DEF_SVE_FUNCTION (svdot_lane, ternary_qq_lane, sd_integer, none)
+DEF_SVE_FUNCTION (svdup, unary_n, all_data, mxz_or_none)
+DEF_SVE_FUNCTION (svdup, unary_n, all_pred, none)
+DEF_SVE_FUNCTION (svdup_lane, binary_uint_n, all_data, none)
+DEF_SVE_FUNCTION (svdupq, dupq, all_data, none)
+DEF_SVE_FUNCTION (svdupq, dupq, all_pred, none)
+DEF_SVE_FUNCTION (svdupq_lane, binary_uint64_n, all_data, none)
+DEF_SVE_FUNCTION (sveor, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (sveor, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (sveorv, reduction, all_integer, implicit)
+DEF_SVE_FUNCTION (svexpa, unary_uint, all_float, none)
+DEF_SVE_FUNCTION (svext, ext, all_data, none)
+DEF_SVE_FUNCTION (svextb, unary, hsd_integer, mxz)
+DEF_SVE_FUNCTION (svexth, unary, sd_integer, mxz)
+DEF_SVE_FUNCTION (svextw, unary, d_integer, mxz)
+DEF_SVE_FUNCTION (svget2, get, all_data, none)
+DEF_SVE_FUNCTION (svget3, get, all_data, none)
+DEF_SVE_FUNCTION (svget4, get, all_data, none)
+DEF_SVE_FUNCTION (svindex, binary_scalar, all_integer, none)
+DEF_SVE_FUNCTION (svinsr, binary_n, all_data, none)
+DEF_SVE_FUNCTION (svlasta, reduction, all_data, implicit)
+DEF_SVE_FUNCTION (svlastb, reduction, all_data, implicit)
+DEF_SVE_FUNCTION (svld1, load, all_data, implicit)
+DEF_SVE_FUNCTION (svld1_gather, load_gather_sv, sd_data, implicit)
+DEF_SVE_FUNCTION (svld1_gather, load_gather_vs, sd_data, implicit)
+DEF_SVE_FUNCTION (svld1rq, load_replicate, all_data, implicit)
+DEF_SVE_FUNCTION (svld1sb, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sb_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sh_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sh_gather, load_ext_gather_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1sw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1sw_gather, load_ext_gather_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1sw_gather, load_ext_gather_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1ub, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svld1ub_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1uh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1uh_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1uh_gather, load_ext_gather_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svld1uw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1uw_gather, load_ext_gather_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svld1uw_gather, load_ext_gather_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1, load, all_data, implicit)
+DEF_SVE_FUNCTION (svldff1_gather, load_gather_sv, sd_data, implicit)
+DEF_SVE_FUNCTION (svldff1_gather, load_gather_vs, sd_data, implicit)
+DEF_SVE_FUNCTION (svldff1sb, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sb_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sh_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sh_gather, load_ext_gather_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sw_gather, load_ext_gather_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1sw_gather, load_ext_gather_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1ub, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1ub_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uh_gather, load_ext_gather_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uh_gather, load_ext_gather_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uw_gather, load_ext_gather_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svldff1uw_gather, load_ext_gather_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1, load, all_data, implicit)
+DEF_SVE_FUNCTION (svldnf1sb, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1sh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1sw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1ub, load_ext, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1uh, load_ext, sd_integer, implicit)
+DEF_SVE_FUNCTION (svldnf1uw, load_ext, d_integer, implicit)
+DEF_SVE_FUNCTION (svldnt1, load, all_data, implicit)
+DEF_SVE_FUNCTION (svld2, load, all_data, implicit)
+DEF_SVE_FUNCTION (svld3, load, all_data, implicit)
+DEF_SVE_FUNCTION (svld4, load, all_data, implicit)
+DEF_SVE_FUNCTION (svlen, count_vector, all_data, none)
+DEF_SVE_FUNCTION (svlsl, binary_uint_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svlsl_wide, binary_uint64_opt_n, bhs_integer, mxz)
+DEF_SVE_FUNCTION (svlsr, binary_uint_opt_n, all_unsigned, mxz)
+DEF_SVE_FUNCTION (svlsr_wide, binary_uint64_opt_n, bhs_unsigned, mxz)
+DEF_SVE_FUNCTION (svmad, ternary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmax, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmaxnm, binary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svmaxnmv, reduction, all_float, implicit)
+DEF_SVE_FUNCTION (svmaxv, reduction, all_data, implicit)
+DEF_SVE_FUNCTION (svmin, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svminnm, binary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svminnmv, reduction, all_float, implicit)
+DEF_SVE_FUNCTION (svminv, reduction, all_data, implicit)
+DEF_SVE_FUNCTION (svmla, ternary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmla_lane, ternary_lane, all_float, none)
+DEF_SVE_FUNCTION (svmls, ternary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmls_lane, ternary_lane, all_float, none)
+DEF_SVE_FUNCTION (svmov, unary, b, z)
+DEF_SVE_FUNCTION (svmsb, ternary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmul, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svmul_lane, binary_lane, all_float, none)
+DEF_SVE_FUNCTION (svmulh, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svmulx, binary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnand, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svneg, unary, all_float_and_signed, mxz)
+DEF_SVE_FUNCTION (svnmad, ternary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnmla, ternary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnmls, ternary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnmsb, ternary_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svnor, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svnot, unary, all_integer, mxz)
+DEF_SVE_FUNCTION (svnot, unary, b, z)
+DEF_SVE_FUNCTION (svorn, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svorr, binary_opt_n, all_integer, mxz)
+DEF_SVE_FUNCTION (svorr, binary_opt_n, b, z)
+DEF_SVE_FUNCTION (svorv, reduction, all_integer, implicit)
+DEF_SVE_FUNCTION (svpfalse, inherent_b, b, none)
+DEF_SVE_FUNCTION (svpfirst, unary, b, implicit)
+DEF_SVE_FUNCTION (svpnext, unary_pred, all_pred, implicit)
+DEF_SVE_FUNCTION (svprfb, prefetch, none, implicit)
+DEF_SVE_FUNCTION (svprfb_gather, prefetch_gather_offset, none, implicit)
+DEF_SVE_FUNCTION (svprfd, prefetch, none, implicit)
+DEF_SVE_FUNCTION (svprfd_gather, prefetch_gather_index, none, implicit)
+DEF_SVE_FUNCTION (svprfh, prefetch, none, implicit)
+DEF_SVE_FUNCTION (svprfh_gather, prefetch_gather_index, none, implicit)
+DEF_SVE_FUNCTION (svprfw, prefetch, none, implicit)
+DEF_SVE_FUNCTION (svprfw_gather, prefetch_gather_index, none, implicit)
+DEF_SVE_FUNCTION (svptest_any, ptest, none, implicit)
+DEF_SVE_FUNCTION (svptest_first, ptest, none, implicit)
+DEF_SVE_FUNCTION (svptest_last, ptest, none, implicit)
+DEF_SVE_FUNCTION (svptrue, inherent, all_pred, none)
+DEF_SVE_FUNCTION (svptrue_pat, pattern_pred, all_pred, none)
+DEF_SVE_FUNCTION (svqadd, binary_opt_n, all_integer, none)
+DEF_SVE_FUNCTION (svqdecb, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecb_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecd, inc_dec, d_integer, none)
+DEF_SVE_FUNCTION (svqdecd, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecd_pat, inc_dec_pat, d_integer, none)
+DEF_SVE_FUNCTION (svqdecd_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqdech, inc_dec, h_integer, none)
+DEF_SVE_FUNCTION (svqdech, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqdech_pat, inc_dec_pat, h_integer, none)
+DEF_SVE_FUNCTION (svqdech_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecp, inc_dec_pred, hsd_integer, none)
+DEF_SVE_FUNCTION (svqdecp, inc_dec_pred_scalar, inc_dec_n, none)
+DEF_SVE_FUNCTION (svqdecw, inc_dec, s_integer, none)
+DEF_SVE_FUNCTION (svqdecw, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqdecw_pat, inc_dec_pat, s_integer, none)
+DEF_SVE_FUNCTION (svqdecw_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqincb, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqincb_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqincd, inc_dec, d_integer, none)
+DEF_SVE_FUNCTION (svqincd, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqincd_pat, inc_dec_pat, d_integer, none)
+DEF_SVE_FUNCTION (svqincd_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqinch, inc_dec, h_integer, none)
+DEF_SVE_FUNCTION (svqinch, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqinch_pat, inc_dec_pat, h_integer, none)
+DEF_SVE_FUNCTION (svqinch_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqincp, inc_dec_pred, hsd_integer, none)
+DEF_SVE_FUNCTION (svqincp, inc_dec_pred_scalar, inc_dec_n, none)
+DEF_SVE_FUNCTION (svqincw, inc_dec, s_integer, none)
+DEF_SVE_FUNCTION (svqincw, inc_dec, sd_integer, none)
+DEF_SVE_FUNCTION (svqincw_pat, inc_dec_pat, s_integer, none)
+DEF_SVE_FUNCTION (svqincw_pat, inc_dec_pat, sd_integer, none)
+DEF_SVE_FUNCTION (svqsub, binary_opt_n, all_integer, none)
+DEF_SVE_FUNCTION (svrbit, unary, all_integer, mxz)
+DEF_SVE_FUNCTION (svrdffr, rdffr, none, z_or_none)
+DEF_SVE_FUNCTION (svrecpe, unary, all_float, none)
+DEF_SVE_FUNCTION (svrecps, binary, all_float, none)
+DEF_SVE_FUNCTION (svrecpx, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svreinterpret, unary_convert, reinterpret, none)
+DEF_SVE_FUNCTION (svrev, unary, all_data, none)
+DEF_SVE_FUNCTION (svrev, unary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svrevb, unary, hsd_integer, mxz)
+DEF_SVE_FUNCTION (svrevh, unary, sd_integer, mxz)
+DEF_SVE_FUNCTION (svrevw, unary, d_integer, mxz)
+DEF_SVE_FUNCTION (svrinta, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrinti, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintm, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintn, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintp, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintx, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrintz, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svrsqrte, unary, all_float, none)
+DEF_SVE_FUNCTION (svrsqrts, binary, all_float, none)
+DEF_SVE_FUNCTION (svscale, binary_int_opt_n, all_float, mxz)
+DEF_SVE_FUNCTION (svsel, binary, all_data, implicit)
+DEF_SVE_FUNCTION (svsel, binary, b, implicit)
+DEF_SVE_FUNCTION (svset2, set, all_data, none)
+DEF_SVE_FUNCTION (svset3, set, all_data, none)
+DEF_SVE_FUNCTION (svset4, set, all_data, none)
+DEF_SVE_FUNCTION (svsetffr, setffr, none, none)
+DEF_SVE_FUNCTION (svsplice, binary, all_data, implicit)
+DEF_SVE_FUNCTION (svsqrt, unary, all_float, mxz)
+DEF_SVE_FUNCTION (svst1, store, all_data, implicit)
+DEF_SVE_FUNCTION (svst1_scatter, store_scatter_index, sd_data, implicit)
+DEF_SVE_FUNCTION (svst1_scatter, store_scatter_offset, sd_data, implicit)
+DEF_SVE_FUNCTION (svst1b, store, hsd_integer, implicit)
+DEF_SVE_FUNCTION (svst1b_scatter, store_scatter_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svst1h, store, sd_integer, implicit)
+DEF_SVE_FUNCTION (svst1h_scatter, store_scatter_index, sd_integer, implicit)
+DEF_SVE_FUNCTION (svst1h_scatter, store_scatter_offset, sd_integer, implicit)
+DEF_SVE_FUNCTION (svst1w, store, d_integer, implicit)
+DEF_SVE_FUNCTION (svst1w_scatter, store_scatter_index, d_integer, implicit)
+DEF_SVE_FUNCTION (svst1w_scatter, store_scatter_offset, d_integer, implicit)
+DEF_SVE_FUNCTION (svst2, store, all_data, implicit)
+DEF_SVE_FUNCTION (svst3, store, all_data, implicit)
+DEF_SVE_FUNCTION (svst4, store, all_data, implicit)
+DEF_SVE_FUNCTION (svstnt1, store, all_data, implicit)
+DEF_SVE_FUNCTION (svsub, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svsubr, binary_opt_n, all_data, mxz)
+DEF_SVE_FUNCTION (svtbl, binary_uint, all_data, none)
+DEF_SVE_FUNCTION (svtmad, tmad, all_float, none)
+DEF_SVE_FUNCTION (svtrn1, binary, all_data, none)
+DEF_SVE_FUNCTION (svtrn1, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svtrn2, binary, all_data, none)
+DEF_SVE_FUNCTION (svtrn2, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svtsmul, binary_uint, all_float, none)
+DEF_SVE_FUNCTION (svtssel, binary_uint, all_float, none)
+DEF_SVE_FUNCTION (svundef, inherent, all_data, none)
+DEF_SVE_FUNCTION (svundef2, inherent, all_data, none)
+DEF_SVE_FUNCTION (svundef3, inherent, all_data, none)
+DEF_SVE_FUNCTION (svundef4, inherent, all_data, none)
+DEF_SVE_FUNCTION (svunpkhi, unary_widen, hsd_integer, none)
+DEF_SVE_FUNCTION (svunpkhi, unary_widen, b, none)
+DEF_SVE_FUNCTION (svunpklo, unary_widen, hsd_integer, none)
+DEF_SVE_FUNCTION (svunpklo, unary_widen, b, none)
+DEF_SVE_FUNCTION (svuzp1, binary, all_data, none)
+DEF_SVE_FUNCTION (svuzp1, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svuzp2, binary, all_data, none)
+DEF_SVE_FUNCTION (svuzp2, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svwhilele, compare_scalar, while, none)
+DEF_SVE_FUNCTION (svwhilelt, compare_scalar, while, none)
+DEF_SVE_FUNCTION (svwrffr, setffr, none, implicit)
+DEF_SVE_FUNCTION (svzip1, binary, all_data, none)
+DEF_SVE_FUNCTION (svzip1, binary_pred, all_pred, none)
+DEF_SVE_FUNCTION (svzip2, binary, all_data, none)
+DEF_SVE_FUNCTION (svzip2, binary_pred, all_pred, none)
+#undef REQUIRED_EXTENSIONS
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-base.h b/gcc/config/aarch64/aarch64-sve-builtins-base.h
new file mode 100644 (file)
index 0000000..41ab12f
--- /dev/null
@@ -0,0 +1,283 @@
+/* ACLE support for AArch64 SVE (__ARM_FEATURE_SVE intrinsics)
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_AARCH64_SVE_BUILTINS_BASE_H
+#define GCC_AARCH64_SVE_BUILTINS_BASE_H
+
+namespace aarch64_sve
+{
+  namespace functions
+  {
+    extern const function_base *const svabd;
+    extern const function_base *const svabs;
+    extern const function_base *const svacge;
+    extern const function_base *const svacgt;
+    extern const function_base *const svacle;
+    extern const function_base *const svaclt;
+    extern const function_base *const svadd;
+    extern const function_base *const svadda;
+    extern const function_base *const svaddv;
+    extern const function_base *const svadrb;
+    extern const function_base *const svadrd;
+    extern const function_base *const svadrh;
+    extern const function_base *const svadrw;
+    extern const function_base *const svand;
+    extern const function_base *const svandv;
+    extern const function_base *const svasr;
+    extern const function_base *const svasr_wide;
+    extern const function_base *const svasrd;
+    extern const function_base *const svbic;
+    extern const function_base *const svbrka;
+    extern const function_base *const svbrkb;
+    extern const function_base *const svbrkn;
+    extern const function_base *const svbrkpa;
+    extern const function_base *const svbrkpb;
+    extern const function_base *const svcadd;
+    extern const function_base *const svclasta;
+    extern const function_base *const svclastb;
+    extern const function_base *const svcls;
+    extern const function_base *const svclz;
+    extern const function_base *const svcmla;
+    extern const function_base *const svcmla_lane;
+    extern const function_base *const svcmpeq;
+    extern const function_base *const svcmpeq_wide;
+    extern const function_base *const svcmpge;
+    extern const function_base *const svcmpge_wide;
+    extern const function_base *const svcmpgt;
+    extern const function_base *const svcmpgt_wide;
+    extern const function_base *const svcmple;
+    extern const function_base *const svcmple_wide;
+    extern const function_base *const svcmplt;
+    extern const function_base *const svcmplt_wide;
+    extern const function_base *const svcmpne;
+    extern const function_base *const svcmpne_wide;
+    extern const function_base *const svcmpuo;
+    extern const function_base *const svcnot;
+    extern const function_base *const svcnt;
+    extern const function_base *const svcntb;
+    extern const function_base *const svcntb_pat;
+    extern const function_base *const svcntd;
+    extern const function_base *const svcntd_pat;
+    extern const function_base *const svcnth;
+    extern const function_base *const svcnth_pat;
+    extern const function_base *const svcntp;
+    extern const function_base *const svcntw;
+    extern const function_base *const svcntw_pat;
+    extern const function_base *const svcompact;
+    extern const function_base *const svcreate2;
+    extern const function_base *const svcreate3;
+    extern const function_base *const svcreate4;
+    extern const function_base *const svcvt;
+    extern const function_base *const svdiv;
+    extern const function_base *const svdivr;
+    extern const function_base *const svdot;
+    extern const function_base *const svdot_lane;
+    extern const function_base *const svdup;
+    extern const function_base *const svdup_lane;
+    extern const function_base *const svdupq;
+    extern const function_base *const svdupq_lane;
+    extern const function_base *const sveor;
+    extern const function_base *const sveorv;
+    extern const function_base *const svexpa;
+    extern const function_base *const svext;
+    extern const function_base *const svextb;
+    extern const function_base *const svexth;
+    extern const function_base *const svextw;
+    extern const function_base *const svget2;
+    extern const function_base *const svget3;
+    extern const function_base *const svget4;
+    extern const function_base *const svindex;
+    extern const function_base *const svinsr;
+    extern const function_base *const svlasta;
+    extern const function_base *const svlastb;
+    extern const function_base *const svld1;
+    extern const function_base *const svld1_gather;
+    extern const function_base *const svld1rq;
+    extern const function_base *const svld1sb;
+    extern const function_base *const svld1sb_gather;
+    extern const function_base *const svld1sh;
+    extern const function_base *const svld1sh_gather;
+    extern const function_base *const svld1sw;
+    extern const function_base *const svld1sw_gather;
+    extern const function_base *const svld1ub;
+    extern const function_base *const svld1ub_gather;
+    extern const function_base *const svld1uh;
+    extern const function_base *const svld1uh_gather;
+    extern const function_base *const svld1uw;
+    extern const function_base *const svld1uw_gather;
+    extern const function_base *const svld2;
+    extern const function_base *const svld3;
+    extern const function_base *const svld4;
+    extern const function_base *const svldff1;
+    extern const function_base *const svldff1_gather;
+    extern const function_base *const svldff1sb;
+    extern const function_base *const svldff1sb_gather;
+    extern const function_base *const svldff1sh;
+    extern const function_base *const svldff1sh_gather;
+    extern const function_base *const svldff1sw;
+    extern const function_base *const svldff1sw_gather;
+    extern const function_base *const svldff1ub;
+    extern const function_base *const svldff1ub_gather;
+    extern const function_base *const svldff1uh;
+    extern const function_base *const svldff1uh_gather;
+    extern const function_base *const svldff1uw;
+    extern const function_base *const svldff1uw_gather;
+    extern const function_base *const svldnf1;
+    extern const function_base *const svldnf1sb;
+    extern const function_base *const svldnf1sh;
+    extern const function_base *const svldnf1sw;
+    extern const function_base *const svldnf1ub;
+    extern const function_base *const svldnf1uh;
+    extern const function_base *const svldnf1uw;
+    extern const function_base *const svldnt1;
+    extern const function_base *const svlen;
+    extern const function_base *const svlsl;
+    extern const function_base *const svlsl_wide;
+    extern const function_base *const svlsr;
+    extern const function_base *const svlsr_wide;
+    extern const function_base *const svmad;
+    extern const function_base *const svmax;
+    extern const function_base *const svmaxnm;
+    extern const function_base *const svmaxnmv;
+    extern const function_base *const svmaxv;
+    extern const function_base *const svmin;
+    extern const function_base *const svminnm;
+    extern const function_base *const svminnmv;
+    extern const function_base *const svminv;
+    extern const function_base *const svmla;
+    extern const function_base *const svmla_lane;
+    extern const function_base *const svmls;
+    extern const function_base *const svmls_lane;
+    extern const function_base *const svmov;
+    extern const function_base *const svmsb;
+    extern const function_base *const svmul;
+    extern const function_base *const svmul_lane;
+    extern const function_base *const svmulh;
+    extern const function_base *const svmulx;
+    extern const function_base *const svnand;
+    extern const function_base *const svneg;
+    extern const function_base *const svnmad;
+    extern const function_base *const svnmla;
+    extern const function_base *const svnmls;
+    extern const function_base *const svnmsb;
+    extern const function_base *const svnor;
+    extern const function_base *const svnot;
+    extern const function_base *const svorn;
+    extern const function_base *const svorr;
+    extern const function_base *const svorv;
+    extern const function_base *const svpfalse;
+    extern const function_base *const svpfirst;
+    extern const function_base *const svpnext;
+    extern const function_base *const svprfb;
+    extern const function_base *const svprfb_gather;
+    extern const function_base *const svprfd;
+    extern const function_base *const svprfd_gather;
+    extern const function_base *const svprfh;
+    extern const function_base *const svprfh_gather;
+    extern const function_base *const svprfw;
+    extern const function_base *const svprfw_gather;
+    extern const function_base *const svptest_any;
+    extern const function_base *const svptest_first;
+    extern const function_base *const svptest_last;
+    extern const function_base *const svptrue;
+    extern const function_base *const svptrue_pat;
+    extern const function_base *const svqadd;
+    extern const function_base *const svqdecb;
+    extern const function_base *const svqdecb_pat;
+    extern const function_base *const svqdecd;
+    extern const function_base *const svqdecd_pat;
+    extern const function_base *const svqdech;
+    extern const function_base *const svqdech_pat;
+    extern const function_base *const svqdecp;
+    extern const function_base *const svqdecw;
+    extern const function_base *const svqdecw_pat;
+    extern const function_base *const svqincb;
+    extern const function_base *const svqincb_pat;
+    extern const function_base *const svqincd;
+    extern const function_base *const svqincd_pat;
+    extern const function_base *const svqinch;
+    extern const function_base *const svqinch_pat;
+    extern const function_base *const svqincp;
+    extern const function_base *const svqincw;
+    extern const function_base *const svqincw_pat;
+    extern const function_base *const svqsub;
+    extern const function_base *const svrbit;
+    extern const function_base *const svrdffr;
+    extern const function_base *const svrecpe;
+    extern const function_base *const svrecps;
+    extern const function_base *const svrecpx;
+    extern const function_base *const svreinterpret;
+    extern const function_base *const svrev;
+    extern const function_base *const svrevb;
+    extern const function_base *const svrevh;
+    extern const function_base *const svrevw;
+    extern const function_base *const svrinta;
+    extern const function_base *const svrinti;
+    extern const function_base *const svrintm;
+    extern const function_base *const svrintn;
+    extern const function_base *const svrintp;
+    extern const function_base *const svrintx;
+    extern const function_base *const svrintz;
+    extern const function_base *const svrsqrte;
+    extern const function_base *const svrsqrts;
+    extern const function_base *const svscale;
+    extern const function_base *const svsel;
+    extern const function_base *const svset2;
+    extern const function_base *const svset3;
+    extern const function_base *const svset4;
+    extern const function_base *const svsetffr;
+    extern const function_base *const svsplice;
+    extern const function_base *const svsqrt;
+    extern const function_base *const svst1;
+    extern const function_base *const svst1_scatter;
+    extern const function_base *const svst1b;
+    extern const function_base *const svst1b_scatter;
+    extern const function_base *const svst1h;
+    extern const function_base *const svst1h_scatter;
+    extern const function_base *const svst1w;
+    extern const function_base *const svst1w_scatter;
+    extern const function_base *const svst2;
+    extern const function_base *const svst3;
+    extern const function_base *const svst4;
+    extern const function_base *const svstnt1;
+    extern const function_base *const svsub;
+    extern const function_base *const svsubr;
+    extern const function_base *const svtbl;
+    extern const function_base *const svtmad;
+    extern const function_base *const svtrn1;
+    extern const function_base *const svtrn2;
+    extern const function_base *const svtsmul;
+    extern const function_base *const svtssel;
+    extern const function_base *const svundef;
+    extern const function_base *const svundef2;
+    extern const function_base *const svundef3;
+    extern const function_base *const svundef4;
+    extern const function_base *const svunpkhi;
+    extern const function_base *const svunpklo;
+    extern const function_base *const svuzp1;
+    extern const function_base *const svuzp2;
+    extern const function_base *const svwhilele;
+    extern const function_base *const svwhilelt;
+    extern const function_base *const svwrffr;
+    extern const function_base *const svzip1;
+    extern const function_base *const svzip2;
+  }
+}
+
+#endif
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-functions.h b/gcc/config/aarch64/aarch64-sve-builtins-functions.h
new file mode 100644 (file)
index 0000000..0df7306
--- /dev/null
@@ -0,0 +1,444 @@
+/* ACLE support for AArch64 SVE (function_base classes)
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_AARCH64_SVE_BUILTINS_FUNCTIONS_H
+#define GCC_AARCH64_SVE_BUILTINS_FUNCTIONS_H
+
+namespace aarch64_sve {
+
+/* Wrap T, which is derived from function_base, and indicate that the
+   function never has side effects.  It is only necessary to use this
+   wrapper on functions that might have floating-point suffixes, since
+   otherwise we assume by default that the function has no side effects.  */
+template<typename T>
+class quiet : public T
+{
+public:
+  CONSTEXPR quiet () : T () {}
+
+  /* Unfortunately we can't use parameter packs yet.  */
+  template<typename T1>
+  CONSTEXPR quiet (const T1 &t1) : T (t1) {}
+
+  template<typename T1, typename T2>
+  CONSTEXPR quiet (const T1 &t1, const T2 &t2) : T (t1, t2) {}
+
+  template<typename T1, typename T2, typename T3>
+  CONSTEXPR quiet (const T1 &t1, const T2 &t2, const T3 &t3)
+    : T (t1, t2, t3) {}
+
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return 0;
+  }
+};
+
+/* A function_base that sometimes or always operates on tuples of
+   vectors.  */
+class multi_vector_function : public function_base
+{
+public:
+  CONSTEXPR multi_vector_function (unsigned int vectors_per_tuple)
+    : m_vectors_per_tuple (vectors_per_tuple) {}
+
+  unsigned int
+  vectors_per_tuple () const OVERRIDE
+  {
+    return m_vectors_per_tuple;
+  }
+
+  /* The number of vectors in a tuple, or 1 if the function only operates
+     on single vectors.  */
+  unsigned int m_vectors_per_tuple;
+};
+
+/* A function_base that loads or stores contiguous memory elements
+   without extending or truncating them.  */
+class full_width_access : public multi_vector_function
+{
+public:
+  CONSTEXPR full_width_access (unsigned int vectors_per_tuple = 1)
+    : multi_vector_function (vectors_per_tuple) {}
+
+  tree
+  memory_scalar_type (const function_instance &fi) const OVERRIDE
+  {
+    return fi.scalar_type (0);
+  }
+
+  machine_mode
+  memory_vector_mode (const function_instance &fi) const OVERRIDE
+  {
+    machine_mode mode = fi.vector_mode (0);
+    if (m_vectors_per_tuple != 1)
+      mode = targetm.array_mode (mode, m_vectors_per_tuple).require ();
+    return mode;
+  }
+};
+
+/* A function_base that loads elements from memory and extends them
+   to a wider element.  The memory element type is a fixed part of
+   the function base name.  */
+class extending_load : public function_base
+{
+public:
+  CONSTEXPR extending_load (type_suffix_index memory_type)
+    : m_memory_type (memory_type) {}
+
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_READ_MEMORY;
+  }
+
+  tree
+  memory_scalar_type (const function_instance &) const OVERRIDE
+  {
+    return scalar_types[type_suffixes[m_memory_type].vector_type];
+  }
+
+  machine_mode
+  memory_vector_mode (const function_instance &fi) const OVERRIDE
+  {
+    machine_mode mem_mode = type_suffixes[m_memory_type].vector_mode;
+    machine_mode reg_mode = fi.vector_mode (0);
+    return aarch64_sve_data_mode (GET_MODE_INNER (mem_mode),
+                                 GET_MODE_NUNITS (reg_mode)).require ();
+  }
+
+  /* Return the rtx code associated with the kind of extension that
+     the load performs.  */
+  rtx_code
+  extend_rtx_code () const
+  {
+    return (type_suffixes[m_memory_type].unsigned_p
+           ? ZERO_EXTEND : SIGN_EXTEND);
+  }
+
+  /* The type of the memory elements.  This is part of the function base
+     name rather than a true type suffix.  */
+  type_suffix_index m_memory_type;
+};
+
+/* A function_base that truncates vector elements and stores them to memory.
+   The memory element width is a fixed part of the function base name.  */
+class truncating_store : public function_base
+{
+public:
+  CONSTEXPR truncating_store (scalar_int_mode to_mode) : m_to_mode (to_mode) {}
+
+  unsigned int
+  call_properties (const function_instance &) const OVERRIDE
+  {
+    return CP_WRITE_MEMORY;
+  }
+
+  tree
+  memory_scalar_type (const function_instance &fi) const OVERRIDE
+  {
+    /* In truncating stores, the signedness of the memory element is defined
+       to be the same as the signedness of the vector element.  The signedness
+       doesn't make any difference to the behavior of the function.  */
+    type_class_index tclass = fi.type_suffix (0).tclass;
+    unsigned int element_bits = GET_MODE_BITSIZE (m_to_mode);
+    type_suffix_index suffix = find_type_suffix (tclass, element_bits);
+    return scalar_types[type_suffixes[suffix].vector_type];
+  }
+
+  machine_mode
+  memory_vector_mode (const function_instance &fi) const OVERRIDE
+  {
+    poly_uint64 nunits = GET_MODE_NUNITS (fi.vector_mode (0));
+    return aarch64_sve_data_mode (m_to_mode, nunits).require ();
+  }
+
+  /* The mode of a single memory element.  */
+  scalar_int_mode m_to_mode;
+};
+
+/* A function_base for functions that have an associated rtx code.
+   It supports all forms of predication except PRED_implicit.  */
+class rtx_code_function : public function_base
+{
+public:
+  CONSTEXPR rtx_code_function (rtx_code code_for_sint, rtx_code code_for_uint,
+                              int unspec_for_fp = -1)
+    : m_code_for_sint (code_for_sint), m_code_for_uint (code_for_uint),
+      m_unspec_for_fp (unspec_for_fp) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.map_to_rtx_codes (m_code_for_sint, m_code_for_uint,
+                              m_unspec_for_fp);
+  }
+
+  /* The rtx code to use for signed and unsigned integers respectively.
+     Can be UNKNOWN for functions that don't have integer forms.  */
+  rtx_code m_code_for_sint;
+  rtx_code m_code_for_uint;
+
+  /* The UNSPEC_COND_* to use for floating-point operations.  Can be -1
+     for functions that only operate on integers.  */
+  int m_unspec_for_fp;
+};
+
+/* Like rtx_code_function, but for functions that take what is normally
+   the final argument first.  One use of this class is to handle binary
+   reversed operations; another is to handle MLA-style operations that
+   are normally expressed in GCC as MAD-style operations.  */
+class rtx_code_function_rotated : public function_base
+{
+public:
+  CONSTEXPR rtx_code_function_rotated (rtx_code code_for_sint,
+                                      rtx_code code_for_uint,
+                                      int unspec_for_fp = -1)
+    : m_code_for_sint (code_for_sint), m_code_for_uint (code_for_uint),
+      m_unspec_for_fp (unspec_for_fp) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Rotate the inputs into their normal order, but continue to make _m
+       functions merge with what was originally the first vector argument.  */
+    unsigned int nargs = e.args.length ();
+    e.rotate_inputs_left (e.pred != PRED_none ? 1 : 0, nargs);
+    return e.map_to_rtx_codes (m_code_for_sint, m_code_for_uint,
+                              m_unspec_for_fp, nargs - 1);
+  }
+
+  /* The rtx code to use for signed and unsigned integers respectively.
+     Can be UNKNOWN for functions that don't have integer forms.  */
+  rtx_code m_code_for_sint;
+  rtx_code m_code_for_uint;
+
+  /* The UNSPEC_COND_* to use for floating-point operations.  Can be -1
+     for functions that only operate on integers.  */
+  int m_unspec_for_fp;
+};
+
+/* A function_base for functions that have an associated unspec code.
+   It supports all forms of predication except PRED_implicit.  */
+class unspec_based_function : public function_base
+{
+public:
+  CONSTEXPR unspec_based_function (int unspec_for_sint, int unspec_for_uint,
+                                  int unspec_for_fp)
+    : m_unspec_for_sint (unspec_for_sint),
+      m_unspec_for_uint (unspec_for_uint),
+      m_unspec_for_fp (unspec_for_fp)
+  {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    return e.map_to_unspecs (m_unspec_for_sint, m_unspec_for_uint,
+                            m_unspec_for_fp);
+  }
+
+  /* The unspec code associated with signed-integer, unsigned-integer
+     and floating-point operations respectively.  */
+  int m_unspec_for_sint;
+  int m_unspec_for_uint;
+  int m_unspec_for_fp;
+};
+
+/* Like unspec_based_function, but for functions that take what is normally
+   the final argument first.  One use of this class is to handle binary
+   reversed operations; another is to handle MLA-style operations that
+   are normally expressed in GCC as MAD-style operations.  */
+class unspec_based_function_rotated : public function_base
+{
+public:
+  CONSTEXPR unspec_based_function_rotated (int unspec_for_sint,
+                                          int unspec_for_uint,
+                                          int unspec_for_fp)
+    : m_unspec_for_sint (unspec_for_sint),
+      m_unspec_for_uint (unspec_for_uint),
+      m_unspec_for_fp (unspec_for_fp)
+  {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* Rotate the inputs into their normal order, but continue to make _m
+       functions merge with what was originally the first vector argument.  */
+    unsigned int nargs = e.args.length ();
+    e.rotate_inputs_left (e.pred != PRED_none ? 1 : 0, nargs);
+    return e.map_to_unspecs (m_unspec_for_sint, m_unspec_for_uint,
+                            m_unspec_for_fp, nargs - 1);
+  }
+
+  /* The unspec code associated with signed-integer, unsigned-integer
+     and floating-point operations respectively.  */
+  int m_unspec_for_sint;
+  int m_unspec_for_uint;
+  int m_unspec_for_fp;
+};
+
+/* A function_base for functions that permute their arguments.  */
+class permute : public quiet<function_base>
+{
+public:
+  /* Fold a unary or binary permute with the permute vector given by
+     BUILDER.  */
+  gimple *
+  fold_permute (const gimple_folder &f, const vec_perm_builder &builder) const
+  {
+    /* Punt for now on _b16 and wider; we'd need more complex evpc logic
+       to rerecognize the result.  */
+    if (f.type_suffix (0).bool_p && f.type_suffix (0).element_bits > 8)
+      return NULL;
+
+    unsigned int nargs = gimple_call_num_args (f.call);
+    poly_uint64 nelts = TYPE_VECTOR_SUBPARTS (TREE_TYPE (f.lhs));
+    vec_perm_indices indices (builder, nargs, nelts);
+    tree perm_type = build_vector_type (ssizetype, nelts);
+    return gimple_build_assign (f.lhs, VEC_PERM_EXPR,
+                               gimple_call_arg (f.call, 0),
+                               gimple_call_arg (f.call, nargs - 1),
+                               vec_perm_indices_to_tree (perm_type, indices));
+  }
+};
+
+/* A function_base for functions that permute two vectors using a fixed
+   choice of indices.  */
+class binary_permute : public permute
+{
+public:
+  CONSTEXPR binary_permute (int unspec) : m_unspec (unspec) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    insn_code icode = code_for_aarch64_sve (m_unspec, e.vector_mode (0));
+    return e.use_exact_insn (icode);
+  }
+
+  /* The unspec code associated with the operation.  */
+  int m_unspec;
+};
+
+/* A function_base for functions that reduce a vector to a scalar.  */
+class reduction : public function_base
+{
+public:
+  CONSTEXPR reduction (int unspec)
+    : m_unspec_for_sint (unspec),
+      m_unspec_for_uint (unspec),
+      m_unspec_for_fp (unspec)
+  {}
+
+  CONSTEXPR reduction (int unspec_for_sint, int unspec_for_uint,
+                      int unspec_for_fp)
+    : m_unspec_for_sint (unspec_for_sint),
+      m_unspec_for_uint (unspec_for_uint),
+      m_unspec_for_fp (unspec_for_fp)
+  {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+    int unspec = (!e.type_suffix (0).integer_p ? m_unspec_for_fp
+                 : e.type_suffix (0).unsigned_p ? m_unspec_for_uint
+                 : m_unspec_for_sint);
+    /* There's no distinction between SADDV and UADDV for 64-bit elements;
+       the signed versions only exist for narrower elements.  */
+    if (GET_MODE_UNIT_BITSIZE (mode) == 64 && unspec == UNSPEC_SADDV)
+      unspec = UNSPEC_UADDV;
+    return e.use_exact_insn (code_for_aarch64_pred_reduc (unspec, mode));
+  }
+
+  /* The unspec code associated with signed-integer, unsigned-integer
+     and floating-point operations respectively.  */
+  int m_unspec_for_sint;
+  int m_unspec_for_uint;
+  int m_unspec_for_fp;
+};
+
+/* A function_base for functions that shift narrower-than-64-bit values
+   by 64-bit amounts.  */
+class shift_wide : public function_base
+{
+public:
+  CONSTEXPR shift_wide (rtx_code code, int wide_unspec)
+    : m_code (code), m_wide_unspec (wide_unspec) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    machine_mode mode = e.vector_mode (0);
+    machine_mode elem_mode = GET_MODE_INNER (mode);
+
+    /* If the argument is a constant that the normal shifts can handle
+       directly, use them instead.  */
+    rtx shift = unwrap_const_vec_duplicate (e.args.last ());
+    if (aarch64_simd_shift_imm_p (shift, elem_mode, m_code == ASHIFT))
+      {
+       e.args.last () = shift;
+       return e.map_to_rtx_codes (m_code, m_code, -1);
+      }
+
+    if (e.pred == PRED_x)
+      return e.use_unpred_insn (code_for_aarch64_sve (m_wide_unspec, mode));
+
+    return e.use_cond_insn (code_for_cond (m_wide_unspec, mode));
+  }
+
+  /* The rtx code associated with a "normal" shift.  */
+  rtx_code m_code;
+
+  /* The unspec code associated with the wide shift.  */
+  int m_wide_unspec;
+};
+
+/* A function_base for unary functions that count bits.  */
+class unary_count : public quiet<function_base>
+{
+public:
+  CONSTEXPR unary_count (rtx_code code) : m_code (code) {}
+
+  rtx
+  expand (function_expander &e) const OVERRIDE
+  {
+    /* The md patterns treat the operand as an integer.  */
+    machine_mode mode = mode_for_int_vector (e.vector_mode (0)).require ();
+    e.args.last () = gen_lowpart (mode, e.args.last ());
+
+    if (e.pred == PRED_x)
+      return e.use_pred_x_insn (code_for_aarch64_pred (m_code, mode));
+
+    return e.use_cond_insn (code_for_cond (m_code, mode));
+  }
+
+  /* The rtx code associated with the operation.  */
+  rtx_code m_code;
+};
+
+}
+
+/* Declare the global function base NAME, creating it from an instance
+   of class CLASS with constructor arguments ARGS.  */
+#define FUNCTION(NAME, CLASS, ARGS) \
+  namespace { static CONSTEXPR const CLASS NAME##_obj ARGS; } \
+  namespace functions { const function_base *const NAME = &NAME##_obj; }
+
+#endif
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc b/gcc/config/aarch64/aarch64-sve-builtins-shapes.cc
new file mode 100644 (file)
index 0000000..6ab233b
--- /dev/null
@@ -0,0 +1,2236 @@
+/* ACLE support for AArch64 SVE (function shapes)
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "memmodel.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "aarch64-sve-builtins.h"
+#include "aarch64-sve-builtins-shapes.h"
+
+/* In the comments below, _t0 represents the first type suffix and _t1
+   represents the second.  Square brackets enclose characters that are
+   present in only the full name, not the overloaded name.  Governing
+   predicate arguments and predicate suffixes are not shown, since they
+   depend on the predication type, which is a separate piece of
+   information from the shape.
+
+   Non-overloaded functions may have additional suffixes beyond the
+   ones shown, if those suffixes don't affect the types in the type
+   signature.  E.g. the predicate form of svtrn1 has a _b<bits> suffix,
+   but this does not affect the prototype, which is always
+   "svbool_t(svbool_t, svbool_t)".  */
+
+namespace aarch64_sve {
+
+/* Return a representation of "const T *".  */
+static tree
+build_const_pointer (tree t)
+{
+  return build_pointer_type (build_qualified_type (t, TYPE_QUAL_CONST));
+}
+
+/* If INSTANCE has a governing predicate, add it to the list of argument
+   types in ARGUMENT_TYPES.  RETURN_TYPE is the type returned by the
+   function.  */
+static void
+apply_predication (const function_instance &instance, tree return_type,
+                  vec<tree> &argument_types)
+{
+  if (instance.pred != PRED_none)
+    {
+      argument_types.quick_insert (0, get_svbool_t ());
+      /* For unary merge operations, the first argument is a vector with
+        the same type as the result.  */
+      if (argument_types.length () == 2 && instance.pred == PRED_m)
+       argument_types.quick_insert (0, return_type);
+    }
+}
+
+/* Parse and move past an element type in FORMAT and return it as a type
+   suffix.  The format is:
+
+   [01]    - the element type in type suffix 0 or 1 of INSTANCE
+   f<bits> - a floating-point type with the given number of bits
+   f[01]   - a floating-point type with the same width as type suffix 0 or 1
+   h<elt>  - a half-sized version of <elt>
+   p       - a predicate (represented as TYPE_SUFFIX_b)
+   q<elt>  - a quarter-sized version of <elt>
+   s<bits> - a signed type with the given number of bits
+   s[01]   - a signed type with the same width as type suffix 0 or 1
+   u<bits> - an unsigned type with the given number of bits
+   u[01]   - an unsigned type with the same width as type suffix 0 or 1
+   w<elt>  - a 64-bit version of <elt> if <elt> is integral, otherwise <elt>
+
+   where <elt> is another element type.  */
+static type_suffix_index
+parse_element_type (const function_instance &instance, const char *&format)
+{
+  int ch = *format++;
+
+  if (ch == 'f' || ch == 's' || ch == 'u')
+    {
+      type_class_index tclass = (ch == 'f' ? TYPE_float
+                                : ch == 's' ? TYPE_signed
+                                : TYPE_unsigned);
+      char *end;
+      unsigned int bits = strtol (format, &end, 10);
+      format = end;
+      if (bits == 0 || bits == 1)
+       bits = instance.type_suffix (bits).element_bits;
+      return find_type_suffix (tclass, bits);
+    }
+
+  if (ch == 'w')
+    {
+      type_suffix_index suffix = parse_element_type (instance, format);
+      if (type_suffixes[suffix].integer_p)
+       return find_type_suffix (type_suffixes[suffix].tclass, 64);
+      return suffix;
+    }
+
+  if (ch == 'p')
+    return TYPE_SUFFIX_b;
+
+  if (ch == 'q')
+    {
+      type_suffix_index suffix = parse_element_type (instance, format);
+      return find_type_suffix (type_suffixes[suffix].tclass,
+                              type_suffixes[suffix].element_bits / 4);
+    }
+
+  if (ch == 'h')
+    {
+      type_suffix_index suffix = parse_element_type (instance, format);
+      /* Widening and narrowing doesn't change the type for predicates;
+        everything's still an svbool_t.  */
+      if (suffix == TYPE_SUFFIX_b)
+       return suffix;
+      return find_type_suffix (type_suffixes[suffix].tclass,
+                              type_suffixes[suffix].element_bits / 2);
+    }
+
+  if (ch == '0' || ch == '1')
+    return instance.type_suffix_ids[ch - '0'];
+
+  gcc_unreachable ();
+}
+
+/* Read and return a type from FORMAT for function INSTANCE.  Advance
+   FORMAT beyond the type string.  The format is:
+
+   _       - void
+   al      - array pointer for loads
+   ap      - array pointer for prefetches
+   as      - array pointer for stores
+   b       - base vector type (from a _<m0>base suffix)
+   d       - displacement vector type (from a _<m1>index or _<m1>offset suffix)
+   e<name> - an enum with the given name
+   s<elt>  - a scalar type with the given element suffix
+   t<elt>  - a vector or tuple type with given element suffix [*1]
+   v<elt>  - a vector with the given element suffix
+
+   where <elt> has the format described above parse_element_type
+
+   [*1] the vectors_per_tuple function indicates whether the type should
+        be a tuple, and if so, how many vectors it should contain.  */
+static tree
+parse_type (const function_instance &instance, const char *&format)
+{
+  int ch = *format++;
+
+  if (ch == '_')
+    return void_type_node;
+
+  if (ch == 'a')
+    {
+      ch = *format++;
+      if (ch == 'l')
+       return build_const_pointer (instance.memory_scalar_type ());
+      if (ch == 'p')
+       return const_ptr_type_node;
+      if (ch == 's')
+       return build_pointer_type (instance.memory_scalar_type ());
+      gcc_unreachable ();
+    }
+
+  if (ch == 'b')
+    return instance.base_vector_type ();
+
+  if (ch == 'd')
+    return instance.displacement_vector_type ();
+
+  if (ch == 'e')
+    {
+      if (strncmp (format, "pattern", 7) == 0)
+       {
+         format += 7;
+         return acle_svpattern;
+       }
+      if (strncmp (format, "prfop", 5) == 0)
+       {
+         format += 5;
+         return acle_svprfop;
+       }
+      gcc_unreachable ();
+    }
+
+  if (ch == 's')
+    {
+      type_suffix_index suffix = parse_element_type (instance, format);
+      return scalar_types[type_suffixes[suffix].vector_type];
+    }
+
+  if (ch == 't')
+    {
+      type_suffix_index suffix = parse_element_type (instance, format);
+      vector_type_index vector_type = type_suffixes[suffix].vector_type;
+      unsigned int num_vectors = instance.vectors_per_tuple ();
+      return acle_vector_types[num_vectors - 1][vector_type];
+    }
+
+  if (ch == 'v')
+    {
+      type_suffix_index suffix = parse_element_type (instance, format);
+      return acle_vector_types[0][type_suffixes[suffix].vector_type];
+    }
+
+  gcc_unreachable ();
+}
+
+/* Read and move past any argument count at FORMAT for the function
+   signature of INSTANCE.  The counts are:
+
+   *q: one argument per element in a 128-bit quadword (as for svdupq)
+   *t: one argument per vector in a tuple (as for svcreate)
+
+   Otherwise the count is 1.  */
+static unsigned int
+parse_count (const function_instance &instance, const char *&format)
+{
+  if (format[0] == '*' && format[1] == 'q')
+    {
+      format += 2;
+      return instance.elements_per_vq (0);
+    }
+  if (format[0] == '*' && format[1] == 't')
+    {
+      format += 2;
+      return instance.vectors_per_tuple ();
+    }
+  return 1;
+}
+
+/* Read a type signature for INSTANCE from FORMAT.  Add the argument types
+   to ARGUMENT_TYPES and return the return type.
+
+   The format is a comma-separated list of types (as for parse_type),
+   with the first type being the return type and the rest being the
+   argument types.  Each argument type can be followed by an optional
+   count (as for parse_count).  */
+static tree
+parse_signature (const function_instance &instance, const char *format,
+                vec<tree> &argument_types)
+{
+  tree return_type = parse_type (instance, format);
+  while (format[0] == ',')
+    {
+      format += 1;
+      tree argument_type = parse_type (instance, format);
+      unsigned int count = parse_count (instance, format);
+      for (unsigned int i = 0; i < count; ++i)
+       argument_types.quick_push (argument_type);
+    }
+  gcc_assert (format[0] == 0);
+  return return_type;
+}
+
+/* Add one function instance for GROUP, using mode suffix MODE_SUFFIX_ID,
+   the type suffixes at index TI and the predication suffix at index PI.
+   The other arguments are as for build_all.  */
+static void
+build_one (function_builder &b, const char *signature,
+          const function_group_info &group, mode_suffix_index mode_suffix_id,
+          unsigned int ti, unsigned int pi, bool force_direct_overloads)
+{
+  /* Byte forms of svdupq take 16 arguments.  */
+  auto_vec<tree, 16> argument_types;
+  function_instance instance (group.base_name, *group.base, *group.shape,
+                             mode_suffix_id, group.types[ti],
+                             group.preds[pi]);
+  tree return_type = parse_signature (instance, signature, argument_types);
+  apply_predication (instance, return_type, argument_types);
+  b.add_unique_function (instance, return_type, argument_types,
+                        group.required_extensions, force_direct_overloads);
+}
+
+/* Add a function instance for every type and predicate combination
+   in GROUP, which describes some sort of gather or scatter operation.
+   If the function has any type suffixes (as for loads and stores),
+   the first function type suffix specifies either a 32-bit or a 64-bit
+   type; use MODE32 for the former and MODE64 for the latter.  If the
+   function has no type suffixes (as for prefetches), add one MODE32 form
+   and one MODE64 form for each predication type.
+
+   The other arguments are as for build_all.  */
+static void
+build_32_64 (function_builder &b, const char *signature,
+            const function_group_info &group, mode_suffix_index mode32,
+            mode_suffix_index mode64, bool force_direct_overloads = false)
+{
+  for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+    if (group.types[0][0] == NUM_TYPE_SUFFIXES)
+      {
+       build_one (b, signature, group, mode32, 0, pi,
+                  force_direct_overloads);
+       build_one (b, signature, group, mode64, 0, pi,
+                  force_direct_overloads);
+      }
+    else
+      for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
+       {
+         unsigned int bits = type_suffixes[group.types[ti][0]].element_bits;
+         gcc_assert (bits == 32 || bits == 64);
+         mode_suffix_index mode = bits == 32 ? mode32 : mode64;
+         build_one (b, signature, group, mode, ti, pi,
+                    force_direct_overloads);
+       }
+}
+
+/* For every type and predicate combination in GROUP, add one function
+   that takes a scalar (pointer) base and a signed vector array index,
+   and another that instead takes an unsigned vector array index.
+   The vector array index has the same element size as the first
+   function type suffix.  SIGNATURE is as for build_all.  */
+static void
+build_sv_index (function_builder &b, const char *signature,
+               const function_group_info &group)
+{
+  build_32_64 (b, signature, group, MODE_s32index, MODE_s64index);
+  build_32_64 (b, signature, group, MODE_u32index, MODE_u64index);
+}
+
+/* Like build_sv_index, but taking vector byte offsets instead of vector
+   array indices.  */
+static void
+build_sv_offset (function_builder &b, const char *signature,
+                const function_group_info &group)
+{
+  build_32_64 (b, signature, group, MODE_s32offset, MODE_s64offset);
+  build_32_64 (b, signature, group, MODE_u32offset, MODE_u64offset);
+}
+
+/* For every type and predicate combination in GROUP, add a function
+   that takes a vector base address and no displacement.  The vector
+   base has the same element size as the first type suffix.
+
+   The other arguments are as for build_all.  */
+static void
+build_v_base (function_builder &b, const char *signature,
+             const function_group_info &group,
+             bool force_direct_overloads = false)
+{
+  build_32_64 (b, signature, group, MODE_u32base, MODE_u64base,
+              force_direct_overloads);
+}
+
+/* Like build_v_base, but for functions that also take a scalar array
+   index.  */
+static void
+build_vs_index (function_builder &b, const char *signature,
+               const function_group_info &group,
+               bool force_direct_overloads = false)
+{
+  build_32_64 (b, signature, group, MODE_u32base_index, MODE_u64base_index,
+              force_direct_overloads);
+}
+
+/* Like build_v_base, but for functions that also take a scalar byte
+   offset.  */
+static void
+build_vs_offset (function_builder &b, const char *signature,
+                const function_group_info &group,
+                bool force_direct_overloads = false)
+{
+  build_32_64 (b, signature, group, MODE_u32base_offset, MODE_u64base_offset,
+              force_direct_overloads);
+}
+
+/* Add a function instance for every type and predicate combination
+   in GROUP.  Take the function base name from GROUP and the mode suffix
+   from MODE_SUFFIX_ID.  Use SIGNATURE to construct the function signature
+   without a governing predicate, then use apply_predication to add in the
+   predicate.  FORCE_DIRECT_OVERLOADS is true if there is a one-to-one
+   mapping between "short" and "full" names, and if standard overload
+   resolution therefore isn't necessary.  */
+static void
+build_all (function_builder &b, const char *signature,
+          const function_group_info &group, mode_suffix_index mode_suffix_id,
+          bool force_direct_overloads = false)
+{
+  for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+    for (unsigned int ti = 0;
+        ti == 0 || group.types[ti][0] != NUM_TYPE_SUFFIXES; ++ti)
+      build_one (b, signature, group, mode_suffix_id, ti, pi,
+                force_direct_overloads);
+}
+
+/* Declare the function shape NAME, pointing it to an instance
+   of class <NAME>_def.  */
+#define SHAPE(NAME) \
+  static CONSTEXPR const NAME##_def NAME##_obj; \
+  namespace shapes { const function_shape *const NAME = &NAME##_obj; }
+
+/* Base class for functions that are not overloaded.  */
+struct nonoverloaded_base : public function_shape
+{
+  bool
+  explicit_type_suffix_p (unsigned int) const OVERRIDE
+  {
+    return true;
+  }
+
+  tree
+  resolve (function_resolver &) const OVERRIDE
+  {
+    gcc_unreachable ();
+  }
+};
+
+/* Base class for overloaded functions.  Bit N of EXPLICIT_MASK is true
+   if type suffix N appears in the overloaded name.  */
+template<unsigned int EXPLICIT_MASK>
+struct overloaded_base : public function_shape
+{
+  bool
+  explicit_type_suffix_p (unsigned int i) const OVERRIDE
+  {
+    return (EXPLICIT_MASK >> i) & 1;
+  }
+};
+
+/* Base class for adr_index and adr_offset.  */
+struct adr_base : public overloaded_base<0>
+{
+  /* The function takes two arguments: a vector base and a vector displacement
+     (either an index or an offset).  Resolve based on them both.  */
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    mode_suffix_index mode;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (mode = r.resolve_adr_address (0)) == MODE_none)
+      return error_mark_node;
+
+    return r.resolve_to (mode);
+  };
+};
+
+/* Base class for inc_dec and inc_dec_pat.  */
+struct inc_dec_base : public overloaded_base<0>
+{
+  CONSTEXPR inc_dec_base (bool pat_p) : m_pat_p (pat_p) {}
+
+  /* Resolve based on the first argument only, which must be either a
+     scalar or a vector.  If it's a scalar, it must be a 32-bit or
+     64-bit integer.  */
+  tree
+  resolve (function_resolver &r) const
+  {
+    unsigned int i, nargs;
+    if (!r.check_gp_argument (m_pat_p ? 3 : 2, i, nargs)
+       || !r.require_vector_or_scalar_type (i))
+      return error_mark_node;
+
+    mode_suffix_index mode;
+    type_suffix_index type;
+    if (r.scalar_argument_p (i))
+      {
+       mode = MODE_n;
+       type = r.infer_integer_scalar_type (i);
+      }
+    else
+      {
+       mode = MODE_none;
+       type = r.infer_vector_type (i);
+      }
+    if (type == NUM_TYPE_SUFFIXES)
+      return error_mark_node;
+
+    for (++i; i < nargs; ++i)
+      if (!r.require_integer_immediate (i))
+       return error_mark_node;
+
+    return r.resolve_to (mode, type);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    return c.require_immediate_range (m_pat_p ? 2 : 1, 1, 16);
+  }
+
+  bool m_pat_p;
+};
+
+/* Base class for load and load_replicate.  */
+struct load_contiguous_base : public overloaded_base<0>
+{
+  /* Resolve a call based purely on a pointer argument.  The other arguments
+     are a governing predicate and (for MODE_vnum) a vnum offset.  */
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    bool vnum_p = r.mode_suffix_id == MODE_vnum;
+    gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
+
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (vnum_p ? 2 : 1, i, nargs)
+       || (type = r.infer_pointer_type (i)) == NUM_TYPE_SUFFIXES
+       || (vnum_p && !r.require_scalar_type (i + 1, "int64_t")))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+};
+
+/* Base class for load_ext_gather_index and load_ext_gather_offset,
+   which differ only in the units of the displacement.  */
+struct load_ext_gather_base : public overloaded_base<1>
+{
+  /* Resolve a gather load that takes one of:
+
+     - a scalar pointer base and a vector displacement
+     - a vector base with no displacement or
+     - a vector base and a scalar displacement
+
+     The function has an explicit type suffix that determines the type
+     of the loaded data.  */
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    /* No resolution is needed for a vector base with no displacement;
+       there's a one-to-one mapping between short and long names.  */
+    gcc_assert (r.displacement_units () != UNITS_none);
+
+    type_suffix_index type = r.type_suffix_ids[0];
+
+    unsigned int i, nargs;
+    mode_suffix_index mode;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (mode = r.resolve_gather_address (i, type, true)) == MODE_none)
+      return error_mark_node;
+
+    return r.resolve_to (mode, type);
+  }
+};
+
+/* Base class for prefetch_gather_index and prefetch_gather_offset,
+   which differ only in the units of the displacement.  */
+struct prefetch_gather_base : public overloaded_base<0>
+{
+  /* Resolve a gather prefetch that takes one of:
+
+     - a scalar pointer base (const void *) and a vector displacement
+     - a vector base with no displacement or
+     - a vector base and a scalar displacement
+
+     The prefetch operation is the final argument.  This is purely a
+     mode-based resolution; there are no type suffixes.  */
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    bool has_displacement_p = r.displacement_units () != UNITS_none;
+
+    unsigned int i, nargs;
+    mode_suffix_index mode;
+    if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
+       || (mode = r.resolve_gather_address (i, NUM_TYPE_SUFFIXES,
+                                            false)) == MODE_none
+       || !r.require_integer_immediate (nargs - 1))
+      return error_mark_node;
+
+    return r.resolve_to (mode);
+  }
+};
+
+/* Base class for store_scatter_index and store_scatter_offset,
+   which differ only in the units of the displacement.  */
+struct store_scatter_base : public overloaded_base<0>
+{
+  /* Resolve a scatter store that takes one of:
+
+     - a scalar pointer base and a vector displacement
+     - a vector base with no displacement or
+     - a vector base and a scalar displacement
+
+     The stored data is the final argument, and it determines the
+     type suffix.  */
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    bool has_displacement_p = r.displacement_units () != UNITS_none;
+
+    unsigned int i, nargs;
+    mode_suffix_index mode;
+    type_suffix_index type;
+    if (!r.check_gp_argument (has_displacement_p ? 3 : 2, i, nargs)
+       || (type = r.infer_sd_vector_type (nargs - 1)) == NUM_TYPE_SUFFIXES
+       || (mode = r.resolve_gather_address (i, type, false)) == MODE_none)
+      return error_mark_node;
+
+    return r.resolve_to (mode, type);
+  }
+};
+
+/* sv<m0>_t svfoo[_m0base]_[m1]index(sv<m0>_t, sv<m1>_t)
+
+   for all valid combinations of vector base type <m0> and vector
+   displacement type <m1>.  */
+struct adr_index_def : public adr_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_index);
+    build_all (b, "b,b,d", group, MODE_u32base_s32index);
+    build_all (b, "b,b,d", group, MODE_u32base_u32index);
+    build_all (b, "b,b,d", group, MODE_u64base_s64index);
+    build_all (b, "b,b,d", group, MODE_u64base_u64index);
+  }
+};
+SHAPE (adr_index)
+
+/* sv<m0>_t svfoo[_m0base]_[m1]offset(sv<m0>_t, sv<m1>_t).
+
+   for all valid combinations of vector base type <m0> and vector
+   displacement type <m1>.  */
+struct adr_offset_def : public adr_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_offset);
+    build_all (b, "b,b,d", group, MODE_u32base_s32offset);
+    build_all (b, "b,b,d", group, MODE_u32base_u32offset);
+    build_all (b, "b,b,d", group, MODE_u64base_s64offset);
+    build_all (b, "b,b,d", group, MODE_u64base_u64offset);
+  }
+};
+SHAPE (adr_offset)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
+
+   i.e. a binary operation with uniform types, but with no scalar form.  */
+struct binary_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (2);
+  }
+};
+SHAPE (binary)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:int>_t)
+   sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:int>_t).
+
+   i.e. a version of the standard binary shape binary_opt_n in which
+   the final argument is always a signed integer.  */
+struct binary_int_opt_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,vs0", group, MODE_none);
+    build_all (b, "v0,v0,ss0", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+      return error_mark_node;
+
+    return r.finish_opt_n_resolution (i + 1, i, type, TYPE_signed);
+  }
+};
+SHAPE (binary_int_opt_n)
+
+/* sv<t0>_t svfoo_<t0>(sv<t0>_t, sv<t0>_t, uint64_t)
+
+   where the final argument is an integer constant expression in the
+   range [0, 16 / sizeof (<t0>_t) - 1].  */
+struct binary_lane_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (2, 1);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    return c.require_immediate_lane_index (2);
+  }
+};
+SHAPE (binary_lane)
+
+/* sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t).
+
+   i.e. a binary operation in which the final argument is always a scalar
+   rather than a vector.  */
+struct binary_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_n);
+    build_all (b, "v0,v0,s0", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_derived_scalar_type (i + 1, r.SAME_TYPE_CLASS))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+};
+SHAPE (binary_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
+   sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
+
+   i.e. the standard shape for binary operations that operate on
+   uniform types.  */
+struct binary_opt_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0", group, MODE_none);
+    /* _b functions do not have an _n form, but are classified as
+       binary_opt_n so that they can be overloaded with vector
+       functions.  */
+    if (group.types[0][0] == TYPE_SUFFIX_b)
+      gcc_assert (group.types[0][1] == NUM_TYPE_SUFFIXES);
+    else
+      build_all (b, "v0,v0,s0", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform_opt_n (2);
+  }
+};
+SHAPE (binary_opt_n)
+
+/* svbool_t svfoo(svbool_t, svbool_t).  */
+struct binary_pred_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "v0,v0,v0", group, MODE_none);
+  }
+};
+SHAPE (binary_pred)
+
+/* sv<t0>_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
+
+   where the final argument must be 90 or 270.  */
+struct binary_rotate_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (2, 1);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    return c.require_immediate_either_or (2, 90, 270);
+  }
+};
+SHAPE (binary_rotate)
+
+/* sv<t0>_t svfoo_t0(<t0>_t, <t0>_t)
+
+   i.e. a binary function that takes two scalars and returns a vector.
+   An explicit type suffix is required.  */
+struct binary_scalar_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "v0,s0,s0", group, MODE_none);
+  }
+};
+SHAPE (binary_scalar)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
+
+   i.e. a version of "binary" in which the final argument is always an
+   unsigned integer.  */
+struct binary_uint_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,vu0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_derived_vector_type (i + 1, i, type, TYPE_unsigned))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+};
+SHAPE (binary_uint)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, <t0:uint>_t)
+
+   i.e. a version of binary_n in which the final argument is always an
+   unsigned integer.  */
+struct binary_uint_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,su0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_derived_scalar_type (i + 1, TYPE_unsigned))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+};
+SHAPE (binary_uint_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0:uint>_t)
+   sv<t0>_t svfoo[_n_t0](sv<t0>_t, <t0:uint>_t)
+
+   i.e. a version of the standard binary shape binary_opt_n in which
+   the final argument is always an unsigned integer.  */
+struct binary_uint_opt_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,vu0", group, MODE_none);
+    build_all (b, "v0,v0,su0", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+      return error_mark_node;
+
+    return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned);
+  }
+};
+SHAPE (binary_uint_opt_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t).
+
+   i.e. a version of binary_n in which the final argument is always
+   a 64-bit unsigned integer.  */
+struct binary_uint64_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_scalar_type (i + 1, "uint64_t"))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+};
+SHAPE (binary_uint64_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, svuint64_t)
+   sv<t0>_t svfoo[_n_t0](sv<t0>_t, uint64_t)
+
+   i.e. a version of the standard binary shape binary_opt_n in which
+   the final argument is always a uint64_t.  */
+struct binary_uint64_opt_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,vu64", group, MODE_none);
+    build_all (b, "v0,v0,su64", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+      return error_mark_node;
+
+    return r.finish_opt_n_resolution (i + 1, i, type, TYPE_unsigned, 64);
+  }
+};
+SHAPE (binary_uint64_opt_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
+   <t0>_t svfoo[_n_t0](<t0>_t, sv<t0>_t).  */
+struct clast_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0", group, MODE_none);
+    build_all (b, "s0,s0,v0", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    if (!r.check_gp_argument (2, i, nargs)
+       || !r.require_vector_or_scalar_type (i))
+      return error_mark_node;
+
+    if (r.scalar_argument_p (i))
+      {
+       type_suffix_index type;
+       if (!r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
+           || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
+         return error_mark_node;
+       return r.resolve_to (MODE_n, type);
+      }
+    else
+      {
+       type_suffix_index type;
+       if ((type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+           || !r.require_matching_vector_type (i + 1, type))
+         return error_mark_node;
+       return r.resolve_to (MODE_none, type);
+      }
+  }
+};
+SHAPE (clast)
+
+/* svbool_t svfoo[_t0](sv<t0>_t, sv<t0>_t)
+   svbool_t svfoo[_n_t0](sv<t0>_t, <t0>_t)
+
+   i.e. a comparison between two vectors, or between a vector and a scalar.  */
+struct compare_opt_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "vp,v0,v0", group, MODE_none);
+    build_all (b, "vp,v0,s0", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform_opt_n (2);
+  }
+};
+SHAPE (compare_opt_n)
+
+/* svbool_t svfoo_t0[_t1](<t1>_t, <t1>_t)
+
+   where _t0 is a _b<bits> suffix that describes the predicate result.
+   There is no direct relationship between the element sizes of _t0
+   and _t1.  */
+struct compare_scalar_def : public overloaded_base<1>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "vp,s1,s1", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_matching_integer_scalar_type (i + 1, i, type))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, r.type_suffix_ids[0], type);
+  }
+};
+SHAPE (compare_scalar)
+
+/* svbool_t svfoo[_t0](sv<t0>_t, svint64_t)  (for signed t0)
+   svbool_t svfoo[_n_t0](sv<t0>_t, int64_t)  (for signed t0)
+   svbool_t svfoo[_t0](sv<t0>_t, svuint64_t)  (for unsigned t0)
+   svbool_t svfoo[_n_t0](sv<t0>_t, uint64_t)  (for unsigned t0)
+
+   i.e. a comparison in which the second argument is 64 bits.  */
+struct compare_wide_opt_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "vp,v0,vw0", group, MODE_none);
+    build_all (b, "vp,v0,sw0", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+      return error_mark_node;
+
+    return r.finish_opt_n_resolution (i + 1, i, type, r.SAME_TYPE_CLASS, 64);
+  }
+};
+SHAPE (compare_wide_opt_n)
+
+/* uint64_t svfoo().  */
+struct count_inherent_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "su64", group, MODE_none);
+  }
+};
+SHAPE (count_inherent)
+
+/* uint64_t svfoo(enum svpattern).  */
+struct count_pat_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "su64,epattern", group, MODE_none);
+  }
+};
+SHAPE (count_pat)
+
+/* uint64_t svfoo(svbool_t).  */
+struct count_pred_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "su64,vp", group, MODE_none);
+  }
+};
+SHAPE (count_pred)
+
+/* uint64_t svfoo[_t0](sv<t0>_t).  */
+struct count_vector_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "su64,v0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (1);
+  }
+};
+SHAPE (count_vector)
+
+/* sv<t0>xN_t svfoo[_t0](sv<t0>_t, ..., sv<t0>_t)
+
+   where there are N arguments in total.  */
+struct create_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "t0,v0*t", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (r.vectors_per_tuple ());
+  }
+};
+SHAPE (create)
+
+/* sv<t0>_t svfoo[_n]_t0(<t0>_t, ..., <t0>_t)
+
+   where there are enough arguments to fill 128 bits of data (or to
+   control 128 bits of data in the case of predicates).  */
+struct dupq_def : public overloaded_base<1>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    /* The "_n" suffix is optional; the full name has it, but the short
+       name doesn't.  */
+    build_all (b, "v0,s0*q", group, MODE_n, true);
+  }
+
+  tree
+  resolve (function_resolver &) const OVERRIDE
+  {
+    /* The short forms just make "_n" implicit, so no resolution is needed.  */
+    gcc_unreachable ();
+  }
+};
+SHAPE (dupq)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, uint64_t)
+
+   where the final argument is an integer constant expression that when
+   multiplied by the number of bytes in t0 is in the range [0, 255].  */
+struct ext_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (2, 1);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    unsigned int bytes = c.type_suffix (0).element_bytes;
+    return c.require_immediate_range (2, 0, 256 / bytes - 1);
+  }
+};
+SHAPE (ext)
+
+/* <t0>_t svfoo[_t0](<t0>_t, sv<t0>_t).  */
+struct fold_left_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "s0,s0,v0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || !r.require_derived_scalar_type (i, r.SAME_TYPE_CLASS)
+       || (type = r.infer_vector_type (i + 1)) == NUM_TYPE_SUFFIXES)
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+};
+SHAPE (fold_left)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>xN_t, uint64_t)
+
+   where the final argument is an integer constant expression in
+   the range [0, N - 1].  */
+struct get_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,t0,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_integer_immediate (i + 1))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    unsigned int nvectors = c.vectors_per_tuple ();
+    return c.require_immediate_range (1, 0, nvectors - 1);
+  }
+};
+SHAPE (get)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, uint64_t)
+   <t0>_t svfoo[_n_t0](<t0>_t, uint64_t)
+
+   where the t0 in the vector form is a signed or unsigned integer
+   whose size is tied to the [bhwd] suffix of "svfoo".  */
+struct inc_dec_def : public inc_dec_base
+{
+  CONSTEXPR inc_dec_def () : inc_dec_base (false) {}
+
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    /* These functions are unusual in that the type suffixes for
+       the scalar and vector forms are not related.  The vector
+       form always has exactly two potential suffixes while the
+       scalar form always has four.  */
+    if (group.types[2][0] == NUM_TYPE_SUFFIXES)
+      build_all (b, "v0,v0,su64", group, MODE_none);
+    else
+      build_all (b, "s0,s0,su64", group, MODE_n);
+  }
+};
+SHAPE (inc_dec)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, enum svpattern, uint64_t)
+   <t0>_t svfoo[_n_t0](<t0>_t, enum svpattern, uint64_t)
+
+   where the t0 in the vector form is a signed or unsigned integer
+   whose size is tied to the [bhwd] suffix of "svfoo".  */
+struct inc_dec_pat_def : public inc_dec_base
+{
+  CONSTEXPR inc_dec_pat_def () : inc_dec_base (true) {}
+
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    /* These functions are unusual in that the type suffixes for
+       the scalar and vector forms are not related.  The vector
+       form always has exactly two potential suffixes while the
+       scalar form always has four.  */
+    if (group.types[2][0] == NUM_TYPE_SUFFIXES)
+      build_all (b, "v0,v0,epattern,su64", group, MODE_none);
+    else
+      build_all (b, "s0,s0,epattern,su64", group, MODE_n);
+  }
+};
+SHAPE (inc_dec_pat)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, svbool_t).  */
+struct inc_dec_pred_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,vp", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+};
+SHAPE (inc_dec_pred)
+
+/* <t0>_t svfoo[_n_t0]_t1(<t0>_t, svbool_t)
+
+   where _t1 is a _b<bits> suffix that describes the svbool_t argument.  */
+struct inc_dec_pred_scalar_def : public overloaded_base<2>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_n);
+    build_all (b, "s0,s0,vp", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_integer_scalar_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_vector_type (i + 1, VECTOR_TYPE_svbool_t))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type, r.type_suffix_ids[1]);
+  }
+};
+SHAPE (inc_dec_pred_scalar)
+
+/* sv<t0>[xN]_t svfoo_t0().  */
+struct inherent_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "t0", group, MODE_none);
+  }
+};
+SHAPE (inherent)
+
+/* svbool_t svfoo[_b]().  */
+struct inherent_b_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    /* The "_b" suffix is optional; the full name has it, but the short
+       name doesn't.  */
+    build_all (b, "v0", group, MODE_none, true);
+  }
+
+  tree
+  resolve (function_resolver &) const OVERRIDE
+  {
+    /* The short forms just make "_b" implicit, so no resolution is needed.  */
+    gcc_unreachable ();
+  }
+};
+SHAPE (inherent_b)
+
+/* sv<t0>[xN]_t svfoo[_t0](const <t0>_t *)
+   sv<t0>[xN]_t svfoo_vnum[_t0](const <t0>_t *, int64_t).  */
+struct load_def : public load_contiguous_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    b.add_overloaded_functions (group, MODE_vnum);
+    build_all (b, "t0,al", group, MODE_none);
+    build_all (b, "t0,al,ss64", group, MODE_vnum);
+  }
+};
+SHAPE (load)
+
+/* sv<t0>_t svfoo_t0(const <X>_t *)
+   sv<t0>_t svfoo_vnum_t0(const <X>_t *, int64_t)
+
+   where <X> is determined by the function base name.  */
+struct load_ext_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "t0,al", group, MODE_none);
+    build_all (b, "t0,al,ss64", group, MODE_vnum);
+  }
+};
+SHAPE (load_ext)
+
+/* sv<t0>_t svfoo_[s32]index_t0(const <X>_t *, svint32_t)
+   sv<t0>_t svfoo_[s64]index_t0(const <X>_t *, svint64_t)
+   sv<t0>_t svfoo_[u32]index_t0(const <X>_t *, svuint32_t)
+   sv<t0>_t svfoo_[u64]index_t0(const <X>_t *, svuint64_t)
+
+   sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
+   sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
+
+   where <X> is determined by the function base name.  */
+struct load_ext_gather_index_def : public load_ext_gather_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_index);
+    build_sv_index (b, "t0,al,d", group);
+    build_vs_index (b, "t0,b,ss64", group);
+  }
+};
+SHAPE (load_ext_gather_index)
+
+/* sv<t0>_t svfoo_[s32]offset_t0(const <X>_t *, svint32_t)
+   sv<t0>_t svfoo_[s64]offset_t0(const <X>_t *, svint64_t)
+   sv<t0>_t svfoo_[u32]offset_t0(const <X>_t *, svuint32_t)
+   sv<t0>_t svfoo_[u64]offset_t0(const <X>_t *, svuint64_t)
+
+   sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
+   sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
+
+   sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
+   sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t)
+
+   where <X> is determined by the function base name.  */
+struct load_ext_gather_offset_def : public load_ext_gather_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_offset);
+    build_sv_offset (b, "t0,al,d", group);
+    build_v_base (b, "t0,b", group, true);
+    build_vs_offset (b, "t0,b,ss64", group);
+  }
+};
+SHAPE (load_ext_gather_offset)
+
+/* sv<t0>_t svfoo_[s32]index[_t0](const <t0>_t *, svint32_t)
+   sv<t0>_t svfoo_[s64]index[_t0](const <t0>_t *, svint64_t)
+   sv<t0>_t svfoo_[u32]index[_t0](const <t0>_t *, svuint32_t)
+   sv<t0>_t svfoo_[u64]index[_t0](const <t0>_t *, svuint64_t)
+
+   sv<t0>_t svfoo_[s32]offset[_t0](const <t0>_t *, svint32_t)
+   sv<t0>_t svfoo_[s64]offset[_t0](const <t0>_t *, svint64_t)
+   sv<t0>_t svfoo_[u32]offset[_t0](const <t0>_t *, svuint32_t)
+   sv<t0>_t svfoo_[u64]offset[_t0](const <t0>_t *, svuint64_t).  */
+struct load_gather_sv_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_index);
+    b.add_overloaded_functions (group, MODE_offset);
+    build_sv_index (b, "t0,al,d", group);
+    build_sv_offset (b, "t0,al,d", group);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    mode_suffix_index mode;
+    type_suffix_index type;
+    if (!r.check_gp_argument (2, i, nargs)
+       || (type = r.infer_pointer_type (i, true)) == NUM_TYPE_SUFFIXES
+       || (mode = r.resolve_sv_displacement (i + 1, type, true),
+           mode == MODE_none))
+      return error_mark_node;
+
+    return r.resolve_to (mode, type);
+  }
+};
+SHAPE (load_gather_sv)
+
+/* sv<t0>_t svfoo[_u32base]_t0(svuint32_t)
+   sv<t0>_t svfoo[_u64base]_t0(svuint64_t)
+
+   sv<t0>_t svfoo[_u32base]_index_t0(svuint32_t, int64_t)
+   sv<t0>_t svfoo[_u64base]_index_t0(svuint64_t, int64_t)
+
+   sv<t0>_t svfoo[_u32base]_offset_t0(svuint32_t, int64_t)
+   sv<t0>_t svfoo[_u64base]_offset_t0(svuint64_t, int64_t).  */
+struct load_gather_vs_def : public overloaded_base<1>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    /* The base vector mode is optional; the full name has it but the
+       short name doesn't.  There is no ambiguity with SHAPE_load_gather_sv
+       because the latter uses an implicit type suffix.  */
+    build_v_base (b, "t0,b", group, true);
+    build_vs_index (b, "t0,b,ss64", group, true);
+    build_vs_offset (b, "t0,b,ss64", group, true);
+  }
+
+  tree
+  resolve (function_resolver &) const OVERRIDE
+  {
+    /* The short name just makes the base vector mode implicit;
+       no resolution is needed.  */
+    gcc_unreachable ();
+  }
+};
+SHAPE (load_gather_vs)
+
+/* sv<t0>_t svfoo[_t0](const <t0>_t *)
+
+   The only difference from "load" is that this shape has no vnum form.  */
+struct load_replicate_def : public load_contiguous_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "t0,al", group, MODE_none);
+  }
+};
+SHAPE (load_replicate)
+
+/* svbool_t svfoo(enum svpattern).  */
+struct pattern_pred_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "vp,epattern", group, MODE_none);
+  }
+};
+SHAPE (pattern_pred)
+
+/* void svfoo(const void *, svprfop)
+   void svfoo_vnum(const void *, int64_t, svprfop).  */
+struct prefetch_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "_,ap,eprfop", group, MODE_none);
+    build_all (b, "_,ap,ss64,eprfop", group, MODE_vnum);
+  }
+};
+SHAPE (prefetch)
+
+/* void svfoo_[s32]index(const void *, svint32_t, svprfop)
+   void svfoo_[s64]index(const void *, svint64_t, svprfop)
+   void svfoo_[u32]index(const void *, svuint32_t, svprfop)
+   void svfoo_[u64]index(const void *, svuint64_t, svprfop)
+
+   void svfoo[_u32base](svuint32_t, svprfop)
+   void svfoo[_u64base](svuint64_t, svprfop)
+
+   void svfoo[_u32base]_index(svuint32_t, int64_t, svprfop)
+   void svfoo[_u64base]_index(svuint64_t, int64_t, svprfop).  */
+struct prefetch_gather_index_def : public prefetch_gather_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    b.add_overloaded_functions (group, MODE_index);
+    build_sv_index (b, "_,ap,d,eprfop", group);
+    build_v_base (b, "_,b,eprfop", group);
+    build_vs_index (b, "_,b,ss64,eprfop", group);
+  }
+};
+SHAPE (prefetch_gather_index)
+
+/* void svfoo_[s32]offset(const void *, svint32_t, svprfop)
+   void svfoo_[s64]offset(const void *, svint64_t, svprfop)
+   void svfoo_[u32]offset(const void *, svuint32_t, svprfop)
+   void svfoo_[u64]offset(const void *, svuint64_t, svprfop)
+
+   void svfoo[_u32base](svuint32_t, svprfop)
+   void svfoo[_u64base](svuint64_t, svprfop)
+
+   void svfoo[_u32base]_offset(svuint32_t, int64_t, svprfop)
+   void svfoo[_u64base]_offset(svuint64_t, int64_t, svprfop).  */
+struct prefetch_gather_offset_def : public prefetch_gather_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    b.add_overloaded_functions (group, MODE_offset);
+    build_sv_offset (b, "_,ap,d,eprfop", group);
+    build_v_base (b, "_,b,eprfop", group);
+    build_vs_offset (b, "_,b,ss64,eprfop", group);
+  }
+};
+SHAPE (prefetch_gather_offset)
+
+/* bool svfoo(svbool_t).  */
+struct ptest_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "sp,vp", group, MODE_none);
+  }
+};
+SHAPE (ptest)
+
+/* svbool_t svfoo().  */
+struct rdffr_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "vp", group, MODE_none);
+  }
+};
+SHAPE (rdffr)
+
+/* <t0>_t svfoo[_t0](sv<t0>_t).  */
+struct reduction_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "s0,v0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (1);
+  }
+};
+SHAPE (reduction)
+
+/* int64_t svfoo[_t0](sv<t0>_t)  (for signed t0)
+   uint64_t svfoo[_t0](sv<t0>_t)  (for unsigned t0)
+   <t0>_t svfoo[_t0](sv<t0>_t)  (for floating-point t0)
+
+   i.e. a version of "reduction" in which the return type for integers
+   always has 64 bits.  */
+struct reduction_wide_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "sw0,v0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (1);
+  }
+};
+SHAPE (reduction_wide)
+
+/* sv<t0>xN_t svfoo[_t0](sv<t0>xN_t, uint64_t, sv<t0>_t)
+
+   where the second argument is an integer constant expression in the
+   range [0, N - 1].  */
+struct set_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "t0,t0,su64,v0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (3, i, nargs)
+       || (type = r.infer_tuple_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_integer_immediate (i + 1)
+       || !r.require_derived_vector_type (i + 2, i, type))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    unsigned int nvectors = c.vectors_per_tuple ();
+    return c.require_immediate_range (1, 0, nvectors - 1);
+  }
+};
+SHAPE (set)
+
+/* void svfoo().  */
+struct setffr_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "_", group, MODE_none);
+  }
+};
+SHAPE (setffr)
+
+/* sv<t0>_t svfoo[_n_t0])(sv<t0>_t, uint64_t)
+
+   where the final argument must be an integer constant expression in the
+   range [1, sizeof (<t0>_t) * 8].  */
+struct shift_right_imm_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_n);
+    build_all (b, "v0,v0,su64", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (1, 1);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    unsigned int bits = c.type_suffix (0).element_bits;
+    return c.require_immediate_range (1, 1, bits);
+  }
+};
+SHAPE (shift_right_imm)
+
+/* void svfoo[_t0](<X>_t *, sv<t0>[xN]_t)
+   void svfoo_vnum[_t0](<X>_t *, int64_t, sv<t0>[xN]_t)
+
+   where <X> might be tied to <t0> (for non-truncating stores) or might
+   depend on the function base name (for truncating stores).  */
+struct store_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    b.add_overloaded_functions (group, MODE_vnum);
+    build_all (b, "_,as,t0", group, MODE_none);
+    build_all (b, "_,as,ss64,t0", group, MODE_vnum);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    bool vnum_p = r.mode_suffix_id == MODE_vnum;
+    gcc_assert (r.mode_suffix_id == MODE_none || vnum_p);
+
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (vnum_p ? 3 : 2, i, nargs)
+       || !r.require_pointer_type (i)
+       || (vnum_p && !r.require_scalar_type (i + 1, "int64_t"))
+       || ((type = r.infer_tuple_type (nargs - 1)) == NUM_TYPE_SUFFIXES))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+};
+SHAPE (store)
+
+/* void svfoo_[s32]index[_t0](<X>_t *, svint32_t, sv<t0>_t)
+   void svfoo_[s64]index[_t0](<X>_t *, svint64_t, sv<t0>_t)
+   void svfoo_[u32]index[_t0](<X>_t *, svuint32_t, sv<t0>_t)
+   void svfoo_[u64]index[_t0](<X>_t *, svuint64_t, sv<t0>_t)
+
+   void svfoo[_u32base]_index[_t0](svuint32_t, int64_t, sv<t0>_t)
+   void svfoo[_u64base]_index[_t0](svuint64_t, int64_t, sv<t0>_t)
+
+   where <X> might be tied to <t0> (for non-truncating stores) or might
+   depend on the function base name (for truncating stores).  */
+struct store_scatter_index_def : public store_scatter_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_index);
+    build_sv_index (b, "_,as,d,t0", group);
+    build_vs_index (b, "_,b,ss64,t0", group);
+  }
+};
+SHAPE (store_scatter_index)
+
+/* void svfoo_[s32]offset[_t0](<X>_t *, svint32_t, sv<t0>_t)
+   void svfoo_[s64]offset[_t0](<X>_t *, svint64_t, sv<t0>_t)
+   void svfoo_[u32]offset[_t0](<X>_t *, svuint32_t, sv<t0>_t)
+   void svfoo_[u64]offset[_t0](<X>_t *, svuint64_t, sv<t0>_t)
+
+   void svfoo[_u32base_t0](svuint32_t, sv<t0>_t)
+   void svfoo[_u64base_t0](svuint64_t, sv<t0>_t)
+
+   void svfoo[_u32base]_offset[_t0](svuint32_t, int64_t, sv<t0>_t)
+   void svfoo[_u64base]_offset[_t0](svuint64_t, int64_t, sv<t0>_t)
+
+   where <X> might be tied to <t0> (for non-truncating stores) or might
+   depend on the function base name (for truncating stores).  */
+struct store_scatter_offset_def : public store_scatter_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    b.add_overloaded_functions (group, MODE_offset);
+    build_sv_offset (b, "_,as,d,t0", group);
+    build_v_base (b, "_,b,t0", group);
+    build_vs_offset (b, "_,b,ss64,t0", group);
+  }
+};
+SHAPE (store_scatter_offset)
+
+/* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
+
+   where the final argument is an integer constant expression in the
+   range [0, 16 / sizeof (<t0>_t) - 1].  */
+struct ternary_lane_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0,v0,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (3, 1);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    return c.require_immediate_lane_index (3);
+  }
+};
+SHAPE (ternary_lane)
+
+/* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t, uint64_t)
+
+   where the penultimate argument is an integer constant expression in
+   the range [0, 8 / sizeof (<t0>_t) - 1] and where the final argument
+   is an integer constant expression in {0, 90, 180, 270}.  */
+struct ternary_lane_rotate_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0,v0,su64,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (3, 2);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    return (c.require_immediate_lane_index (3, 2)
+           && c.require_immediate_one_of (4, 0, 90, 180, 270));
+  }
+};
+SHAPE (ternary_lane_rotate)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0>_t, sv<t0>_t)
+   sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0>_t, <t0>_t)
+
+   i.e. the standard shape for ternary operations that operate on
+   uniform types.  */
+struct ternary_opt_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0,v0", group, MODE_none);
+    build_all (b, "v0,v0,v0,s0", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform_opt_n (3);
+  }
+};
+SHAPE (ternary_opt_n)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0.quarter>_t, sv<t0.quarter>_t, uint64_t)
+
+   where the final argument is an integer constant expression in the range
+   [0, 16 / sizeof (<t0>_t) - 1].  */
+struct ternary_qq_lane_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,vq0,vq0,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (4, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
+                                          r.QUARTER_SIZE)
+       || !r.require_derived_vector_type (i + 2, i, type, r.SAME_TYPE_CLASS,
+                                          r.QUARTER_SIZE)
+       || !r.require_integer_immediate (i + 3))
+      return error_mark_node;
+
+    return r.resolve_to (r.mode_suffix_id, type);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    return c.require_immediate_lane_index (3, 4);
+  }
+};
+SHAPE (ternary_qq_lane)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t, sv<t0.quarter>_t, sv<t0.quarter>_t)
+   sv<t0>_t svfoo[_n_t0](sv<t0>_t, sv<t0.quarter>_t, <t0.quarter>_t)
+
+   i.e. a version of the standard ternary shape ternary_opt_n in which
+   the element type of the last two arguments is the quarter-sized
+   equivalent of <t0>.  */
+struct ternary_qq_opt_n_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,vq0,vq0", group, MODE_none);
+    build_all (b, "v0,v0,vq0,sq0", group, MODE_n);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (3, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES
+       || !r.require_derived_vector_type (i + 1, i, type, r.SAME_TYPE_CLASS,
+                                          r.QUARTER_SIZE))
+      return error_mark_node;
+
+    return r.finish_opt_n_resolution (i + 2, i, type, r.SAME_TYPE_CLASS,
+                                     r.QUARTER_SIZE);
+  }
+};
+SHAPE (ternary_qq_opt_n)
+
+/* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, sv<t0>_t, uint64_t)
+
+   where the final argument is an integer constant expression in
+   {0, 90, 180, 270}.  */
+struct ternary_rotate_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0,v0,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (3, 1);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    return c.require_immediate_one_of (3, 0, 90, 180, 270);
+  }
+};
+SHAPE (ternary_rotate)
+
+/* svbool_t svfoo[_<t0>](sv<t0>_t, sv<t0>_t, uint64_t)
+
+   where the final argument is an integer constant expression in the
+   range [0, 7].  */
+struct tmad_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0,v0,su64", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_uniform (2, 1);
+  }
+
+  bool
+  check (function_checker &c) const OVERRIDE
+  {
+    return c.require_immediate_range (2, 0, 7);
+  }
+};
+SHAPE (tmad)
+
+/* sv<t0>_t svfoo[_t0](sv<t0>_t)
+
+   i.e. the standard shape for unary operations that operate on
+   uniform types.  */
+struct unary_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_unary ();
+  }
+};
+SHAPE (unary)
+
+/* sv<t0>_t svfoo_t0[_t1](svbool_t, sv<t1>_t)
+
+   where the target type <t0> must be specified explicitly but the source
+   type <t1> can be inferred.  */
+struct unary_convert_def : public overloaded_base<1>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,v1", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_unary (r.type_suffix (0).tclass,
+                           r.type_suffix (0).element_bits);
+  }
+};
+SHAPE (unary_convert)
+
+/* sv<t0:uint>_t svfoo[_t0](sv<t0>_t)
+
+   i.e. a version of "unary" in which the returned vector contains
+   unsigned integers.  */
+struct unary_count_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "vu0,v0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    return r.resolve_unary (TYPE_unsigned);
+  }
+};
+SHAPE (unary_count)
+
+/* sv<t0>_t svfoo[_n]_t0(<t0>_t).  */
+struct unary_n_def : public overloaded_base<1>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    /* The "_n" suffix is optional; the full name has it, but the short
+       name doesn't.  */
+    build_all (b, "v0,s0", group, MODE_n, true);
+  }
+
+  tree
+  resolve (function_resolver &) const OVERRIDE
+  {
+    /* The short forms just make "_n" implicit, so no resolution is needed.  */
+    gcc_unreachable ();
+  }
+};
+SHAPE (unary_n)
+
+/* svbool_t svfoo(svbool_t).  */
+struct unary_pred_def : public nonoverloaded_base
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    build_all (b, "v0,v0", group, MODE_none);
+  }
+};
+SHAPE (unary_pred)
+
+/* sv<t0>_t svfoo[_t0](sv<t0:uint>_t)
+
+   where <t0> always belongs a certain type class, and where <t0:uint>
+   therefore uniquely determines <t0>.  */
+struct unary_uint_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,vu0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (1, i, nargs)
+       || (type = r.infer_unsigned_vector_type (i)) == NUM_TYPE_SUFFIXES)
+      return error_mark_node;
+
+    /* Search for a valid suffix with the same number of bits as TYPE.  */
+    unsigned int element_bits = type_suffixes[type].element_bits;
+    if (type_suffixes[type].unsigned_p)
+      for (unsigned int j = 0; j < NUM_TYPE_SUFFIXES; ++j)
+       if (type_suffixes[j].element_bits == element_bits)
+         if (tree res = r.lookup_form (r.mode_suffix_id,
+                                       type_suffix_index (j)))
+           return res;
+
+    return r.report_no_such_form (type);
+  }
+};
+SHAPE (unary_uint)
+
+/* sv<t0>_t svfoo[_<t0>](sv<t0:half>_t)
+
+   i.e. a version of "unary" in which the source elements are half the
+   size of the destination elements, but have the same type class.  */
+struct unary_widen_def : public overloaded_base<0>
+{
+  void
+  build (function_builder &b, const function_group_info &group) const OVERRIDE
+  {
+    b.add_overloaded_functions (group, MODE_none);
+    build_all (b, "v0,vh0", group, MODE_none);
+  }
+
+  tree
+  resolve (function_resolver &r) const OVERRIDE
+  {
+    unsigned int i, nargs;
+    type_suffix_index type;
+    if (!r.check_gp_argument (1, i, nargs)
+       || (type = r.infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+      return error_mark_node;
+
+    /* There is only a single form for predicates.  */
+    if (type == TYPE_SUFFIX_b)
+      return r.resolve_to (r.mode_suffix_id, type);
+
+    if (type_suffixes[type].integer_p
+       && type_suffixes[type].element_bits < 64)
+      {
+       type_suffix_index wide_suffix
+         = find_type_suffix (type_suffixes[type].tclass,
+                             type_suffixes[type].element_bits * 2);
+       if (tree res = r.lookup_form (r.mode_suffix_id, wide_suffix))
+         return res;
+      }
+
+    return r.report_no_such_form (type);
+  }
+};
+SHAPE (unary_widen)
+
+}
diff --git a/gcc/config/aarch64/aarch64-sve-builtins-shapes.h b/gcc/config/aarch64/aarch64-sve-builtins-shapes.h
new file mode 100644 (file)
index 0000000..1a102e0
--- /dev/null
@@ -0,0 +1,146 @@
+/* ACLE support for AArch64 SVE (function shapes)
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_AARCH64_SVE_BUILTINS_SHAPES_H
+#define GCC_AARCH64_SVE_BUILTINS_SHAPES_H
+
+namespace aarch64_sve
+{
+  /* The naming convention is:
+
+     - to use the name of the function if the rules are very specific to
+       a particular function (e.g. svext, for which the range of the
+       final immediate value is in no way generic).
+
+     - to use names like "unary" etc. if the rules are somewhat generic,
+       especially if there are no ranges involved.
+
+     When using generic names, the handling of the final vector argument
+     can be modified as follows:
+
+     - an "_n" suffix changes the argument from a vector to a scalar.
+
+     - an "_opt_n" suffix says that there are two forms of each function:
+       one in which the argument is the usual vector, and one in which it
+       is replaced by a scalar.
+
+     - "_int" and "_uint" replace the argument's element type with a
+       signed or unsigned integer of the same width.  The suffixes above
+       then indicate whether this final argument is or might be a scalar.
+
+     - "_int64" and "_uint64" similarly replace the argument's element type
+       with int64_t or uint64_t.
+
+     - "_wide" replaces the argument's element type with a 64-bit integer
+       of the same signedness.  This only makes sense for integer elements.
+
+     - "_lane" indicates that the argument is indexed by a constant lane
+       number, provided as an immediately-following argument of type uint64_t.
+
+     Also:
+
+     - "inherent" means that the function takes no arguments.
+
+     - "_rotate" means that the final argument is a rotation amount
+       (0, 90, 180 or 270).
+
+     - "_scalar" indicates that all data arguments are scalars rather
+       than vectors.
+
+     - in gather/scatter addresses, "sv" stands for "scalar base,
+       vector displacement" while "vs" stands for "vector base,
+       scalar displacement".
+
+     - "_pred" indicates that the function takes an svbool_t argument
+       that does not act as a governing predicate..  */
+  namespace shapes
+  {
+    extern const function_shape *const adr_index;
+    extern const function_shape *const adr_offset;
+    extern const function_shape *const binary;
+    extern const function_shape *const binary_int_opt_n;
+    extern const function_shape *const binary_lane;
+    extern const function_shape *const binary_n;
+    extern const function_shape *const binary_opt_n;
+    extern const function_shape *const binary_pred;
+    extern const function_shape *const binary_rotate;
+    extern const function_shape *const binary_scalar;
+    extern const function_shape *const binary_uint;
+    extern const function_shape *const binary_uint_n;
+    extern const function_shape *const binary_uint_opt_n;
+    extern const function_shape *const binary_uint64_n;
+    extern const function_shape *const binary_uint64_opt_n;
+    extern const function_shape *const clast;
+    extern const function_shape *const compare_opt_n;
+    extern const function_shape *const compare_scalar;
+    extern const function_shape *const compare_wide_opt_n;
+    extern const function_shape *const count_inherent;
+    extern const function_shape *const count_pat;
+    extern const function_shape *const count_pred;
+    extern const function_shape *const count_vector;
+    extern const function_shape *const create;
+    extern const function_shape *const dupq;
+    extern const function_shape *const ext;
+    extern const function_shape *const fold_left;
+    extern const function_shape *const get;
+    extern const function_shape *const inc_dec;
+    extern const function_shape *const inc_dec_pat;
+    extern const function_shape *const inc_dec_pred;
+    extern const function_shape *const inc_dec_pred_scalar;
+    extern const function_shape *const inherent;
+    extern const function_shape *const inherent_b;
+    extern const function_shape *const load;
+    extern const function_shape *const load_ext;
+    extern const function_shape *const load_ext_gather_index;
+    extern const function_shape *const load_ext_gather_offset;
+    extern const function_shape *const load_gather_sv;
+    extern const function_shape *const load_gather_vs;
+    extern const function_shape *const load_replicate;
+    extern const function_shape *const pattern_pred;
+    extern const function_shape *const prefetch;
+    extern const function_shape *const prefetch_gather_index;
+    extern const function_shape *const prefetch_gather_offset;
+    extern const function_shape *const ptest;
+    extern const function_shape *const rdffr;
+    extern const function_shape *const reduction;
+    extern const function_shape *const reduction_wide;
+    extern const function_shape *const set;
+    extern const function_shape *const setffr;
+    extern const function_shape *const shift_right_imm;
+    extern const function_shape *const store;
+    extern const function_shape *const store_scatter_index;
+    extern const function_shape *const store_scatter_offset;
+    extern const function_shape *const ternary_lane;
+    extern const function_shape *const ternary_lane_rotate;
+    extern const function_shape *const ternary_opt_n;
+    extern const function_shape *const ternary_qq_lane;
+    extern const function_shape *const ternary_qq_opt_n;
+    extern const function_shape *const ternary_rotate;
+    extern const function_shape *const tmad;
+    extern const function_shape *const unary;
+    extern const function_shape *const unary_convert;
+    extern const function_shape *const unary_count;
+    extern const function_shape *const unary_n;
+    extern const function_shape *const unary_pred;
+    extern const function_shape *const unary_uint;
+    extern const function_shape *const unary_widen;
+  }
+}
+
+#endif
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.cc b/gcc/config/aarch64/aarch64-sve-builtins.cc
new file mode 100644 (file)
index 0000000..70d7b1a
--- /dev/null
@@ -0,0 +1,3313 @@
+/* ACLE support for AArch64 SVE
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#define IN_TARGET_CODE 1
+
+#include "config.h"
+#include "system.h"
+#include "coretypes.h"
+#include "tm.h"
+#include "tree.h"
+#include "rtl.h"
+#include "tm_p.h"
+#include "memmodel.h"
+#include "insn-codes.h"
+#include "optabs.h"
+#include "recog.h"
+#include "diagnostic.h"
+#include "expr.h"
+#include "basic-block.h"
+#include "function.h"
+#include "fold-const.h"
+#include "gimple.h"
+#include "gimple-iterator.h"
+#include "gimplify.h"
+#include "explow.h"
+#include "emit-rtl.h"
+#include "tree-vector-builder.h"
+#include "stor-layout.h"
+#include "regs.h"
+#include "alias.h"
+#include "gimple-fold.h"
+#include "langhooks.h"
+#include "stringpool.h"
+#include "aarch64-sve-builtins.h"
+#include "aarch64-sve-builtins-base.h"
+#include "aarch64-sve-builtins-shapes.h"
+
+namespace aarch64_sve {
+
+/* Static information about each single-predicate or single-vector
+   ABI and ACLE type.  */
+struct vector_type_info
+{
+  /* The name of the type as declared by arm_sve.h.  */
+  const char *acle_name;
+
+  /* The name of the type specified in AAPCS64.  The type is always
+     available under this name, even when arm_sve.h isn't included.  */
+  const char *abi_name;
+
+  /* The C++ mangling of ABI_NAME.  */
+  const char *mangled_name;
+};
+
+/* Describes a function decl.  */
+class GTY(()) registered_function
+{
+public:
+  /* The ACLE function that the decl represents.  */
+  function_instance instance GTY ((skip));
+
+  /* The decl itself.  */
+  tree decl;
+
+  /* The architecture extensions that the function requires, as a set of
+     AARCH64_FL_* flags.  */
+  uint64_t required_extensions;
+
+  /* True if the decl represents an overloaded function that needs to be
+     resolved by function_resolver.  */
+  bool overloaded_p;
+};
+
+/* Hash traits for registered_function.  */
+struct registered_function_hasher : nofree_ptr_hash <registered_function>
+{
+  typedef function_instance compare_type;
+
+  static hashval_t hash (value_type);
+  static bool equal (value_type, const compare_type &);
+};
+
+/* Information about each single-predicate or single-vector type.  */
+static CONSTEXPR const vector_type_info vector_types[] = {
+#define DEF_SVE_TYPE(ACLE_NAME, NCHARS, ABI_NAME, SCALAR_TYPE) \
+  { #ACLE_NAME, #ABI_NAME, #NCHARS #ABI_NAME },
+#include "aarch64-sve-builtins.def"
+};
+
+/* The function name suffix associated with each predication type.  */
+static const char *const pred_suffixes[NUM_PREDS + 1] = {
+  "",
+  "",
+  "_m",
+  "_x",
+  "_z",
+  ""
+};
+
+/* Static information about each mode_suffix_index.  */
+CONSTEXPR const mode_suffix_info mode_suffixes[] = {
+#define VECTOR_TYPE_none NUM_VECTOR_TYPES
+#define DEF_SVE_MODE(NAME, BASE, DISPLACEMENT, UNITS) \
+  { "_" #NAME, VECTOR_TYPE_##BASE, VECTOR_TYPE_##DISPLACEMENT, UNITS_##UNITS },
+#include "aarch64-sve-builtins.def"
+#undef VECTOR_TYPE_none
+  { "", NUM_VECTOR_TYPES, NUM_VECTOR_TYPES, UNITS_none }
+};
+
+/* Static information about each type_suffix_index.  */
+CONSTEXPR const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1] = {
+#define DEF_SVE_TYPE_SUFFIX(NAME, ACLE_TYPE, CLASS, BITS, MODE) \
+  { "_" #NAME, \
+    VECTOR_TYPE_##ACLE_TYPE, \
+    TYPE_##CLASS, \
+    BITS, \
+    BITS / BITS_PER_UNIT, \
+    TYPE_##CLASS == TYPE_signed || TYPE_##CLASS == TYPE_unsigned, \
+    TYPE_##CLASS == TYPE_unsigned, \
+    TYPE_##CLASS == TYPE_float, \
+    TYPE_##CLASS == TYPE_bool, \
+    0, \
+    MODE },
+#include "aarch64-sve-builtins.def"
+  { "", NUM_VECTOR_TYPES, TYPE_bool, 0, 0, false, false, false, false,
+    0, VOIDmode }
+};
+
+/* Define a TYPES_<combination> macro for each combination of type
+   suffixes that an ACLE function can have, where <combination> is the
+   name used in DEF_SVE_FUNCTION entries.
+
+   Use S (T) for single type suffix T and D (T1, T2) for a pair of type
+   suffixes T1 and T2.  Use commas to separate the suffixes.
+
+   Although the order shouldn't matter, the convention is to sort the
+   suffixes lexicographically after dividing suffixes into a type
+   class ("b", "f", etc.) and a numerical bit count.  */
+
+/* _b8 _b16 _b32 _b64.  */
+#define TYPES_all_pred(S, D) \
+  S (b8), S (b16), S (b32), S (b64)
+
+/* _f16 _f32 _f64.  */
+#define TYPES_all_float(S, D) \
+  S (f16), S (f32), S (f64)
+
+/* _s8 _s16 _s32 _s64.  */
+#define TYPES_all_signed(S, D) \
+  S (s8), S (s16), S (s32), S (s64)
+
+/*     _f16 _f32 _f64
+   _s8 _s16 _s32 _s64.  */
+#define TYPES_all_float_and_signed(S, D) \
+  TYPES_all_float (S, D), TYPES_all_signed (S, D)
+
+/* _u8 _u16 _u32 _u64.  */
+#define TYPES_all_unsigned(S, D) \
+  S (u8), S (u16), S (u32), S (u64)
+
+/* _s8 _s16 _s32 _s64
+   _u8 _u16 _u32 _u64.  */
+#define TYPES_all_integer(S, D) \
+  TYPES_all_signed (S, D), TYPES_all_unsigned (S, D)
+
+/*     _f16 _f32 _f64
+   _s8 _s16 _s32 _s64
+   _u8 _u16 _u32 _u64.  */
+#define TYPES_all_data(S, D) \
+  TYPES_all_float (S, D), TYPES_all_integer (S, D)
+
+/* _b only.  */
+#define TYPES_b(S, D) \
+  S (b)
+
+/* _s8 _s16 _s32.  */
+#define TYPES_bhs_signed(S, D) \
+  S (s8), S (s16), S (s32)
+
+/* _u8 _u16 _u32.  */
+#define TYPES_bhs_unsigned(S, D) \
+  S (u8), S (u16), S (u32)
+
+/* _s8 _s16 _s32
+   _u8 _u16 _u32.  */
+#define TYPES_bhs_integer(S, D) \
+  TYPES_bhs_signed (S, D), TYPES_bhs_unsigned (S, D)
+
+/* _s16
+   _u16.  */
+#define TYPES_h_integer(S, D) \
+  S (s16), S (u16)
+
+/* _f16 _f32.  */
+#define TYPES_hs_float(S, D) \
+  S (f16), S (f32)
+
+/* _s16 _s32 _s64
+   _u16 _u32 _u64.  */
+#define TYPES_hsd_integer(S, D) \
+  S (s16), S (s32), S (s64), S (u16), S (u32), S (u64)
+
+/* _s32 _u32.  */
+#define TYPES_s_integer(S, D) \
+  S (s32), S (u32)
+
+/* _s32 _s64
+   _u32 _u64.  */
+#define TYPES_sd_integer(S, D) \
+  S (s32), S (s64), S (u32), S (u64)
+
+/* _f32 _f64
+   _s32 _s64
+   _u32 _u64.  */
+#define TYPES_sd_data(S, D) \
+  S (f32), S (f64), TYPES_sd_integer (S, D)
+
+/* _f16 _f32 _f64
+       _s32 _s64
+       _u32 _u64.  */
+#define TYPES_all_float_and_sd_integer(S, D) \
+  TYPES_all_float (S, D), TYPES_sd_integer (S, D)
+
+/* _s64
+   _u64.  */
+#define TYPES_d_integer(S, D) \
+  S (s64), S (u64)
+
+/* All the type combinations allowed by svcvt.  */
+#define TYPES_cvt(S, D) \
+  D (f16, f32), D (f16, f64), \
+  D (f16, s16), D (f16, s32), D (f16, s64), \
+  D (f16, u16), D (f16, u32), D (f16, u64), \
+  \
+  D (f32, f16), D (f32, f64), \
+  D (f32, s32), D (f32, s64), \
+  D (f32, u32), D (f32, u64), \
+  \
+  D (f64, f16), D (f64, f32), \
+  D (f64, s32), D (f64, s64), \
+  D (f64, u32), D (f64, u64), \
+  \
+  D (s16, f16), \
+  D (s32, f16), D (s32, f32), D (s32, f64), \
+  D (s64, f16), D (s64, f32), D (s64, f64), \
+  \
+  D (u16, f16), \
+  D (u32, f16), D (u32, f32), D (u32, f64), \
+  D (u64, f16), D (u64, f32), D (u64, f64)
+
+/* { _s32 _s64 } x { _b8 _b16 _b32 _b64 }
+   { _u32 _u64 }.  */
+#define TYPES_inc_dec_n1(D, A) \
+  D (A, b8), D (A, b16), D (A, b32), D (A, b64)
+#define TYPES_inc_dec_n(S, D) \
+  TYPES_inc_dec_n1 (D, s32), \
+  TYPES_inc_dec_n1 (D, s64), \
+  TYPES_inc_dec_n1 (D, u32), \
+  TYPES_inc_dec_n1 (D, u64)
+
+/* {     _f16 _f32 _f64 }   {     _f16 _f32 _f64 }
+   { _s8 _s16 _s32 _s64 } x { _s8 _s16 _s32 _s64 }
+   { _u8 _u16 _u32 _u64 }   { _u8 _u16 _u32 _u64 }.  */
+#define TYPES_reinterpret1(D, A) \
+  D (A, f16), D (A, f32), D (A, f64), \
+  D (A, s8), D (A, s16), D (A, s32), D (A, s64), \
+  D (A, u8), D (A, u16), D (A, u32), D (A, u64)
+#define TYPES_reinterpret(S, D) \
+  TYPES_reinterpret1 (D, f16), \
+  TYPES_reinterpret1 (D, f32), \
+  TYPES_reinterpret1 (D, f64), \
+  TYPES_reinterpret1 (D, s8), \
+  TYPES_reinterpret1 (D, s16), \
+  TYPES_reinterpret1 (D, s32), \
+  TYPES_reinterpret1 (D, s64), \
+  TYPES_reinterpret1 (D, u8), \
+  TYPES_reinterpret1 (D, u16), \
+  TYPES_reinterpret1 (D, u32), \
+  TYPES_reinterpret1 (D, u64)
+
+/* { _b8 _b16 _b32 _b64 } x { _s32 _s64 }
+                           { _u32 _u64 } */
+#define TYPES_while1(D, bn) \
+  D (bn, s32), D (bn, s64), D (bn, u32), D (bn, u64)
+#define TYPES_while(S, D) \
+  TYPES_while1 (D, b8), \
+  TYPES_while1 (D, b16), \
+  TYPES_while1 (D, b32), \
+  TYPES_while1 (D, b64)
+
+/* Describe a pair of type suffixes in which only the first is used.  */
+#define DEF_VECTOR_TYPE(X) { TYPE_SUFFIX_ ## X, NUM_TYPE_SUFFIXES }
+
+/* Describe a pair of type suffixes in which both are used.  */
+#define DEF_DOUBLE_TYPE(X, Y) { TYPE_SUFFIX_ ## X, TYPE_SUFFIX_ ## Y }
+
+/* Create an array that can be used in aarch64-sve-builtins.def to
+   select the type suffixes in TYPES_<NAME>.  */
+#define DEF_SVE_TYPES_ARRAY(NAME) \
+  static const type_suffix_pair types_##NAME[] = { \
+    TYPES_##NAME (DEF_VECTOR_TYPE, DEF_DOUBLE_TYPE), \
+    { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES } \
+  }
+
+/* For functions that don't take any type suffixes.  */
+static const type_suffix_pair types_none[] = {
+  { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES },
+  { NUM_TYPE_SUFFIXES, NUM_TYPE_SUFFIXES }
+};
+
+/* Create an array for each TYPES_<combination> macro above.  */
+DEF_SVE_TYPES_ARRAY (all_pred);
+DEF_SVE_TYPES_ARRAY (all_float);
+DEF_SVE_TYPES_ARRAY (all_signed);
+DEF_SVE_TYPES_ARRAY (all_float_and_signed);
+DEF_SVE_TYPES_ARRAY (all_unsigned);
+DEF_SVE_TYPES_ARRAY (all_integer);
+DEF_SVE_TYPES_ARRAY (all_data);
+DEF_SVE_TYPES_ARRAY (b);
+DEF_SVE_TYPES_ARRAY (bhs_signed);
+DEF_SVE_TYPES_ARRAY (bhs_unsigned);
+DEF_SVE_TYPES_ARRAY (bhs_integer);
+DEF_SVE_TYPES_ARRAY (h_integer);
+DEF_SVE_TYPES_ARRAY (hs_float);
+DEF_SVE_TYPES_ARRAY (hsd_integer);
+DEF_SVE_TYPES_ARRAY (s_integer);
+DEF_SVE_TYPES_ARRAY (sd_integer);
+DEF_SVE_TYPES_ARRAY (sd_data);
+DEF_SVE_TYPES_ARRAY (all_float_and_sd_integer);
+DEF_SVE_TYPES_ARRAY (d_integer);
+DEF_SVE_TYPES_ARRAY (cvt);
+DEF_SVE_TYPES_ARRAY (inc_dec_n);
+DEF_SVE_TYPES_ARRAY (reinterpret);
+DEF_SVE_TYPES_ARRAY (while);
+
+/* Used by functions that have no governing predicate.  */
+static const predication_index preds_none[] = { PRED_none, NUM_PREDS };
+
+/* Used by functions that have a governing predicate but do not have an
+   explicit suffix.  */
+static const predication_index preds_implicit[] = { PRED_implicit, NUM_PREDS };
+
+/* Used by functions that allow merging, zeroing and "don't care"
+   predication.  */
+static const predication_index preds_mxz[] = {
+  PRED_m, PRED_x, PRED_z, NUM_PREDS
+};
+
+/* Used by functions that have the mxz predicated forms above, and in addition
+   have an unpredicated form.  */
+static const predication_index preds_mxz_or_none[] = {
+  PRED_m, PRED_x, PRED_z, PRED_none, NUM_PREDS
+};
+
+/* Used by functions that allow merging and zeroing predication but have
+   no "_x" form.  */
+static const predication_index preds_mz[] = { PRED_m, PRED_z, NUM_PREDS };
+
+/* Used by functions that have an unpredicated form and a _z predicated
+   form.  */
+static const predication_index preds_z_or_none[] = {
+  PRED_z, PRED_none, NUM_PREDS
+};
+
+/* Used by (mostly predicate) functions that only support "_z" predication.  */
+static const predication_index preds_z[] = { PRED_z, NUM_PREDS };
+
+/* A list of all SVE ACLE functions.  */
+static CONSTEXPR const function_group_info function_groups[] = {
+#define DEF_SVE_FUNCTION(NAME, SHAPE, TYPES, PREDS) \
+  { #NAME, &functions::NAME, &shapes::SHAPE, types_##TYPES, preds_##PREDS, \
+    REQUIRED_EXTENSIONS | AARCH64_FL_SVE },
+#include "aarch64-sve-builtins.def"
+};
+
+/* The scalar type associated with each vector type.  */
+GTY(()) tree scalar_types[NUM_VECTOR_TYPES];
+
+/* The single-predicate and single-vector types, with their built-in
+   "__SV..._t" name.  Allow an index of NUM_VECTOR_TYPES, which always
+   yields a null tree.  */
+static GTY(()) tree abi_vector_types[NUM_VECTOR_TYPES + 1];
+
+/* Same, but with the arm_sve.h "sv..._t" name.  */
+GTY(()) tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
+
+/* The svpattern enum type.  */
+GTY(()) tree acle_svpattern;
+
+/* The svprfop enum type.  */
+GTY(()) tree acle_svprfop;
+
+/* The list of all registered function decls, indexed by code.  */
+static GTY(()) vec<registered_function *, va_gc> *registered_functions;
+
+/* All registered function decls, hashed on the function_instance
+   that they implement.  This is used for looking up implementations of
+   overloaded functions.  */
+static hash_table<registered_function_hasher> *function_table;
+
+/* True if we've already complained about attempts to use functions
+   when the required extension is disabled.  */
+static bool reported_missing_extension_p;
+
+/* If TYPE is an ACLE vector type, return the associated vector_type,
+   otherwise return NUM_VECTOR_TYPES.  */
+static vector_type_index
+find_vector_type (const_tree type)
+{
+  /* A linear search should be OK here, since the code isn't hot and
+     the number of types is only small.  */
+  type = TYPE_MAIN_VARIANT (type);
+  for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i)
+    if (type == abi_vector_types[i])
+      return vector_type_index (i);
+  return NUM_VECTOR_TYPES;
+}
+
+/* If TYPE is a valid SVE element type, return the corresponding type
+   suffix, otherwise return NUM_TYPE_SUFFIXES.  */
+static type_suffix_index
+find_type_suffix_for_scalar_type (const_tree type)
+{
+  /* A linear search should be OK here, since the code isn't hot and
+     the number of types is only small.  */
+  type = TYPE_MAIN_VARIANT (type);
+  for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i)
+    if (!type_suffixes[suffix_i].bool_p)
+      {
+       vector_type_index vector_i = type_suffixes[suffix_i].vector_type;
+       if (type == TYPE_MAIN_VARIANT (scalar_types[vector_i]))
+         return type_suffix_index (suffix_i);
+      }
+  return NUM_TYPE_SUFFIXES;
+}
+
+/* Report an error against LOCATION that the user has tried to use
+   function FNDECL when extension EXTENSION is disabled.  */
+static void
+report_missing_extension (location_t location, tree fndecl,
+                         const char *extension)
+{
+  /* Avoid reporting a slew of messages for a single oversight.  */
+  if (reported_missing_extension_p)
+    return;
+
+  error_at (location, "ACLE function %qD requires ISA extension %qs",
+           fndecl, extension);
+  inform (location, "you can enable %qs using the command-line"
+         " option %<-march%>, or by using the %<target%>"
+         " attribute or pragma", extension);
+  reported_missing_extension_p = true;
+}
+
+/* Check whether all the AARCH64_FL_* values in REQUIRED_EXTENSIONS are
+   enabled, given that those extensions are required for function FNDECL.
+   Report an error against LOCATION if not.  */
+static bool
+check_required_extensions (location_t location, tree fndecl,
+                          uint64_t required_extensions)
+{
+  uint64_t missing_extensions = required_extensions & ~aarch64_isa_flags;
+  if (missing_extensions == 0)
+    return true;
+
+  static const struct { uint64_t flag; const char *name; } extensions[] = {
+#define AARCH64_OPT_EXTENSION(EXT_NAME, FLAG_CANONICAL, FLAGS_ON, FLAGS_OFF, \
+                             SYNTHETIC, FEATURE_STRING) \
+    { FLAG_CANONICAL, EXT_NAME },
+#include "aarch64-option-extensions.def"
+  };
+
+  for (unsigned int i = 0; i < ARRAY_SIZE (extensions); ++i)
+    if (missing_extensions & extensions[i].flag)
+      {
+       report_missing_extension (location, fndecl, extensions[i].name);
+       return false;
+      }
+  gcc_unreachable ();
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO
+   was not an integer constant expression.  ARGNO counts from zero.  */
+static void
+report_non_ice (location_t location, tree fndecl, unsigned int argno)
+{
+  error_at (location, "argument %d of %qE must be an integer constant"
+           " expression", argno + 1, fndecl);
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO has
+   the value ACTUAL, whereas the function requires a value in the range
+   [MIN, MAX].  ARGNO counts from zero.  */
+static void
+report_out_of_range (location_t location, tree fndecl, unsigned int argno,
+                    HOST_WIDE_INT actual, HOST_WIDE_INT min,
+                    HOST_WIDE_INT max)
+{
+  error_at (location, "passing %wd to argument %d of %qE, which expects"
+           " a value in the range [%wd, %wd]", actual, argno + 1, fndecl,
+           min, max);
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO has
+   the value ACTUAL, whereas the function requires either VALUE0 or
+   VALUE1.  ARGNO counts from zero.  */
+static void
+report_neither_nor (location_t location, tree fndecl, unsigned int argno,
+                   HOST_WIDE_INT actual, HOST_WIDE_INT value0,
+                   HOST_WIDE_INT value1)
+{
+  error_at (location, "passing %wd to argument %d of %qE, which expects"
+           " either %wd or %wd", actual, argno + 1, fndecl, value0, value1);
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO has
+   the value ACTUAL, whereas the function requires one of VALUE0..3.
+   ARGNO counts from zero.  */
+static void
+report_not_one_of (location_t location, tree fndecl, unsigned int argno,
+                  HOST_WIDE_INT actual, HOST_WIDE_INT value0,
+                  HOST_WIDE_INT value1, HOST_WIDE_INT value2,
+                  HOST_WIDE_INT value3)
+{
+  error_at (location, "passing %wd to argument %d of %qE, which expects"
+           " %wd, %wd, %wd or %wd", actual, argno + 1, fndecl, value0, value1,
+           value2, value3);
+}
+
+/* Report that LOCATION has a call to FNDECL in which argument ARGNO has
+   the value ACTUAL, whereas the function requires a valid value of
+   enum type ENUMTYPE.  ARGNO counts from zero.  */
+static void
+report_not_enum (location_t location, tree fndecl, unsigned int argno,
+                HOST_WIDE_INT actual, tree enumtype)
+{
+  error_at (location, "passing %wd to argument %d of %qE, which expects"
+           " a valid %qT value", actual, argno + 1, fndecl, enumtype);
+}
+
+/* Return a hash code for a function_instance.  */
+hashval_t
+function_instance::hash () const
+{
+  inchash::hash h;
+  /* BASE uniquely determines BASE_NAME, so we don't need to hash both.  */
+  h.add_ptr (base);
+  h.add_ptr (shape);
+  h.add_int (mode_suffix_id);
+  h.add_int (type_suffix_ids[0]);
+  h.add_int (type_suffix_ids[1]);
+  h.add_int (pred);
+  return h.end ();
+}
+
+/* Return a set of CP_* flags that describe what the function could do,
+   taking the command-line flags into account.  */
+unsigned int
+function_instance::call_properties () const
+{
+  unsigned int flags = base->call_properties (*this);
+
+  /* -fno-trapping-math means that we can assume any FP exceptions
+     are not user-visible.  */
+  if (!flag_trapping_math)
+    flags &= ~CP_RAISE_FP_EXCEPTIONS;
+
+  return flags;
+}
+
+/* Return true if calls to the function could read some form of
+   global state.  */
+bool
+function_instance::reads_global_state_p () const
+{
+  unsigned int flags = call_properties ();
+
+  /* Preserve any dependence on rounding mode, flush to zero mode, etc.
+     There is currently no way of turning this off; in particular,
+     -fno-rounding-math (which is the default) means that we should make
+     the usual assumptions about rounding mode, which for intrinsics means
+     acting as the instructions do.  */
+  if (flags & CP_READ_FPCR)
+    return true;
+
+  /* Handle direct reads of global state.  */
+  return flags & (CP_READ_MEMORY | CP_READ_FFR);
+}
+
+/* Return true if calls to the function could modify some form of
+   global state.  */
+bool
+function_instance::modifies_global_state_p () const
+{
+  unsigned int flags = call_properties ();
+
+  /* Preserve any exception state written back to the FPCR,
+     unless -fno-trapping-math says this is unnecessary.  */
+  if (flags & CP_RAISE_FP_EXCEPTIONS)
+    return true;
+
+  /* Treat prefetches as modifying global state, since that's the
+     only means we have of keeping them in their correct position.  */
+  if (flags & CP_PREFETCH_MEMORY)
+    return true;
+
+  /* Handle direct modifications of global state.  */
+  return flags & (CP_WRITE_MEMORY | CP_WRITE_FFR);
+}
+
+/* Return true if calls to the function could raise a signal.  */
+bool
+function_instance::could_trap_p () const
+{
+  unsigned int flags = call_properties ();
+
+  /* Handle functions that could raise SIGFPE.  */
+  if (flags & CP_RAISE_FP_EXCEPTIONS)
+    return true;
+
+  /* Handle functions that could raise SIGBUS or SIGSEGV.  */
+  if (flags & (CP_READ_MEMORY | CP_WRITE_MEMORY))
+    return true;
+
+  return false;
+}
+
+inline hashval_t
+registered_function_hasher::hash (value_type value)
+{
+  return value->instance.hash ();
+}
+
+inline bool
+registered_function_hasher::equal (value_type value, const compare_type &key)
+{
+  return value->instance == key;
+}
+
+sve_switcher::sve_switcher ()
+  : m_old_isa_flags (aarch64_isa_flags)
+{
+  /* Changing the ISA flags and have_regs_of_mode should be enough here.
+     We shouldn't need to pay the compile-time cost of a full target
+     switch.  */
+  aarch64_isa_flags = (AARCH64_FL_FP | AARCH64_FL_SIMD | AARCH64_FL_F16
+                      | AARCH64_FL_SVE);
+
+  memcpy (m_old_have_regs_of_mode, have_regs_of_mode,
+         sizeof (have_regs_of_mode));
+  for (int i = 0; i < NUM_MACHINE_MODES; ++i)
+    if (aarch64_sve_mode_p ((machine_mode) i))
+      have_regs_of_mode[i] = true;
+}
+
+sve_switcher::~sve_switcher ()
+{
+  memcpy (have_regs_of_mode, m_old_have_regs_of_mode,
+         sizeof (have_regs_of_mode));
+  aarch64_isa_flags = m_old_isa_flags;
+}
+
+function_builder::function_builder ()
+{
+  m_overload_type = build_function_type (void_type_node, void_list_node);
+  m_direct_overloads = lang_GNU_CXX ();
+  gcc_obstack_init (&m_string_obstack);
+}
+
+function_builder::~function_builder ()
+{
+  obstack_free (&m_string_obstack, NULL);
+}
+
+/* Add NAME to the end of the function name being built.  */
+void
+function_builder::append_name (const char *name)
+{
+  obstack_grow (&m_string_obstack, name, strlen (name));
+}
+
+/* Zero-terminate and complete the function name being built.  */
+char *
+function_builder::finish_name ()
+{
+  obstack_1grow (&m_string_obstack, 0);
+  return (char *) obstack_finish (&m_string_obstack);
+}
+
+/* Return the overloaded or full function name for INSTANCE; OVERLOADED_P
+   selects which.  Allocate the string on m_string_obstack; the caller
+   must use obstack_free to free it after use.  */
+char *
+function_builder::get_name (const function_instance &instance,
+                           bool overloaded_p)
+{
+  append_name (instance.base_name);
+  if (overloaded_p)
+    switch (instance.displacement_units ())
+      {
+      case UNITS_none:
+       break;
+
+      case UNITS_bytes:
+       append_name ("_offset");
+       break;
+
+      case UNITS_elements:
+       append_name ("_index");
+       break;
+
+      case UNITS_vectors:
+       append_name ("_vnum");
+       break;
+      }
+  else
+    append_name (instance.mode_suffix ().string);
+  for (unsigned int i = 0; i < 2; ++i)
+    if (!overloaded_p || instance.shape->explicit_type_suffix_p (i))
+      append_name (instance.type_suffix (i).string);
+  append_name (pred_suffixes[instance.pred]);
+  return finish_name ();
+}
+
+/* Add attribute NAME to ATTRS.  */
+static tree
+add_attribute (const char *name, tree attrs)
+{
+  return tree_cons (get_identifier (name), NULL_TREE, attrs);
+}
+
+/* Return the appropriate function attributes for INSTANCE.  */
+tree
+function_builder::get_attributes (const function_instance &instance)
+{
+  tree attrs = NULL_TREE;
+
+  if (!instance.modifies_global_state_p ())
+    {
+      if (instance.reads_global_state_p ())
+       attrs = add_attribute ("pure", attrs);
+      else
+       attrs = add_attribute ("const", attrs);
+    }
+
+  if (!flag_non_call_exceptions || !instance.could_trap_p ())
+    attrs = add_attribute ("nothrow", attrs);
+
+  return add_attribute ("leaf", attrs);
+}
+
+/* Add a function called NAME with type FNTYPE and attributes ATTRS.
+   INSTANCE describes what the function does and OVERLOADED_P indicates
+   whether it is overloaded.  REQUIRED_EXTENSIONS are the set of
+   architecture extensions that the function requires.  */
+registered_function &
+function_builder::add_function (const function_instance &instance,
+                               const char *name, tree fntype, tree attrs,
+                               uint64_t required_extensions,
+                               bool overloaded_p)
+{
+  unsigned int code = vec_safe_length (registered_functions);
+  code = (code << AARCH64_BUILTIN_SHIFT) | AARCH64_BUILTIN_SVE;
+  tree decl = simulate_builtin_function_decl (input_location, name, fntype,
+                                             code, NULL, attrs);
+
+  registered_function &rfn = *ggc_alloc <registered_function> ();
+  rfn.instance = instance;
+  rfn.decl = decl;
+  rfn.required_extensions = required_extensions;
+  rfn.overloaded_p = overloaded_p;
+  vec_safe_push (registered_functions, &rfn);
+
+  return rfn;
+}
+
+/* Add a built-in function for INSTANCE, with the argument types given
+   by ARGUMENT_TYPES and the return type given by RETURN_TYPE.
+   REQUIRED_EXTENSIONS are the set of architecture extensions that the
+   function requires.  FORCE_DIRECT_OVERLOADS is true if there is a
+   one-to-one mapping between "short" and "full" names, and if standard
+   overload resolution therefore isn't necessary.  */
+void
+function_builder::add_unique_function (const function_instance &instance,
+                                      tree return_type,
+                                      vec<tree> &argument_types,
+                                      uint64_t required_extensions,
+                                      bool force_direct_overloads)
+{
+  /* Add the function under its full (unique) name.  */
+  char *name = get_name (instance, false);
+  tree fntype = build_function_type_array (return_type,
+                                          argument_types.length (),
+                                          argument_types.address ());
+  tree attrs = get_attributes (instance);
+  registered_function &rfn = add_function (instance, name, fntype, attrs,
+                                          required_extensions, false);
+
+  /* Enter the function into the hash table.  */
+  hashval_t hash = instance.hash ();
+  registered_function **rfn_slot
+    = function_table->find_slot_with_hash (instance, hash, INSERT);
+  gcc_assert (!*rfn_slot);
+  *rfn_slot = &rfn;
+
+  /* Also add the function under its overloaded alias, if we want
+     a separate decl for each instance of an overloaded function.  */
+  if (m_direct_overloads || force_direct_overloads)
+    {
+      char *overload_name = get_name (instance, true);
+      if (strcmp (name, overload_name) != 0)
+       {
+         /* Attribute lists shouldn't be shared.  */
+         tree attrs = get_attributes (instance);
+         add_function (instance, overload_name, fntype, attrs,
+                       required_extensions, false);
+       }
+    }
+
+  obstack_free (&m_string_obstack, name);
+}
+
+/* Add one function decl for INSTANCE, to be used with manual overload
+   resolution.  REQUIRED_EXTENSIONS are the set of architecture extensions
+   that the function requires.
+
+   For simplicity, deal with duplicate attempts to add the same
+   function.  */
+void
+function_builder::add_overloaded_function (const function_instance &instance,
+                                          uint64_t required_extensions)
+{
+  char *name = get_name (instance, true);
+  if (registered_function **map_value = m_overload_names.get (name))
+    gcc_assert ((*map_value)->instance == instance
+               && (*map_value)->required_extensions == required_extensions);
+  else
+    {
+      registered_function &rfn
+       = add_function (instance, name, m_overload_type, NULL_TREE,
+                       required_extensions, true);
+      const char *permanent_name = IDENTIFIER_POINTER (DECL_NAME (rfn.decl));
+      m_overload_names.put (permanent_name, &rfn);
+    }
+  obstack_free (&m_string_obstack, name);
+}
+
+/* If we are using manual overload resolution, add one function decl
+   for each overloaded function in GROUP.  Take the function base name
+   from GROUP and the mode from MODE.  */
+void
+function_builder::add_overloaded_functions (const function_group_info &group,
+                                           mode_suffix_index mode)
+{
+  if (m_direct_overloads)
+    return;
+
+  unsigned int explicit_type0 = (*group.shape)->explicit_type_suffix_p (0);
+  unsigned int explicit_type1 = (*group.shape)->explicit_type_suffix_p (1);
+  for (unsigned int pi = 0; group.preds[pi] != NUM_PREDS; ++pi)
+    {
+      if (!explicit_type0 && !explicit_type1)
+       {
+         /* Deal with the common case in which there is one overloaded
+            function for all type combinations.  */
+         function_instance instance (group.base_name, *group.base,
+                                     *group.shape, mode, types_none[0],
+                                     group.preds[pi]);
+         add_overloaded_function (instance, group.required_extensions);
+       }
+      else
+       for (unsigned int ti = 0; group.types[ti][0] != NUM_TYPE_SUFFIXES;
+            ++ti)
+         {
+           /* Stub out the types that are determined by overload
+              resolution.  */
+           type_suffix_pair types = {
+             explicit_type0 ? group.types[ti][0] : NUM_TYPE_SUFFIXES,
+             explicit_type1 ? group.types[ti][1] : NUM_TYPE_SUFFIXES
+           };
+           function_instance instance (group.base_name, *group.base,
+                                       *group.shape, mode, types,
+                                       group.preds[pi]);
+           add_overloaded_function (instance, group.required_extensions);
+         }
+    }
+}
+
+/* Register all the functions in GROUP.  */
+void
+function_builder::register_function_group (const function_group_info &group)
+{
+  (*group.shape)->build (*this, group);
+}
+
+function_call_info::function_call_info (location_t location_in,
+                                       const function_instance &instance_in,
+                                       tree fndecl_in)
+  : function_instance (instance_in), location (location_in), fndecl (fndecl_in)
+{
+}
+
+function_resolver::function_resolver (location_t location,
+                                     const function_instance &instance,
+                                     tree fndecl, vec<tree, va_gc> &arglist)
+  : function_call_info (location, instance, fndecl), m_arglist (arglist)
+{
+}
+
+/* Return the vector type associated with type suffix TYPE.  */
+tree
+function_resolver::get_vector_type (type_suffix_index type)
+{
+  return acle_vector_types[0][type_suffixes[type].vector_type];
+}
+
+/* Return the <stdint.h> name associated with TYPE.  Using the <stdint.h>
+   name should be more user-friendly than the underlying canonical type,
+   since it makes the signedness and bitwidth explicit.  */
+const char *
+function_resolver::get_scalar_type_name (type_suffix_index type)
+{
+  return vector_types[type_suffixes[type].vector_type].acle_name + 2;
+}
+
+/* Return the type of argument I, or error_mark_node if it isn't
+   well-formed.  */
+tree
+function_resolver::get_argument_type (unsigned int i)
+{
+  tree arg = m_arglist[i];
+  return arg == error_mark_node ? arg : TREE_TYPE (arg);
+}
+
+/* Return true if argument I is some form of scalar value.  */
+bool
+function_resolver::scalar_argument_p (unsigned int i)
+{
+  tree type = get_argument_type (i);
+  return (INTEGRAL_TYPE_P (type)
+         /* Allow pointer types, leaving the frontend to warn where
+            necessary.  */
+         || POINTER_TYPE_P (type)
+         || SCALAR_FLOAT_TYPE_P (type));
+}
+
+/* Report that the function has no form that takes type suffix TYPE.
+   Return error_mark_node.  */
+tree
+function_resolver::report_no_such_form (type_suffix_index type)
+{
+  error_at (location, "%qE has no form that takes %qT arguments",
+           fndecl, get_vector_type (type));
+  return error_mark_node;
+}
+
+/* Silently check whether there is an instance of the function with the
+   mode suffix given by MODE and the type suffixes given by TYPE0 and TYPE1.
+   Return its function decl if so, otherwise return null.  */
+tree
+function_resolver::lookup_form (mode_suffix_index mode,
+                               type_suffix_index type0,
+                               type_suffix_index type1)
+{
+  type_suffix_pair types = { type0, type1 };
+  function_instance instance (base_name, base, shape, mode, types, pred);
+  registered_function *rfn
+    = function_table->find_with_hash (instance, instance.hash ());
+  return rfn ? rfn->decl : NULL_TREE;
+}
+
+/* Resolve the function to one with the mode suffix given by MODE and the
+   type suffixes given by TYPE0 and TYPE1.  Return its function decl on
+   success, otherwise report an error and return error_mark_node.  */
+tree
+function_resolver::resolve_to (mode_suffix_index mode,
+                              type_suffix_index type0,
+                              type_suffix_index type1)
+{
+  tree res = lookup_form (mode, type0, type1);
+  if (!res)
+    {
+      if (type1 == NUM_TYPE_SUFFIXES)
+       return report_no_such_form (type0);
+      if (type0 == type_suffix_ids[0])
+       return report_no_such_form (type1);
+      /* To be filled in when we have other cases.  */
+      gcc_unreachable ();
+    }
+  return res;
+}
+
+/* Require argument ARGNO to be a 32-bit or 64-bit scalar integer type.
+   Return the associated type suffix on success, otherwise report an
+   error and return NUM_TYPE_SUFFIXES.  */
+type_suffix_index
+function_resolver::infer_integer_scalar_type (unsigned int argno)
+{
+  tree actual = get_argument_type (argno);
+  if (actual == error_mark_node)
+    return NUM_TYPE_SUFFIXES;
+
+  /* Allow enums and booleans to decay to integers, for compatibility
+     with C++ overloading rules.  */
+  if (INTEGRAL_TYPE_P (actual))
+    {
+      bool uns_p = TYPE_UNSIGNED (actual);
+      /* Honor the usual integer promotions, so that resolution works
+        in the same way as for C++.  */
+      if (TYPE_PRECISION (actual) < 32)
+       return TYPE_SUFFIX_s32;
+      if (TYPE_PRECISION (actual) == 32)
+       return uns_p ? TYPE_SUFFIX_u32 : TYPE_SUFFIX_s32;
+      if (TYPE_PRECISION (actual) == 64)
+       return uns_p ? TYPE_SUFFIX_u64 : TYPE_SUFFIX_s64;
+    }
+
+  error_at (location, "passing %qT to argument %d of %qE, which expects"
+           " a 32-bit or 64-bit integer type", actual, argno + 1, fndecl);
+  return NUM_TYPE_SUFFIXES;
+}
+
+/* Require argument ARGNO to be a pointer to a scalar type that has a
+   corresponding type suffix.  Return that type suffix on success,
+   otherwise report an error and return NUM_TYPE_SUFFIXES.
+   GATHER_SCATTER_P is true if the function is a gather/scatter
+   operation, and so requires a pointer to 32-bit or 64-bit data.  */
+type_suffix_index
+function_resolver::infer_pointer_type (unsigned int argno,
+                                      bool gather_scatter_p)
+{
+  tree actual = get_argument_type (argno);
+  if (actual == error_mark_node)
+    return NUM_TYPE_SUFFIXES;
+
+  if (TREE_CODE (actual) != POINTER_TYPE)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a pointer type", actual, argno + 1, fndecl);
+      if (VECTOR_TYPE_P (actual) && gather_scatter_p)
+       inform (location, "an explicit type suffix is needed"
+               " when using a vector of base addresses");
+      return NUM_TYPE_SUFFIXES;
+    }
+
+  tree target = TREE_TYPE (actual);
+  type_suffix_index type = find_type_suffix_for_scalar_type (target);
+  if (type == NUM_TYPE_SUFFIXES)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, but %qT is not"
+               " a valid SVE element type", actual, argno + 1, fndecl,
+               target);
+      return NUM_TYPE_SUFFIXES;
+    }
+  unsigned int bits = type_suffixes[type].element_bits;
+  if (gather_scatter_p && bits != 32 && bits != 64)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a pointer to 32-bit or 64-bit elements",
+               actual, argno + 1, fndecl);
+      return NUM_TYPE_SUFFIXES;
+    }
+
+  return type;
+}
+
+/* Require argument ARGNO to be a single vector or a tuple of NUM_VECTORS
+   vectors; NUM_VECTORS is 1 for the former.  Return the associated type
+   suffix on success, using TYPE_SUFFIX_b for predicates.  Report an error
+   and return NUM_TYPE_SUFFIXES on failure.  */
+type_suffix_index
+function_resolver::infer_vector_or_tuple_type (unsigned int argno,
+                                              unsigned int num_vectors)
+{
+  tree actual = get_argument_type (argno);
+  if (actual == error_mark_node)
+    return NUM_TYPE_SUFFIXES;
+
+  /* A linear search should be OK here, since the code isn't hot and
+     the number of types is only small.  */
+  for (unsigned int size_i = 0; size_i < MAX_TUPLE_SIZE; ++size_i)
+    for (unsigned int suffix_i = 0; suffix_i < NUM_TYPE_SUFFIXES; ++suffix_i)
+      {
+       vector_type_index type_i = type_suffixes[suffix_i].vector_type;
+       tree type = acle_vector_types[size_i][type_i];
+       if (type && TYPE_MAIN_VARIANT (actual) == TYPE_MAIN_VARIANT (type))
+         {
+           if (size_i + 1 == num_vectors)
+             return type_suffix_index (suffix_i);
+
+           if (num_vectors == 1)
+             error_at (location, "passing %qT to argument %d of %qE, which"
+                       " expects a single SVE vector rather than a tuple",
+                       actual, argno + 1, fndecl);
+           else if (size_i == 0 && type_i != VECTOR_TYPE_svbool_t)
+             error_at (location, "passing single vector %qT to argument %d"
+                       " of %qE, which expects a tuple of %d vectors",
+                       actual, argno + 1, fndecl, num_vectors);
+           else
+             error_at (location, "passing %qT to argument %d of %qE, which"
+                       " expects a tuple of %d vectors", actual, argno + 1,
+                       fndecl, num_vectors);
+           return NUM_TYPE_SUFFIXES;
+         }
+      }
+
+  if (num_vectors == 1)
+    error_at (location, "passing %qT to argument %d of %qE, which"
+             " expects an SVE vector type", actual, argno + 1, fndecl);
+  else
+    error_at (location, "passing %qT to argument %d of %qE, which"
+             " expects an SVE tuple type", actual, argno + 1, fndecl);
+  return NUM_TYPE_SUFFIXES;
+}
+
+/* Require argument ARGNO to have some form of vector type.  Return the
+   associated type suffix on success, using TYPE_SUFFIX_b for predicates.
+   Report an error and return NUM_TYPE_SUFFIXES on failure.  */
+type_suffix_index
+function_resolver::infer_vector_type (unsigned int argno)
+{
+  return infer_vector_or_tuple_type (argno, 1);
+}
+
+/* Like infer_vector_type, but also require the type to be integral.  */
+type_suffix_index
+function_resolver::infer_integer_vector_type (unsigned int argno)
+{
+  type_suffix_index type = infer_vector_type (argno);
+  if (type == NUM_TYPE_SUFFIXES)
+    return type;
+
+  if (!type_suffixes[type].integer_p)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a vector of integers", get_argument_type (argno),
+               argno + 1, fndecl);
+      return NUM_TYPE_SUFFIXES;
+    }
+
+  return type;
+}
+
+/* Like infer_vector_type, but also require the type to be an unsigned
+   integer.  */
+type_suffix_index
+function_resolver::infer_unsigned_vector_type (unsigned int argno)
+{
+  type_suffix_index type = infer_vector_type (argno);
+  if (type == NUM_TYPE_SUFFIXES)
+    return type;
+
+  if (!type_suffixes[type].unsigned_p)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a vector of unsigned integers",
+               get_argument_type (argno), argno + 1, fndecl);
+      return NUM_TYPE_SUFFIXES;
+    }
+
+  return type;
+}
+
+/* Like infer_vector_type, but also require the element size to be
+   32 or 64 bits.  */
+type_suffix_index
+function_resolver::infer_sd_vector_type (unsigned int argno)
+{
+  type_suffix_index type = infer_vector_type (argno);
+  if (type == NUM_TYPE_SUFFIXES)
+    return type;
+
+  unsigned int bits = type_suffixes[type].element_bits;
+  if (bits != 32 && bits != 64)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a vector of 32-bit or 64-bit elements",
+               get_argument_type (argno), argno + 1, fndecl);
+      return NUM_TYPE_SUFFIXES;
+    }
+
+  return type;
+}
+
+/* If the function operates on tuples of vectors, require argument ARGNO to be
+   a tuple with the appropriate number of vectors, otherwise require it to be
+   a single vector.  Return the associated type suffix on success, using
+   TYPE_SUFFIX_b for predicates.  Report an error and return NUM_TYPE_SUFFIXES
+   on failure.  */
+type_suffix_index
+function_resolver::infer_tuple_type (unsigned int argno)
+{
+  return infer_vector_or_tuple_type (argno, vectors_per_tuple ());
+}
+
+/* Require argument ARGNO to be a vector or scalar argument.  Return true
+   if it is, otherwise report an appropriate error.  */
+bool
+function_resolver::require_vector_or_scalar_type (unsigned int argno)
+{
+  tree actual = get_argument_type (argno);
+  if (actual == error_mark_node)
+    return false;
+
+  if (!scalar_argument_p (argno) && !VECTOR_TYPE_P (actual))
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a vector or scalar type", actual, argno + 1, fndecl);
+      return false;
+    }
+
+  return true;
+}
+
+/* Require argument ARGNO to have vector type TYPE, in cases where this
+   requirement holds for all uses of the function.  Return true if the
+   argument has the right form, otherwise report an appropriate error.  */
+bool
+function_resolver::require_vector_type (unsigned int argno,
+                                       vector_type_index type)
+{
+  tree expected = acle_vector_types[0][type];
+  tree actual = get_argument_type (argno);
+  if (actual != error_mark_node
+      && TYPE_MAIN_VARIANT (expected) != TYPE_MAIN_VARIANT (actual))
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects %qT", actual, argno + 1, fndecl, expected);
+      return false;
+    }
+  return true;
+}
+
+/* Like require_vector_type, but TYPE is inferred from previous arguments
+   rather than being a fixed part of the function signature.  This changes
+   the nature of the error messages.  */
+bool
+function_resolver::require_matching_vector_type (unsigned int argno,
+                                                type_suffix_index type)
+{
+  type_suffix_index new_type = infer_vector_type (argno);
+  if (new_type == NUM_TYPE_SUFFIXES)
+    return false;
+
+  if (type != new_type)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, but"
+               " previous arguments had type %qT",
+               get_vector_type (new_type), argno + 1, fndecl,
+               get_vector_type (type));
+      return false;
+    }
+  return true;
+}
+
+/* Require argument ARGNO to be a vector type with the following properties:
+
+   - the type class must be the same as FIRST_TYPE's if EXPECTED_TCLASS
+     is SAME_TYPE_CLASS, otherwise it must be EXPECTED_TCLASS itself.
+
+   - the element size must be:
+
+     - the same as FIRST_TYPE's if EXPECTED_BITS == SAME_SIZE
+     - half of FIRST_TYPE's if EXPECTED_BITS == HALF_SIZE
+     - a quarter of FIRST_TYPE's if EXPECTED_BITS == QUARTER_SIZE
+     - EXPECTED_BITS itself otherwise
+
+   Return true if the argument has the required type, otherwise report
+   an appropriate error.
+
+   FIRST_ARGNO is the first argument that is known to have type FIRST_TYPE.
+   Usually it comes before ARGNO, but sometimes it is more natural to resolve
+   arguments out of order.
+
+   If the required properties depend on FIRST_TYPE then both FIRST_ARGNO and
+   ARGNO contribute to the resolution process.  If the required properties
+   are fixed, only FIRST_ARGNO contributes to the resolution process.
+
+   This function is a bit of a Swiss army knife.  The complication comes
+   from trying to give good error messages when FIRST_ARGNO and ARGNO are
+   inconsistent, since either of them might be wrong.  */
+bool function_resolver::
+require_derived_vector_type (unsigned int argno,
+                            unsigned int first_argno,
+                            type_suffix_index first_type,
+                            type_class_index expected_tclass,
+                            unsigned int expected_bits)
+{
+  /* If the type needs to match FIRST_ARGNO exactly, use the preferred
+     error message for that case.  The VECTOR_TYPE_P test excludes tuple
+     types, which we handle below instead.  */
+  bool both_vectors_p = VECTOR_TYPE_P (get_argument_type (first_argno));
+  if (both_vectors_p
+      && expected_tclass == SAME_TYPE_CLASS
+      && expected_bits == SAME_SIZE)
+    {
+      /* There's no need to resolve this case out of order.  */
+      gcc_assert (argno > first_argno);
+      return require_matching_vector_type (argno, first_type);
+    }
+
+  /* Use FIRST_TYPE to get the expected type class and element size.  */
+  type_class_index orig_expected_tclass = expected_tclass;
+  if (expected_tclass == NUM_TYPE_CLASSES)
+    expected_tclass = type_suffixes[first_type].tclass;
+
+  unsigned int orig_expected_bits = expected_bits;
+  if (expected_bits == SAME_SIZE)
+    expected_bits = type_suffixes[first_type].element_bits;
+  else if (expected_bits == HALF_SIZE)
+    expected_bits = type_suffixes[first_type].element_bits / 2;
+  else if (expected_bits == QUARTER_SIZE)
+    expected_bits = type_suffixes[first_type].element_bits / 4;
+
+  /* If the expected type doesn't depend on FIRST_TYPE at all,
+     just check for the fixed choice of vector type.  */
+  if (expected_tclass == orig_expected_tclass
+      && expected_bits == orig_expected_bits)
+    {
+      const type_suffix_info &expected_suffix
+       = type_suffixes[find_type_suffix (expected_tclass, expected_bits)];
+      return require_vector_type (argno, expected_suffix.vector_type);
+    }
+
+  /* Require the argument to be some form of SVE vector type,
+     without being specific about the type of vector we want.  */
+  type_suffix_index actual_type = infer_vector_type (argno);
+  if (actual_type == NUM_TYPE_SUFFIXES)
+    return false;
+
+  /* Exit now if we got the right type.  */
+  bool tclass_ok_p = (type_suffixes[actual_type].tclass == expected_tclass);
+  bool size_ok_p = (type_suffixes[actual_type].element_bits == expected_bits);
+  if (tclass_ok_p && size_ok_p)
+    return true;
+
+  /* First look for cases in which the actual type contravenes a fixed
+     size requirement, without having to refer to FIRST_TYPE.  */
+  if (!size_ok_p && expected_bits == orig_expected_bits)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a vector of %d-bit elements",
+               get_vector_type (actual_type), argno + 1, fndecl,
+               expected_bits);
+      return false;
+    }
+
+  /* Likewise for a fixed type class requirement.  This is only ever
+     needed for signed and unsigned types, so don't create unnecessary
+     translation work for other type classes.  */
+  if (!tclass_ok_p && orig_expected_tclass == TYPE_signed)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a vector of signed integers",
+               get_vector_type (actual_type), argno + 1, fndecl);
+      return false;
+    }
+  if (!tclass_ok_p && orig_expected_tclass == TYPE_unsigned)
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a vector of unsigned integers",
+               get_vector_type (actual_type), argno + 1, fndecl);
+      return false;
+    }
+
+  /* Make sure that FIRST_TYPE itself is sensible before using it
+     as a basis for an error message.  */
+  if (resolve_to (mode_suffix_id, first_type) == error_mark_node)
+    return false;
+
+  /* If the arguments have consistent type classes, but a link between
+     the sizes has been broken, try to describe the error in those terms.  */
+  if (both_vectors_p && tclass_ok_p && orig_expected_bits == SAME_SIZE)
+    {
+      if (argno < first_argno)
+       {
+         std::swap (argno, first_argno);
+         std::swap (actual_type, first_type);
+       }
+      error_at (location, "arguments %d and %d of %qE must have the"
+               " same element size, but the values passed here have type"
+               " %qT and %qT respectively", first_argno + 1, argno + 1,
+               fndecl, get_vector_type (first_type),
+               get_vector_type (actual_type));
+      return false;
+    }
+
+  /* Likewise in reverse: look for cases in which the sizes are consistent
+     but a link between the type classes has been broken.  */
+  if (both_vectors_p
+      && size_ok_p
+      && orig_expected_tclass == SAME_TYPE_CLASS
+      && type_suffixes[first_type].integer_p
+      && type_suffixes[actual_type].integer_p)
+    {
+      if (argno < first_argno)
+       {
+         std::swap (argno, first_argno);
+         std::swap (actual_type, first_type);
+       }
+      error_at (location, "arguments %d and %d of %qE must have the"
+               " same signedness, but the values passed here have type"
+               " %qT and %qT respectively", first_argno + 1, argno + 1,
+               fndecl, get_vector_type (first_type),
+               get_vector_type (actual_type));
+      return false;
+    }
+
+  /* The two arguments are wildly inconsistent.  */
+  type_suffix_index expected_type
+    = find_type_suffix (expected_tclass, expected_bits);
+  error_at (location, "passing %qT instead of the expected %qT to argument"
+           " %d of %qE, after passing %qT to argument %d",
+           get_vector_type (actual_type), get_vector_type (expected_type),
+           argno + 1, fndecl, get_argument_type (first_argno),
+           first_argno + 1);
+  return false;
+}
+
+/* Require argument ARGNO to be a (possibly variable) scalar, using EXPECTED
+   as the name of its expected type.  Return true if the argument has the
+   right form, otherwise report an appropriate error.  */
+bool
+function_resolver::require_scalar_type (unsigned int argno,
+                                       const char *expected)
+{
+  if (!scalar_argument_p (argno))
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects %qs", get_argument_type (argno), argno + 1,
+               fndecl, expected);
+      return false;
+    }
+  return true;
+}
+
+/* Require argument ARGNO to be some form of pointer, without being specific
+   about its target type.  Return true if the argument has the right form,
+   otherwise report an appropriate error.  */
+bool
+function_resolver::require_pointer_type (unsigned int argno)
+{
+  if (!scalar_argument_p (argno))
+    {
+      error_at (location, "passing %qT to argument %d of %qE, which"
+               " expects a scalar pointer", get_argument_type (argno),
+               argno + 1, fndecl);
+      return false;
+    }
+  return true;
+}
+
+/* Argument FIRST_ARGNO is a scalar with type EXPECTED_TYPE, and argument
+   ARGNO should be consistent with it.  Return true if it is, otherwise
+   report an appropriate error.  */
+bool function_resolver::
+require_matching_integer_scalar_type (unsigned int argno,
+                                     unsigned int first_argno,
+                                     type_suffix_index expected_type)
+{
+  type_suffix_index actual_type = infer_integer_scalar_type (argno);
+  if (actual_type == NUM_TYPE_SUFFIXES)
+    return false;
+
+  if (actual_type == expected_type)
+    return true;
+
+  error_at (location, "call to %qE is ambiguous; argument %d has type"
+           " %qs but argument %d has type %qs", fndecl,
+           first_argno + 1, get_scalar_type_name (expected_type),
+           argno + 1, get_scalar_type_name (actual_type));
+  return false;
+}
+
+/* Require argument ARGNO to be a (possibly variable) scalar, expecting it
+   to have the following properties:
+
+   - the type class must be the same as for type suffix 0 if EXPECTED_TCLASS
+     is SAME_TYPE_CLASS, otherwise it must be EXPECTED_TCLASS itself.
+
+   - the element size must be the same as for type suffix 0 if EXPECTED_BITS
+     is SAME_TYPE_SIZE, otherwise it must be EXPECTED_BITS itself.
+
+   Return true if the argument is valid, otherwise report an appropriate error.
+
+   Note that we don't check whether the scalar type actually has the required
+   properties, since that's subject to implicit promotions and conversions.
+   Instead we just use the expected properties to tune the error message.  */
+bool function_resolver::
+require_derived_scalar_type (unsigned int argno,
+                            type_class_index expected_tclass,
+                            unsigned int expected_bits)
+{
+  gcc_assert (expected_tclass == SAME_TYPE_CLASS
+             || expected_tclass == TYPE_signed
+             || expected_tclass == TYPE_unsigned);
+
+  /* If the expected type doesn't depend on the type suffix at all,
+     just check for the fixed choice of scalar type.  */
+  if (expected_tclass != SAME_TYPE_CLASS && expected_bits != SAME_SIZE)
+    {
+      type_suffix_index expected_type
+       = find_type_suffix (expected_tclass, expected_bits);
+      return require_scalar_type (argno, get_scalar_type_name (expected_type));
+    }
+
+  if (scalar_argument_p (argno))
+    return true;
+
+  if (expected_tclass == SAME_TYPE_CLASS)
+    /* It doesn't really matter whether the element is expected to be
+       the same size as type suffix 0.  */
+    error_at (location, "passing %qT to argument %d of %qE, which"
+             " expects a scalar element", get_argument_type (argno),
+             argno + 1, fndecl);
+  else
+    /* It doesn't seem useful to distinguish between signed and unsigned
+       scalars here.  */
+    error_at (location, "passing %qT to argument %d of %qE, which"
+             " expects a scalar integer", get_argument_type (argno),
+             argno + 1, fndecl);
+  return false;
+}
+
+/* Require argument ARGNO to be suitable for an integer constant expression.
+   Return true if it is, otherwise report an appropriate error.
+
+   function_checker checks whether the argument is actually constant and
+   has a suitable range.  The reason for distinguishing immediate arguments
+   here is because it provides more consistent error messages than
+   require_scalar_type would.  */
+bool
+function_resolver::require_integer_immediate (unsigned int argno)
+{
+  if (!scalar_argument_p (argno))
+    {
+      report_non_ice (location, fndecl, argno);
+      return false;
+    }
+  return true;
+}
+
+/* Require argument ARGNO to be a vector base in a gather-style address.
+   Return its type on success, otherwise return NUM_VECTOR_TYPES.  */
+vector_type_index
+function_resolver::infer_vector_base_type (unsigned int argno)
+{
+  type_suffix_index type = infer_vector_type (argno);
+  if (type == NUM_TYPE_SUFFIXES)
+    return NUM_VECTOR_TYPES;
+
+  if (type == TYPE_SUFFIX_u32 || type == TYPE_SUFFIX_u64)
+    return type_suffixes[type].vector_type;
+
+  error_at (location, "passing %qT to argument %d of %qE, which"
+           " expects %qs or %qs", get_argument_type (argno),
+           argno + 1, fndecl, "svuint32_t", "svuint64_t");
+  return NUM_VECTOR_TYPES;
+}
+
+/* Require argument ARGNO to be a vector displacement in a gather-style
+   address.  Return its type on success, otherwise return NUM_VECTOR_TYPES.  */
+vector_type_index
+function_resolver::infer_vector_displacement_type (unsigned int argno)
+{
+  type_suffix_index type = infer_integer_vector_type (argno);
+  if (type == NUM_TYPE_SUFFIXES)
+    return NUM_VECTOR_TYPES;
+
+  if (type_suffixes[type].integer_p
+      && (type_suffixes[type].element_bits == 32
+         || type_suffixes[type].element_bits == 64))
+    return type_suffixes[type].vector_type;
+
+  error_at (location, "passing %qT to argument %d of %qE, which"
+           " expects a vector of 32-bit or 64-bit integers",
+           get_argument_type (argno), argno + 1, fndecl);
+  return NUM_VECTOR_TYPES;
+}
+
+/* Require argument ARGNO to be a vector displacement in a gather-style
+   address.  There are three possible uses:
+
+   - for loading into elements of type TYPE (when LOAD_P is true)
+   - for storing from elements of type TYPE (when LOAD_P is false)
+   - for prefetching data (when TYPE is NUM_TYPE_SUFFIXES)
+
+   The overloaded function's mode suffix determines the units of the
+   displacement (bytes for "_offset", elements for "_index").
+
+   Return the associated mode on success, otherwise report an error
+   and return MODE_none.  */
+mode_suffix_index
+function_resolver::resolve_sv_displacement (unsigned int argno,
+                                           type_suffix_index type,
+                                           bool load_p)
+{
+  if (type == NUM_TYPE_SUFFIXES)
+    {
+      /* For prefetches, the base is a void pointer and the displacement
+        can be any valid offset or index type.  */
+      vector_type_index displacement_vector_type
+       = infer_vector_displacement_type (argno);
+      if (displacement_vector_type == NUM_VECTOR_TYPES)
+       return MODE_none;
+
+      mode_suffix_index mode = find_mode_suffix (NUM_VECTOR_TYPES,
+                                                displacement_vector_type,
+                                                displacement_units ());
+      gcc_assert (mode != MODE_none);
+      return mode;
+    }
+
+  /* Check for some form of vector type, without naming any in particular
+     as being expected.  */
+  type_suffix_index displacement_type = infer_vector_type (argno);
+  if (displacement_type == NUM_TYPE_SUFFIXES)
+    return MODE_none;
+
+  /* If the displacement type is consistent with the data vector type,
+     try to find the associated mode suffix.  This will fall through
+     for non-integral displacement types.  */
+  unsigned int required_bits = type_suffixes[type].element_bits;
+  if (type_suffixes[displacement_type].element_bits == required_bits)
+    {
+      vector_type_index displacement_vector_type
+       = type_suffixes[displacement_type].vector_type;
+      mode_suffix_index mode = find_mode_suffix (NUM_VECTOR_TYPES,
+                                                displacement_vector_type,
+                                                displacement_units ());
+      if (mode != MODE_none)
+       return mode;
+    }
+
+  if (type_suffix_ids[0] == NUM_TYPE_SUFFIXES)
+    {
+      /* TYPE has been inferred rather than specified by the user,
+        so mention it in the error messages.  */
+      if (load_p)
+       error_at (location, "passing %qT to argument %d of %qE, which when"
+                 " loading %qT expects a vector of %d-bit integers",
+                 get_argument_type (argno), argno + 1, fndecl,
+                 get_vector_type (type), required_bits);
+      else
+       error_at (location, "passing %qT to argument %d of %qE, which when"
+                 " storing %qT expects a vector of %d-bit integers",
+                 get_argument_type (argno), argno + 1, fndecl,
+                 get_vector_type (type), required_bits);
+    }
+  else
+    /* TYPE is part of the function name.  */
+    error_at (location, "passing %qT to argument %d of %qE, which"
+             " expects a vector of %d-bit integers",
+             get_argument_type (argno), argno + 1, fndecl, required_bits);
+  return MODE_none;
+}
+
+/* Require the arguments starting at ARGNO to form a gather-style address.
+   There are three possible uses:
+
+   - for loading into elements of type TYPE (when LOAD_P is true)
+   - for storing from elements of type TYPE (when LOAD_P is false)
+   - for prefetching data (when TYPE is NUM_TYPE_SUFFIXES)
+
+   The three possible addresses are:
+
+   - a vector base with no displacement
+   - a vector base and a scalar displacement
+   - a scalar (pointer) base and a vector displacement
+
+   The overloaded function's mode suffix determines whether there is
+   a displacement, and if so, what units it uses:
+
+   - MODE_none: no displacement
+   - MODE_offset: the displacement is measured in bytes
+   - MODE_index: the displacement is measured in elements
+
+   Return the mode of the non-overloaded function on success, otherwise
+   report an error and return MODE_none.  */
+mode_suffix_index
+function_resolver::resolve_gather_address (unsigned int argno,
+                                          type_suffix_index type,
+                                          bool load_p)
+{
+  tree actual = get_argument_type (argno);
+  if (actual == error_mark_node)
+    return MODE_none;
+
+  if (displacement_units () != UNITS_none)
+    {
+      /* Some form of displacement is needed.  First handle a scalar
+        pointer base and a vector displacement.  */
+      if (scalar_argument_p (argno))
+       /* Don't check the pointer type here, since there's only one valid
+          choice.  Leave that to the frontend.  */
+       return resolve_sv_displacement (argno + 1, type, load_p);
+
+      if (!VECTOR_TYPE_P (actual))
+       {
+         error_at (location, "passing %qT to argument %d of %qE,"
+                   " which expects a vector or pointer base address",
+                   actual, argno + 1, fndecl);
+         return MODE_none;
+       }
+    }
+
+  /* Check for the correct choice of vector base type.  */
+  vector_type_index base_vector_type;
+  if (type == NUM_TYPE_SUFFIXES)
+    {
+      /* Since prefetches have no type suffix, there is a free choice
+        between 32-bit and 64-bit base addresses.  */
+      base_vector_type = infer_vector_base_type (argno);
+      if (base_vector_type == NUM_VECTOR_TYPES)
+       return MODE_none;
+    }
+  else
+    {
+      /* Check for some form of vector type, without saying which type
+        we expect.  */
+      type_suffix_index base_type = infer_vector_type (argno);
+      if (base_type == NUM_TYPE_SUFFIXES)
+       return MODE_none;
+
+      /* Check whether the type is the right one.  */
+      unsigned int required_bits = type_suffixes[type].element_bits;
+      gcc_assert (required_bits == 32 || required_bits == 64);
+      type_suffix_index required_type = (required_bits == 32
+                                        ? TYPE_SUFFIX_u32
+                                        : TYPE_SUFFIX_u64);
+      if (required_type != base_type)
+       {
+         error_at (location, "passing %qT to argument %d of %qE,"
+                   " which expects %qT", actual, argno + 1, fndecl,
+                   get_vector_type (required_type));
+         return MODE_none;
+       }
+      base_vector_type = type_suffixes[base_type].vector_type;
+    }
+
+  /* Check the scalar displacement, if any.  */
+  if (displacement_units () != UNITS_none
+      && !require_scalar_type (argno + 1, "int64_t"))
+    return MODE_none;
+
+  /* Find the appropriate mode suffix.  The checks above should have
+     weeded out all erroneous cases.  */
+  for (unsigned int mode_i = 0; mode_i < ARRAY_SIZE (mode_suffixes); ++mode_i)
+    {
+      const mode_suffix_info &mode = mode_suffixes[mode_i];
+      if (mode.base_vector_type == base_vector_type
+         && mode.displacement_vector_type == NUM_VECTOR_TYPES
+         && mode.displacement_units == displacement_units ())
+       return mode_suffix_index (mode_i);
+    }
+
+  gcc_unreachable ();
+}
+
+/* Require arguments ARGNO and ARGNO + 1 to form an ADR-style address,
+   i.e. one with a vector of base addresses and a vector of displacements.
+   The overloaded function's mode suffix determines the units of the
+   displacement (bytes for "_offset", elements for "_index").
+
+   Return the associated mode suffix on success, otherwise report
+   an error and return MODE_none.  */
+mode_suffix_index
+function_resolver::resolve_adr_address (unsigned int argno)
+{
+  vector_type_index base_type = infer_vector_base_type (argno);
+  if (base_type == NUM_VECTOR_TYPES)
+    return MODE_none;
+
+  vector_type_index displacement_type
+    = infer_vector_displacement_type (argno + 1);
+  if (displacement_type == NUM_VECTOR_TYPES)
+    return MODE_none;
+
+  mode_suffix_index mode = find_mode_suffix (base_type, displacement_type,
+                                            displacement_units ());
+  if (mode == MODE_none)
+    {
+      if (mode_suffix_id == MODE_offset)
+       error_at (location, "cannot combine a base of type %qT with"
+                 " an offset of type %qT",
+                 get_argument_type (argno), get_argument_type (argno + 1));
+      else
+       error_at (location, "cannot combine a base of type %qT with"
+                 " an index of type %qT",
+                 get_argument_type (argno), get_argument_type (argno + 1));
+    }
+  return mode;
+}
+
+/* Require the function to have exactly EXPECTED arguments.  Return true
+   if it does, otherwise report an appropriate error.  */
+bool
+function_resolver::check_num_arguments (unsigned int expected)
+{
+  if (m_arglist.length () < expected)
+    error_at (location, "too few arguments to function %qE", fndecl);
+  else if (m_arglist.length () > expected)
+    error_at (location, "too many arguments to function %qE", fndecl);
+  return m_arglist.length () == expected;
+}
+
+/* If the function is predicated, check that the first argument is a
+   suitable governing predicate.  Also check that there are NOPS further
+   arguments after any governing predicate, but don't check what they are.
+
+   Return true on success, otherwise report a suitable error.
+   When returning true:
+
+   - set I to the number of the first unchecked argument.
+   - set NARGS to the total number of arguments.  */
+bool
+function_resolver::check_gp_argument (unsigned int nops,
+                                     unsigned int &i, unsigned int &nargs)
+{
+  i = 0;
+  if (pred != PRED_none)
+    {
+      /* Unary merge operations should use resolve_unary instead.  */
+      gcc_assert (nops != 1 || pred != PRED_m);
+      nargs = nops + 1;
+      if (!check_num_arguments (nargs)
+         || !require_vector_type (i, VECTOR_TYPE_svbool_t))
+       return false;
+      i += 1;
+    }
+  else
+    {
+      nargs = nops;
+      if (!check_num_arguments (nargs))
+       return false;
+    }
+
+  return true;
+}
+
+/* Finish resolving a function whose final argument can be a vector
+   or a scalar, with the function having an implicit "_n" suffix
+   in the latter case.  This "_n" form might only exist for certain
+   type suffixes.
+
+   ARGNO is the index of the final argument.  The inferred type
+   suffix is FIRST_TYPE, which was obtained from argument FIRST_ARGNO.
+   EXPECTED_TCLASS and EXPECTED_BITS describe the expected properties
+   of the final vector or scalar argument, in the same way as for
+   require_derived_vector_type.
+
+   Return the function decl of the resolved function on success,
+   otherwise report a suitable error and return error_mark_node.  */
+tree function_resolver::
+finish_opt_n_resolution (unsigned int argno, unsigned int first_argno,
+                        type_suffix_index first_type,
+                        type_class_index expected_tclass,
+                        unsigned int expected_bits)
+{
+  tree scalar_form = lookup_form (MODE_n, first_type);
+
+  /* Allow the final argument to be scalar, if an _n form exists.  */
+  if (scalar_argument_p (argno))
+    {
+      if (scalar_form)
+       return scalar_form;
+
+      /* Check the vector form normally.  If that succeeds, raise an
+        error about having no corresponding _n form.  */
+      tree res = resolve_to (mode_suffix_id, first_type);
+      if (res != error_mark_node)
+       error_at (location, "passing %qT to argument %d of %qE, but its"
+                 " %qT form does not accept scalars",
+                 get_argument_type (argno), argno + 1, fndecl,
+                 get_vector_type (first_type));
+      return error_mark_node;
+    }
+
+  /* If an _n form does exist, provide a more accurate message than
+     require_derived_vector_type would for arguments that are neither
+     vectors nor scalars.  */
+  if (scalar_form && !require_vector_or_scalar_type (argno))
+    return error_mark_node;
+
+  /* Check for the correct vector type.  */
+  if (!require_derived_vector_type (argno, first_argno, first_type,
+                                   expected_tclass, expected_bits))
+    return error_mark_node;
+
+  return resolve_to (mode_suffix_id, first_type);
+}
+
+/* Resolve a (possibly predicated) unary function.  If the function uses
+   merge predication, there is an extra vector argument before the
+   governing predicate that specifies the values of inactive elements.
+   This argument has the following properties:
+
+   - the type class must be the same as for active elements if MERGE_TCLASS
+     is SAME_TYPE_CLASS, otherwise it must be MERGE_TCLASS itself.
+
+   - the element size must be the same as for active elements if MERGE_BITS
+     is SAME_TYPE_SIZE, otherwise it must be MERGE_BITS itself.
+
+   Return the function decl of the resolved function on success,
+   otherwise report a suitable error and return error_mark_node.  */
+tree
+function_resolver::resolve_unary (type_class_index merge_tclass,
+                                 unsigned int merge_bits)
+{
+  type_suffix_index type;
+  if (pred == PRED_m)
+    {
+      if (!check_num_arguments (3))
+       return error_mark_node;
+      if (merge_tclass == SAME_TYPE_CLASS && merge_bits == SAME_SIZE)
+       {
+         /* The inactive elements are the same as the active elements,
+            so we can use normal left-to-right resolution.  */
+         if ((type = infer_vector_type (0)) == NUM_TYPE_SUFFIXES
+             || !require_vector_type (1, VECTOR_TYPE_svbool_t)
+             || !require_matching_vector_type (2, type))
+           return error_mark_node;
+       }
+      else
+       {
+         /* The inactive element type is a function of the active one,
+            so resolve the active one first.  */
+         if (!require_vector_type (1, VECTOR_TYPE_svbool_t)
+             || (type = infer_vector_type (2)) == NUM_TYPE_SUFFIXES
+             || !require_derived_vector_type (0, 2, type, merge_tclass,
+                                              merge_bits))
+           return error_mark_node;
+       }
+    }
+  else
+    {
+      /* We just need to check the predicate (if any) and the single
+        vector argument.  */
+      unsigned int i, nargs;
+      if (!check_gp_argument (1, i, nargs)
+         || (type = infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+       return error_mark_node;
+    }
+
+  /* Handle convert-like functions in which the first type suffix is
+     explicit.  */
+  if (type_suffix_ids[0] != NUM_TYPE_SUFFIXES)
+    return resolve_to (mode_suffix_id, type_suffix_ids[0], type);
+
+  return resolve_to (mode_suffix_id, type);
+}
+
+/* Resolve a (possibly predicated) function that takes NOPS like-typed
+   vector arguments followed by NIMM integer immediates.  Return the
+   function decl of the resolved function on success, otherwise report
+   a suitable error and return error_mark_node.  */
+tree
+function_resolver::resolve_uniform (unsigned int nops, unsigned int nimm)
+{
+  unsigned int i, nargs;
+  type_suffix_index type;
+  if (!check_gp_argument (nops + nimm, i, nargs)
+      || (type = infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+    return error_mark_node;
+
+  i += 1;
+  for (; i < nargs - nimm; ++i)
+    if (!require_matching_vector_type (i, type))
+      return error_mark_node;
+
+  for (; i < nargs; ++i)
+    if (!require_integer_immediate (i))
+      return error_mark_node;
+
+  return resolve_to (mode_suffix_id, type);
+}
+
+/* Resolve a (possibly predicated) function that offers a choice between
+   taking:
+
+   - NOPS like-typed vector arguments or
+   - NOPS - 1 like-typed vector arguments followed by a scalar argument
+
+   Return the function decl of the resolved function on success,
+   otherwise report a suitable error and return error_mark_node.  */
+tree
+function_resolver::resolve_uniform_opt_n (unsigned int nops)
+{
+  unsigned int i, nargs;
+  type_suffix_index type;
+  if (!check_gp_argument (nops, i, nargs)
+      || (type = infer_vector_type (i)) == NUM_TYPE_SUFFIXES)
+    return error_mark_node;
+
+  unsigned int first_arg = i++;
+  for (; i < nargs - 1; ++i)
+    if (!require_matching_vector_type (i, type))
+      return error_mark_node;
+
+  return finish_opt_n_resolution (i, first_arg, type);
+}
+
+/* If the call is erroneous, report an appropriate error and return
+   error_mark_node.  Otherwise, if the function is overloaded, return
+   the decl of the non-overloaded function.  Return NULL_TREE otherwise,
+   indicating that the call should be processed in the normal way.  */
+tree
+function_resolver::resolve ()
+{
+  return shape->resolve (*this);
+}
+
+function_checker::function_checker (location_t location,
+                                   const function_instance &instance,
+                                   tree fndecl, tree fntype,
+                                   unsigned int nargs, tree *args)
+  : function_call_info (location, instance, fndecl),
+    m_fntype (fntype), m_nargs (nargs), m_args (args),
+    /* We don't have to worry about unary _m operations here, since they
+       never have arguments that need checking.  */
+    m_base_arg (pred != PRED_none ? 1 : 0)
+{
+}
+
+/* Return true if argument ARGNO exists. which it might not for
+   erroneous calls.  It is safe to wave through checks if this
+   function returns false.  */
+bool
+function_checker::argument_exists_p (unsigned int argno)
+{
+  gcc_assert (argno < (unsigned int) type_num_arguments (m_fntype));
+  return argno < m_nargs;
+}
+
+/* Check that argument ARGNO is an integer constant expression and
+   store its value in VALUE_OUT if so.  The caller should first
+   check that argument ARGNO exists.  */
+bool
+function_checker::require_immediate (unsigned int argno,
+                                    HOST_WIDE_INT &value_out)
+{
+  gcc_assert (argno < m_nargs);
+  tree arg = m_args[argno];
+
+  /* The type and range are unsigned, so read the argument as an
+     unsigned rather than signed HWI.  */
+  if (!tree_fits_uhwi_p (arg))
+    {
+      report_non_ice (location, fndecl, argno);
+      return false;
+    }
+
+  /* ...but treat VALUE_OUT as signed for error reporting, since printing
+     -1 is more user-friendly than the maximum uint64_t value.  */
+  value_out = tree_to_uhwi (arg);
+  return true;
+}
+
+/* Check that argument REL_ARGNO is an integer constant expression that
+   has the value VALUE0 or VALUE1.  REL_ARGNO counts from the end of the
+   predication arguments.  */
+bool
+function_checker::require_immediate_either_or (unsigned int rel_argno,
+                                              HOST_WIDE_INT value0,
+                                              HOST_WIDE_INT value1)
+{
+  unsigned int argno = m_base_arg + rel_argno;
+  if (!argument_exists_p (argno))
+    return true;
+
+  HOST_WIDE_INT actual;
+  if (!require_immediate (argno, actual))
+    return false;
+
+  if (actual != value0 && actual != value1)
+    {
+      report_neither_nor (location, fndecl, argno, actual, 90, 270);
+      return false;
+    }
+
+  return true;
+}
+
+/* Check that argument REL_ARGNO is an integer constant expression that has
+   a valid value for enumeration type TYPE.  REL_ARGNO counts from the end
+   of the predication arguments.  */
+bool
+function_checker::require_immediate_enum (unsigned int rel_argno, tree type)
+{
+  unsigned int argno = m_base_arg + rel_argno;
+  if (!argument_exists_p (argno))
+    return true;
+
+  HOST_WIDE_INT actual;
+  if (!require_immediate (argno, actual))
+    return false;
+
+  for (tree entry = TYPE_VALUES (type); entry; entry = TREE_CHAIN (entry))
+    {
+      /* The value is an INTEGER_CST for C and a CONST_DECL wrapper
+        around an INTEGER_CST for C++.  */
+      tree value = TREE_VALUE (entry);
+      if (TREE_CODE (value) == CONST_DECL)
+       value = DECL_INITIAL (value);
+      if (wi::to_widest (value) == actual)
+       return true;
+    }
+
+  report_not_enum (location, fndecl, argno, actual, type);
+  return false;
+}
+
+/* Check that argument REL_ARGNO is suitable for indexing argument
+   REL_ARGNO - 1, in groups of GROUP_SIZE elements.  REL_ARGNO counts
+   from the end of the predication arguments.  */
+bool
+function_checker::require_immediate_lane_index (unsigned int rel_argno,
+                                               unsigned int group_size)
+{
+  unsigned int argno = m_base_arg + rel_argno;
+  if (!argument_exists_p (argno))
+    return true;
+
+  /* Get the type of the previous argument.  tree_argument_type wants a
+     1-based number, whereas ARGNO is 0-based.  */
+  machine_mode mode = TYPE_MODE (type_argument_type (m_fntype, argno));
+  gcc_assert (VECTOR_MODE_P (mode));
+  unsigned int nlanes = 128 / (group_size * GET_MODE_UNIT_BITSIZE (mode));
+  return require_immediate_range (rel_argno, 0, nlanes - 1);
+}
+
+/* Check that argument REL_ARGNO is an integer constant expression that
+   has one of the given values.  */
+bool
+function_checker::require_immediate_one_of (unsigned int rel_argno,
+                                           HOST_WIDE_INT value0,
+                                           HOST_WIDE_INT value1,
+                                           HOST_WIDE_INT value2,
+                                           HOST_WIDE_INT value3)
+{
+  unsigned int argno = m_base_arg + rel_argno;
+  if (!argument_exists_p (argno))
+    return true;
+
+  HOST_WIDE_INT actual;
+  if (!require_immediate (argno, actual))
+    return false;
+
+  if (actual != value0
+      && actual != value1
+      && actual != value2
+      && actual != value3)
+    {
+      report_not_one_of (location, fndecl, argno, actual,
+                        value0, value1, value2, value3);
+      return false;
+    }
+
+  return true;
+}
+
+/* Check that argument REL_ARGNO is an integer constant expression in the
+   range [MIN, MAX].  REL_ARGNO counts from the end of the predication
+   arguments.  */
+bool
+function_checker::require_immediate_range (unsigned int rel_argno,
+                                          HOST_WIDE_INT min,
+                                          HOST_WIDE_INT max)
+{
+  unsigned int argno = m_base_arg + rel_argno;
+  if (!argument_exists_p (argno))
+    return true;
+
+  /* Required because of the tree_to_uhwi -> HOST_WIDE_INT conversion
+     in require_immediate.  */
+  gcc_assert (min >= 0 && min <= max);
+  HOST_WIDE_INT actual;
+  if (!require_immediate (argno, actual))
+    return false;
+
+  if (!IN_RANGE (actual, min, max))
+    {
+      report_out_of_range (location, fndecl, argno, actual, min, max);
+      return false;
+    }
+
+  return true;
+}
+
+/* Perform semantic checks on the call.  Return true if the call is valid,
+   otherwise report a suitable error.  */
+bool
+function_checker::check ()
+{
+  function_args_iterator iter;
+  tree type;
+  unsigned int i = 0;
+  FOREACH_FUNCTION_ARGS (m_fntype, type, iter)
+    {
+      if (type == void_type_node || i >= m_nargs)
+       break;
+
+      if (i >= m_base_arg
+         && TREE_CODE (type) == ENUMERAL_TYPE
+         && !require_immediate_enum (i - m_base_arg, type))
+       return false;
+
+      i += 1;
+    }
+
+  return shape->check (*this);
+}
+
+gimple_folder::gimple_folder (const function_instance &instance, tree fndecl,
+                             gimple_stmt_iterator *gsi_in, gcall *call_in)
+  : function_call_info (gimple_location (call_in), instance, fndecl),
+    gsi (gsi_in), call (call_in), lhs (gimple_call_lhs (call_in))
+{
+}
+
+/* Convert predicate argument ARGNO so that it has the type appropriate for
+   an operation on VECTYPE.  Add any new statements to STMTS.  */
+tree
+gimple_folder::convert_pred (gimple_seq &stmts, tree vectype,
+                            unsigned int argno)
+{
+  tree predtype = build_same_sized_truth_vector_type (vectype);
+  tree pred = gimple_call_arg (call, argno);
+  return gimple_build (&stmts, VIEW_CONVERT_EXPR, predtype, pred);
+}
+
+/* Return a pointer to the address in a contiguous load or store,
+   given that each memory vector has type VECTYPE.  Add any new
+   statements to STMTS.  */
+tree
+gimple_folder::fold_contiguous_base (gimple_seq &stmts, tree vectype)
+{
+  tree base = gimple_call_arg (call, 1);
+  if (mode_suffix_id == MODE_vnum)
+    {
+      tree offset = gimple_call_arg (call, 2);
+      offset = gimple_convert (&stmts, sizetype, offset);
+      offset = gimple_build (&stmts, MULT_EXPR, sizetype, offset,
+                            TYPE_SIZE_UNIT (vectype));
+      base = gimple_build (&stmts, POINTER_PLUS_EXPR, TREE_TYPE (base),
+                          base, offset);
+    }
+  return base;
+}
+
+/* Return the alignment and TBAA argument to an internal load or store
+   function like IFN_MASK_LOAD or IFN_MASK_STORE, given that it accesses
+   memory elements of type TYPE.  */
+tree
+gimple_folder::load_store_cookie (tree type)
+{
+  return build_int_cst (build_pointer_type (type), TYPE_ALIGN_UNIT (type));
+}
+
+/* Fold the call to a PTRUE, taking the element size from type suffix 0.  */
+gimple *
+gimple_folder::fold_to_ptrue ()
+{
+  tree svbool_type = TREE_TYPE (lhs);
+  tree bool_type = TREE_TYPE (svbool_type);
+  unsigned int element_bytes = type_suffix (0).element_bytes;
+
+  /* The return type is svbool_t for all type suffixes, thus for b8 we
+     want { 1, 1, 1, 1, ... }, for b16 we want { 1, 0, 1, 0, ... }, etc.  */
+  tree_vector_builder builder (svbool_type, element_bytes, 1);
+  builder.quick_push (build_all_ones_cst (bool_type));
+  for (unsigned int i = 1; i < element_bytes; ++i)
+    builder.quick_push (build_zero_cst (bool_type));
+  return gimple_build_assign (lhs, builder.build ());
+}
+
+/* Fold the call to a PFALSE.  */
+gimple *
+gimple_folder::fold_to_pfalse ()
+{
+  return gimple_build_assign (lhs, build_zero_cst (TREE_TYPE (lhs)));
+}
+
+/* Fold an operation to a constant predicate in which the first VL
+   elements are set and the rest are clear.  Take the element size
+   from type suffix 0.  */
+gimple *
+gimple_folder::fold_to_vl_pred (unsigned int vl)
+{
+  tree vectype = TREE_TYPE (lhs);
+  tree element_type = TREE_TYPE (vectype);
+  tree minus_one = build_all_ones_cst (element_type);
+  tree zero = build_zero_cst (element_type);
+  unsigned int element_bytes = type_suffix (0).element_bytes;
+
+  /* Construct COUNT elements that contain the ptrue followed by
+     a repeating sequence of COUNT elements.  */
+  unsigned int count = constant_lower_bound (TYPE_VECTOR_SUBPARTS (vectype));
+  gcc_assert (vl * element_bytes <= count);
+  tree_vector_builder builder (vectype, count, 2);
+  for (unsigned int i = 0; i < count * 2; ++i)
+    {
+      bool bit = (i & (element_bytes - 1)) == 0 && i < vl * element_bytes;
+      builder.quick_push (bit ? minus_one : zero);
+    }
+  return gimple_build_assign (lhs, builder.build ());
+}
+
+/* Try to fold the call.  Return the new statement on success and null
+   on failure.  */
+gimple *
+gimple_folder::fold ()
+{
+  /* Don't fold anything when SVE is disabled; emit an error during
+     expansion instead.  */
+  if (!TARGET_SVE)
+    return NULL;
+
+  /* Punt if the function has a return type and no result location is
+     provided.  The attributes should allow target-independent code to
+     remove the calls if appropriate.  */
+  if (!lhs && TREE_TYPE (gimple_call_fntype (call)) != void_type_node)
+    return NULL;
+
+  return base->fold (*this);
+}
+
+function_expander::function_expander (const function_instance &instance,
+                                     tree fndecl, tree call_expr_in,
+                                     rtx possible_target_in)
+  : function_call_info (EXPR_LOCATION (call_expr_in), instance, fndecl),
+    call_expr (call_expr_in), possible_target (possible_target_in)
+{
+}
+
+/* Return the handler of direct optab OP for type suffix SUFFIX_I.  */
+insn_code
+function_expander::direct_optab_handler (optab op, unsigned int suffix_i)
+{
+  return ::direct_optab_handler (op, vector_mode (suffix_i));
+}
+
+/* Choose between signed and unsigned direct optabs SIGNED_OP and
+   UNSIGNED_OP based on the signedness of type suffix SUFFIX_I, then
+   pick the appropriate optab handler for the mode.  Use MODE as the
+   mode if given, otherwise use the mode of type suffix SUFFIX_I.  */
+insn_code
+function_expander::direct_optab_handler_for_sign (optab signed_op,
+                                                 optab unsigned_op,
+                                                 unsigned int suffix_i,
+                                                 machine_mode mode)
+{
+  if (mode == VOIDmode)
+    mode = vector_mode (suffix_i);
+  optab op = type_suffix (suffix_i).unsigned_p ? unsigned_op : signed_op;
+  return ::direct_optab_handler (op, mode);
+}
+
+/* Return true if X overlaps any input.  */
+bool
+function_expander::overlaps_input_p (rtx x)
+{
+  for (unsigned int i = 0; i < args.length (); ++i)
+    if (reg_overlap_mentioned_p (x, args[i]))
+      return true;
+  return false;
+}
+
+/* Return the base address for a contiguous load or store function.
+   MEM_MODE is the mode of the addressed memory.  */
+rtx
+function_expander::get_contiguous_base (machine_mode mem_mode)
+{
+  rtx base = args[1];
+  if (mode_suffix_id == MODE_vnum)
+    {
+      /* Use the size of the memory mode for extending loads and truncating
+        stores.  Use the size of a full vector for non-extending loads
+        and non-truncating stores (including svld[234] and svst[234]).  */
+      poly_int64 size = ordered_min (GET_MODE_SIZE (mem_mode),
+                                    BYTES_PER_SVE_VECTOR);
+      rtx offset = gen_int_mode (size, Pmode);
+      offset = simplify_gen_binary (MULT, Pmode, args[2], offset);
+      base = simplify_gen_binary (PLUS, Pmode, base, offset);
+    }
+  return base;
+}
+
+/* For a function that does the equivalent of:
+
+     OUTPUT = COND ? FN (INPUTS) : FALLBACK;
+
+   return the value of FALLBACK.
+
+   MODE is the mode of OUTPUT.  NOPS is the number of operands in INPUTS.
+   MERGE_ARGNO is the argument that provides FALLBACK for _m functions,
+   or DEFAULT_MERGE_ARGNO if we should apply the usual rules.
+
+   ARGNO is the caller's index into args.  If the returned value is
+   argument 0 (as for unary _m operations), increment ARGNO past the
+   returned argument.  */
+rtx
+function_expander::get_fallback_value (machine_mode mode, unsigned int nops,
+                                      unsigned int merge_argno,
+                                      unsigned int &argno)
+{
+  if (pred == PRED_z)
+    return CONST0_RTX (mode);
+
+  gcc_assert (pred == PRED_m || pred == PRED_x);
+  if (merge_argno == DEFAULT_MERGE_ARGNO)
+    merge_argno = nops == 1 && pred == PRED_m ? 0 : 1;
+
+  if (merge_argno == 0)
+    return args[argno++];
+
+  return args[merge_argno];
+}
+
+/* Return a REG rtx that can be used for the result of the function,
+   using the preferred target if suitable.  */
+rtx
+function_expander::get_reg_target ()
+{
+  machine_mode target_mode = TYPE_MODE (TREE_TYPE (TREE_TYPE (fndecl)));
+  if (!possible_target || GET_MODE (possible_target) != target_mode)
+    possible_target = gen_reg_rtx (target_mode);
+  return possible_target;
+}
+
+/* As for get_reg_target, but make sure that the returned REG does not
+   overlap any inputs.  */
+rtx
+function_expander::get_nonoverlapping_reg_target ()
+{
+  if (possible_target && overlaps_input_p (possible_target))
+    possible_target = NULL_RTX;
+  return get_reg_target ();
+}
+
+/* Add an output operand to the instruction we're building, which has
+   code ICODE.  Bind the output to the preferred target rtx if possible.  */
+void
+function_expander::add_output_operand (insn_code icode)
+{
+  unsigned int opno = m_ops.length ();
+  machine_mode mode = insn_data[icode].operand[opno].mode;
+  m_ops.safe_grow (opno + 1);
+  create_output_operand (&m_ops.last (), possible_target, mode);
+}
+
+/* Add an input operand to the instruction we're building, which has
+   code ICODE.  Calculate the value of the operand as follows:
+
+   - If the operand is a vector and X is not, broadcast X to fill a
+     vector of the appropriate mode.
+
+   - Otherwise, if the operand is a predicate, coerce X to have the
+     mode that the instruction expects.  In this case X is known to be
+     VNx16BImode (the mode of svbool_t).
+
+   - Otherwise use X directly.  The expand machinery checks that X has
+     the right mode for the instruction.  */
+void
+function_expander::add_input_operand (insn_code icode, rtx x)
+{
+  unsigned int opno = m_ops.length ();
+  const insn_operand_data &operand = insn_data[icode].operand[opno];
+  machine_mode mode = operand.mode;
+  if (mode == VOIDmode)
+    {
+      /* The only allowable use of VOIDmode is the wildcard
+        aarch64_any_register_operand, which is used to avoid
+        combinatorial explosion in the reinterpret patterns.  */
+      gcc_assert (operand.predicate == aarch64_any_register_operand);
+      mode = GET_MODE (x);
+    }
+  else if (!VECTOR_MODE_P (GET_MODE (x)) && VECTOR_MODE_P (mode))
+    x = expand_vector_broadcast (mode, x);
+  else if (GET_MODE_CLASS (mode) == MODE_VECTOR_BOOL)
+    {
+      gcc_assert (GET_MODE (x) == VNx16BImode);
+      x = gen_lowpart (mode, x);
+    }
+  m_ops.safe_grow (m_ops.length () + 1);
+  create_input_operand (&m_ops.last (), x, mode);
+}
+
+/* Add an integer operand with value X to the instruction.  */
+void
+function_expander::add_integer_operand (HOST_WIDE_INT x)
+{
+  m_ops.safe_grow (m_ops.length () + 1);
+  create_integer_operand (&m_ops.last (), x);
+}
+
+/* Add a memory operand with mode MODE and address ADDR.  */
+void
+function_expander::add_mem_operand (machine_mode mode, rtx addr)
+{
+  gcc_assert (VECTOR_MODE_P (mode));
+  rtx mem = gen_rtx_MEM (mode, memory_address (mode, addr));
+  /* The memory is only guaranteed to be element-aligned.  */
+  set_mem_align (mem, GET_MODE_ALIGNMENT (GET_MODE_INNER (mode)));
+  add_fixed_operand (mem);
+}
+
+/* Add an address operand with value X.  The static operand data says
+   what mode and form the address must have.  */
+void
+function_expander::add_address_operand (rtx x)
+{
+  m_ops.safe_grow (m_ops.length () + 1);
+  create_address_operand (&m_ops.last (), x);
+}
+
+/* Add an operand that must be X.  The only way of legitimizing an
+   invalid X is to reload the address of a MEM.  */
+void
+function_expander::add_fixed_operand (rtx x)
+{
+  m_ops.safe_grow (m_ops.length () + 1);
+  create_fixed_operand (&m_ops.last (), x);
+}
+
+/* Generate instruction ICODE, given that its operands have already
+   been added to M_OPS.  Return the value of the first operand.  */
+rtx
+function_expander::generate_insn (insn_code icode)
+{
+  expand_insn (icode, m_ops.length (), m_ops.address ());
+  return function_returns_void_p () ? const0_rtx : m_ops[0].value;
+}
+
+/* Convert the arguments to a gather/scatter function into the
+   associated md operands.  Argument ARGNO is the scalar or vector base and
+   argument ARGNO + 1 is the scalar or vector displacement (if applicable).
+   The md pattern expects:
+
+   - a scalar base
+   - a vector displacement
+   - a const_int that is 1 if the displacement is zero-extended from 32 bits
+   - a scaling multiplier (1 for bytes, 2 for .h indices, etc.).  */
+void
+function_expander::prepare_gather_address_operands (unsigned int argno)
+{
+  machine_mode mem_mode = memory_vector_mode ();
+  tree vector_type = base_vector_type ();
+  units_index units = displacement_units ();
+  if (units == UNITS_none)
+    {
+      /* Vector base, no displacement.  Convert to an integer zero base
+        and a vector byte offset.  */
+      args.quick_insert (argno, const0_rtx);
+      units = UNITS_bytes;
+    }
+  else if (vector_type)
+    {
+      /* Vector base, scalar displacement.  Convert to a scalar base and
+        a vector byte offset.  */
+      std::swap (args[argno], args[argno + 1]);
+      if (units == UNITS_elements)
+       {
+         /* Convert the original scalar array index to a byte offset.  */
+         rtx size = gen_int_mode (GET_MODE_UNIT_SIZE (mem_mode), DImode);
+         args[argno] = simplify_gen_binary (MULT, DImode, args[argno], size);
+         units = UNITS_bytes;
+       }
+    }
+  else
+    {
+      /* Scalar base, vector displacement.  This is what the md pattern wants,
+        so we just need to make sure that the scalar base has DImode.  */
+      if (Pmode == SImode)
+       args[argno] = simplify_gen_unary (ZERO_EXTEND, DImode,
+                                         args[argno], SImode);
+      vector_type = displacement_vector_type ();
+    }
+  tree scalar_displacement_type = TREE_TYPE (vector_type);
+
+  bool uxtw_p = (TYPE_PRECISION (scalar_displacement_type) < 64
+                && TYPE_UNSIGNED (scalar_displacement_type));
+  unsigned int scale = (units == UNITS_bytes
+                       ? 1 : GET_MODE_UNIT_SIZE (mem_mode));
+
+  args.quick_insert (argno + 2, GEN_INT (uxtw_p));
+  args.quick_insert (argno + 3, GEN_INT (scale));
+}
+
+/* The final argument is an immediate svprfop value.  Add two fake arguments
+   to represent the rw and locality operands of a PREFETCH rtx.  */
+void
+function_expander::prepare_prefetch_operands ()
+{
+  unsigned int prfop = INTVAL (args.last ());
+  /* Bit 3 of the prfop selects stores over loads.  */
+  args.quick_push (GEN_INT ((prfop & 8) != 0));
+  /* Bits 1 and 2 specify the locality; 0-based for svprfop but
+     1-based for PREFETCH.  */
+  args.quick_push (GEN_INT (((prfop >> 1) & 3) + 1));
+}
+
+/* Add a dummy argument to indicate whether predicate argument ARGNO
+   is all-true when interpreted in mode PRED_MODE.  The hint goes
+   immediately after ARGNO.  */
+void
+function_expander::add_ptrue_hint (unsigned int argno, machine_mode pred_mode)
+{
+  rtx pred = gen_lowpart (pred_mode, args[argno]);
+  int hint = (pred == CONSTM1_RTX (pred_mode)
+             ? SVE_KNOWN_PTRUE : SVE_MAYBE_NOT_PTRUE);
+  args.quick_insert (argno + 1, gen_int_mode (hint, SImode));
+}
+
+/* Rotate inputs args[START:END] one position to the left, so that
+   args[START] becomes args[END - 1].  */
+void
+function_expander::rotate_inputs_left (unsigned int start, unsigned int end)
+{
+  rtx new_last = args[start];
+  for (unsigned int i = start; i < end - 1; ++i)
+    args[i] = args[i + 1];
+  args[end - 1] = new_last;
+}
+
+/* Return true if the negation of argument ARGNO can be folded away,
+   replacing it with the negated value if so.  MODE is the associated
+   vector mode, but the argument could be a single element.  The main
+   case this handles is constant arguments.  */
+bool
+function_expander::try_negating_argument (unsigned int argno,
+                                         machine_mode mode)
+{
+  rtx x = args[argno];
+  if (!VECTOR_MODE_P (GET_MODE (x)))
+    mode = GET_MODE_INNER (mode);
+
+  x = simplify_unary_operation (NEG, mode, x, mode);
+  if (!x)
+    return false;
+
+  args[argno] = x;
+  return true;
+}
+
+/* Implement the call using instruction ICODE, with a 1:1 mapping between
+   arguments and input operands.  */
+rtx
+function_expander::use_exact_insn (insn_code icode)
+{
+  unsigned int nops = insn_data[icode].n_operands;
+  if (!function_returns_void_p ())
+    {
+      add_output_operand (icode);
+      nops -= 1;
+    }
+  for (unsigned int i = 0; i < nops; ++i)
+    add_input_operand (icode, args[i]);
+  return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which does not use a
+   governing predicate.  We must therefore drop the GP from an _x call.  */
+rtx
+function_expander::use_unpred_insn (insn_code icode)
+{
+  /* We can't drop the predicate for _z and _m.  */
+  gcc_assert (pred == PRED_x || pred == PRED_none);
+  /* Discount the output operand.  */
+  unsigned int nops = insn_data[icode].n_operands - 1;
+  /* Drop the predicate argument in the case of _x predication.  */
+  unsigned int bias = (pred == PRED_x ? 1 : 0);
+  unsigned int i = 0;
+
+  add_output_operand (icode);
+  for (; i < nops; ++i)
+    add_input_operand (icode, args[i + bias]);
+
+  return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which is a predicated
+   operation that returns arbitrary values for inactive lanes.  */
+rtx
+function_expander::use_pred_x_insn (insn_code icode)
+{
+  /* At present we never need to handle PRED_none, which would involve
+     creating a new predicate rather than using one supplied by the user.  */
+  gcc_assert (pred == PRED_x);
+  /* Discount the output operand.  */
+  unsigned int nops = args.length () - 1;
+
+  bool has_float_operand_p = FLOAT_MODE_P (insn_data[icode].operand[0].mode);
+
+  /* Add the normal operands.  */
+  add_output_operand (icode);
+  add_input_operand (icode, args[0]);
+  for (unsigned int i = 0; i < nops; ++i)
+    {
+      add_input_operand (icode, args[i + 1]);
+      if (FLOAT_MODE_P (GET_MODE (args[i + 1])))
+       has_float_operand_p = true;
+    }
+
+  if (has_float_operand_p)
+    {
+      /* Add a flag that indicates whether unpredicated instructions
+        are allowed.  */
+      rtx pred = m_ops[1].value;
+      if (flag_trapping_math && pred != CONST1_RTX (GET_MODE (pred)))
+       add_integer_operand (SVE_STRICT_GP);
+      else
+       add_integer_operand (SVE_RELAXED_GP);
+    }
+
+  return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which does the equivalent of:
+
+     OUTPUT = COND ? FN (INPUTS) : FALLBACK;
+
+   The instruction operands are in the order above: OUTPUT, COND, INPUTS
+   and FALLBACK.  MERGE_ARGNO is the argument that provides FALLBACK for _m
+   functions, or DEFAULT_MERGE_ARGNO if we should apply the usual rules.  */
+rtx
+function_expander::use_cond_insn (insn_code icode, unsigned int merge_argno)
+{
+  /* At present we never need to handle PRED_none, which would involve
+     creating a new predicate rather than using one supplied by the user.  */
+  gcc_assert (pred != PRED_none);
+  /* Discount the output, predicate and fallback value.  */
+  unsigned int nops = insn_data[icode].n_operands - 3;
+  machine_mode mode = insn_data[icode].operand[0].mode;
+
+  unsigned int opno = 0;
+  rtx fallback_arg = get_fallback_value (mode, nops, merge_argno, opno);
+  rtx pred = args[opno++];
+
+  add_output_operand (icode);
+  add_input_operand (icode, pred);
+  for (unsigned int i = 0; i < nops; ++i)
+    add_input_operand (icode, args[opno + i]);
+  add_input_operand (icode, fallback_arg);
+  return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which is a select-like
+   operation with the following operands:
+
+   0: output
+   1: true value
+   2: false value
+   3: predicate
+
+   MERGE_ARGNO is the argument that provides the "false" value for _m
+   functions, or DEFAULT_MERGE_ARGNO if we should apply the usual rules.  */
+rtx
+function_expander::use_vcond_mask_insn (insn_code icode,
+                                       unsigned int merge_argno)
+{
+  machine_mode mode = vector_mode (0);
+
+  unsigned int opno = 0;
+  rtx false_arg = get_fallback_value (mode, 1, merge_argno, opno);
+  rtx pred_arg = args[opno++];
+  rtx true_arg = args[opno++];
+
+  add_output_operand (icode);
+  add_input_operand (icode, true_arg);
+  add_input_operand (icode, false_arg);
+  add_input_operand (icode, pred_arg);
+  return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which loads memory operand 1
+   into register operand 0 under the control of predicate operand 2.  */
+rtx
+function_expander::use_contiguous_load_insn (insn_code icode)
+{
+  machine_mode mem_mode = memory_vector_mode ();
+
+  add_output_operand (icode);
+  add_mem_operand (mem_mode, get_contiguous_base (mem_mode));
+  add_input_operand (icode, args[0]);
+  return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which prefetches from
+   address operand 1 under the control of predicate operand 0.
+   Operands 2, 3 and 4 respectively specify the svprfop value,
+   the PREFETCH rw flag and the PREFETCH locality.  */
+rtx
+function_expander::use_contiguous_prefetch_insn (insn_code icode)
+{
+  add_input_operand (icode, args[0]);
+  add_address_operand (get_contiguous_base (VNx16QImode));
+  for (unsigned int i = args.length () - 3; i < args.length (); ++i)
+    add_input_operand (icode, args[i]);
+  return generate_insn (icode);
+}
+
+/* Implement the call using instruction ICODE, which stores register operand 1
+   into memory operand 0 under the control of predicate operand 2.  */
+rtx
+function_expander::use_contiguous_store_insn (insn_code icode)
+{
+  machine_mode mem_mode = memory_vector_mode ();
+
+  add_mem_operand (mem_mode, get_contiguous_base (mem_mode));
+  add_input_operand (icode, args.last ());
+  add_input_operand (icode, args[0]);
+  return generate_insn (icode);
+}
+
+/* Implement the call using one of the following strategies, chosen in order:
+
+   (1) "aarch64_pred_<optab><mode>_z" for PRED_z predicate functions
+
+   (2) "aarch64_pred_<optab><mode>" for PRED_x functions
+
+   (3) a normal unpredicated optab for PRED_none and PRED_x functions,
+       dropping the predicate in the latter case
+
+   (4) "cond_<optab><mode>" otherwise
+
+   where <optab> corresponds to:
+
+   - CODE_FOR_SINT for signed integers
+   - CODE_FOR_UINT for unsigned integers
+   - UNSPEC_FOR_FP for floating-point values
+
+   MERGE_ARGNO is the argument that provides the values of inactive lanes for
+   _m functions, or DEFAULT_MERGE_ARGNO if we should apply the usual rules.  */
+rtx
+function_expander::map_to_rtx_codes (rtx_code code_for_sint,
+                                    rtx_code code_for_uint,
+                                    int unspec_for_fp,
+                                    unsigned int merge_argno)
+{
+  machine_mode mode = vector_mode (0);
+  rtx_code code = (type_suffix (0).unsigned_p ? code_for_uint : code_for_sint);
+  insn_code icode;
+
+  /* Handle predicate logic operations, which always use _z predication.  */
+  if (type_suffix (0).tclass == TYPE_bool)
+    {
+      gcc_assert (pred == PRED_z && code_for_uint == code_for_sint);
+      return use_exact_insn (code_for_aarch64_pred_z (code, mode));
+    }
+
+  /* First try using UNSPEC_PRED_X patterns for _x predication,
+     if available.  */
+  if (pred == PRED_x)
+    {
+      if (type_suffix (0).integer_p)
+       icode = maybe_code_for_aarch64_pred (code, mode);
+      else
+       icode = maybe_code_for_aarch64_pred (unspec_for_fp, mode);
+      if (icode != CODE_FOR_nothing)
+       return use_pred_x_insn (icode);
+    }
+
+  /* Otherwise expand PRED_none and PRED_x operations without a predicate.
+     Floating-point operations conventionally use the signed rtx code.  */
+  if (pred == PRED_none || pred == PRED_x)
+    return use_unpred_insn (direct_optab_handler (code_to_optab (code), 0));
+
+  /* Don't use cond_*_optabs here, since not all codes have one yet.  */
+  if (type_suffix (0).integer_p)
+    icode = code_for_cond (code, mode);
+  else
+    icode = code_for_cond (unspec_for_fp, mode);
+  return use_cond_insn (icode, merge_argno);
+}
+
+/* Implement the call using one of the following strategies, chosen in order:
+
+   (1) "aarch64_pred_<optab><mode>" for PRED_x functions; this is a
+       predicated pattern
+
+   (2) "aarch64_sve_<optab><mode>" for PRED_none and PRED_x functions;
+       this is an unpredicated pattern
+
+   (3) "cond_<optab><mode>" otherwise
+
+   where <optab> corresponds to:
+
+   - UNSPEC_FOR_SINT for signed integers
+   - UNSPEC_FOR_UINT for unsigned integers
+   - UNSPEC_FOR_FP for floating-point values
+
+   MERGE_ARGNO is the argument that provides the values of inactive lanes for
+   _m functions, or DEFAULT_MERGE_ARGNO if we should apply the usual rules.  */
+rtx
+function_expander::map_to_unspecs (int unspec_for_sint, int unspec_for_uint,
+                                  int unspec_for_fp, unsigned int merge_argno)
+{
+  machine_mode mode = vector_mode (0);
+  int unspec = (!type_suffix (0).integer_p ? unspec_for_fp
+               : type_suffix (0).unsigned_p ? unspec_for_uint
+               : unspec_for_sint);
+
+  if (pred == PRED_x)
+    {
+      insn_code icode = maybe_code_for_aarch64_pred (unspec, mode);
+      if (icode != CODE_FOR_nothing)
+       return use_pred_x_insn (icode);
+    }
+
+  if (pred == PRED_none || pred == PRED_x)
+    return use_unpred_insn (code_for_aarch64_sve (unspec, mode));
+
+  insn_code icode = code_for_cond (unspec, vector_mode (0));
+  return use_cond_insn (icode, merge_argno);
+}
+
+/* Implement the call using an @aarch64 instruction and the
+   instructions are parameterized by an rtx_code.  CODE_FOR_SINT
+   is the rtx_code for signed integer operations, CODE_FOR_UINT
+   is the rtx_code for unsigned integer operations.  */
+rtx
+function_expander::expand_signed_unpred_op (rtx_code code_for_sint,
+                                           rtx_code code_for_uint)
+{
+  insn_code icode;
+  if (type_suffix (0).unsigned_p)
+    icode = code_for_aarch64 (code_for_uint, code_for_uint, vector_mode (0));
+  else
+    icode = code_for_aarch64 (code_for_sint, code_for_sint, vector_mode (0));
+  return use_unpred_insn (icode);
+}
+
+/* Expand the call and return its lhs.  */
+rtx
+function_expander::expand ()
+{
+  unsigned int nargs = call_expr_nargs (call_expr);
+  args.reserve (nargs);
+  for (unsigned int i = 0; i < nargs; ++i)
+    args.quick_push (expand_normal (CALL_EXPR_ARG (call_expr, i)));
+
+  return base->expand (*this);
+}
+
+/* Register the built-in SVE ABI types, such as __SVBool_t.  */
+static void
+register_builtin_types ()
+{
+#define DEF_SVE_TYPE(ACLE_NAME, NCHARS, ABI_NAME, SCALAR_TYPE) \
+  scalar_types[VECTOR_TYPE_ ## ACLE_NAME] = SCALAR_TYPE;
+#include "aarch64-sve-builtins.def"
+
+  for (unsigned int i = 0; i < NUM_VECTOR_TYPES; ++i)
+    {
+      tree eltype = scalar_types[i];
+      tree vectype;
+      if (eltype == boolean_type_node)
+       {
+         vectype = build_truth_vector_type (BYTES_PER_SVE_VECTOR,
+                                            BYTES_PER_SVE_VECTOR);
+         gcc_assert (TYPE_MODE (vectype) == VNx16BImode
+                     && TYPE_MODE (vectype) == TYPE_MODE_RAW (vectype)
+                     && TYPE_ALIGN (vectype) == 16
+                     && known_eq (wi::to_poly_offset (TYPE_SIZE (vectype)),
+                                  BYTES_PER_SVE_VECTOR));
+       }
+      else
+       {
+         unsigned int elbytes = tree_to_uhwi (TYPE_SIZE_UNIT (eltype));
+         poly_uint64 nunits = exact_div (BYTES_PER_SVE_VECTOR, elbytes);
+         vectype = build_vector_type (eltype, nunits);
+         gcc_assert (VECTOR_MODE_P (TYPE_MODE (vectype))
+                     && TYPE_MODE (vectype) == TYPE_MODE_RAW (vectype)
+                     && TYPE_ALIGN (vectype) == 128
+                     && known_eq (wi::to_poly_offset (TYPE_SIZE (vectype)),
+                                  BITS_PER_SVE_VECTOR));
+       }
+      vectype = build_distinct_type_copy (vectype);
+      SET_TYPE_STRUCTURAL_EQUALITY (vectype);
+      TYPE_ARTIFICIAL (vectype) = 1;
+      abi_vector_types[i] = vectype;
+      lang_hooks.types.register_builtin_type (vectype,
+                                             vector_types[i].abi_name);
+    }
+}
+
+/* Initialize all compiler built-ins related to SVE that should be
+   defined at start-up.  */
+void
+init_builtins ()
+{
+  sve_switcher sve;
+  register_builtin_types ();
+}
+
+/* Register vector type TYPE under its arm_sve.h name.  */
+static void
+register_vector_type (vector_type_index type)
+{
+  tree vectype = abi_vector_types[type];
+  tree id = get_identifier (vector_types[type].acle_name);
+  tree decl = build_decl (input_location, TYPE_DECL, id, vectype);
+  decl = lang_hooks.decls.pushdecl (decl);
+
+  /* Record the new ACLE type if pushdecl succeeded without error.  Use
+     the ABI type otherwise, so that the type we record at least has the
+     right form, even if it doesn't have the right name.  This should give
+     better error recovery behavior than installing error_mark_node or
+     installing an incorrect type.  */
+  if (TREE_CODE (decl) == TYPE_DECL
+      && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) == vectype)
+    vectype = TREE_TYPE (decl);
+  acle_vector_types[0][type] = vectype;
+}
+
+/* Register the tuple type that contains NUM_VECTORS vectors of type TYPE.  */
+static void
+register_tuple_type (unsigned int num_vectors, vector_type_index type)
+{
+  tree tuple_type = lang_hooks.types.make_type (RECORD_TYPE);
+
+  /* The contents of the type are opaque, so we can define them in any
+     way that maps to the correct ABI type.
+
+     Here we choose to use the same layout as for arm_neon.h, but with
+     "__val" instead of "val":
+
+       struct svfooxN_t { svfoo_t __val[N]; };
+
+     (It wouldn't be possible to write that directly in C or C++ for
+     sizeless types, but that's not a problem for this function.)
+
+     Using arrays simplifies the handling of svget and svset for variable
+     arguments.  */
+  tree vector_type = acle_vector_types[0][type];
+  tree array_type = build_array_type_nelts (vector_type, num_vectors);
+  gcc_assert (VECTOR_MODE_P (TYPE_MODE (array_type))
+             && TYPE_MODE_RAW (array_type) == TYPE_MODE (array_type)
+             && TYPE_ALIGN (array_type) == 128);
+
+  tree field = build_decl (input_location, FIELD_DECL,
+                          get_identifier ("__val"), array_type);
+  DECL_FIELD_CONTEXT (field) = tuple_type;
+  TYPE_FIELDS (tuple_type) = field;
+  layout_type (tuple_type);
+  gcc_assert (VECTOR_MODE_P (TYPE_MODE (tuple_type))
+             && TYPE_MODE_RAW (tuple_type) == TYPE_MODE (tuple_type)
+             && TYPE_ALIGN (tuple_type) == 128);
+
+  /* Work out the structure name.  */
+  char buffer[sizeof ("svfloat64x4_t")];
+  const char *vector_type_name = vector_types[type].acle_name;
+  snprintf (buffer, sizeof (buffer), "%.*sx%d_t",
+           (int) strlen (vector_type_name) - 2, vector_type_name,
+           num_vectors);
+
+  tree decl = build_decl (input_location, TYPE_DECL,
+                         get_identifier (buffer), tuple_type);
+  TYPE_NAME (tuple_type) = decl;
+  TYPE_STUB_DECL (tuple_type) = decl;
+  lang_hooks.decls.pushdecl (decl);
+  /* ??? Undo the effect of set_underlying_type for C.  The C frontend
+     doesn't recognize DECL as a built-in because (as intended) the decl has
+     a real location instead of BUILTINS_LOCATION.  The frontend therefore
+     treats the decl like a normal C "typedef struct foo foo;", expecting
+     the type for tag "struct foo" to have a dummy unnamed TYPE_DECL instead
+     of the named one we attached above.  It then sets DECL_ORIGINAL_TYPE
+     on the supposedly unnamed decl, creating a circularity that upsets
+     dwarf2out.
+
+     We don't want to follow the normal C model and create "struct foo"
+     tags for tuple types since (a) the types are supposed to be opaque
+     and (b) they couldn't be defined as a real struct anyway.  Treating
+     the TYPE_DECLs as "typedef struct foo foo;" without creating
+     "struct foo" would lead to confusing error messages.  */
+  DECL_ORIGINAL_TYPE (decl) = NULL_TREE;
+
+  acle_vector_types[num_vectors - 1][type] = tuple_type;
+}
+
+/* Register the svpattern enum.  */
+static void
+register_svpattern ()
+{
+  auto_vec<string_int_pair, 32> values;
+#define PUSH(UPPER, LOWER, VALUE) \
+    values.quick_push (string_int_pair ("SV_" #UPPER, VALUE));
+  AARCH64_FOR_SVPATTERN (PUSH)
+#undef PUSH
+
+  acle_svpattern = lang_hooks.types.simulate_enum_decl (input_location,
+                                                       "svpattern", values);
+}
+
+/* Register the svprfop enum.  */
+static void
+register_svprfop ()
+{
+  auto_vec<string_int_pair, 16> values;
+#define PUSH(UPPER, LOWER, VALUE) \
+    values.quick_push (string_int_pair ("SV_" #UPPER, VALUE));
+  AARCH64_FOR_SVPRFOP (PUSH)
+#undef PUSH
+
+  acle_svprfop = lang_hooks.types.simulate_enum_decl (input_location,
+                                                     "svprfop", values);
+}
+
+/* Implement #pragma GCC aarch64 "arm_sve.h".  */
+void
+handle_arm_sve_h ()
+{
+  if (function_table)
+    {
+      error ("duplicate definition of %qs", "arm_sve.h");
+      return;
+    }
+
+  sve_switcher sve;
+
+  /* Define the vector and tuple types.  */
+  for (unsigned int type_i = 0; type_i < NUM_VECTOR_TYPES; ++type_i)
+    {
+      vector_type_index type = vector_type_index (type_i);
+      register_vector_type (type);
+      if (type != VECTOR_TYPE_svbool_t)
+       for (unsigned int count = 2; count <= MAX_TUPLE_SIZE; ++count)
+         register_tuple_type (count, type);
+    }
+
+  /* Define the enums.  */
+  register_svpattern ();
+  register_svprfop ();
+
+  /* Define the functions.  */
+  function_table = new hash_table<registered_function_hasher> (1023);
+  function_builder builder;
+  for (unsigned int i = 0; i < ARRAY_SIZE (function_groups); ++i)
+    builder.register_function_group (function_groups[i]);
+}
+
+/* Return the function decl with SVE function subcode CODE, or error_mark_node
+   if no such function exists.  */
+tree
+builtin_decl (unsigned int code, bool)
+{
+  if (code >= vec_safe_length (registered_functions))
+    return error_mark_node;
+  return (*registered_functions)[code]->decl;
+}
+
+/* If we're implementing manual overloading, check whether the SVE
+   function with subcode CODE is overloaded, and if so attempt to
+   determine the corresponding non-overloaded function.  The call
+   occurs at location LOCATION and has the arguments given by ARGLIST.
+
+   If the call is erroneous, report an appropriate error and return
+   error_mark_node.  Otherwise, if the function is overloaded, return
+   the decl of the non-overloaded function.  Return NULL_TREE otherwise,
+   indicating that the call should be processed in the normal way.  */
+tree
+resolve_overloaded_builtin (location_t location, unsigned int code,
+                           vec<tree, va_gc> *arglist)
+{
+  if (code >= vec_safe_length (registered_functions))
+    return NULL_TREE;
+
+  registered_function &rfn = *(*registered_functions)[code];
+  if (rfn.overloaded_p)
+    return function_resolver (location, rfn.instance, rfn.decl,
+                             *arglist).resolve ();
+  return NULL_TREE;
+}
+
+/* Perform any semantic checks needed for a call to the SVE function
+   with subcode CODE, such as testing for integer constant expressions.
+   The call occurs at location LOCATION and has NARGS arguments,
+   given by ARGS.  FNDECL is the original function decl, before
+   overload resolution.
+
+   Return true if the call is valid, otherwise report a suitable error.  */
+bool
+check_builtin_call (location_t location, vec<location_t>, unsigned int code,
+                   tree fndecl, unsigned int nargs, tree *args)
+{
+  const registered_function &rfn = *(*registered_functions)[code];
+  if (!check_required_extensions (location, rfn.decl, rfn.required_extensions))
+    return false;
+  return function_checker (location, rfn.instance, fndecl,
+                          TREE_TYPE (rfn.decl), nargs, args).check ();
+}
+
+/* Attempt to fold STMT, given that it's a call to the SVE function
+   with subcode CODE.  Return the new statement on success and null
+   on failure.  Insert any other new statements at GSI.  */
+gimple *
+gimple_fold_builtin (unsigned int code, gimple_stmt_iterator *gsi, gcall *stmt)
+{
+  registered_function &rfn = *(*registered_functions)[code];
+  return gimple_folder (rfn.instance, rfn.decl, gsi, stmt).fold ();
+}
+
+/* Expand a call to the SVE function with subcode CODE.  EXP is the call
+   expression and TARGET is the preferred location for the result.
+   Return the value of the lhs.  */
+rtx
+expand_builtin (unsigned int code, tree exp, rtx target)
+{
+  registered_function &rfn = *(*registered_functions)[code];
+  if (!check_required_extensions (EXPR_LOCATION (exp), rfn.decl,
+                                 rfn.required_extensions))
+    return target;
+  return function_expander (rfn.instance, rfn.decl, exp, target).expand ();
+}
+
+/* Return true if TYPE is the ABI-defined __SVBool_t type.  */
+bool
+svbool_type_p (const_tree type)
+{
+  tree abi_type = abi_vector_types[VECTOR_TYPE_svbool_t];
+  return (type != error_mark_node
+         && TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (abi_type));
+}
+
+/* If TYPE is a built-in type defined by the SVE ABI, return the mangled name,
+   otherwise return NULL.  */
+const char *
+mangle_builtin_type (const_tree type)
+{
+  if (type == error_mark_node)
+    return NULL;
+
+  vector_type_index vtype = find_vector_type (type);
+  if (vtype != NUM_VECTOR_TYPES)
+    return vector_types[vtype].mangled_name;
+
+  return NULL;
+}
+
+/* If TYPE is one of the ABI-defined SVE vector types, or an ACLE-defined
+   tuple of them, return the number of vectors it contains.  Return 0
+   otherwise.  */
+unsigned int
+nvectors_if_data_type (const_tree type)
+{
+  if (type == error_mark_node)
+    return 0;
+
+  type = TYPE_MAIN_VARIANT (type);
+  if (VECTOR_TYPE_P (type))
+    {
+      vector_type_index type_id = find_vector_type (type);
+      if (type_id != VECTOR_TYPE_svbool_t && type_id != NUM_VECTOR_TYPES)
+       return 1;
+    }
+  else if (TREE_CODE (type) == RECORD_TYPE)
+    {
+      for (unsigned int size_i = 1; size_i < MAX_TUPLE_SIZE; ++size_i)
+       for (unsigned int type_i = 0; type_i < NUM_VECTOR_TYPES; ++type_i)
+         {
+           tree tuple_type = acle_vector_types[size_i][type_i];
+           if (tuple_type && type == TYPE_MAIN_VARIANT (tuple_type))
+             return size_i + 1;
+         }
+    }
+
+  return 0;
+}
+
+/* Return true if TYPE is a built-in type defined by the SVE ABI.  */
+bool
+builtin_type_p (const_tree type)
+{
+  return svbool_type_p (type) || nvectors_if_data_type (type) > 0;
+}
+
+}
+
+using namespace aarch64_sve;
+
+inline void
+gt_ggc_mx (function_instance *)
+{
+}
+
+inline void
+gt_pch_nx (function_instance *)
+{
+}
+
+inline void
+gt_pch_nx (function_instance *, void (*) (void *, void *), void *)
+{
+}
+
+#include "gt-aarch64-sve-builtins.h"
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.def b/gcc/config/aarch64/aarch64-sve-builtins.def
new file mode 100644 (file)
index 0000000..da00019
--- /dev/null
@@ -0,0 +1,98 @@
+/* Builtin lists for AArch64 SVE
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef DEF_SVE_MODE
+#define DEF_SVE_MODE(A, B, C, D)
+#endif
+
+#ifndef DEF_SVE_TYPE
+#define DEF_SVE_TYPE(A, B, C, D)
+#endif
+
+#ifndef DEF_SVE_TYPE_SUFFIX
+#define DEF_SVE_TYPE_SUFFIX(A, B, C, D, E)
+#endif
+
+#ifndef DEF_SVE_FUNCTION
+#define DEF_SVE_FUNCTION(A, B, C, D)
+#endif
+
+DEF_SVE_MODE (n, none, none, none)
+DEF_SVE_MODE (index, none, none, elements)
+DEF_SVE_MODE (offset, none, none, bytes)
+DEF_SVE_MODE (s32index, none, svint32_t, elements)
+DEF_SVE_MODE (s32offset, none, svint32_t, bytes)
+DEF_SVE_MODE (s64index,  none, svint64_t, elements)
+DEF_SVE_MODE (s64offset, none, svint64_t, bytes)
+DEF_SVE_MODE (u32base, svuint32_t, none, none)
+DEF_SVE_MODE (u32base_index, svuint32_t, none, elements)
+DEF_SVE_MODE (u32base_offset, svuint32_t, none, bytes)
+DEF_SVE_MODE (u32base_s32index, svuint32_t, svint32_t, elements)
+DEF_SVE_MODE (u32base_s32offset, svuint32_t, svint32_t, bytes)
+DEF_SVE_MODE (u32base_u32index, svuint32_t, svuint32_t, elements)
+DEF_SVE_MODE (u32base_u32offset, svuint32_t, svuint32_t, bytes)
+DEF_SVE_MODE (u32index, none, svuint32_t, elements)
+DEF_SVE_MODE (u32offset, none, svuint32_t, bytes)
+DEF_SVE_MODE (u64base, svuint64_t, none, none)
+DEF_SVE_MODE (u64base_index, svuint64_t, none, elements)
+DEF_SVE_MODE (u64base_offset, svuint64_t, none, bytes)
+DEF_SVE_MODE (u64base_s64index, svuint64_t, svint64_t, elements)
+DEF_SVE_MODE (u64base_s64offset, svuint64_t, svint64_t, bytes)
+DEF_SVE_MODE (u64base_u64index, svuint64_t, svuint64_t, elements)
+DEF_SVE_MODE (u64base_u64offset, svuint64_t, svuint64_t, bytes)
+DEF_SVE_MODE (u64index, none, svuint64_t, elements)
+DEF_SVE_MODE (u64offset, none, svuint64_t, bytes)
+DEF_SVE_MODE (vnum, none, none, vectors)
+
+DEF_SVE_TYPE (svbool_t, 10, __SVBool_t, boolean_type_node)
+DEF_SVE_TYPE (svfloat16_t, 13, __SVFloat16_t, aarch64_fp16_type_node)
+DEF_SVE_TYPE (svfloat32_t, 13, __SVFloat32_t, float_type_node)
+DEF_SVE_TYPE (svfloat64_t, 13, __SVFloat64_t, double_type_node)
+DEF_SVE_TYPE (svint8_t, 10, __SVInt8_t, intQI_type_node)
+DEF_SVE_TYPE (svint16_t, 11, __SVInt16_t, intHI_type_node)
+DEF_SVE_TYPE (svint32_t, 11, __SVInt32_t, intSI_type_node)
+DEF_SVE_TYPE (svint64_t, 11, __SVInt64_t, intDI_type_node)
+DEF_SVE_TYPE (svuint8_t, 11, __SVUint8_t, unsigned_intQI_type_node)
+DEF_SVE_TYPE (svuint16_t, 12, __SVUint16_t, unsigned_intHI_type_node)
+DEF_SVE_TYPE (svuint32_t, 12, __SVUint32_t, unsigned_intSI_type_node)
+DEF_SVE_TYPE (svuint64_t, 12, __SVUint64_t, unsigned_intDI_type_node)
+
+DEF_SVE_TYPE_SUFFIX (b, svbool_t, bool, 8, VNx16BImode)
+DEF_SVE_TYPE_SUFFIX (b8, svbool_t, bool, 8, VNx16BImode)
+DEF_SVE_TYPE_SUFFIX (b16, svbool_t, bool, 16, VNx8BImode)
+DEF_SVE_TYPE_SUFFIX (b32, svbool_t, bool, 32, VNx4BImode)
+DEF_SVE_TYPE_SUFFIX (b64, svbool_t, bool, 64, VNx2BImode)
+DEF_SVE_TYPE_SUFFIX (f16, svfloat16_t, float, 16, VNx8HFmode)
+DEF_SVE_TYPE_SUFFIX (f32, svfloat32_t, float, 32, VNx4SFmode)
+DEF_SVE_TYPE_SUFFIX (f64, svfloat64_t, float, 64, VNx2DFmode)
+DEF_SVE_TYPE_SUFFIX (s8, svint8_t, signed, 8, VNx16QImode)
+DEF_SVE_TYPE_SUFFIX (s16, svint16_t, signed, 16, VNx8HImode)
+DEF_SVE_TYPE_SUFFIX (s32, svint32_t, signed, 32, VNx4SImode)
+DEF_SVE_TYPE_SUFFIX (s64, svint64_t, signed, 64, VNx2DImode)
+DEF_SVE_TYPE_SUFFIX (u8, svuint8_t, unsigned, 8, VNx16QImode)
+DEF_SVE_TYPE_SUFFIX (u16, svuint16_t, unsigned, 16, VNx8HImode)
+DEF_SVE_TYPE_SUFFIX (u32, svuint32_t, unsigned, 32, VNx4SImode)
+DEF_SVE_TYPE_SUFFIX (u64, svuint64_t, unsigned, 64, VNx2DImode)
+
+#include "aarch64-sve-builtins-base.def"
+
+#undef DEF_SVE_FUNCTION
+#undef DEF_SVE_TYPE_SUFFIX
+#undef DEF_SVE_TYPE
+#undef DEF_SVE_MODE
diff --git a/gcc/config/aarch64/aarch64-sve-builtins.h b/gcc/config/aarch64/aarch64-sve-builtins.h
new file mode 100644 (file)
index 0000000..73b07c7
--- /dev/null
@@ -0,0 +1,873 @@
+/* ACLE support for AArch64 SVE
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3, or (at your option)
+   any later version.
+
+   GCC is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GCC; see the file COPYING3.  If not see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef GCC_AARCH64_SVE_BUILTINS_H
+#define GCC_AARCH64_SVE_BUILTINS_H
+
+/* The full name of an SVE ACLE function is the concatenation of:
+
+   - the base name ("svadd", etc.)
+   - the "mode" suffix ("_n", "_index", etc.)
+   - the type suffixes ("_s32", "_b8", etc.)
+   - the predication suffix ("_x", "_z", etc.)
+
+   Each piece of information is individually useful, so we retain this
+   classification throughout:
+
+   - function_base represents the base name
+
+   - mode_suffix_index represents the mode suffix
+
+   - type_suffix_index represents individual type suffixes, while
+     type_suffix_pair represents a pair of them
+
+   - prediction_index extends the predication suffix with an additional
+     alternative: PRED_implicit for implicitly-predicated operations
+
+   In addition to its unique full name, a function may have a shorter
+   overloaded alias.  This alias removes pieces of the suffixes that
+   can be inferred from the arguments, such as by shortening the mode
+   suffix or dropping some of the type suffixes.  The base name and the
+   predication suffix stay the same.
+
+   The function_shape class describes what arguments a given function
+   takes and what its overloaded alias is called.  In broad terms,
+   function_base describes how the underlying instruction behaves while
+   function_shape describes how that instruction has been presented at
+   the language level.
+
+   The static list of functions uses function_group to describe a group
+   of related functions.  The function_builder class is responsible for
+   expanding this static description into a list of individual functions
+   and registering the associated built-in functions.  function_instance
+   describes one of these individual functions in terms of the properties
+   described above.
+
+   The classes involved in compiling a function call are:
+
+   - function_resolver, which resolves an overloaded function call to a
+     specific function_instance and its associated function decl
+
+   - function_checker, which checks whether the values of the arguments
+     conform to the ACLE specification
+
+   - gimple_folder, which tries to fold a function call at the gimple level
+
+   - function_expander, which expands a function call into rtl instructions
+
+   function_resolver and function_checker operate at the language level
+   and so are associated with the function_shape.  gimple_folder and
+   function_expander are concerned with the behavior of the function
+   and so are associated with the function_base.
+
+   Note that we've specifically chosen not to fold calls in the frontend,
+   since SVE intrinsics will hardly ever fold a useful language-level
+   constant.  */
+namespace aarch64_sve
+{
+/* The maximum number of vectors in an ACLE tuple type.  */
+const unsigned int MAX_TUPLE_SIZE = 4;
+
+/* Used to represent the default merge argument index for _m functions.
+   The actual index depends on how many arguments the function takes.  */
+const unsigned int DEFAULT_MERGE_ARGNO = ~0U;
+
+/* Flags that describe what a function might do, in addition to reading
+   its arguments and returning a result.  */
+const unsigned int CP_READ_FPCR = 1U << 0;
+const unsigned int CP_RAISE_FP_EXCEPTIONS = 1U << 1;
+const unsigned int CP_READ_MEMORY = 1U << 2;
+const unsigned int CP_PREFETCH_MEMORY = 1U << 3;
+const unsigned int CP_WRITE_MEMORY = 1U << 4;
+const unsigned int CP_READ_FFR = 1U << 5;
+const unsigned int CP_WRITE_FFR = 1U << 6;
+
+/* Enumerates the SVE predicate and (data) vector types, together called
+   "vector types" for brevity.  */
+enum vector_type_index
+{
+#define DEF_SVE_TYPE(ACLE_NAME, NCHARS, ABI_NAME, SCALAR_TYPE) \
+  VECTOR_TYPE_ ## ACLE_NAME,
+#include "aarch64-sve-builtins.def"
+  NUM_VECTOR_TYPES
+};
+
+/* Classifies the available measurement units for an address displacement.  */
+enum units_index
+{
+  UNITS_none,
+  UNITS_bytes,
+  UNITS_elements,
+  UNITS_vectors
+};
+
+/* Describes the various uses of a governing predicate.  */
+enum predication_index
+{
+  /* No governing predicate is present.  */
+  PRED_none,
+
+  /* A governing predicate is present but there is no predication suffix
+     associated with it.  This is used when the result is neither a vector
+     nor a predicate, since the distinction between "zeroing" and "merging"
+     doesn't apply in that case.  It is also used when a suffix would be
+     redundant (such as for loads and comparisons, which are inherently
+     zeroing operations).  */
+  PRED_implicit,
+
+  /* Merging predication: copy inactive lanes from the first data argument
+     to the vector result.  */
+  PRED_m,
+
+  /* "Don't care" predication: set inactive lanes of the vector result
+     to arbitrary values.  */
+  PRED_x,
+
+  /* Zero predication: set inactive lanes of the vector result to zero.  */
+  PRED_z,
+
+  NUM_PREDS
+};
+
+/* Classifies element types, based on type suffixes with the bit count
+   removed.  */
+enum type_class_index
+{
+  TYPE_bool,
+  TYPE_float,
+  TYPE_signed,
+  TYPE_unsigned,
+  NUM_TYPE_CLASSES
+};
+
+/* Classifies an operation into "modes"; for example, to distinguish
+   vector-scalar operations from vector-vector operations, or to
+   distinguish between different addressing modes.  This classification
+   accounts for the function suffixes that occur between the base name
+   and the first type suffix.  */
+enum mode_suffix_index
+{
+#define DEF_SVE_MODE(NAME, BASE, DISPLACEMENT, UNITS) MODE_##NAME,
+#include "aarch64-sve-builtins.def"
+  MODE_none
+};
+
+/* Enumerates the possible type suffixes.  Each suffix is associated with
+   a vector type, but for predicates provides extra information about the
+   element size.  */
+enum type_suffix_index
+{
+#define DEF_SVE_TYPE_SUFFIX(NAME, ACLE_TYPE, CLASS, BITS, MODE) \
+  TYPE_SUFFIX_ ## NAME,
+#include "aarch64-sve-builtins.def"
+  NUM_TYPE_SUFFIXES
+};
+
+/* Combines two type suffixes.  */
+typedef enum type_suffix_index type_suffix_pair[2];
+
+class function_base;
+class function_shape;
+
+/* Static information about a mode suffix.  */
+struct mode_suffix_info
+{
+  /* The suffix string itself.  */
+  const char *string;
+
+  /* The type of the vector base address, or NUM_VECTOR_TYPES if the
+     mode does not include a vector base address.  */
+  vector_type_index base_vector_type;
+
+  /* The type of the vector displacement, or NUM_VECTOR_TYPES if the
+     mode does not include a vector displacement.  (Note that scalar
+     displacements are always int64_t.)  */
+  vector_type_index displacement_vector_type;
+
+  /* The units in which the vector or scalar displacement is measured,
+     or UNITS_none if the mode doesn't take a displacement.  */
+  units_index displacement_units;
+};
+
+/* Static information about a type suffix.  */
+struct type_suffix_info
+{
+  /* The suffix string itself.  */
+  const char *string;
+
+  /* The associated ACLE vector or predicate type.  */
+  vector_type_index vector_type : 8;
+
+  /* What kind of type the suffix represents.  */
+  type_class_index tclass : 8;
+
+  /* The number of bits and bytes in an element.  For predicates this
+     measures the associated data elements.  */
+  unsigned int element_bits : 8;
+  unsigned int element_bytes : 8;
+
+  /* True if the suffix is for an integer type.  */
+  unsigned int integer_p : 1;
+  /* True if the suffix is for an unsigned type.  */
+  unsigned int unsigned_p : 1;
+  /* True if the suffix is for a floating-point type.  */
+  unsigned int float_p : 1;
+  /* True if the suffix is for a boolean type.  */
+  unsigned int bool_p : 1;
+  unsigned int spare : 12;
+
+  /* The associated vector or predicate mode.  */
+  machine_mode vector_mode : 16;
+};
+
+/* Static information about a set of functions.  */
+struct function_group_info
+{
+  /* The base name, as a string.  */
+  const char *base_name;
+
+  /* Describes the behavior associated with the function base name.  */
+  const function_base *const *base;
+
+  /* The shape of the functions, as described above the class definition.
+     It's possible to have entries with the same base name but different
+     shapes.  */
+  const function_shape *const *shape;
+
+  /* A list of the available type suffixes, and of the available predication
+     types.  The function supports every combination of the two.
+
+     The list of type suffixes is terminated by two NUM_TYPE_SUFFIXES
+     while the list of predication types is terminated by NUM_PREDS.
+     The list of type suffixes is lexicographically ordered based
+     on the index value.  */
+  const type_suffix_pair *types;
+  const predication_index *preds;
+
+  /* The architecture extensions that the functions require, as a set of
+     AARCH64_FL_* flags.  */
+  uint64_t required_extensions;
+};
+
+/* Describes a single fully-resolved function (i.e. one that has a
+   unique full name).  */
+class GTY((user)) function_instance
+{
+public:
+  function_instance (const char *, const function_base *,
+                    const function_shape *, mode_suffix_index,
+                    const type_suffix_pair &, predication_index);
+
+  bool operator== (const function_instance &) const;
+  bool operator!= (const function_instance &) const;
+  hashval_t hash () const;
+
+  unsigned int call_properties () const;
+  bool reads_global_state_p () const;
+  bool modifies_global_state_p () const;
+  bool could_trap_p () const;
+
+  unsigned int vectors_per_tuple () const;
+  tree memory_scalar_type () const;
+  machine_mode memory_vector_mode () const;
+
+  const mode_suffix_info &mode_suffix () const;
+  tree base_vector_type () const;
+  tree displacement_vector_type () const;
+  units_index displacement_units () const;
+
+  const type_suffix_info &type_suffix (unsigned int) const;
+  tree scalar_type (unsigned int) const;
+  tree vector_type (unsigned int) const;
+  tree tuple_type (unsigned int) const;
+  unsigned int elements_per_vq (unsigned int i) const;
+  machine_mode vector_mode (unsigned int) const;
+  machine_mode gp_mode (unsigned int) const;
+
+  /* The properties of the function.  (The explicit "enum"s are required
+     for gengtype.)  */
+  const char *base_name;
+  const function_base *base;
+  const function_shape *shape;
+  enum mode_suffix_index mode_suffix_id;
+  type_suffix_pair type_suffix_ids;
+  enum predication_index pred;
+};
+
+class registered_function;
+
+/* A class for building and registering function decls.  */
+class function_builder
+{
+public:
+  function_builder ();
+  ~function_builder ();
+
+  void add_unique_function (const function_instance &, tree,
+                           vec<tree> &, uint64_t, bool);
+  void add_overloaded_function (const function_instance &, uint64_t);
+  void add_overloaded_functions (const function_group_info &,
+                                mode_suffix_index);
+
+  void register_function_group (const function_group_info &);
+
+private:
+  void append_name (const char *);
+  char *finish_name ();
+
+  char *get_name (const function_instance &, bool);
+
+  tree get_attributes (const function_instance &);
+
+  registered_function &add_function (const function_instance &,
+                                    const char *, tree, tree, uint64_t, bool);
+
+  /* The function type to use for functions that are resolved by
+     function_resolver.  */
+  tree m_overload_type;
+
+  /* True if we should create a separate decl for each instance of an
+     overloaded function, instead of using function_resolver.  */
+  bool m_direct_overloads;
+
+  /* Used for building up function names.  */
+  obstack m_string_obstack;
+
+  /* Maps all overloaded function names that we've registered so far
+     to their associated function_instances.  */
+  hash_map<nofree_string_hash, registered_function *> m_overload_names;
+};
+
+/* A base class for handling calls to built-in functions.  */
+class function_call_info : public function_instance
+{
+public:
+  function_call_info (location_t, const function_instance &, tree);
+
+  bool function_returns_void_p ();
+
+  /* The location of the call.  */
+  location_t location;
+
+  /* The FUNCTION_DECL that is being called.  */
+  tree fndecl;
+};
+
+/* A class for resolving an overloaded function call.  */
+class function_resolver : public function_call_info
+{
+public:
+  enum { SAME_SIZE = 256, HALF_SIZE, QUARTER_SIZE };
+  static const type_class_index SAME_TYPE_CLASS = NUM_TYPE_CLASSES;
+
+  function_resolver (location_t, const function_instance &, tree,
+                    vec<tree, va_gc> &);
+
+  tree get_vector_type (type_suffix_index);
+  const char *get_scalar_type_name (type_suffix_index);
+  tree get_argument_type (unsigned int);
+  bool scalar_argument_p (unsigned int);
+
+  tree report_no_such_form (type_suffix_index);
+  tree lookup_form (mode_suffix_index,
+                   type_suffix_index = NUM_TYPE_SUFFIXES,
+                   type_suffix_index = NUM_TYPE_SUFFIXES);
+  tree resolve_to (mode_suffix_index,
+                  type_suffix_index = NUM_TYPE_SUFFIXES,
+                  type_suffix_index = NUM_TYPE_SUFFIXES);
+
+  type_suffix_index infer_integer_scalar_type (unsigned int);
+  type_suffix_index infer_pointer_type (unsigned int, bool = false);
+  type_suffix_index infer_vector_or_tuple_type (unsigned int, unsigned int);
+  type_suffix_index infer_vector_type (unsigned int);
+  type_suffix_index infer_integer_vector_type (unsigned int);
+  type_suffix_index infer_unsigned_vector_type (unsigned int);
+  type_suffix_index infer_sd_vector_type (unsigned int);
+  type_suffix_index infer_tuple_type (unsigned int);
+
+  bool require_vector_or_scalar_type (unsigned int);
+
+  bool require_vector_type (unsigned int, vector_type_index);
+  bool require_matching_vector_type (unsigned int, type_suffix_index);
+  bool require_derived_vector_type (unsigned int, unsigned int,
+                                   type_suffix_index,
+                                   type_class_index = SAME_TYPE_CLASS,
+                                   unsigned int = SAME_SIZE);
+
+  bool require_scalar_type (unsigned int, const char *);
+  bool require_pointer_type (unsigned int);
+  bool require_matching_integer_scalar_type (unsigned int, unsigned int,
+                                            type_suffix_index);
+  bool require_derived_scalar_type (unsigned int, type_class_index,
+                                   unsigned int = SAME_SIZE);
+  bool require_integer_immediate (unsigned int);
+
+  vector_type_index infer_vector_base_type (unsigned int);
+  vector_type_index infer_vector_displacement_type (unsigned int);
+
+  mode_suffix_index resolve_sv_displacement (unsigned int,
+                                            type_suffix_index, bool);
+  mode_suffix_index resolve_gather_address (unsigned int,
+                                           type_suffix_index, bool);
+  mode_suffix_index resolve_adr_address (unsigned int);
+
+  bool check_num_arguments (unsigned int);
+  bool check_gp_argument (unsigned int, unsigned int &, unsigned int &);
+  tree resolve_unary (type_class_index = SAME_TYPE_CLASS,
+                     unsigned int = SAME_SIZE);
+  tree resolve_uniform (unsigned int, unsigned int = 0);
+  tree resolve_uniform_opt_n (unsigned int);
+  tree finish_opt_n_resolution (unsigned int, unsigned int, type_suffix_index,
+                               type_class_index = SAME_TYPE_CLASS,
+                               unsigned int = SAME_SIZE);
+
+  tree resolve ();
+
+private:
+  /* The arguments to the overloaded function.  */
+  vec<tree, va_gc> &m_arglist;
+};
+
+/* A class for checking that the semantic constraints on a function call are
+   satisfied, such as arguments being integer constant expressions with
+   a particular range.  The parent class's FNDECL is the decl that was
+   called in the original source, before overload resolution.  */
+class function_checker : public function_call_info
+{
+public:
+  function_checker (location_t, const function_instance &, tree,
+                   tree, unsigned int, tree *);
+
+  bool require_immediate_either_or (unsigned int, HOST_WIDE_INT,
+                                   HOST_WIDE_INT);
+  bool require_immediate_enum (unsigned int, tree);
+  bool require_immediate_lane_index (unsigned int, unsigned int = 1);
+  bool require_immediate_one_of (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT,
+                                HOST_WIDE_INT, HOST_WIDE_INT);
+  bool require_immediate_range (unsigned int, HOST_WIDE_INT, HOST_WIDE_INT);
+
+  bool check ();
+
+private:
+  bool argument_exists_p (unsigned int);
+
+  bool require_immediate (unsigned int, HOST_WIDE_INT &);
+
+  /* The type of the resolved function.  */
+  tree m_fntype;
+
+  /* The arguments to the function.  */
+  unsigned int m_nargs;
+  tree *m_args;
+
+  /* The first argument not associated with the function's predication
+     type.  */
+  unsigned int m_base_arg;
+};
+
+/* A class for folding a gimple function call.  */
+class gimple_folder : public function_call_info
+{
+public:
+  gimple_folder (const function_instance &, tree,
+                gimple_stmt_iterator *, gcall *);
+
+  tree convert_pred (gimple_seq &, tree, unsigned int);
+  tree fold_contiguous_base (gimple_seq &, tree);
+  tree load_store_cookie (tree);
+
+  gimple *fold_to_pfalse ();
+  gimple *fold_to_ptrue ();
+  gimple *fold_to_vl_pred (unsigned int);
+
+  gimple *fold ();
+
+  /* Where to insert extra statements that feed the final replacement.  */
+  gimple_stmt_iterator *gsi;
+
+  /* The call we're folding.  */
+  gcall *call;
+
+  /* The result of the call, or null if none.  */
+  tree lhs;
+};
+
+/* A class for expanding a function call into RTL.  */
+class function_expander : public function_call_info
+{
+public:
+  function_expander (const function_instance &, tree, tree, rtx);
+  rtx expand ();
+
+  insn_code direct_optab_handler (optab, unsigned int = 0);
+  insn_code direct_optab_handler_for_sign (optab, optab, unsigned int = 0,
+                                          machine_mode = E_VOIDmode);
+
+  bool overlaps_input_p (rtx);
+
+  rtx get_contiguous_base (machine_mode);
+  rtx get_fallback_value (machine_mode, unsigned int,
+                         unsigned int, unsigned int &);
+  rtx get_reg_target ();
+  rtx get_nonoverlapping_reg_target ();
+
+  void add_output_operand (insn_code);
+  void add_input_operand (insn_code, rtx);
+  void add_integer_operand (HOST_WIDE_INT);
+  void add_mem_operand (machine_mode, rtx);
+  void add_address_operand (rtx);
+  void add_fixed_operand (rtx);
+  rtx generate_insn (insn_code);
+
+  void prepare_gather_address_operands (unsigned int);
+  void prepare_prefetch_operands ();
+  void add_ptrue_hint (unsigned int, machine_mode);
+  void rotate_inputs_left (unsigned int, unsigned int);
+  bool try_negating_argument (unsigned int, machine_mode);
+
+  rtx use_exact_insn (insn_code);
+  rtx use_unpred_insn (insn_code);
+  rtx use_pred_x_insn (insn_code);
+  rtx use_cond_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
+  rtx use_vcond_mask_insn (insn_code, unsigned int = DEFAULT_MERGE_ARGNO);
+  rtx use_contiguous_load_insn (insn_code);
+  rtx use_contiguous_prefetch_insn (insn_code);
+  rtx use_contiguous_store_insn (insn_code);
+
+  rtx map_to_rtx_codes (rtx_code, rtx_code, int,
+                       unsigned int = DEFAULT_MERGE_ARGNO);
+  rtx map_to_unspecs (int, int, int, unsigned int = DEFAULT_MERGE_ARGNO);
+  rtx expand_signed_unpred_op (rtx_code, rtx_code);
+
+  /* The function call expression.  */
+  tree call_expr;
+
+  /* For functions that return a value, this is the preferred location
+     of that value.  It could be null or could have a different mode
+     from the function return type.  */
+  rtx possible_target;
+
+  /* The expanded arguments.  */
+  auto_vec<rtx, 16> args;
+
+private:
+  /* Used to build up the operands to an instruction.  */
+  auto_vec<expand_operand, 8> m_ops;
+};
+
+/* Provides information about a particular function base name, and handles
+   tasks related to the base name.  */
+class function_base
+{
+public:
+  /* Return a set of CP_* flags that describe what the function might do,
+     in addition to reading its arguments and returning a result.  */
+  virtual unsigned int call_properties (const function_instance &) const;
+
+  /* If the function operates on tuples of vectors, return the number
+     of vectors in the tuples, otherwise return 1.  */
+  virtual unsigned int vectors_per_tuple () const { return 1; }
+
+  /* If the function addresses memory, return the type of a single
+     scalar memory element.  */
+  virtual tree
+  memory_scalar_type (const function_instance &) const
+  {
+    gcc_unreachable ();
+  }
+
+  /* If the function addresses memory, return a vector mode whose
+     GET_MODE_NUNITS is the number of elements addressed and whose
+     GET_MODE_INNER is the mode of a single scalar memory element.  */
+  virtual machine_mode
+  memory_vector_mode (const function_instance &) const
+  {
+    gcc_unreachable ();
+  }
+
+  /* Try to fold the given gimple call.  Return the new gimple statement
+     on success, otherwise return null.  */
+  virtual gimple *fold (gimple_folder &) const { return NULL; }
+
+  /* Expand the given call into rtl.  Return the result of the function,
+     or an arbitrary value if the function doesn't return a result.  */
+  virtual rtx expand (function_expander &) const = 0;
+};
+
+/* Classifies functions into "shapes".  The idea is to take all the
+   type signatures for a set of functions, remove the governing predicate
+   (if any), and classify what's left based on:
+
+   - the number of arguments
+
+   - the process of determining the types in the signature from the mode
+     and type suffixes in the function name (including types that are not
+     affected by the suffixes)
+
+   - which arguments must be integer constant expressions, and what range
+     those arguments have
+
+   - the process for mapping overloaded names to "full" names.  */
+class function_shape
+{
+public:
+  virtual bool explicit_type_suffix_p (unsigned int) const = 0;
+
+  /* Define all functions associated with the given group.  */
+  virtual void build (function_builder &,
+                     const function_group_info &) const = 0;
+
+  /* Try to resolve the overloaded call.  Return the non-overloaded
+     function decl on success and error_mark_node on failure.  */
+  virtual tree resolve (function_resolver &) const = 0;
+
+  /* Check whether the given call is semantically valid.  Return true
+     if it is, otherwise report an error and return false.  */
+  virtual bool check (function_checker &) const { return true; }
+};
+
+/* RAII class for enabling enough SVE features to define the built-in
+   types and implement the arm_sve.h pragma.  */
+class sve_switcher
+{
+public:
+  sve_switcher ();
+  ~sve_switcher ();
+
+private:
+  unsigned long m_old_isa_flags;
+  bool m_old_have_regs_of_mode[MAX_MACHINE_MODE];
+};
+
+extern const type_suffix_info type_suffixes[NUM_TYPE_SUFFIXES + 1];
+extern const mode_suffix_info mode_suffixes[MODE_none + 1];
+
+extern tree scalar_types[NUM_VECTOR_TYPES];
+extern tree acle_vector_types[MAX_TUPLE_SIZE][NUM_VECTOR_TYPES + 1];
+extern tree acle_svpattern;
+extern tree acle_svprfop;
+
+/* Return the ACLE type svbool_t.  */
+inline tree
+get_svbool_t (void)
+{
+  return acle_vector_types[0][VECTOR_TYPE_svbool_t];
+}
+
+/* Try to find a mode with the given mode_suffix_info fields.  Return the
+   mode on success or MODE_none on failure.  */
+inline mode_suffix_index
+find_mode_suffix (vector_type_index base_vector_type,
+                 vector_type_index displacement_vector_type,
+                 units_index displacement_units)
+{
+  for (unsigned int mode_i = 0; mode_i < ARRAY_SIZE (mode_suffixes); ++mode_i)
+    {
+      const mode_suffix_info &mode = mode_suffixes[mode_i];
+      if (mode.base_vector_type == base_vector_type
+         && mode.displacement_vector_type == displacement_vector_type
+         && mode.displacement_units == displacement_units)
+       return mode_suffix_index (mode_i);
+    }
+  return MODE_none;
+}
+
+/* Return the type suffix associated with ELEMENT_BITS-bit elements of type
+   class TCLASS.  */
+inline type_suffix_index
+find_type_suffix (type_class_index tclass, unsigned int element_bits)
+{
+  for (unsigned int i = 0; i < NUM_TYPE_SUFFIXES; ++i)
+    if (type_suffixes[i].tclass == tclass
+       && type_suffixes[i].element_bits == element_bits)
+      return type_suffix_index (i);
+  gcc_unreachable ();
+}
+
+/* Return the single field in tuple type TYPE.  */
+inline tree
+tuple_type_field (tree type)
+{
+  for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
+    if (TREE_CODE (field) == FIELD_DECL)
+      return field;
+  gcc_unreachable ();
+}
+
+inline function_instance::
+function_instance (const char *base_name_in,
+                  const function_base *base_in,
+                  const function_shape *shape_in,
+                  mode_suffix_index mode_suffix_id_in,
+                  const type_suffix_pair &type_suffix_ids_in,
+                  predication_index pred_in)
+  : base_name (base_name_in), base (base_in), shape (shape_in),
+    mode_suffix_id (mode_suffix_id_in), pred (pred_in)
+{
+  memcpy (type_suffix_ids, type_suffix_ids_in, sizeof (type_suffix_ids));
+}
+
+inline bool
+function_instance::operator== (const function_instance &other) const
+{
+  return (base == other.base
+         && shape == other.shape
+         && mode_suffix_id == other.mode_suffix_id
+         && pred == other.pred
+         && type_suffix_ids[0] == other.type_suffix_ids[0]
+         && type_suffix_ids[1] == other.type_suffix_ids[1]);
+}
+
+inline bool
+function_instance::operator!= (const function_instance &other) const
+{
+  return !operator== (other);
+}
+
+/* If the function operates on tuples of vectors, return the number
+   of vectors in the tuples, otherwise return 1.  */
+inline unsigned int
+function_instance::vectors_per_tuple () const
+{
+  return base->vectors_per_tuple ();
+}
+
+/* If the function addresses memory, return the type of a single
+   scalar memory element.  */
+inline tree
+function_instance::memory_scalar_type () const
+{
+  return base->memory_scalar_type (*this);
+}
+
+/* If the function addresses memory, return a vector mode whose
+   GET_MODE_NUNITS is the number of elements addressed and whose
+   GET_MODE_INNER is the mode of a single scalar memory element.  */
+inline machine_mode
+function_instance::memory_vector_mode () const
+{
+  return base->memory_vector_mode (*this);
+}
+
+/* Return information about the function's mode suffix.  */
+inline const mode_suffix_info &
+function_instance::mode_suffix () const
+{
+  return mode_suffixes[mode_suffix_id];
+}
+
+/* Return the type of the function's vector base address argument,
+   or null it doesn't have a vector base address.  */
+inline tree
+function_instance::base_vector_type () const
+{
+  return acle_vector_types[0][mode_suffix ().base_vector_type];
+}
+
+/* Return the type of the function's vector index or offset argument,
+   or null if doesn't have a vector index or offset argument.  */
+inline tree
+function_instance::displacement_vector_type () const
+{
+  return acle_vector_types[0][mode_suffix ().displacement_vector_type];
+}
+
+/* If the function takes a vector or scalar displacement, return the units
+   in which the displacement is measured, otherwise return UNITS_none.  */
+inline units_index
+function_instance::displacement_units () const
+{
+  return mode_suffix ().displacement_units;
+}
+
+/* Return information about type suffix I.  */
+inline const type_suffix_info &
+function_instance::type_suffix (unsigned int i) const
+{
+  return type_suffixes[type_suffix_ids[i]];
+}
+
+/* Return the scalar type associated with type suffix I.  */
+inline tree
+function_instance::scalar_type (unsigned int i) const
+{
+  return scalar_types[type_suffix (i).vector_type];
+}
+
+/* Return the vector type associated with type suffix I.  */
+inline tree
+function_instance::vector_type (unsigned int i) const
+{
+  return acle_vector_types[0][type_suffix (i).vector_type];
+}
+
+/* If the function operates on tuples of vectors, return the tuple type
+   associated with type suffix I, otherwise return the vector type associated
+   with type suffix I.  */
+inline tree
+function_instance::tuple_type (unsigned int i) const
+{
+  unsigned int num_vectors = vectors_per_tuple ();
+  return acle_vector_types[num_vectors - 1][type_suffix (i).vector_type];
+}
+
+/* Return the number of elements of type suffix I that fit within a
+   128-bit block.  */
+inline unsigned int
+function_instance::elements_per_vq (unsigned int i) const
+{
+  return 128 / type_suffix (i).element_bits;
+}
+
+/* Return the vector or predicate mode associated with type suffix I.  */
+inline machine_mode
+function_instance::vector_mode (unsigned int i) const
+{
+  return type_suffix (i).vector_mode;
+}
+
+/* Return the mode of the governing predicate to use when operating on
+   type suffix I.  */
+inline machine_mode
+function_instance::gp_mode (unsigned int i) const
+{
+  return aarch64_sve_pred_mode (type_suffix (i).element_bytes).require ();
+}
+
+/* Return true if the function has no return value.  */
+inline bool
+function_call_info::function_returns_void_p ()
+{
+  return TREE_TYPE (TREE_TYPE (fndecl)) == void_type_node;
+}
+
+/* Default implementation of function::call_properties, with conservatively
+   correct behavior for floating-point instructions.  */
+inline unsigned int
+function_base::call_properties (const function_instance &instance) const
+{
+  unsigned int flags = 0;
+  if (instance.type_suffix (0).float_p || instance.type_suffix (1).float_p)
+    flags |= CP_READ_FPCR | CP_RAISE_FP_EXCEPTIONS;
+  return flags;
+}
+
+}
+
+#endif
index 2d93d72b0de8a6686103b8ec0ecd5149e0970bbc..57db06a3a770409a152e88801b83babc68395fc9 100644 (file)
 ;; ---- Description of UNSPEC_PRED_Z
 ;; ---- Note on predicated integer arithemtic and UNSPEC_PRED_X
 ;; ---- Note on predicated FP arithmetic patterns and GP "strictness"
+;; ---- Note on FFR handling
 ;;
 ;; == Moves
 ;; ---- Moves of single vectors
 ;; ---- Moves of multiple vectors
 ;; ---- Moves of predicates
+;; ---- Moves relating to the FFR
 ;;
 ;; == Loads
 ;; ---- Normal contiguous loads
+;; ---- Extending contiguous loads
+;; ---- First-faulting contiguous loads
+;; ---- First-faulting extending contiguous loads
+;; ---- Non-temporal contiguous loads
 ;; ---- Normal gather loads
+;; ---- Extending gather loads
+;; ---- First-faulting gather loads
+;; ---- First-faulting extending gather loads
+;;
+;; == Prefetches
+;; ---- Contiguous prefetches
+;; ---- Gather prefetches
 ;;
 ;; == Stores
 ;; ---- Normal contiguous stores
+;; ---- Truncating contiguous stores
+;; ---- Non-temporal contiguous stores
 ;; ---- Normal scatter stores
+;; ---- Truncating scatter stores
 ;;
 ;; == Vector creation
 ;; ---- [INT,FP] Duplicate element
 ;; == Unary arithmetic
 ;; ---- [INT] General unary arithmetic corresponding to rtx codes
 ;; ---- [INT] General unary arithmetic corresponding to unspecs
+;; ---- [INT] Sign extension
 ;; ---- [INT] Zero extension
 ;; ---- [INT] Logical inverse
+;; ---- [FP<-INT] General unary arithmetic that maps to unspecs
 ;; ---- [FP] General unary arithmetic corresponding to unspecs
 ;; ---- [PRED] Inverse
 
 ;; ---- [INT] Subtraction
 ;; ---- [INT] Take address
 ;; ---- [INT] Absolute difference
+;; ---- [INT] Saturating addition and subtraction
 ;; ---- [INT] Highpart multiplication
 ;; ---- [INT] Division
 ;; ---- [INT] Binary logical operations
 ;; ---- [INT] Binary logical operations (inverted second input)
-;; ---- [INT] Shifts
+;; ---- [INT] Shifts (rounding towards -Inf)
 ;; ---- [INT] Shifts (rounding towards 0)
+;; ---- [FP<-INT] General binary arithmetic corresponding to unspecs
 ;; ---- [FP] General binary arithmetic corresponding to rtx codes
 ;; ---- [FP] General binary arithmetic corresponding to unspecs
 ;; ---- [FP] Addition
+;; ---- [FP] Complex addition
 ;; ---- [FP] Subtraction
 ;; ---- [FP] Absolute difference
 ;; ---- [FP] Multiplication
 ;; ---- [INT] Dot product
 ;; ---- [INT] Sum of absolute differences
 ;; ---- [FP] General ternary arithmetic corresponding to unspecs
+;; ---- [FP] Complex multiply-add
+;; ---- [FP] Trigonometric multiply-add
 ;;
 ;; == Comparisons and selects
 ;; ---- [INT,FP] Select based on predicates
 ;; ---- [INT] While tests
 ;; ---- [FP] Direct comparisons
 ;; ---- [FP] Absolute comparisons
+;; ---- [PRED] Select
 ;; ---- [PRED] Test bits
 ;;
 ;; == Reductions
 ;; ---- [FP<-FP] Unpacks
 ;; ---- [PRED<-PRED] Packs
 ;; ---- [PRED<-PRED] Unpacks
+;;
+;; == Vector partitioning
+;; ---- [PRED] Unary partitioning
+;; ---- [PRED] Binary partitioning
+;; ---- [PRED] Scalarization
+;;
+;; == Counting elements
+;; ---- [INT] Count elements in a pattern (scalar)
+;; ---- [INT] Increment by the number of elements in a pattern (scalar)
+;; ---- [INT] Increment by the number of elements in a pattern (vector)
+;; ---- [INT] Decrement by the number of elements in a pattern (scalar)
+;; ---- [INT] Decrement by the number of elements in a pattern (vector)
+;; ---- [INT] Count elements in a predicate (scalar)
+;; ---- [INT] Increment by the number of elements in a predicate (scalar)
+;; ---- [INT] Increment by the number of elements in a predicate (vector)
+;; ---- [INT] Decrement by the number of elements in a predicate (scalar)
+;; ---- [INT] Decrement by the number of elements in a predicate (vector)
 
 ;; =========================================================================
 ;; == General notes
 ;; - OP0 OP1 ... are the normal input operands to the operation.
 ;;
 ;; - MNEMONIC is the mnemonic of the associated SVE instruction.
+;;
+;; -------------------------------------------------------------------------
+;; ---- Note on FFR handling
+;; -------------------------------------------------------------------------
+;;
+;; Logically we want to divide FFR-related instructions into regions
+;; that contain exactly one of:
+;;
+;; - a single write to the FFR
+;; - any number of reads from the FFR (but only one read is likely)
+;; - any number of LDFF1 and LDNF1 instructions
+;;
+;; However, LDFF1 and LDNF1 instructions should otherwise behave like
+;; normal loads as far as possible.  This means that they should be
+;; schedulable within a region in the same way that LD1 would be,
+;; and they should be deleted as dead if the result is unused.  The loads
+;; should therefore not write to the FFR, since that would both serialize
+;; the loads with respect to each other and keep the loads live for any
+;; later RDFFR.
+;;
+;; We get around this by using a fake "FFR token" (FFRT) to help describe
+;; the dependencies.  Writing to the FFRT starts a new "FFRT region",
+;; while using the FFRT keeps the instruction within its region.
+;; Specifically:
+;;
+;; - Writes start a new FFRT region as well as setting the FFR:
+;;
+;;       W1: parallel (FFRT = <new value>, FFR = <actual FFR value>)
+;;
+;; - Loads use an LD1-like instruction that also uses the FFRT, so that the
+;;   loads stay within the same FFRT region:
+;;
+;;       L1: load data while using the FFRT
+;;
+;;   In addition, any FFRT region that includes a load also has at least one
+;;   instance of:
+;;
+;;       L2: FFR = update(FFR, FFRT)  [type == no_insn]
+;;
+;;   to make it clear that the region both reads from and writes to the FFR.
+;;
+;; - Reads do the following:
+;;
+;;       R1: FFRT = FFR               [type == no_insn]
+;;       R2: read from the FFRT
+;;       R3: FFRT = update(FFRT)      [type == no_insn]
+;;
+;;   R1 and R3 both create new FFRT regions, so that previous LDFF1s and
+;;   LDNF1s cannot move forwards across R1 and later LDFF1s and LDNF1s
+;;   cannot move backwards across R3.
+;;
+;; This way, writes are only kept alive by later loads or reads,
+;; and write/read pairs fold normally.  For two consecutive reads,
+;; the first R3 is made dead by the second R1, which in turn becomes
+;; redundant with the first R1.  We then have:
+;;
+;;     first R1: FFRT = FFR
+;;     first read from the FFRT
+;;     second read from the FFRT
+;;     second R3: FFRT = update(FFRT)
+;;
+;; i.e. the two FFRT regions collapse into a single one with two
+;; independent reads.
+;;
+;; The model still prevents some valid optimizations though.  For example,
+;; if all loads in an FFRT region are deleted as dead, nothing would remove
+;; the L2 instructions.
 
 ;; =========================================================================
 ;; == Moves
 ;; special predicate for operand 1 to reduce the number of patterns.
 (define_insn_and_split "*aarch64_sve_reinterpret<mode>"
   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
-       (unspec:SVE_ALL [(match_operand 1 "aarch64_any_register_operand" "0")]
+       (unspec:SVE_ALL [(match_operand 1 "aarch64_any_register_operand" "w")]
                        UNSPEC_REINTERPRET))]
   "TARGET_SVE"
   "#"
   "&& reload_completed"
   [(set (match_dup 0) (match_dup 1))]
   {
-    emit_note (NOTE_INSN_DELETED);
-    DONE;
+    operands[1] = aarch64_replace_reg_mode (operands[1], <MODE>mode);
   }
 )
 
 ;; - LDR
 ;; - PFALSE
 ;; - PTRUE
+;; - PTRUES
 ;; - STR
 ;; -------------------------------------------------------------------------
 
    * return aarch64_output_sve_mov_immediate (operands[1]);"
 )
 
+;; Match PTRUES Pn.B when both the predicate and flags are useful.
+(define_insn_and_rewrite "*aarch64_sve_ptruevnx16bi_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand 2)
+          (match_operand 3)
+          (const_int SVE_KNOWN_PTRUE)
+          (match_operator:VNx16BI 1 "aarch64_sve_ptrue_svpattern_immediate"
+            [(unspec:VNx16BI
+               [(match_operand:SI 4 "const_int_operand")
+                (match_operand:VNx16BI 5 "aarch64_simd_imm_zero")]
+               UNSPEC_PTRUE)])]
+         UNSPEC_PTEST))
+   (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (match_dup 1))]
+  "TARGET_SVE"
+  {
+    return aarch64_output_sve_ptrues (operands[1]);
+  }
+  "&& (!CONSTANT_P (operands[2]) || !CONSTANT_P (operands[3]))"
+  {
+    operands[2] = operands[3] = CONSTM1_RTX (VNx16BImode);
+  }
+)
+
+;; Match PTRUES Pn.[HSD] when both the predicate and flags are useful.
+(define_insn_and_rewrite "*aarch64_sve_ptrue<mode>_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand 2)
+          (match_operand 3)
+          (const_int SVE_KNOWN_PTRUE)
+          (subreg:PRED_HSD
+            (match_operator:VNx16BI 1 "aarch64_sve_ptrue_svpattern_immediate"
+              [(unspec:VNx16BI
+                 [(match_operand:SI 4 "const_int_operand")
+                  (match_operand:PRED_HSD 5 "aarch64_simd_imm_zero")]
+                 UNSPEC_PTRUE)]) 0)]
+         UNSPEC_PTEST))
+   (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (match_dup 1))]
+  "TARGET_SVE"
+  {
+    return aarch64_output_sve_ptrues (operands[1]);
+  }
+  "&& (!CONSTANT_P (operands[2]) || !CONSTANT_P (operands[3]))"
+  {
+    operands[2] = CONSTM1_RTX (VNx16BImode);
+    operands[3] = CONSTM1_RTX (<MODE>mode);
+  }
+)
+
+;; Match PTRUES Pn.B when only the flags result is useful (which is
+;; a way of testing VL).
+(define_insn_and_rewrite "*aarch64_sve_ptruevnx16bi_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand 2)
+          (match_operand 3)
+          (const_int SVE_KNOWN_PTRUE)
+          (match_operator:VNx16BI 1 "aarch64_sve_ptrue_svpattern_immediate"
+            [(unspec:VNx16BI
+               [(match_operand:SI 4 "const_int_operand")
+                (match_operand:VNx16BI 5 "aarch64_simd_imm_zero")]
+               UNSPEC_PTRUE)])]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+  "TARGET_SVE"
+  {
+    return aarch64_output_sve_ptrues (operands[1]);
+  }
+  "&& (!CONSTANT_P (operands[2]) || !CONSTANT_P (operands[3]))"
+  {
+    operands[2] = operands[3] = CONSTM1_RTX (VNx16BImode);
+  }
+)
+
+;; Match PTRUES Pn.[HWD] when only the flags result is useful (which is
+;; a way of testing VL).
+(define_insn_and_rewrite "*aarch64_sve_ptrue<mode>_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand 2)
+          (match_operand 3)
+          (const_int SVE_KNOWN_PTRUE)
+          (subreg:PRED_HSD
+            (match_operator:VNx16BI 1 "aarch64_sve_ptrue_svpattern_immediate"
+              [(unspec:VNx16BI
+                 [(match_operand:SI 4 "const_int_operand")
+                  (match_operand:PRED_HSD 5 "aarch64_simd_imm_zero")]
+                 UNSPEC_PTRUE)]) 0)]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+  "TARGET_SVE"
+  {
+    return aarch64_output_sve_ptrues (operands[1]);
+  }
+  "&& (!CONSTANT_P (operands[2]) || !CONSTANT_P (operands[3]))"
+  {
+    operands[2] = CONSTM1_RTX (VNx16BImode);
+    operands[3] = CONSTM1_RTX (<MODE>mode);
+  }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Moves relating to the FFR
+;; -------------------------------------------------------------------------
+;; RDFFR
+;; RDFFRS
+;; SETFFR
+;; WRFFR
+;; -------------------------------------------------------------------------
+
+;; [W1 in the block comment above about FFR handling]
+;;
+;; Write to the FFR and start a new FFRT scheduling region.
+(define_insn "aarch64_wrffr"
+  [(set (reg:VNx16BI FFR_REGNUM)
+       (match_operand:VNx16BI 0 "aarch64_simd_reg_or_minus_one" "Dm, Upa"))
+   (set (reg:VNx16BI FFRT_REGNUM)
+       (match_dup 0))]
+  "TARGET_SVE"
+  "@
+   setffr
+   wrffr\t%0.b"
+)
+
+;; [L2 in the block comment above about FFR handling]
+;;
+;; Introduce a read from and write to the FFR in the current FFRT region,
+;; so that the FFR value is live on entry to the region and so that the FFR
+;; value visibly changes within the region.  This is used (possibly multiple
+;; times) in an FFRT region that includes LDFF1 or LDNF1 instructions.
+(define_insn "aarch64_update_ffr_for_load"
+  [(set (reg:VNx16BI FFR_REGNUM)
+       (unspec:VNx16BI [(reg:VNx16BI FFRT_REGNUM)
+                        (reg:VNx16BI FFR_REGNUM)] UNSPEC_UPDATE_FFR))]
+  "TARGET_SVE"
+  ""
+  [(set_attr "type" "no_insn")]
+)
+
+;; [R1 in the block comment above about FFR handling]
+;;
+;; Notionally copy the FFR to the FFRT, so that the current FFR value
+;; can be read from there by the RDFFR instructions below.  This acts
+;; as a scheduling barrier for earlier LDFF1 and LDNF1 instructions and
+;; creates a natural dependency with earlier writes.
+(define_insn "aarch64_copy_ffr_to_ffrt"
+  [(set (reg:VNx16BI FFRT_REGNUM)
+       (reg:VNx16BI FFR_REGNUM))]
+  "TARGET_SVE"
+  ""
+  [(set_attr "type" "no_insn")]
+)
+
+;; [R2 in the block comment above about FFR handling]
+;;
+;; Read the FFR via the FFRT.
+(define_insn "aarch64_rdffr"
+  [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (reg:VNx16BI FFRT_REGNUM))]
+  "TARGET_SVE"
+  "rdffr\t%0.b"
+)
+
+;; Likewise with zero predication.
+(define_insn "aarch64_rdffr_z"
+  [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (and:VNx16BI
+         (reg:VNx16BI FFRT_REGNUM)
+         (match_operand:VNx16BI 1 "register_operand" "Upa")))]
+  "TARGET_SVE"
+  "rdffr\t%0.b, %1/z"
+)
+
+;; Read the FFR to test for a fault, without using the predicate result.
+(define_insn "*aarch64_rdffr_z_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_dup 1)
+          (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+          (and:VNx16BI
+            (reg:VNx16BI FFRT_REGNUM)
+            (match_dup 1))]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+  "TARGET_SVE"
+  "rdffrs\t%0.b, %1/z"
+)
+
+;; Same for unpredicated RDFFR when tested with a known PTRUE.
+(define_insn "*aarch64_rdffr_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_dup 1)
+          (const_int SVE_KNOWN_PTRUE)
+          (reg:VNx16BI FFRT_REGNUM)]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+  "TARGET_SVE"
+  "rdffrs\t%0.b, %1/z"
+)
+
+;; Read the FFR with zero predication and test the result.
+(define_insn "*aarch64_rdffr_z_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_dup 1)
+          (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+          (and:VNx16BI
+            (reg:VNx16BI FFRT_REGNUM)
+            (match_dup 1))]
+         UNSPEC_PTEST))
+   (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (and:VNx16BI
+         (reg:VNx16BI FFRT_REGNUM)
+         (match_dup 1)))]
+  "TARGET_SVE"
+  "rdffrs\t%0.b, %1/z"
+)
+
+;; Same for unpredicated RDFFR when tested with a known PTRUE.
+(define_insn "*aarch64_rdffr_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_dup 1)
+          (const_int SVE_KNOWN_PTRUE)
+          (reg:VNx16BI FFRT_REGNUM)]
+         UNSPEC_PTEST))
+   (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (reg:VNx16BI FFRT_REGNUM))]
+  "TARGET_SVE"
+  "rdffrs\t%0.b, %1/z"
+)
+
+;; [R3 in the block comment above about FFR handling]
+;;
+;; Arbitrarily update the FFRT after a read from the FFR.  This acts as
+;; a scheduling barrier for later LDFF1 and LDNF1 instructions.
+(define_insn "aarch64_update_ffrt"
+  [(set (reg:VNx16BI FFRT_REGNUM)
+       (unspec:VNx16BI [(reg:VNx16BI FFRT_REGNUM)] UNSPEC_UPDATE_FFRT))]
+  "TARGET_SVE"
+  ""
+  [(set_attr "type" "no_insn")]
+)
+
 ;; =========================================================================
 ;; == Loads
 ;; =========================================================================
   "ld<vector_count><Vesize>\t%0, %2/z, %1"
 )
 
+;; -------------------------------------------------------------------------
+;; ---- Extending contiguous loads
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; LD1B
+;; LD1H
+;; LD1SB
+;; LD1SH
+;; LD1SW
+;; LD1W
+;; -------------------------------------------------------------------------
+
+;; Predicated load and extend, with 8 elements per 128-bit block.
+(define_insn "@aarch64_load_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>"
+  [(set (match_operand:VNx8_WIDE 0 "register_operand" "=w")
+       (ANY_EXTEND:VNx8_WIDE
+         (unspec:VNx8_NARROW
+           [(match_operand:VNx8BI 2 "register_operand" "Upl")
+            (match_operand:VNx8_NARROW 1 "memory_operand" "m")]
+           UNSPEC_LD1_SVE)))]
+  "TARGET_SVE"
+  "ld1<ANY_EXTEND:s><VNx8_NARROW:Vesize>\t%0.<VNx8_WIDE:Vetype>, %2/z, %1"
+)
+
+;; Predicated load and extend, with 4 elements per 128-bit block.
+(define_insn "@aarch64_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>"
+  [(set (match_operand:VNx4_WIDE 0 "register_operand" "=w")
+       (ANY_EXTEND:VNx4_WIDE
+         (unspec:VNx4_NARROW
+           [(match_operand:VNx4BI 2 "register_operand" "Upl")
+            (match_operand:VNx4_NARROW 1 "memory_operand" "m")]
+           UNSPEC_LD1_SVE)))]
+  "TARGET_SVE"
+  "ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.<VNx4_WIDE:Vetype>, %2/z, %1"
+)
+
+;; Predicated load and extend, with 2 elements per 128-bit block.
+(define_insn "@aarch64_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>"
+  [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w")
+       (ANY_EXTEND:VNx2_WIDE
+         (unspec:VNx2_NARROW
+           [(match_operand:VNx2BI 2 "register_operand" "Upl")
+            (match_operand:VNx2_NARROW 1 "memory_operand" "m")]
+           UNSPEC_LD1_SVE)))]
+  "TARGET_SVE"
+  "ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.<VNx2_WIDE:Vetype>, %2/z, %1"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- First-faulting contiguous loads
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; - LDFF1B
+;; - LDFF1D
+;; - LDFF1H
+;; - LDFF1W
+;; - LDNF1B
+;; - LDNF1D
+;; - LDNF1H
+;; - LDNF1W
+;; -------------------------------------------------------------------------
+
+;; Contiguous non-extending first-faulting or non-faulting loads.
+(define_insn "@aarch64_ld<fn>f1<mode>"
+  [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+       (unspec:SVE_ALL
+         [(match_operand:<VPRED> 2 "register_operand" "Upl")
+          (match_operand:SVE_ALL 1 "aarch64_sve_ld<fn>f1_operand" "Ut<fn>")
+          (reg:VNx16BI FFRT_REGNUM)]
+         SVE_LDFF1_LDNF1))]
+  "TARGET_SVE"
+  "ld<fn>f1<Vesize>\t%0.<Vetype>, %2/z, %1"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- First-faulting extending contiguous loads
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; - LDFF1B
+;; - LDFF1H
+;; - LDFF1SB
+;; - LDFF1SH
+;; - LDFF1SW
+;; - LDFF1W
+;; - LDNF1B
+;; - LDNF1H
+;; - LDNF1SB
+;; - LDNF1SH
+;; - LDNF1SW
+;; - LDNF1W
+;; -------------------------------------------------------------------------
+
+;; Predicated first-faulting or non-faulting load and extend, with 8 elements
+;; per 128-bit block.
+(define_insn "@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx8_WIDE:mode><VNx8_NARROW:mode>"
+  [(set (match_operand:VNx8_WIDE 0 "register_operand" "=w")
+       (ANY_EXTEND:VNx8_WIDE
+         (unspec:VNx8_NARROW
+           [(match_operand:VNx8BI 2 "register_operand" "Upl")
+            (match_operand:VNx8_NARROW 1 "aarch64_sve_ld<fn>f1_operand" "Ut<fn>")
+            (reg:VNx16BI FFRT_REGNUM)]
+           SVE_LDFF1_LDNF1)))]
+  "TARGET_SVE"
+  "ld<fn>f1<ANY_EXTEND:s><VNx8_NARROW:Vesize>\t%0.<VNx8_WIDE:Vetype>, %2/z, %1"
+)
+
+;; Predicated first-faulting or non-faulting load and extend, with 4 elements
+;; per 128-bit block.
+(define_insn "@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>"
+  [(set (match_operand:VNx4_WIDE 0 "register_operand" "=w")
+       (ANY_EXTEND:VNx4_WIDE
+         (unspec:VNx4_NARROW
+           [(match_operand:VNx4BI 2 "register_operand" "Upl")
+            (match_operand:VNx4_NARROW 1 "aarch64_sve_ld<fn>f1_operand" "Ut<fn>")
+            (reg:VNx16BI FFRT_REGNUM)]
+           SVE_LDFF1_LDNF1)))]
+  "TARGET_SVE"
+  "ld<fn>f1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.<VNx4_WIDE:Vetype>, %2/z, %1"
+)
+
+;; Predicated first-faulting or non-faulting load and extend, with 2 elements
+;; per 128-bit block.
+(define_insn "@aarch64_ld<fn>f1_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>"
+  [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w")
+       (ANY_EXTEND:VNx2_WIDE
+         (unspec:VNx2_NARROW
+           [(match_operand:VNx2BI 2 "register_operand" "Upl")
+            (match_operand:VNx2_NARROW 1 "aarch64_sve_ld<fn>f1_operand" "Ut<fn>")
+            (reg:VNx16BI FFRT_REGNUM)]
+           SVE_LDFF1_LDNF1)))]
+  "TARGET_SVE"
+  "ld<fn>f1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.<VNx2_WIDE:Vetype>, %2/z, %1"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Non-temporal contiguous loads
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - LDNT1B
+;; - LDNT1D
+;; - LDNT1H
+;; - LDNT1W
+;; -------------------------------------------------------------------------
+
+;; Predicated contiguous non-temporal load.
+(define_insn "@aarch64_ldnt1<mode>"
+  [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+       (unspec:SVE_ALL
+         [(match_operand:<VPRED> 2 "register_operand" "Upl")
+          (match_operand:SVE_ALL 1 "memory_operand" "m")]
+         UNSPEC_LDNT1_SVE))]
+  "TARGET_SVE"
+  "ldnt1<Vesize>\t%0.<Vetype>, %2/z, %1"
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- Normal gather loads
 ;; -------------------------------------------------------------------------
   [(set (match_operand:SVE_SD 0 "register_operand")
        (unspec:SVE_SD
          [(match_dup 5)
-          (match_operand:DI 1 "aarch64_reg_or_zero")
+          (match_operand:DI 1 "aarch64_sve_gather_offset_<Vesize>")
           (match_operand:<V_INT_EQUIV> 2 "register_operand")
           (match_operand:DI 3 "const_int_operand")
           (match_operand:DI 4 "aarch64_gather_scale_operand_<Vesize>")
 ;; Predicated gather loads for 32-bit elements.  Operand 3 is true for
 ;; unsigned extension and false for signed extension.
 (define_insn "mask_gather_load<mode>"
-  [(set (match_operand:SVE_S 0 "register_operand" "=w, w, w, w, w")
+  [(set (match_operand:SVE_S 0 "register_operand" "=w, w, w, w, w, w")
        (unspec:SVE_S
-         [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl, Upl, Upl")
-          (match_operand:DI 1 "aarch64_reg_or_zero" "Z, rk, rk, rk, rk")
-          (match_operand:<V_INT_EQUIV> 2 "register_operand" "w, w, w, w, w")
-          (match_operand:DI 3 "const_int_operand" "i, Z, Ui1, Z, Ui1")
-          (match_operand:DI 4 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, i, i")
+         [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+          (match_operand:DI 1 "aarch64_sve_gather_offset_w" "Z, vgw, rk, rk, rk, rk")
+          (match_operand:VNx4SI 2 "register_operand" "w, w, w, w, w, w")
+          (match_operand:DI 3 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1")
+          (match_operand:DI 4 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, Ui1, i, i")
           (mem:BLK (scratch))]
          UNSPEC_LD1_GATHER))]
   "TARGET_SVE"
   "@
    ld1w\t%0.s, %5/z, [%2.s]
+   ld1w\t%0.s, %5/z, [%2.s, #%1]
    ld1w\t%0.s, %5/z, [%1, %2.s, sxtw]
    ld1w\t%0.s, %5/z, [%1, %2.s, uxtw]
    ld1w\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
 ;; Predicated gather loads for 64-bit elements.  The value of operand 3
 ;; doesn't matter in this case.
 (define_insn "mask_gather_load<mode>"
-  [(set (match_operand:SVE_D 0 "register_operand" "=w, w, w")
+  [(set (match_operand:SVE_D 0 "register_operand" "=w, w, w, w")
        (unspec:SVE_D
-         [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl")
-          (match_operand:DI 1 "aarch64_reg_or_zero" "Z, rk, rk")
-          (match_operand:<V_INT_EQUIV> 2 "register_operand" "w, w, w")
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+          (match_operand:DI 1 "aarch64_sve_gather_offset_d" "Z, vgd, rk, rk")
+          (match_operand:VNx2DI 2 "register_operand" "w, w, w, w")
           (match_operand:DI 3 "const_int_operand")
-          (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, Ui1, i")
+          (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, Ui1, Ui1, i")
           (mem:BLK (scratch))]
          UNSPEC_LD1_GATHER))]
   "TARGET_SVE"
   "@
    ld1d\t%0.d, %5/z, [%2.d]
+   ld1d\t%0.d, %5/z, [%2.d, #%1]
    ld1d\t%0.d, %5/z, [%1, %2.d]
    ld1d\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
 )
 
-;; =========================================================================
-;; == Stores
-;; =========================================================================
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn "*mask_gather_load<mode>_sxtw"
+  [(set (match_operand:SVE_D 0 "register_operand" "=w, w")
+       (unspec:SVE_D
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+          (match_operand:DI 1 "register_operand" "rk, rk")
+          (unspec:VNx2DI
+            [(match_dup 5)
+             (sign_extend:VNx2DI
+               (truncate:VNx2SI
+                 (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+            UNSPEC_PRED_X)
+          (match_operand:DI 3 "const_int_operand")
+          (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, i")
+          (mem:BLK (scratch))]
+         UNSPEC_LD1_GATHER))]
+  "TARGET_SVE"
+  "@
+   ld1d\t%0.d, %5/z, [%1, %2.d, sxtw]
+   ld1d\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*mask_gather_load<mode>_uxtw"
+  [(set (match_operand:SVE_D 0 "register_operand" "=w, w")
+       (unspec:SVE_D
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+          (match_operand:DI 1 "register_operand" "rk, rk")
+          (and:VNx2DI
+            (match_operand:VNx2DI 2 "register_operand" "w, w")
+            (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+          (match_operand:DI 3 "const_int_operand")
+          (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, i")
+          (mem:BLK (scratch))]
+         UNSPEC_LD1_GATHER))]
+  "TARGET_SVE"
+  "@
+   ld1d\t%0.d, %5/z, [%1, %2.d, uxtw]
+   ld1d\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+)
 
 ;; -------------------------------------------------------------------------
-;; ---- Normal contiguous stores
+;; ---- Extending gather loads
 ;; -------------------------------------------------------------------------
-;; Includes contiguous forms of:
-;; - ST1B
-;; - ST1D
-;; - ST1H
-;; - ST1W
-;; - ST2B
-;; - ST2D
-;; - ST2H
-;; - ST2W
-;; - ST3B
-;; - ST3D
-;; - ST3H
-;; - ST3W
-;; - ST4B
-;; - ST4D
-;; - ST4H
-;; - ST4W
+;; Includes gather forms of:
+;; - LD1B
+;; - LD1H
+;; - LD1SB
+;; - LD1SH
+;; - LD1SW
+;; - LD1W
 ;; -------------------------------------------------------------------------
 
-;; Predicated ST1.
-(define_insn "maskstore<mode><vpred>"
-  [(set (match_operand:SVE_ALL 0 "memory_operand" "+m")
-       (unspec:SVE_ALL [(match_operand:<VPRED> 2 "register_operand" "Upl")
-                        (match_operand:SVE_ALL 1 "register_operand" "w")
-                        (match_dup 0)]
-                       UNSPEC_ST1_SVE))]
+;; Predicated extending gather loads for 32-bit elements.  Operand 3 is
+;; true for unsigned extension and false for signed extension.
+(define_insn "@aarch64_gather_load_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>"
+  [(set (match_operand:VNx4_WIDE 0 "register_operand" "=w, w, w, w, w, w")
+       (ANY_EXTEND:VNx4_WIDE
+         (unspec:VNx4_NARROW
+           [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+            (match_operand:DI 1 "aarch64_sve_gather_offset_<VNx4_NARROW:Vesize>" "Z, vg<VNx4_NARROW:Vesize>, rk, rk, rk, rk")
+            (match_operand:VNx4_WIDE 2 "register_operand" "w, w, w, w, w, w")
+            (match_operand:DI 3 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1")
+            (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx4_NARROW:Vesize>" "Ui1, Ui1, Ui1, Ui1, i, i")
+            (mem:BLK (scratch))]
+           UNSPEC_LD1_GATHER)))]
   "TARGET_SVE"
-  "st1<Vesize>\t%1.<Vetype>, %2, %0"
-)
-
-;; Unpredicated ST[234].  This is always a full update, so the dependence
-;; on the old value of the memory location (via (match_dup 0)) is redundant.
-;; There doesn't seem to be any obvious benefit to treating the all-true
-;; case differently though.  In particular, it's very unlikely that we'll
-;; only find out during RTL that a store_lanes is dead.
-(define_expand "vec_store_lanes<mode><vsingle>"
-  [(set (match_operand:SVE_STRUCT 0 "memory_operand")
-       (unspec:SVE_STRUCT
-         [(match_dup 2)
-          (match_operand:SVE_STRUCT 1 "register_operand")
-          (match_dup 0)]
-         UNSPEC_STN))]
+  "@
+   ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%2.s]
+   ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%2.s, #%1]
+   ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw]
+   ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw]
+   ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
+   ld1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw %p4]"
+)
+
+;; Predicated extending gather loads for 64-bit elements.  The value of
+;; operand 3 doesn't matter in this case.
+(define_insn "@aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>"
+  [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w, w, w")
+       (ANY_EXTEND:VNx2_WIDE
+         (unspec:VNx2_NARROW
+           [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+            (match_operand:DI 1 "aarch64_sve_gather_offset_<VNx2_NARROW:Vesize>" "Z, vg<VNx2_NARROW:Vesize>, rk, rk")
+            (match_operand:VNx2_WIDE 2 "register_operand" "w, w, w, w")
+            (match_operand:DI 3 "const_int_operand")
+            (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, Ui1, Ui1, i")
+            (mem:BLK (scratch))]
+           UNSPEC_LD1_GATHER)))]
+  "TARGET_SVE"
+  "@
+   ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%2.d]
+   ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%2.d, #%1]
+   ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d]
+   ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw"
+  [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w")
+       (ANY_EXTEND:VNx2_WIDE
+         (unspec:VNx2_NARROW
+           [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+            (match_operand:DI 1 "aarch64_reg_or_zero" "rk, rk")
+            (unspec:VNx2DI
+              [(match_operand 6)
+               (sign_extend:VNx2DI
+                 (truncate:VNx2SI
+                   (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+              UNSPEC_PRED_X)
+            (match_operand:DI 3 "const_int_operand")
+            (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+            (mem:BLK (scratch))]
+           UNSPEC_LD1_GATHER)))]
   "TARGET_SVE"
+  "@
+   ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, sxtw]
+   ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+  "&& !rtx_equal_p (operands[5], operands[6])"
   {
-    operands[2] = aarch64_ptrue_reg (<VPRED>mode);
+    operands[6] = copy_rtx (operands[5]);
   }
 )
 
-;; Predicated ST[234].
-(define_insn "vec_mask_store_lanes<mode><vsingle>"
-  [(set (match_operand:SVE_STRUCT 0 "memory_operand" "+m")
-       (unspec:SVE_STRUCT
-         [(match_operand:<VPRED> 2 "register_operand" "Upl")
-          (match_operand:SVE_STRUCT 1 "register_operand" "w")
-          (match_dup 0)]
-         UNSPEC_STN))]
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_gather_load_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw"
+  [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w")
+       (ANY_EXTEND:VNx2_WIDE
+         (unspec:VNx2_NARROW
+           [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+            (match_operand:DI 1 "aarch64_reg_or_zero" "rk, rk")
+            (and:VNx2DI
+              (match_operand:VNx2DI 2 "register_operand" "w, w")
+              (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+            (match_operand:DI 3 "const_int_operand")
+            (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+            (mem:BLK (scratch))]
+           UNSPEC_LD1_GATHER)))]
   "TARGET_SVE"
-  "st<vector_count><Vesize>\t%1, %2, %0"
+  "@
+   ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, uxtw]
+   ld1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
 )
 
 ;; -------------------------------------------------------------------------
-;; ---- Normal scatter stores
+;; ---- First-faulting gather loads
 ;; -------------------------------------------------------------------------
-;; Includes scatter forms of:
-;; - ST1D
-;; - ST1W
+;; Includes gather forms of:
+;; - LDFF1D
+;; - LDFF1W
 ;; -------------------------------------------------------------------------
 
-;; Unpredicated scatter stores.
-(define_expand "scatter_store<mode>"
+;; Predicated first-faulting gather loads for 32-bit elements.  Operand
+;; 3 is true for unsigned extension and false for signed extension.
+(define_insn "@aarch64_ldff1_gather<mode>"
+  [(set (match_operand:SVE_S 0 "register_operand" "=w, w, w, w, w, w")
+       (unspec:SVE_S
+         [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+          (match_operand:DI 1 "aarch64_sve_gather_offset_w" "Z, vgw, rk, rk, rk, rk")
+          (match_operand:VNx4SI 2 "register_operand" "w, w, w, w, w, w")
+          (match_operand:DI 3 "const_int_operand" "i, i, Z, Ui1, Z, Ui1")
+          (match_operand:DI 4 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, Ui1, i, i")
+          (mem:BLK (scratch))
+          (reg:VNx16BI FFRT_REGNUM)]
+         UNSPEC_LDFF1_GATHER))]
+  "TARGET_SVE"
+  "@
+   ldff1w\t%0.s, %5/z, [%2.s]
+   ldff1w\t%0.s, %5/z, [%2.s, #%1]
+   ldff1w\t%0.s, %5/z, [%1, %2.s, sxtw]
+   ldff1w\t%0.s, %5/z, [%1, %2.s, uxtw]
+   ldff1w\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
+   ldff1w\t%0.s, %5/z, [%1, %2.s, uxtw %p4]"
+)
+
+;; Predicated first-faulting gather loads for 64-bit elements.  The value
+;; of operand 3 doesn't matter in this case.
+(define_insn "@aarch64_ldff1_gather<mode>"
+  [(set (match_operand:SVE_D 0 "register_operand" "=w, w, w, w")
+       (unspec:SVE_D
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+          (match_operand:DI 1 "aarch64_sve_gather_offset_d" "Z, vgd, rk, rk")
+          (match_operand:VNx2DI 2 "register_operand" "w, w, w, w")
+          (match_operand:DI 3 "const_int_operand")
+          (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, Ui1, Ui1, i")
+          (mem:BLK (scratch))
+          (reg:VNx16BI FFRT_REGNUM)]
+         UNSPEC_LDFF1_GATHER))]
+  "TARGET_SVE"
+  "@
+   ldff1d\t%0.d, %5/z, [%2.d]
+   ldff1d\t%0.d, %5/z, [%2.d, #%1]
+   ldff1d\t%0.d, %5/z, [%1, %2.d]
+   ldff1d\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_ldff1_gather<mode>_sxtw"
+  [(set (match_operand:SVE_D 0 "register_operand" "=w, w")
+       (unspec:SVE_D
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+          (match_operand:DI 1 "register_operand" "rk, rk")
+          (unspec:VNx2DI
+            [(match_operand 6)
+             (sign_extend:VNx2DI
+               (truncate:VNx2SI
+                 (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+            UNSPEC_PRED_X)
+          (match_operand:DI 3 "const_int_operand")
+          (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, i")
+          (mem:BLK (scratch))
+          (reg:VNx16BI FFRT_REGNUM)]
+         UNSPEC_LDFF1_GATHER))]
+  "TARGET_SVE"
+  "@
+   ldff1d\t%0.d, %5/z, [%1, %2.d, sxtw]
+   ldff1d\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+  "&& !rtx_equal_p (operands[5], operands[6])"
+  {
+    operands[6] = copy_rtx (operands[5]);
+  }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_ldff1_gather<mode>_uxtw"
+  [(set (match_operand:SVE_D 0 "register_operand" "=w, w")
+       (unspec:SVE_D
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+          (match_operand:DI 1 "register_operand" "rk, rk")
+          (and:VNx2DI
+            (match_operand:VNx2DI 2 "register_operand" "w, w")
+            (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+          (match_operand:DI 3 "const_int_operand")
+          (match_operand:DI 4 "aarch64_gather_scale_operand_d" "Ui1, i")
+          (mem:BLK (scratch))
+          (reg:VNx16BI FFRT_REGNUM)]
+         UNSPEC_LDFF1_GATHER))]
+  "TARGET_SVE"
+  "@
+   ldff1d\t%0.d, %5/z, [%1, %2.d, uxtw]
+   ldff1d\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- First-faulting extending gather loads
+;; -------------------------------------------------------------------------
+;; Includes gather forms of:
+;; - LDFF1B
+;; - LDFF1H
+;; - LDFF1SB
+;; - LDFF1SH
+;; - LDFF1SW
+;; - LDFF1W
+;; -------------------------------------------------------------------------
+
+;; Predicated extending first-faulting gather loads for 32-bit elements.
+;; Operand 3 is true for unsigned extension and false for signed extension.
+(define_insn "@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx4_WIDE:mode><VNx4_NARROW:mode>"
+  [(set (match_operand:VNx4_WIDE 0 "register_operand" "=w, w, w, w, w, w")
+       (ANY_EXTEND:VNx4_WIDE
+         (unspec:VNx4_NARROW
+           [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+            (match_operand:DI 1 "aarch64_sve_gather_offset_<VNx4_NARROW:Vesize>" "Z, vg<VNx4_NARROW:Vesize>, rk, rk, rk, rk")
+            (match_operand:VNx4_WIDE 2 "register_operand" "w, w, w, w, w, w")
+            (match_operand:DI 3 "const_int_operand" "i, i, Z, Ui1, Z, Ui1")
+            (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx4_NARROW:Vesize>" "Ui1, Ui1, Ui1, Ui1, i, i")
+            (mem:BLK (scratch))
+            (reg:VNx16BI FFRT_REGNUM)]
+           UNSPEC_LDFF1_GATHER)))]
+  "TARGET_SVE"
+  "@
+   ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%2.s]
+   ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%2.s, #%1]
+   ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw]
+   ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw]
+   ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, sxtw %p4]
+   ldff1<ANY_EXTEND:s><VNx4_NARROW:Vesize>\t%0.s, %5/z, [%1, %2.s, uxtw %p4]"
+)
+
+;; Predicated extending first-faulting gather loads for 64-bit elements.
+;; The value of operand 3 doesn't matter in this case.
+(define_insn "@aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>"
+  [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w, w, w")
+       (ANY_EXTEND:VNx2_WIDE
+         (unspec:VNx2_NARROW
+           [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+            (match_operand:DI 1 "aarch64_sve_gather_offset_<VNx2_NARROW:Vesize>" "Z, vg<VNx2_NARROW:Vesize>, rk, rk")
+            (match_operand:VNx2_WIDE 2 "register_operand" "w, w, w, w")
+            (match_operand:DI 3 "const_int_operand")
+            (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, Ui1, Ui1, i")
+            (mem:BLK (scratch))
+            (reg:VNx16BI FFRT_REGNUM)]
+           UNSPEC_LDFF1_GATHER)))]
+  "TARGET_SVE"
+  "@
+   ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%2.d]
+   ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%2.d, #%1]
+   ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d]
+   ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, lsl %p4]"
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_sxtw"
+  [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w")
+       (ANY_EXTEND:VNx2_WIDE
+         (unspec:VNx2_NARROW
+           [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+            (match_operand:DI 1 "aarch64_reg_or_zero" "rk, rk")
+            (unspec:VNx2DI
+              [(match_operand 6)
+               (sign_extend:VNx2DI
+                 (truncate:VNx2SI
+                   (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+              UNSPEC_PRED_X)
+            (match_operand:DI 3 "const_int_operand")
+            (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+            (mem:BLK (scratch))
+            (reg:VNx16BI FFRT_REGNUM)]
+           UNSPEC_LDFF1_GATHER)))]
+  "TARGET_SVE"
+  "@
+   ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, sxtw]
+   ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, sxtw %p4]"
+  "&& !rtx_equal_p (operands[5], operands[6])"
+  {
+    operands[6] = copy_rtx (operands[5]);
+  }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_ldff1_gather_<ANY_EXTEND:optab><VNx2_WIDE:mode><VNx2_NARROW:mode>_uxtw"
+  [(set (match_operand:VNx2_WIDE 0 "register_operand" "=w, w")
+       (ANY_EXTEND:VNx2_WIDE
+         (unspec:VNx2_NARROW
+           [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+            (match_operand:DI 1 "aarch64_reg_or_zero" "rk, rk")
+            (and:VNx2DI
+              (match_operand:VNx2DI 2 "register_operand" "w, w")
+              (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+            (match_operand:DI 3 "const_int_operand")
+            (match_operand:DI 4 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+            (mem:BLK (scratch))
+            (reg:VNx16BI FFRT_REGNUM)]
+           UNSPEC_LDFF1_GATHER)))]
+  "TARGET_SVE"
+  "@
+   ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, uxtw]
+   ldff1<ANY_EXTEND:s><VNx2_NARROW:Vesize>\t%0.d, %5/z, [%1, %2.d, uxtw %p4]"
+)
+
+;; =========================================================================
+;; == Prefetches
+;; =========================================================================
+
+;; -------------------------------------------------------------------------
+;; ---- Contiguous prefetches
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; - PRFB
+;; - PRFD
+;; - PRFH
+;; - PRFW
+;; -------------------------------------------------------------------------
+
+;; Contiguous predicated prefetches.  Operand 2 gives the real prefetch
+;; operation (as an svprfop), with operands 3 and 4 providing distilled
+;; information.
+(define_insn "@aarch64_sve_prefetch<mode>"
+  [(prefetch (unspec:DI
+              [(match_operand:<VPRED> 0 "register_operand" "Upl")
+               (match_operand:SVE_I 1 "aarch64_sve_prefetch_operand" "UP<Vesize>")
+               (match_operand:DI 2 "const_int_operand")]
+              UNSPEC_SVE_PREFETCH)
+            (match_operand:DI 3 "const_int_operand")
+            (match_operand:DI 4 "const_int_operand"))]
+  "TARGET_SVE"
+  {
+    operands[1] = gen_rtx_MEM (<MODE>mode, operands[1]);
+    return aarch64_output_sve_prefetch ("prf<Vesize>", operands[2], "%0, %1");
+  }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Gather prefetches
+;; -------------------------------------------------------------------------
+;; Includes gather forms of:
+;; - PRFB
+;; - PRFD
+;; - PRFH
+;; - PRFW
+;; -------------------------------------------------------------------------
+
+;; Predicated gather prefetches for 32-bit bases and offsets.  The operands
+;; are:
+;; 0: the governing predicate
+;; 1: the scalar component of the address
+;; 2: the vector component of the address
+;; 3: 1 for zero extension, 0 for sign extension
+;; 4: the scale multiplier
+;; 5: a vector zero that identifies the mode of data being accessed
+;; 6: the prefetch operator (an svprfop)
+;; 7: the normal RTL prefetch rw flag
+;; 8: the normal RTL prefetch locality value
+(define_insn "@aarch64_sve_gather_prefetch<SVE_I:mode><VNx4SI_ONLY:mode>"
+  [(prefetch (unspec:DI
+              [(match_operand:VNx4BI 0 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+               (match_operand:DI 1 "aarch64_sve_gather_offset_<SVE_I:Vesize>" "Z, vg<SVE_I:Vesize>, rk, rk, rk, rk")
+               (match_operand:VNx4SI_ONLY 2 "register_operand" "w, w, w, w, w, w")
+               (match_operand:DI 3 "const_int_operand" "i, i, Z, Ui1, Z, Ui1")
+               (match_operand:DI 4 "aarch64_gather_scale_operand_<SVE_I:Vesize>" "Ui1, Ui1, Ui1, Ui1, i, i")
+               (match_operand:SVE_I 5 "aarch64_simd_imm_zero")
+               (match_operand:DI 6 "const_int_operand")]
+              UNSPEC_SVE_PREFETCH_GATHER)
+            (match_operand:DI 7 "const_int_operand")
+            (match_operand:DI 8 "const_int_operand"))]
+  "TARGET_SVE"
+  {
+    static const char *const insns[][2] = {
+      "prf<SVE_I:Vesize>", "%0, [%2.s]",
+      "prf<SVE_I:Vesize>", "%0, [%2.s, #%1]",
+      "prfb", "%0, [%1, %2.s, sxtw]",
+      "prfb", "%0, [%1, %2.s, uxtw]",
+      "prf<SVE_I:Vesize>", "%0, [%1, %2.s, sxtw %p4]",
+      "prf<SVE_I:Vesize>", "%0, [%1, %2.s, uxtw %p4]"
+    };
+    const char *const *parts = insns[which_alternative];
+    return aarch64_output_sve_prefetch (parts[0], operands[6], parts[1]);
+  }
+)
+
+;; Predicated gather prefetches for 64-bit elements.  The value of operand 3
+;; doesn't matter in this case.
+(define_insn "@aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>"
+  [(prefetch (unspec:DI
+              [(match_operand:VNx2BI 0 "register_operand" "Upl, Upl, Upl, Upl")
+               (match_operand:DI 1 "aarch64_sve_gather_offset_<SVE_I:Vesize>" "Z, vg<SVE_I:Vesize>, rk, rk")
+               (match_operand:VNx2DI_ONLY 2 "register_operand" "w, w, w, w")
+               (match_operand:DI 3 "const_int_operand")
+               (match_operand:DI 4 "aarch64_gather_scale_operand_<SVE_I:Vesize>" "Ui1, Ui1, Ui1, i")
+               (match_operand:SVE_I 5 "aarch64_simd_imm_zero")
+               (match_operand:DI 6 "const_int_operand")]
+              UNSPEC_SVE_PREFETCH_GATHER)
+            (match_operand:DI 7 "const_int_operand")
+            (match_operand:DI 8 "const_int_operand"))]
+  "TARGET_SVE"
+  {
+    static const char *const insns[][2] = {
+      "prf<SVE_I:Vesize>", "%0, [%2.d]",
+      "prf<SVE_I:Vesize>", "%0, [%2.d, #%1]",
+      "prfb", "%0, [%1, %2.d]",
+      "prf<SVE_I:Vesize>", "%0, [%1, %2.d, lsl %p4]"
+    };
+    const char *const *parts = insns[which_alternative];
+    return aarch64_output_sve_prefetch (parts[0], operands[6], parts[1]);
+  }
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_sxtw"
+  [(prefetch (unspec:DI
+              [(match_operand:VNx2BI 0 "register_operand" "Upl, Upl")
+               (match_operand:DI 1 "register_operand" "rk, rk")
+               (unspec:VNx2DI_ONLY
+                 [(match_operand 9)
+                  (sign_extend:VNx2DI
+                    (truncate:VNx2SI
+                      (match_operand:VNx2DI 2 "register_operand" "w, w")))]
+                 UNSPEC_PRED_X)
+               (match_operand:DI 3 "const_int_operand")
+               (match_operand:DI 4 "aarch64_gather_scale_operand_<SVE_I:Vesize>" "Ui1, i")
+               (match_operand:SVE_I 5 "aarch64_simd_imm_zero")
+               (match_operand:DI 6 "const_int_operand")]
+              UNSPEC_SVE_PREFETCH_GATHER)
+            (match_operand:DI 7 "const_int_operand")
+            (match_operand:DI 8 "const_int_operand"))]
+  "TARGET_SVE"
+  {
+    static const char *const insns[][2] = {
+      "prfb", "%0, [%1, %2.d, sxtw]",
+      "prf<SVE_I:Vesize>", "%0, [%1, %2.d, sxtw %p4]"
+    };
+    const char *const *parts = insns[which_alternative];
+    return aarch64_output_sve_prefetch (parts[0], operands[6], parts[1]);
+  }
+  "&& !rtx_equal_p (operands[0], operands[9])"
+  {
+    operands[9] = copy_rtx (operands[0]);
+  }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_sve_gather_prefetch<SVE_I:mode><VNx2DI_ONLY:mode>_uxtw"
+  [(prefetch (unspec:DI
+              [(match_operand:VNx2BI 0 "register_operand" "Upl, Upl")
+               (match_operand:DI 1 "register_operand" "rk, rk")
+               (and:VNx2DI_ONLY
+                 (match_operand:VNx2DI 2 "register_operand" "w, w")
+                 (match_operand:VNx2DI 9 "aarch64_sve_uxtw_immediate"))
+               (match_operand:DI 3 "const_int_operand")
+               (match_operand:DI 4 "aarch64_gather_scale_operand_<SVE_I:Vesize>" "Ui1, i")
+               (match_operand:SVE_I 5 "aarch64_simd_imm_zero")
+               (match_operand:DI 6 "const_int_operand")]
+              UNSPEC_SVE_PREFETCH_GATHER)
+            (match_operand:DI 7 "const_int_operand")
+            (match_operand:DI 8 "const_int_operand"))]
+  "TARGET_SVE"
+  {
+    static const char *const insns[][2] = {
+      "prfb", "%0, [%1, %2.d, uxtw]",
+      "prf<SVE_I:Vesize>", "%0, [%1, %2.d, uxtw %p4]"
+    };
+    const char *const *parts = insns[which_alternative];
+    return aarch64_output_sve_prefetch (parts[0], operands[6], parts[1]);
+  }
+)
+
+;; =========================================================================
+;; == Stores
+;; =========================================================================
+
+;; -------------------------------------------------------------------------
+;; ---- Normal contiguous stores
+;; -------------------------------------------------------------------------
+;; Includes contiguous forms of:
+;; - ST1B
+;; - ST1D
+;; - ST1H
+;; - ST1W
+;; - ST2B
+;; - ST2D
+;; - ST2H
+;; - ST2W
+;; - ST3B
+;; - ST3D
+;; - ST3H
+;; - ST3W
+;; - ST4B
+;; - ST4D
+;; - ST4H
+;; - ST4W
+;; -------------------------------------------------------------------------
+
+;; Predicated ST1.
+(define_insn "maskstore<mode><vpred>"
+  [(set (match_operand:SVE_ALL 0 "memory_operand" "+m")
+       (unspec:SVE_ALL [(match_operand:<VPRED> 2 "register_operand" "Upl")
+                        (match_operand:SVE_ALL 1 "register_operand" "w")
+                        (match_dup 0)]
+                       UNSPEC_ST1_SVE))]
+  "TARGET_SVE"
+  "st1<Vesize>\t%1.<Vetype>, %2, %0"
+)
+
+;; Unpredicated ST[234].  This is always a full update, so the dependence
+;; on the old value of the memory location (via (match_dup 0)) is redundant.
+;; There doesn't seem to be any obvious benefit to treating the all-true
+;; case differently though.  In particular, it's very unlikely that we'll
+;; only find out during RTL that a store_lanes is dead.
+(define_expand "vec_store_lanes<mode><vsingle>"
+  [(set (match_operand:SVE_STRUCT 0 "memory_operand")
+       (unspec:SVE_STRUCT
+         [(match_dup 2)
+          (match_operand:SVE_STRUCT 1 "register_operand")
+          (match_dup 0)]
+         UNSPEC_STN))]
+  "TARGET_SVE"
+  {
+    operands[2] = aarch64_ptrue_reg (<VPRED>mode);
+  }
+)
+
+;; Predicated ST[234].
+(define_insn "vec_mask_store_lanes<mode><vsingle>"
+  [(set (match_operand:SVE_STRUCT 0 "memory_operand" "+m")
+       (unspec:SVE_STRUCT
+         [(match_operand:<VPRED> 2 "register_operand" "Upl")
+          (match_operand:SVE_STRUCT 1 "register_operand" "w")
+          (match_dup 0)]
+         UNSPEC_STN))]
+  "TARGET_SVE"
+  "st<vector_count><Vesize>\t%1, %2, %0"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Truncating contiguous stores
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - ST1B
+;; - ST1H
+;; - ST1W
+;; -------------------------------------------------------------------------
+
+;; Predicated truncate and store, with 8 elements per 128-bit block.
+(define_insn "@aarch64_store_trunc<VNx8_NARROW:mode><VNx8_WIDE:mode>"
+  [(set (match_operand:VNx8_NARROW 0 "memory_operand" "+m")
+       (unspec:VNx8_NARROW
+         [(match_operand:VNx8BI 2 "register_operand" "Upl")
+          (truncate:VNx8_NARROW
+            (match_operand:VNx8_WIDE 1 "register_operand" "w"))
+          (match_dup 0)]
+         UNSPEC_ST1_SVE))]
+  "TARGET_SVE"
+  "st1<VNx8_NARROW:Vesize>\t%1.<VNx8_WIDE:Vetype>, %2, %0"
+)
+
+;; Predicated truncate and store, with 4 elements per 128-bit block.
+(define_insn "@aarch64_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>"
+  [(set (match_operand:VNx4_NARROW 0 "memory_operand" "+m")
+       (unspec:VNx4_NARROW
+         [(match_operand:VNx4BI 2 "register_operand" "Upl")
+          (truncate:VNx4_NARROW
+            (match_operand:VNx4_WIDE 1 "register_operand" "w"))
+          (match_dup 0)]
+         UNSPEC_ST1_SVE))]
+  "TARGET_SVE"
+  "st1<VNx4_NARROW:Vesize>\t%1.<VNx4_WIDE:Vetype>, %2, %0"
+)
+
+;; Predicated truncate and store, with 2 elements per 128-bit block.
+(define_insn "@aarch64_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>"
+  [(set (match_operand:VNx2_NARROW 0 "memory_operand" "+m")
+       (unspec:VNx2_NARROW
+         [(match_operand:VNx2BI 2 "register_operand" "Upl")
+          (truncate:VNx2_NARROW
+            (match_operand:VNx2_WIDE 1 "register_operand" "w"))
+          (match_dup 0)]
+         UNSPEC_ST1_SVE))]
+  "TARGET_SVE"
+  "st1<VNx2_NARROW:Vesize>\t%1.<VNx2_WIDE:Vetype>, %2, %0"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Non-temporal contiguous stores
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - STNT1B
+;; - STNT1D
+;; - STNT1H
+;; - STNT1W
+;; -------------------------------------------------------------------------
+
+(define_insn "@aarch64_stnt1<mode>"
+  [(set (match_operand:SVE_ALL 0 "memory_operand" "+m")
+       (unspec:SVE_ALL [(match_operand:<VPRED> 2 "register_operand" "Upl")
+                        (match_operand:SVE_ALL 1 "register_operand" "w")
+                        (match_dup 0)]
+                       UNSPEC_STNT1_SVE))]
+  "TARGET_SVE"
+  "stnt1<Vesize>\t%1.<Vetype>, %2, %0"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Normal scatter stores
+;; -------------------------------------------------------------------------
+;; Includes scatter forms of:
+;; - ST1D
+;; - ST1W
+;; -------------------------------------------------------------------------
+
+;; Unpredicated scatter stores.
+(define_expand "scatter_store<mode>"
   [(set (mem:BLK (scratch))
        (unspec:BLK
          [(match_dup 5)
-          (match_operand:DI 0 "aarch64_reg_or_zero")
+          (match_operand:DI 0 "aarch64_sve_gather_offset_<Vesize>")
           (match_operand:<V_INT_EQUIV> 1 "register_operand")
           (match_operand:DI 2 "const_int_operand")
           (match_operand:DI 3 "aarch64_gather_scale_operand_<Vesize>")
 (define_insn "mask_scatter_store<mode>"
   [(set (mem:BLK (scratch))
        (unspec:BLK
-         [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl, Upl, Upl")
-          (match_operand:DI 0 "aarch64_reg_or_zero" "Z, rk, rk, rk, rk")
-          (match_operand:<V_INT_EQUIV> 1 "register_operand" "w, w, w, w, w")
-          (match_operand:DI 2 "const_int_operand" "i, Z, Ui1, Z, Ui1")
-          (match_operand:DI 3 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, i, i")
-          (match_operand:SVE_S 4 "register_operand" "w, w, w, w, w")]
+         [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+          (match_operand:DI 0 "aarch64_sve_gather_offset_w" "Z, vgw, rk, rk, rk, rk")
+          (match_operand:VNx4SI 1 "register_operand" "w, w, w, w, w, w")
+          (match_operand:DI 2 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1")
+          (match_operand:DI 3 "aarch64_gather_scale_operand_w" "Ui1, Ui1, Ui1, Ui1, i, i")
+          (match_operand:SVE_S 4 "register_operand" "w, w, w, w, w, w")]
          UNSPEC_ST1_SCATTER))]
   "TARGET_SVE"
   "@
    st1w\t%4.s, %5, [%1.s]
+   st1w\t%4.s, %5, [%1.s, #%0]
    st1w\t%4.s, %5, [%0, %1.s, sxtw]
    st1w\t%4.s, %5, [%0, %1.s, uxtw]
    st1w\t%4.s, %5, [%0, %1.s, sxtw %p3]
 (define_insn "mask_scatter_store<mode>"
   [(set (mem:BLK (scratch))
        (unspec:BLK
-         [(match_operand:<VPRED> 5 "register_operand" "Upl, Upl, Upl")
-          (match_operand:DI 0 "aarch64_reg_or_zero" "Z, rk, rk")
-          (match_operand:<V_INT_EQUIV> 1 "register_operand" "w, w, w")
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+          (match_operand:DI 0 "aarch64_sve_gather_offset_d" "Z, vgd, rk, rk")
+          (match_operand:VNx2DI 1 "register_operand" "w, w, w, w")
           (match_operand:DI 2 "const_int_operand")
-          (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, Ui1, i")
-          (match_operand:SVE_D 4 "register_operand" "w, w, w")]
+          (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, Ui1, Ui1, i")
+          (match_operand:SVE_D 4 "register_operand" "w, w, w, w")]
          UNSPEC_ST1_SCATTER))]
   "TARGET_SVE"
   "@
    st1d\t%4.d, %5, [%1.d]
+   st1d\t%4.d, %5, [%1.d, #%0]
    st1d\t%4.d, %5, [%0, %1.d]
    st1d\t%4.d, %5, [%0, %1.d, lsl %p3]"
 )
 
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*mask_scatter_store<mode>_sxtw"
+  [(set (mem:BLK (scratch))
+       (unspec:BLK
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+          (match_operand:DI 0 "register_operand" "rk, rk")
+          (unspec:VNx2DI
+            [(match_operand 6)
+             (sign_extend:VNx2DI
+               (truncate:VNx2SI
+                 (match_operand:VNx2DI 1 "register_operand" "w, w")))]
+            UNSPEC_PRED_X)
+          (match_operand:DI 2 "const_int_operand")
+          (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, i")
+          (match_operand:SVE_D 4 "register_operand" "w, w")]
+         UNSPEC_ST1_SCATTER))]
+  "TARGET_SVE"
+  "@
+   st1d\t%4.d, %5, [%0, %1.d, sxtw]
+   st1d\t%4.d, %5, [%0, %1.d, sxtw %p3]"
+  "&& !rtx_equal_p (operands[5], operands[6])"
+  {
+    operands[6] = copy_rtx (operands[5]);
+  }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*mask_scatter_store<mode>_uxtw"
+  [(set (mem:BLK (scratch))
+       (unspec:BLK
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+          (match_operand:DI 0 "aarch64_reg_or_zero" "rk, rk")
+          (and:VNx2DI
+            (match_operand:VNx2DI 1 "register_operand" "w, w")
+            (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+          (match_operand:DI 2 "const_int_operand")
+          (match_operand:DI 3 "aarch64_gather_scale_operand_d" "Ui1, i")
+          (match_operand:SVE_D 4 "register_operand" "w, w")]
+         UNSPEC_ST1_SCATTER))]
+  "TARGET_SVE"
+  "@
+   st1d\t%4.d, %5, [%0, %1.d, uxtw]
+   st1d\t%4.d, %5, [%0, %1.d, uxtw %p3]"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- Truncating scatter stores
+;; -------------------------------------------------------------------------
+;; Includes scatter forms of:
+;; - ST1B
+;; - ST1H
+;; - ST1W
+;; -------------------------------------------------------------------------
+
+;; Predicated truncating scatter stores for 32-bit elements.  Operand 2 is
+;; true for unsigned extension and false for signed extension.
+(define_insn "@aarch64_scatter_store_trunc<VNx4_NARROW:mode><VNx4_WIDE:mode>"
+  [(set (mem:BLK (scratch))
+       (unspec:BLK
+         [(match_operand:VNx4BI 5 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+          (match_operand:DI 0 "aarch64_sve_gather_offset_<VNx4_NARROW:Vesize>" "Z, vg<VNx4_NARROW:Vesize>, rk, rk, rk, rk")
+          (match_operand:VNx4SI 1 "register_operand" "w, w, w, w, w, w")
+          (match_operand:DI 2 "const_int_operand" "Ui1, Ui1, Z, Ui1, Z, Ui1")
+          (match_operand:DI 3 "aarch64_gather_scale_operand_<VNx4_NARROW:Vesize>" "Ui1, Ui1, Ui1, Ui1, i, i")
+          (truncate:VNx4_NARROW
+            (match_operand:VNx4_WIDE 4 "register_operand" "w, w, w, w, w, w"))]
+         UNSPEC_ST1_SCATTER))]
+  "TARGET_SVE"
+  "@
+   st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%1.s]
+   st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%1.s, #%0]
+   st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, sxtw]
+   st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, uxtw]
+   st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, sxtw %p3]
+   st1<VNx4_NARROW:Vesize>\t%4.s, %5, [%0, %1.s, uxtw %p3]"
+)
+
+;; Predicated truncating scatter stores for 64-bit elements.  The value of
+;; operand 2 doesn't matter in this case.
+(define_insn "@aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>"
+  [(set (mem:BLK (scratch))
+       (unspec:BLK
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl, Upl, Upl")
+          (match_operand:DI 0 "aarch64_sve_gather_offset_<VNx2_NARROW:Vesize>" "Z, vg<VNx2_NARROW:Vesize>, rk, rk")
+          (match_operand:VNx2DI 1 "register_operand" "w, w, w, w")
+          (match_operand:DI 2 "const_int_operand")
+          (match_operand:DI 3 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, Ui1, Ui1, i")
+          (truncate:VNx2_NARROW
+            (match_operand:VNx2_WIDE 4 "register_operand" "w, w, w, w"))]
+         UNSPEC_ST1_SCATTER))]
+  "TARGET_SVE"
+  "@
+   st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%1.d]
+   st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%1.d, #%0]
+   st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d]
+   st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, lsl %p3]"
+)
+
+;; Likewise, but with the offset being sign-extended from 32 bits.
+(define_insn_and_rewrite "*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_sxtw"
+  [(set (mem:BLK (scratch))
+       (unspec:BLK
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+          (match_operand:DI 0 "register_operand" "rk, rk")
+          (unspec:VNx2DI
+            [(match_operand 6)
+             (sign_extend:VNx2DI
+               (truncate:VNx2SI
+                 (match_operand:VNx2DI 1 "register_operand" "w, w")))]
+            UNSPEC_PRED_X)
+          (match_operand:DI 2 "const_int_operand")
+          (match_operand:DI 3 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+          (truncate:VNx2_NARROW
+            (match_operand:VNx2_WIDE 4 "register_operand" "w, w"))]
+         UNSPEC_ST1_SCATTER))]
+  "TARGET_SVE"
+  "@
+   st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, sxtw]
+   st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, sxtw %p3]"
+  "&& !rtx_equal_p (operands[5], operands[6])"
+  {
+    operands[6] = copy_rtx (operands[5]);
+  }
+)
+
+;; Likewise, but with the offset being zero-extended from 32 bits.
+(define_insn "*aarch64_scatter_store_trunc<VNx2_NARROW:mode><VNx2_WIDE:mode>_uxtw"
+  [(set (mem:BLK (scratch))
+       (unspec:BLK
+         [(match_operand:VNx2BI 5 "register_operand" "Upl, Upl")
+          (match_operand:DI 0 "aarch64_reg_or_zero" "rk, rk")
+          (and:VNx2DI
+            (match_operand:VNx2DI 1 "register_operand" "w, w")
+            (match_operand:VNx2DI 6 "aarch64_sve_uxtw_immediate"))
+          (match_operand:DI 2 "const_int_operand")
+          (match_operand:DI 3 "aarch64_gather_scale_operand_<VNx2_NARROW:Vesize>" "Ui1, i")
+          (truncate:VNx2_NARROW
+            (match_operand:VNx2_WIDE 4 "register_operand" "w, w"))]
+         UNSPEC_ST1_SCATTER))]
+  "TARGET_SVE"
+  "@
+   st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, uxtw]
+   st1<VNx2_NARROW:Vesize>\t%4.d, %5, [%0, %1.d, uxtw %p3]"
+)
+
 ;; =========================================================================
 ;; == Vector creation
 ;; =========================================================================
 ;; ---- [INT,FP] Duplicate element
 ;; -------------------------------------------------------------------------
 ;; Includes:
+;; - DUP
 ;; - MOV
 ;; - LD1RB
 ;; - LD1RD
 ;; duplicate the input and do a compare with zero.
 (define_expand "vec_duplicate<mode>"
   [(set (match_operand:PRED_ALL 0 "register_operand")
-       (vec_duplicate:PRED_ALL (match_operand 1 "register_operand")))]
+       (vec_duplicate:PRED_ALL (match_operand:QI 1 "register_operand")))]
   "TARGET_SVE"
   {
     rtx tmp = gen_reg_rtx (DImode);
 ;; ---- [INT,FP] Extract active element
 ;; -------------------------------------------------------------------------
 ;; Includes:
+;; - LASTA
 ;; - LASTB
 ;; -------------------------------------------------------------------------
 
 ;; Extract the last active element of operand 1 into operand 0.
 ;; If no elements are active, extract the last inactive element instead.
-(define_insn "extract_last_<mode>"
-  [(set (match_operand:<VEL> 0 "register_operand" "=r, w")
+(define_insn "@extract_<last_op>_<mode>"
+  [(set (match_operand:<VEL> 0 "register_operand" "=?r, w")
        (unspec:<VEL>
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
           (match_operand:SVE_ALL 2 "register_operand" "w, w")]
-         UNSPEC_LASTB))]
+         LAST))]
   "TARGET_SVE"
   "@
-   lastb\t%<vwcore>0, %1, %2.<Vetype>
-   lastb\t%<Vetype>0, %1, %2.<Vetype>"
+   last<ab>\t%<vwcore>0, %1, %2.<Vetype>
+   last<ab>\t%<Vetype>0, %1, %2.<Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
 )
 
 ;; Integer unary arithmetic predicated with a PTRUE.
-(define_insn "*<optab><mode>2"
+(define_insn "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_I 0 "register_operand" "=w")
        (unspec:SVE_I
          [(match_operand:<VPRED> 1 "register_operand" "Upl")
   "<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
 )
 
-;; Predicated integer unary arithmetic, merging with the first input.
-(define_insn "*cond_<optab><mode>_2"
-  [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
+;; Predicated integer unary arithmetic with merging.
+(define_expand "@cond_<optab><mode>"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand")
+          (SVE_INT_UNARY:SVE_I
+            (match_operand:SVE_I 2 "register_operand"))
+          (match_operand:SVE_I 3 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+)
+
+;; Predicated integer unary arithmetic, merging with the first input.
+(define_insn "*cond_<optab><mode>_2"
+  [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
        (unspec:SVE_I
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
           (SVE_INT_UNARY:SVE_I
 ;; ---- [INT] General unary arithmetic corresponding to unspecs
 ;; -------------------------------------------------------------------------
 ;; Includes
+;; - RBIT
 ;; - REVB
 ;; - REVH
 ;; - REVW
   "<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
 )
 
+;; Predicated integer unary operations with merging.
+(define_insn "@cond_<optab><mode>"
+  [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w, ?&w")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
+          (unspec:SVE_I
+            [(match_operand:SVE_I 2 "register_operand" "w, w, w")]
+            SVE_INT_UNARY)
+          (match_operand:SVE_I 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+         UNSPEC_SEL))]
+  "TARGET_SVE && <elem_bits> >= <min_elem_bits>"
+  "@
+   <sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
+   movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>
+   movprfx\t%0, %3\;<sve_int_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
+  [(set_attr "movprfx" "*,yes,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Sign extension
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - SXTB
+;; - SXTH
+;; - SXTW
+;; -------------------------------------------------------------------------
+
+;; Predicated SXT[BHW].
+(define_insn "@aarch64_pred_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>"
+  [(set (match_operand:SVE_HSDI 0 "register_operand" "=w")
+       (unspec:SVE_HSDI
+         [(match_operand:<VPRED> 1 "register_operand" "Upl")
+          (sign_extend:SVE_HSDI
+            (truncate:SVE_PARTIAL
+              (match_operand:SVE_HSDI 2 "register_operand" "w")))]
+         UNSPEC_PRED_X))]
+  "TARGET_SVE && (~<narrower_mask> & <self_mask>) == 0"
+  "sxt<SVE_PARTIAL:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>"
+)
+
+;; Predicated SXT[BHW] with merging.
+(define_insn "@aarch64_cond_sxt<SVE_HSDI:mode><SVE_PARTIAL:mode>"
+  [(set (match_operand:SVE_HSDI 0 "register_operand" "=w, ?&w, ?&w")
+       (unspec:SVE_HSDI
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
+          (sign_extend:SVE_HSDI
+            (truncate:SVE_PARTIAL
+              (match_operand:SVE_HSDI 2 "register_operand" "w, w, w")))
+          (match_operand:SVE_HSDI 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+         UNSPEC_SEL))]
+  "TARGET_SVE && (~<narrower_mask> & <self_mask>) == 0"
+  "@
+   sxt<SVE_PARTIAL:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
+   movprfx\t%0.<SVE_HSDI:Vetype>, %1/z, %2.<SVE_HSDI:Vetype>\;sxt<SVE_PARTIAL:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>
+   movprfx\t%0, %3\;sxt<SVE_PARTIAL:Vesize>\t%0.<SVE_HSDI:Vetype>, %1/m, %2.<SVE_HSDI:Vetype>"
+  [(set_attr "movprfx" "*,yes,yes")]
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [INT] Zero extension
 ;; -------------------------------------------------------------------------
 ;; -------------------------------------------------------------------------
 ;; ---- [INT] Logical inverse
 ;; -------------------------------------------------------------------------
+;; Includes:
+;; - CNOT
+;; -------------------------------------------------------------------------
 
 ;; Predicated logical inverse.
+(define_expand "@aarch64_pred_cnot<mode>"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (unspec:SVE_I
+         [(unspec:<VPRED>
+            [(match_operand:<VPRED> 1 "register_operand")
+             (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+             (eq:<VPRED>
+               (match_operand:SVE_I 3 "register_operand")
+               (match_dup 4))]
+            UNSPEC_PRED_Z)
+          (match_dup 5)
+          (match_dup 4)]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+  {
+    operands[4] = CONST0_RTX (<MODE>mode);
+    operands[5] = CONST1_RTX (<MODE>mode);
+  }
+)
+
 (define_insn "*cnot<mode>"
   [(set (match_operand:SVE_I 0 "register_operand" "=w")
        (unspec:SVE_I
   "cnot\t%0.<Vetype>, %1/m, %2.<Vetype>"
 )
 
+;; Predicated logical inverse with merging.
+(define_expand "@cond_cnot<mode>"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand")
+          (unspec:SVE_I
+            [(unspec:<VPRED>
+               [(match_dup 4)
+                (const_int SVE_KNOWN_PTRUE)
+                (eq:<VPRED>
+                  (match_operand:SVE_I 2 "register_operand")
+                  (match_dup 5))]
+               UNSPEC_PRED_Z)
+             (match_dup 6)
+             (match_dup 5)]
+            UNSPEC_SEL)
+          (match_operand:SVE_I 3 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+  {
+    operands[4] = CONSTM1_RTX (<VPRED>mode);
+    operands[5] = CONST0_RTX (<MODE>mode);
+    operands[6] = CONST1_RTX (<MODE>mode);
+  }
+)
+
 ;; Predicated logical inverse, merging with the first input.
 (define_insn_and_rewrite "*cond_cnot<mode>_2"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
   [(set_attr "movprfx" "*,yes,yes")]
 )
 
+;; -------------------------------------------------------------------------
+;; ---- [FP<-INT] General unary arithmetic that maps to unspecs
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - FEXPA
+;; -------------------------------------------------------------------------
+
+;; Unpredicated unary operations that take an integer and return a float.
+(define_insn "@aarch64_sve_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w")
+       (unspec:SVE_F [(match_operand:<V_INT_EQUIV> 1 "register_operand" "w")]
+                     SVE_FP_UNARY_INT))]
+  "TARGET_SVE"
+  "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>"
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [FP] General unary arithmetic corresponding to unspecs
 ;; -------------------------------------------------------------------------
 ;; Includes:
 ;; - FABS
 ;; - FNEG
+;; - FRECPE
+;; - FRECPX
 ;; - FRINTA
 ;; - FRINTI
 ;; - FRINTM
 ;; - FRINTP
 ;; - FRINTX
 ;; - FRINTZ
+;; - FRSQRT
 ;; - FSQRT
 ;; -------------------------------------------------------------------------
 
+;; Unpredicated floating-point unary operations.
+(define_insn "@aarch64_sve_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w")
+       (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "w")]
+                     SVE_FP_UNARY))]
+  "TARGET_SVE"
+  "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>"
+)
+
 ;; Unpredicated floating-point unary operations.
 (define_expand "<optab><mode>2"
   [(set (match_operand:SVE_F 0 "register_operand")
 )
 
 ;; Predicated floating-point unary operations.
-(define_insn "*<optab><mode>2"
+(define_insn "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_F 0 "register_operand" "=w")
        (unspec:SVE_F
          [(match_operand:<VPRED> 1 "register_operand" "Upl")
   "<sve_fp_op>\t%0.<Vetype>, %1/m, %2.<Vetype>"
 )
 
+;; Predicated floating-point unary arithmetic with merging.
+(define_expand "@cond_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand")
+          (unspec:SVE_F
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:SVE_F 2 "register_operand")]
+            SVE_COND_FP_UNARY)
+          (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+)
+
 ;; Predicated floating-point unary arithmetic, merging with the first input.
 (define_insn_and_rewrite "*cond_<optab><mode>_2"
   [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
 ;; and third alternatives, but using Upa or X isn't likely to gain much
 ;; and would make the instruction seem less uniform to the register
 ;; allocator.
-(define_insn_and_split "*<optab><mode>3"
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w, ?&w")
        (unspec:SVE_I
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
 ;; - ADR
 ;; -------------------------------------------------------------------------
 
-;; Unshifted ADR, with the offset being zero-extended from the low 32 bits.
-(define_insn "*aarch64_adr_uxtw"
+;; An unshifted and unscaled ADR.  This is functionally equivalent to an ADD,
+;; but the svadrb intrinsics should preserve the user's choice.
+(define_insn "@aarch64_adr<mode>"
+  [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
+       (unspec:SVE_SDI
+         [(match_operand:SVE_SDI 1 "register_operand" "w")
+          (match_operand:SVE_SDI 2 "register_operand" "w")]
+         UNSPEC_ADR))]
+  "TARGET_SVE"
+  "adr\t%0.<Vetype>, [%1.<Vetype>, %2.<Vetype>]"
+)
+
+;; Same, but with the offset being sign-extended from the low 32 bits.
+(define_insn_and_rewrite "*aarch64_adr_sxtw"
+  [(set (match_operand:VNx2DI 0 "register_operand" "=w")
+       (unspec:VNx2DI
+         [(match_operand:VNx2DI 1 "register_operand" "w")
+          (unspec:VNx2DI
+            [(match_operand 3)
+             (sign_extend:VNx2DI
+               (truncate:VNx2SI
+                 (match_operand:VNx2DI 2 "register_operand" "w")))]
+            UNSPEC_PRED_X)]
+         UNSPEC_ADR))]
+  "TARGET_SVE"
+  "adr\t%0.d, [%1.d, %2.d, sxtw]"
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (VNx2BImode);
+  }
+)
+
+;; Same, but with the offset being zero-extended from the low 32 bits.
+(define_insn "*aarch64_adr_uxtw_unspec"
+  [(set (match_operand:VNx2DI 0 "register_operand" "=w")
+       (unspec:VNx2DI
+         [(match_operand:VNx2DI 1 "register_operand" "w")
+          (and:VNx2DI
+            (match_operand:VNx2DI 2 "register_operand" "w")
+            (match_operand:VNx2DI 3 "aarch64_sve_uxtw_immediate"))]
+         UNSPEC_ADR))]
+  "TARGET_SVE"
+  "adr\t%0.d, [%1.d, %2.d, uxtw]"
+)
+
+;; Same, matching as a PLUS rather than unspec.
+(define_insn "*aarch64_adr_uxtw_and"
   [(set (match_operand:VNx2DI 0 "register_operand" "=w")
        (plus:VNx2DI
          (and:VNx2DI
 )
 
 ;; ADR with a nonzero shift.
+(define_expand "@aarch64_adr<mode>_shift"
+  [(set (match_operand:SVE_SDI 0 "register_operand")
+       (plus:SVE_SDI
+         (unspec:SVE_SDI
+           [(match_dup 4)
+            (ashift:SVE_SDI
+              (match_operand:SVE_SDI 2 "register_operand")
+              (match_operand:SVE_SDI 3 "const_1_to_3_operand"))]
+           UNSPEC_PRED_X)
+         (match_operand:SVE_SDI 1 "register_operand")))]
+  "TARGET_SVE"
+  {
+    operands[4] = CONSTM1_RTX (<VPRED>mode);
+  }
+)
+
 (define_insn_and_rewrite "*aarch64_adr<mode>_shift"
   [(set (match_operand:SVE_SDI 0 "register_operand" "=w")
        (plus:SVE_SDI
   }
 )
 
+;; Same, but with the index being sign-extended from the low 32 bits.
+(define_insn_and_rewrite "*aarch64_adr_shift_sxtw"
+  [(set (match_operand:VNx2DI 0 "register_operand" "=w")
+       (plus:VNx2DI
+         (unspec:VNx2DI
+           [(match_operand 4)
+            (ashift:VNx2DI
+              (unspec:VNx2DI
+                [(match_operand 5)
+                 (sign_extend:VNx2DI
+                   (truncate:VNx2SI
+                     (match_operand:VNx2DI 2 "register_operand" "w")))]
+                UNSPEC_PRED_X)
+              (match_operand:VNx2DI 3 "const_1_to_3_operand"))]
+           UNSPEC_PRED_X)
+         (match_operand:VNx2DI 1 "register_operand" "w")))]
+  "TARGET_SVE"
+  "adr\t%0.d, [%1.d, %2.d, sxtw %3]"
+  "&& (!CONSTANT_P (operands[4]) || !CONSTANT_P (operands[5]))"
+  {
+    operands[5] = operands[4] = CONSTM1_RTX (VNx2BImode);
+  }
+)
+
 ;; Same, but with the index being zero-extended from the low 32 bits.
 (define_insn_and_rewrite "*aarch64_adr_shift_uxtw"
   [(set (match_operand:VNx2DI 0 "register_operand" "=w")
   "TARGET_SVE"
   {
     rtx pred = aarch64_ptrue_reg (<VPRED>mode);
-    emit_insn (gen_aarch64_<su>abd<mode>_3 (operands[0], pred, operands[1],
-                                           operands[2]));
+    emit_insn (gen_aarch64_pred_<su>abd<mode> (operands[0], pred, operands[1],
+                                              operands[2]));
     DONE;
   }
 )
 
 ;; Predicated integer absolute difference.
-(define_insn "aarch64_<su>abd<mode>_3"
+(define_insn "@aarch64_pred_<su>abd<mode>"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
        (unspec:SVE_I
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   [(set_attr "movprfx" "*,yes")]
 )
 
+(define_expand "@aarch64_cond_<su>abd<mode>"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand")
+          (minus:SVE_I
+            (unspec:SVE_I
+              [(match_dup 1)
+               (USMAX:SVE_I
+                 (match_operand:SVE_I 2 "register_operand")
+                 (match_operand:SVE_I 3 "register_operand"))]
+              UNSPEC_PRED_X)
+            (unspec:SVE_I
+              [(match_dup 1)
+               (<max_opp>:SVE_I
+                 (match_dup 2)
+                 (match_dup 3))]
+              UNSPEC_PRED_X))
+          (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+{
+  if (rtx_equal_p (operands[3], operands[4]))
+    std::swap (operands[2], operands[3]);
+})
+
 ;; Predicated integer absolute difference, merging with the first input.
 (define_insn_and_rewrite "*aarch64_cond_<su>abd<mode>_2"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
   [(set_attr "movprfx" "yes")]
 )
 
+;; -------------------------------------------------------------------------
+;; ---- [INT] Saturating addition and subtraction
+;; -------------------------------------------------------------------------
+;; - SQADD
+;; - SQSUB
+;; - UQADD
+;; - UQSUB
+;; -------------------------------------------------------------------------
+
+;; Unpredicated saturating signed addition and subtraction.
+(define_insn "@aarch64_<su_optab><optab><mode>"
+  [(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w, ?&w, w")
+       (SBINQOPS:SVE_I
+         (match_operand:SVE_I 1 "register_operand" "0, 0, w, w, w")
+         (match_operand:SVE_I 2 "aarch64_sve_sqadd_operand" "vsQ, vsS, vsQ, vsS, w")))]
+  "TARGET_SVE"
+  "@
+   <binqops_op>\t%0.<Vetype>, %0.<Vetype>, #%D2
+   <binqops_op_rev>\t%0.<Vetype>, %0.<Vetype>, #%N2
+   movprfx\t%0, %1\;<binqops_op>\t%0.<Vetype>, %0.<Vetype>, #%D2
+   movprfx\t%0, %1\;<binqops_op_rev>\t%0.<Vetype>, %0.<Vetype>, #%N2
+   <binqops_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "movprfx" "*,*,yes,yes,*")]
+)
+
+;; Unpredicated saturating unsigned addition and subtraction.
+(define_insn "@aarch64_<su_optab><optab><mode>"
+  [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w, w")
+       (UBINQOPS:SVE_I
+         (match_operand:SVE_I 1 "register_operand" "0, w, w")
+         (match_operand:SVE_I 2 "aarch64_sve_arith_operand" "vsa, vsa, w")))]
+  "TARGET_SVE"
+  "@
+   <binqops_op>\t%0.<Vetype>, %0.<Vetype>, #%D2
+   movprfx\t%0, %1\;<binqops_op>\t%0.<Vetype>, %0.<Vetype>, #%D2
+   <binqops_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+  [(set_attr "movprfx" "*,yes,*")]
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [INT] Highpart multiplication
 ;; -------------------------------------------------------------------------
 )
 
 ;; Predicated highpart multiplication.
-(define_insn "*<su>mul<mode>3_highpart"
+(define_insn "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
        (unspec:SVE_I
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   [(set_attr "movprfx" "*,yes")]
 )
 
+;; Predicated highpart multiplications with merging.
+(define_expand "@cond_<optab><mode>"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand")
+          (unspec:SVE_I
+            [(match_operand:SVE_I 2 "register_operand")
+             (match_operand:SVE_I 3 "register_operand")]
+            MUL_HIGHPART)
+          (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+{
+  /* Only target code is aware of these operations, so we don't need
+     to handle the fully-general case.  */
+  gcc_assert (rtx_equal_p (operands[2], operands[4])
+             || CONSTANT_P (operands[4]));
+})
+
+;; Predicated highpart multiplications, merging with the first input.
+(define_insn "*cond_<optab><mode>_2"
+  [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (unspec:SVE_I
+            [(match_operand:SVE_I 2 "register_operand" "0, w")
+             (match_operand:SVE_I 3 "register_operand" "w, w")]
+            MUL_HIGHPART)
+          (match_dup 2)]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+  "@
+   <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+   movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+  [(set_attr "movprfx" "*,yes")])
+
+;; Predicated highpart multiplications, merging with zero.
+(define_insn "*cond_<optab><mode>_z"
+  [(set (match_operand:SVE_I 0 "register_operand" "=&w, &w")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (unspec:SVE_I
+            [(match_operand:SVE_I 2 "register_operand" "%0, w")
+             (match_operand:SVE_I 3 "register_operand" "w, w")]
+            MUL_HIGHPART)
+          (match_operand:SVE_I 4 "aarch64_simd_imm_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+  "@
+   movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+   movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+  [(set_attr "movprfx" "yes")])
+
 ;; -------------------------------------------------------------------------
 ;; ---- [INT] Division
 ;; -------------------------------------------------------------------------
 )
 
 ;; Integer division predicated with a PTRUE.
-(define_insn "*<optab><mode>3"
+(define_insn "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_SDI 0 "register_operand" "=w, w, ?&w")
        (unspec:SVE_SDI
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
 )
 
 ;; Predicated integer division with merging.
-(define_expand "cond_<optab><mode>"
+(define_expand "@cond_<optab><mode>"
   [(set (match_operand:SVE_SDI 0 "register_operand")
        (unspec:SVE_SDI
          [(match_operand:<VPRED> 1 "register_operand")
 ;; - BIC
 ;; -------------------------------------------------------------------------
 
+;; Unpredicated BIC.
+(define_expand "@aarch64_bic<mode>"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (and:SVE_I
+         (unspec:SVE_I
+           [(match_dup 3)
+            (not:SVE_I (match_operand:SVE_I 2 "register_operand"))]
+           UNSPEC_PRED_X)
+         (match_operand:SVE_I 1 "register_operand")))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+)
+
+;; Predicated BIC.
 (define_insn_and_rewrite "*bic<mode>3"
   [(set (match_operand:SVE_I 0 "register_operand" "=w")
        (and:SVE_I
   }
 )
 
+;; Predicated BIC with merging.
+(define_expand "@cond_bic<mode>"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand")
+          (and:SVE_I
+            (not:SVE_I (match_operand:SVE_I 3 "register_operand"))
+            (match_operand:SVE_I 2 "register_operand"))
+          (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+)
+
 ;; Predicated integer BIC, merging with the first input.
 (define_insn "*cond_bic<mode>_2"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
 )
 
 ;; -------------------------------------------------------------------------
-;; ---- [INT] Shifts
+;; ---- [INT] Shifts (rounding towards -Inf)
 ;; -------------------------------------------------------------------------
 ;; Includes:
 ;; - ASR
+;; - ASRR
 ;; - LSL
+;; - LSLR
 ;; - LSR
+;; - LSRR
 ;; -------------------------------------------------------------------------
 
 ;; Unpredicated shift by a scalar, which expands into one of the vector
 ;; the predicate for the first alternative, but using Upa or X isn't
 ;; likely to gain much and would make the instruction seem less uniform
 ;; to the register allocator.
-(define_insn_and_split "*v<optab><mode>3"
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, w, ?&w")
        (unspec:SVE_I
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
   [(set_attr "movprfx" "yes")]
 )
 
-;; -------------------------------------------------------------------------
-;; ---- [INT] Shifts (rounding towards 0)
-;; -------------------------------------------------------------------------
-;; Includes:
-;; - ASRD
-;; -------------------------------------------------------------------------
+;; Unpredicated shifts of narrow elements by 64-bit amounts.
+(define_insn "@aarch64_sve_<sve_int_op><mode>"
+  [(set (match_operand:SVE_BHSI 0 "register_operand" "=w")
+       (unspec:SVE_BHSI
+         [(match_operand:SVE_BHSI 1 "register_operand" "w")
+          (match_operand:VNx2DI 2 "register_operand" "w")]
+         SVE_SHIFT_WIDE))]
+  "TARGET_SVE"
+  "<sve_int_op>\t%0.<Vetype>, %1.<Vetype>, %2.d"
+)
 
-;; Unpredicated arithmetic right shift for division by power-of-2.
-(define_expand "sdiv_pow2<mode>3"
-  [(set (match_operand:SVE_I 0 "register_operand")
-       (unspec:SVE_I
-         [(match_dup 3)
-          (unspec:SVE_I
-            [(match_operand:SVE_I 1 "register_operand")
-             (match_operand 2 "aarch64_simd_rshift_imm")]
-           UNSPEC_ASRD)]
-        UNSPEC_PRED_X))]
+;; Merging predicated shifts of narrow elements by 64-bit amounts.
+(define_expand "@cond_<sve_int_op><mode>"
+  [(set (match_operand:SVE_BHSI 0 "register_operand")
+       (unspec:SVE_BHSI
+         [(match_operand:<VPRED> 1 "register_operand")
+          (unspec:SVE_BHSI
+            [(match_operand:SVE_BHSI 2 "register_operand")
+             (match_operand:VNx2DI 3 "register_operand")]
+            SVE_SHIFT_WIDE)
+          (match_operand:SVE_BHSI 4 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
   "TARGET_SVE"
-  {
-    operands[3] = aarch64_ptrue_reg (<VPRED>mode);
-  }
 )
 
-;; Predicated ASRD with PTRUE.
-(define_insn "*sdiv_pow2<mode>3"
+;; Predicated shifts of narrow elements by 64-bit amounts, merging with
+;; the first input.
+(define_insn "*cond_<sve_int_op><mode>_m"
+  [(set (match_operand:SVE_BHSI 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_BHSI
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (unspec:SVE_BHSI
+            [(match_operand:SVE_BHSI 2 "register_operand" "0, w")
+             (match_operand:VNx2DI 3 "register_operand" "w, w")]
+            SVE_SHIFT_WIDE)
+          (match_dup 2)]
+        UNSPEC_SEL))]
+  "TARGET_SVE"
+  "@
+   <sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d
+   movprfx\t%0, %2\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d"
+  [(set_attr "movprfx" "*, yes")])
+
+;; Predicated shifts of narrow elements by 64-bit amounts, merging with zero.
+(define_insn "*cond_<sve_int_op><mode>_z"
+  [(set (match_operand:SVE_BHSI 0 "register_operand" "=&w, &w")
+       (unspec:SVE_BHSI
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (unspec:SVE_BHSI
+            [(match_operand:SVE_BHSI 2 "register_operand" "0, w")
+             (match_operand:VNx2DI 3 "register_operand" "w, w")]
+            SVE_SHIFT_WIDE)
+          (match_operand:SVE_BHSI 4 "aarch64_simd_imm_zero")]
+        UNSPEC_SEL))]
+  "TARGET_SVE"
+  "@
+   movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d
+   movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_int_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.d"
+  [(set_attr "movprfx" "yes")])
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Shifts (rounding towards 0)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - ASRD
+;; -------------------------------------------------------------------------
+
+;; Unpredicated ASRD.
+(define_expand "sdiv_pow2<mode>3"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (unspec:SVE_I
+         [(match_dup 3)
+          (unspec:SVE_I
+            [(match_operand:SVE_I 1 "register_operand")
+             (match_operand 2 "aarch64_simd_rshift_imm")]
+            UNSPEC_ASRD)
+          (match_dup 1)]
+        UNSPEC_SEL))]
+  "TARGET_SVE"
+  {
+    operands[3] = aarch64_ptrue_reg (<VPRED>mode);
+  }
+)
+
+;; Predicated ASRD with merging.
+(define_expand "@cond_asrd<mode>"
+  [(set (match_operand:SVE_I 0 "register_operand")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand")
+          (unspec:SVE_I
+            [(match_operand:SVE_I 2 "register_operand")
+             (match_operand:SVE_I 3 "aarch64_simd_rshift_imm")]
+            UNSPEC_ASRD)
+          (match_operand:SVE_I 4 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+)
+
+;; Predicated ASRD, merging with the first input.
+(define_insn "*cond_asrd<mode>_2"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, ?&w")
        (unspec:SVE_I
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
           (unspec:SVE_I
             [(match_operand:SVE_I 2 "register_operand" "0, w")
-             (match_operand 3 "aarch64_simd_rshift_imm")]
-           UNSPEC_ASRD)]
-        UNSPEC_PRED_X))]
+             (match_operand:SVE_I 3 "aarch64_simd_rshift_imm")]
+            UNSPEC_ASRD)
+          (match_dup 2)]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+  "@
+   asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
+   movprfx\t%0, %2\;asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3"
+  [(set_attr "movprfx" "*,yes")])
+
+;; Predicated ASRD, merging with zero.
+(define_insn "*cond_asrd<mode>_z"
+  [(set (match_operand:SVE_I 0 "register_operand" "=w")
+       (unspec:SVE_I
+         [(match_operand:<VPRED> 1 "register_operand" "Upl")
+          (unspec:SVE_I
+            [(match_operand:SVE_I 2 "register_operand" "w")
+             (match_operand:SVE_I 3 "aarch64_simd_rshift_imm")]
+            UNSPEC_ASRD)
+          (match_operand:SVE_I 4 "aarch64_simd_imm_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+  "movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3"
+  [(set_attr "movprfx" "yes")])
+
+;; -------------------------------------------------------------------------
+;; ---- [FP<-INT] General binary arithmetic corresponding to unspecs
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - FSCALE
+;; - FTSMUL
+;; - FTSSEL
+;; -------------------------------------------------------------------------
+
+;; Unpredicated floating-point binary operations that take an integer as
+;; their second operand.
+(define_insn "@aarch64_sve_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w")
+       (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "w")
+                      (match_operand:<V_INT_EQUIV> 2 "register_operand" "w")]
+                     SVE_FP_BINARY_INT))]
+  "TARGET_SVE"
+  "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+)
+
+;; Predicated floating-point binary operations that take an integer
+;; as their second operand.
+(define_insn "@aarch64_pred_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (match_operand:SI 4 "aarch64_sve_gp_strictness")
+          (match_operand:SVE_F 2 "register_operand" "0, w")
+          (match_operand:<V_INT_EQUIV> 3 "register_operand" "w, w")]
+         SVE_COND_FP_BINARY_INT))]
+  "TARGET_SVE"
+  "@
+   <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+   movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated floating-point binary operations with merging, taking an
+;; integer as their second operand.
+(define_expand "@cond_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand")
+          (unspec:SVE_F
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:SVE_F 2 "register_operand")
+             (match_operand:<V_INT_EQUIV> 3 "register_operand")]
+            SVE_COND_FP_BINARY_INT)
+          (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
   "TARGET_SVE"
+)
+
+;; Predicated floating-point binary operations that take an integer as their
+;; second operand, with inactive lanes coming from the first operand.
+(define_insn_and_rewrite "*cond_<optab><mode>_2"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (unspec:SVE_F
+            [(match_operand 4)
+             (match_operand:SI 5 "aarch64_sve_gp_strictness")
+             (match_operand:SVE_F 2 "register_operand" "0, w")
+             (match_operand:<V_INT_EQUIV> 3 "register_operand" "w, w")]
+            SVE_COND_FP_BINARY_INT)
+          (match_dup 2)]
+         UNSPEC_SEL))]
+  "TARGET_SVE && aarch64_sve_pred_dominates_p (&operands[4], operands[1])"
   "@
-  asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
-  movprfx\t%0, %2\;asrd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3"
+   <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+   movprfx\t%0, %2\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
+  "&& !rtx_equal_p (operands[1], operands[4])"
+  {
+    operands[4] = copy_rtx (operands[1]);
+  }
   [(set_attr "movprfx" "*,yes")]
 )
 
+;; Predicated floating-point binary operations that take an integer as
+;; their second operand, with the values of inactive lanes being distinct
+;; from the other inputs.
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
+  [(set (match_operand:SVE_F 0 "register_operand" "=&w, &w, &w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
+          (unspec:SVE_F
+            [(match_operand 5)
+             (match_operand:SI 6 "aarch64_sve_gp_strictness")
+             (match_operand:SVE_F 2 "register_operand" "0, w, w, w")
+             (match_operand:<V_INT_EQUIV> 3 "register_operand" "w, w, w, w")]
+            SVE_COND_FP_BINARY_INT)
+          (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero" "Dz, Dz, 0, w")]
+         UNSPEC_SEL))]
+  "TARGET_SVE
+   && !rtx_equal_p (operands[2], operands[4])
+   && aarch64_sve_pred_dominates_p (&operands[5], operands[1])"
+  "@
+   movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+   movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+   movprfx\t%0.<Vetype>, %1/m, %2.<Vetype>\;<sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+   #"
+  "&& 1"
+  {
+    if (reload_completed
+        && register_operand (operands[4], <MODE>mode)
+        && !rtx_equal_p (operands[0], operands[4]))
+      {
+       emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[2],
+                                                operands[4], operands[1]));
+       operands[4] = operands[2] = operands[0];
+      }
+    else if (!rtx_equal_p (operands[1], operands[5]))
+      operands[5] = copy_rtx (operands[1]);
+    else
+      FAIL;
+  }
+  [(set_attr "movprfx" "yes")]
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [FP] General binary arithmetic corresponding to rtx codes
 ;; -------------------------------------------------------------------------
 ;; - FADD    (constant forms handled in the "Addition" section)
 ;; - FDIV
 ;; - FDIVR
+;; - FMAX
 ;; - FMAXNM  (including #0.0 and #1.0)
+;; - FMIN
 ;; - FMINNM  (including #0.0 and #1.0)
 ;; - FMUL    (including #0.5 and #2.0)
+;; - FMULX
+;; - FRECPS
+;; - FRSQRTS
 ;; - FSUB    (constant forms handled in the "Addition" section)
 ;; - FSUBR   (constant forms handled in the "Subtraction" section)
 ;; -------------------------------------------------------------------------
 
 ;; Unpredicated floating-point binary operations.
+(define_insn "@aarch64_sve_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w")
+       (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "w")
+                      (match_operand:SVE_F 2 "register_operand" "w")]
+                     SVE_FP_BINARY))]
+  "TARGET_SVE"
+  "<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>"
+)
+
+;; Unpredicated floating-point binary operations that need to be predicated
+;; for SVE.
 (define_expand "<optab><mode>3"
   [(set (match_operand:SVE_F 0 "register_operand")
        (unspec:SVE_F
 )
 
 ;; Predicated floating-point binary operations that have no immediate forms.
-(define_insn "*<optab><mode>3"
+(define_insn "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
        (unspec:SVE_F
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
 )
 
 ;; Predicated floating-point operations with merging.
-(define_expand "cond_<optab><mode>"
+(define_expand "@cond_<optab><mode>"
   [(set (match_operand:SVE_F 0 "register_operand")
        (unspec:SVE_F
          [(match_operand:<VPRED> 1 "register_operand")
 ;; -------------------------------------------------------------------------
 
 ;; Predicated floating-point addition.
-(define_insn_and_split "*add<mode>3"
-  [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, ?&w, ?&w")
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, w, ?&w, ?&w, ?&w")
        (unspec:SVE_F
-         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl")
-          (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, i, Z, i, i")
-          (match_operand:SVE_F 2 "register_operand" "%0, 0, w, w, w")
-          (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_operand" "vsA, vsN, w, vsA, vsN")]
-         UNSPEC_COND_FADD))]
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl, Upl")
+          (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, i, Z, Ui1, i, i, Ui1")
+          (match_operand:SVE_F 2 "register_operand" "%0, 0, w, 0, w, w, w")
+          (match_operand:SVE_F 3 "aarch64_sve_float_arith_with_sub_operand" "vsA, vsN, w, w, vsA, vsN, w")]
+         SVE_COND_FP_ADD))]
   "TARGET_SVE"
   "@
    fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
    fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
    #
+   fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
    movprfx\t%0, %2\;fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
-   movprfx\t%0, %2\;fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3"
+   movprfx\t%0, %2\;fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, #%N3
+   movprfx\t%0, %2\;fadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   ; Split the unpredicated form after reload, so that we don't have
   ; the unnecessary PTRUE.
   "&& reload_completed
-   && register_operand (operands[3], <MODE>mode)"
+   && register_operand (operands[3], <MODE>mode)
+   && INTVAL (operands[4]) == SVE_RELAXED_GP"
   [(set (match_dup 0) (plus:SVE_F (match_dup 2) (match_dup 3)))]
   ""
-  [(set_attr "movprfx" "*,*,*,yes,yes")]
+  [(set_attr "movprfx" "*,*,*,*,yes,yes,yes")]
 )
 
 ;; Predicated floating-point addition of a constant, merging with the
 
 ;; Register merging forms are handled through SVE_COND_FP_BINARY.
 
+;; -------------------------------------------------------------------------
+;; ---- [FP] Complex addition
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - FCADD
+;; -------------------------------------------------------------------------
+
+;; Predicated FCADD.
+(define_insn "@aarch64_pred_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (match_operand:SI 4 "aarch64_sve_gp_strictness")
+          (match_operand:SVE_F 2 "register_operand" "0, w")
+          (match_operand:SVE_F 3 "register_operand" "w, w")]
+         SVE_COND_FCADD))]
+  "TARGET_SVE"
+  "@
+   fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+   movprfx\t%0, %2\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>"
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated FCADD with merging.
+(define_expand "@cond_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand")
+          (unspec:SVE_F
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:SVE_F 2 "register_operand")
+             (match_operand:SVE_F 3 "register_operand")]
+            SVE_COND_FCADD)
+          (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+)
+
+;; Predicated FCADD, merging with the first input.
+(define_insn_and_rewrite "*cond_<optab><mode>_2"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (unspec:SVE_F
+            [(match_operand 4)
+             (match_operand:SI 5 "aarch64_sve_gp_strictness")
+             (match_operand:SVE_F 2 "register_operand" "0, w")
+             (match_operand:SVE_F 3 "register_operand" "w, w")]
+            SVE_COND_FCADD)
+          (match_dup 2)]
+         UNSPEC_SEL))]
+  "TARGET_SVE && aarch64_sve_pred_dominates_p (&operands[4], operands[1])"
+  "@
+   fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+   movprfx\t%0, %2\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>"
+  "&& !rtx_equal_p (operands[1], operands[4])"
+  {
+    operands[4] = copy_rtx (operands[1]);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated FCADD, merging with an independent value.
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
+  [(set (match_operand:SVE_F 0 "register_operand" "=&w, &w, &w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
+          (unspec:SVE_F
+            [(match_operand 5)
+             (match_operand:SI 6 "aarch64_sve_gp_strictness")
+             (match_operand:SVE_F 2 "register_operand" "w, 0, w, w")
+             (match_operand:SVE_F 3 "register_operand" "w, w, w, w")]
+            SVE_COND_FCADD)
+          (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero" "Dz, Dz, 0, w")]
+         UNSPEC_SEL))]
+  "TARGET_SVE
+   && !rtx_equal_p (operands[2], operands[4])
+   && aarch64_sve_pred_dominates_p (&operands[5], operands[1])"
+  "@
+   movprfx\t%0.<Vetype>, %1/z, %2.<Vetype>\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+   movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+   movprfx\t%0.<Vetype>, %1/m, %2.<Vetype>\;fcadd\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>, #<rot>
+   #"
+  "&& 1"
+  {
+    if (reload_completed
+        && register_operand (operands[4], <MODE>mode)
+        && !rtx_equal_p (operands[0], operands[4]))
+      {
+       emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[2],
+                                                operands[4], operands[1]));
+       operands[4] = operands[2] = operands[0];
+      }
+    else if (!rtx_equal_p (operands[1], operands[5]))
+      operands[5] = copy_rtx (operands[1]);
+    else
+      FAIL;
+  }
+  [(set_attr "movprfx" "yes")]
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [FP] Subtraction
 ;; -------------------------------------------------------------------------
 ;; -------------------------------------------------------------------------
 
 ;; Predicated floating-point subtraction.
-(define_insn_and_split "*sub<mode>3"
-  [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, w, ?&w, ?&w")
        (unspec:SVE_F
-         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
-          (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, Z, i")
-          (match_operand:SVE_F 2 "aarch64_sve_float_arith_operand" "vsA, w, vsA")
-          (match_operand:SVE_F 3 "register_operand" "0, w, 0")]
-         UNSPEC_COND_FSUB))]
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl, Upl")
+          (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, Z, Ui1, Ui1, i, Ui1")
+          (match_operand:SVE_F 2 "aarch64_sve_float_arith_operand" "vsA, w, 0, w, vsA, w")
+          (match_operand:SVE_F 3 "register_operand" "0, w, w, 0, w, w")]
+         SVE_COND_FP_SUB))]
   "TARGET_SVE"
   "@
    fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2
    #
-   movprfx\t%0, %3\;fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2"
+   fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+   fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, %2.<Vetype>
+   movprfx\t%0, %3\;fsubr\t%0.<Vetype>, %1/m, %0.<Vetype>, #%2
+   movprfx\t%0, %2\;fsub\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   ; Split the unpredicated form after reload, so that we don't have
   ; the unnecessary PTRUE.
   "&& reload_completed
-   && register_operand (operands[2], <MODE>mode)"
+   && register_operand (operands[2], <MODE>mode)
+   && INTVAL (operands[4]) == SVE_RELAXED_GP"
   [(set (match_dup 0) (minus:SVE_F (match_dup 2) (match_dup 3)))]
   ""
-  [(set_attr "movprfx" "*,*,yes")]
+  [(set_attr "movprfx" "*,*,*,*,yes,yes")]
 )
 
 ;; Predicated floating-point subtraction from a constant, merging with the
 ;; -------------------------------------------------------------------------
 
 ;; Predicated floating-point absolute difference.
-(define_insn_and_rewrite "*fabd<mode>3"
+(define_expand "@aarch64_pred_abd<mode>"
+  [(set (match_operand:SVE_F 0 "register_operand")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand")
+          (match_operand:SI 4 "aarch64_sve_gp_strictness")
+          (unspec:SVE_F
+            [(match_dup 1)
+             (match_dup 4)
+             (match_operand:SVE_F 2 "register_operand")
+             (match_operand:SVE_F 3 "register_operand")]
+            UNSPEC_COND_FSUB)]
+         UNSPEC_COND_FABS))]
+  "TARGET_SVE"
+)
+
+;; Predicated floating-point absolute difference.
+(define_insn_and_rewrite "*aarch64_pred_abd<mode>"
   [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
        (unspec:SVE_F
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
   [(set_attr "movprfx" "*,yes")]
 )
 
-;; Predicated floating-point absolute difference, merging with the first
-;; input.
-(define_insn_and_rewrite "*aarch64_cond_abd<mode>_2"
-  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+(define_expand "@aarch64_cond_abd<mode>"
+  [(set (match_operand:SVE_F 0 "register_operand")
        (unspec:SVE_F
-         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+         [(match_operand:<VPRED> 1 "register_operand")
+          (unspec:SVE_F
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (unspec:SVE_F
+               [(match_dup 1)
+                (const_int SVE_STRICT_GP)
+                (match_operand:SVE_F 2 "register_operand")
+                (match_operand:SVE_F 3 "register_operand")]
+               UNSPEC_COND_FSUB)]
+            UNSPEC_COND_FABS)
+          (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+{
+  if (rtx_equal_p (operands[3], operands[4]))
+    std::swap (operands[2], operands[3]);
+})
+
+;; Predicated floating-point absolute difference, merging with the first
+;; input.
+(define_insn_and_rewrite "*aarch64_cond_abd<mode>_2"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
           (unspec:SVE_F
             [(match_operand 4)
              (match_operand:SI 5 "aarch64_sve_gp_strictness")
 ;; -------------------------------------------------------------------------
 
 ;; Predicated floating-point multiplication.
-(define_insn_and_split "*mul<mode>3"
-  [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
+(define_insn_and_split "@aarch64_pred_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, w, w, ?&w, ?&w")
        (unspec:SVE_F
-         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
-          (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, Z, i")
-          (match_operand:SVE_F 2 "register_operand" "%0, w, 0")
-          (match_operand:SVE_F 3 "aarch64_sve_float_mul_operand" "vsM, w, vsM")]
-         UNSPEC_COND_FMUL))]
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl, Upl")
+          (match_operand:SI 4 "aarch64_sve_gp_strictness" "i, Z, Ui1, i, Ui1")
+          (match_operand:SVE_F 2 "register_operand" "%0, w, 0, w, w")
+          (match_operand:SVE_F 3 "aarch64_sve_float_mul_operand" "vsM, w, w, vsM, w")]
+         SVE_COND_FP_MUL))]
   "TARGET_SVE"
   "@
    fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
    #
-   movprfx\t%0, %2\;fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3"
+   fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>
+   movprfx\t%0, %2\;fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
+   movprfx\t%0, %2\;fmul\t%0.<Vetype>, %1/m, %0.<Vetype>, %3.<Vetype>"
   ; Split the unpredicated form after reload, so that we don't have
   ; the unnecessary PTRUE.
   "&& reload_completed
-   && register_operand (operands[3], <MODE>mode)"
+   && register_operand (operands[3], <MODE>mode)
+   && INTVAL (operands[4]) == SVE_RELAXED_GP"
   [(set (match_dup 0) (mult:SVE_F (match_dup 2) (match_dup 3)))]
   ""
-  [(set_attr "movprfx" "*,*,yes")]
+  [(set_attr "movprfx" "*,*,*,yes,yes")]
 )
 
 ;; Merging forms are handled through SVE_COND_FP_BINARY and
 ;; SVE_COND_FP_BINARY_I1.
 
+;; Unpredicated multiplication by selected lanes.
+(define_insn "@aarch64_mul_lane_<mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w")
+       (mult:SVE_F
+         (unspec:SVE_F
+           [(match_operand:SVE_F 2 "register_operand" "<sve_lane_con>")
+            (match_operand:SI 3 "const_int_operand")]
+           UNSPEC_SVE_LANE_SELECT)
+         (match_operand:SVE_F 1 "register_operand" "w")))]
+  "TARGET_SVE"
+  "fmul\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]"
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [FP] Binary logical operations
 ;; -------------------------------------------------------------------------
 ;; ---- [FP] Maximum and minimum
 ;; -------------------------------------------------------------------------
 ;; Includes:
+;; - FMAX
 ;; - FMAXNM
+;; - FMIN
 ;; - FMINNM
 ;; -------------------------------------------------------------------------
 
 )
 
 ;; Predicated floating-point maximum/minimum.
-(define_insn "*<optab><mode>3"
+(define_insn "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w, ?&w")
        (unspec:SVE_F
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
           (match_operand:SI 4 "aarch64_sve_gp_strictness")
           (match_operand:SVE_F 2 "register_operand" "%0, 0, w, w")
           (match_operand:SVE_F 3 "aarch64_sve_float_maxmin_operand" "vsB, w, vsB, w")]
-         SVE_COND_FP_MAXMIN_PUBLIC))]
+         SVE_COND_FP_MAXMIN))]
   "TARGET_SVE"
   "@
    <sve_fp_op>\t%0.<Vetype>, %1/m, %0.<Vetype>, #%3
   "<logical>s\t%0.b, %1/z, %2.b, %3.b"
 )
 
+;; Same with just the flags result.
+(define_insn "*<optab><mode>3_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_operand 4)
+          (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+          (and:PRED_ALL
+            (LOGICAL:PRED_ALL
+              (match_operand:PRED_ALL 2 "register_operand" "Upa")
+              (match_operand:PRED_ALL 3 "register_operand" "Upa"))
+            (match_dup 4))]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+  "TARGET_SVE"
+  "<logical>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [PRED] Binary logical operations (inverted second input)
 ;; -------------------------------------------------------------------------
 ;; -------------------------------------------------------------------------
 
 ;; Predicated predicate BIC and ORN.
-(define_insn "*<nlogical><mode>3"
+(define_insn "aarch64_pred_<nlogical><mode>_z"
   [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
        (and:PRED_ALL
          (NLOGICAL:PRED_ALL
   "<nlogical>\t%0.b, %1/z, %2.b, %3.b"
 )
 
+;; Same, but set the flags as a side-effect.
+(define_insn "*<nlogical><mode>3_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_operand 4)
+          (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+          (and:PRED_ALL
+            (NLOGICAL:PRED_ALL
+              (not:PRED_ALL
+                (match_operand:PRED_ALL 3 "register_operand" "Upa"))
+              (match_operand:PRED_ALL 2 "register_operand" "Upa"))
+            (match_dup 4))]
+         UNSPEC_PTEST))
+   (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+       (and:PRED_ALL (NLOGICAL:PRED_ALL
+                       (not:PRED_ALL (match_dup 3))
+                       (match_dup 2))
+                     (match_dup 4)))]
+  "TARGET_SVE"
+  "<nlogical>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
+;; Same with just the flags result.
+(define_insn "*<nlogical><mode>3_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_operand 4)
+          (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+          (and:PRED_ALL
+            (NLOGICAL:PRED_ALL
+              (not:PRED_ALL
+                (match_operand:PRED_ALL 3 "register_operand" "Upa"))
+              (match_operand:PRED_ALL 2 "register_operand" "Upa"))
+            (match_dup 4))]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+  "TARGET_SVE"
+  "<nlogical>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [PRED] Binary logical operations (inverted result)
 ;; -------------------------------------------------------------------------
 ;; -------------------------------------------------------------------------
 
 ;; Predicated predicate NAND and NOR.
-(define_insn "*<logical_nn><mode>3"
+(define_insn "aarch64_pred_<logical_nn><mode>_z"
   [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
        (and:PRED_ALL
          (NLOGICAL:PRED_ALL
   "<logical_nn>\t%0.b, %1/z, %2.b, %3.b"
 )
 
+;; Same, but set the flags as a side-effect.
+(define_insn "*<logical_nn><mode>3_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_operand 4)
+          (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+          (and:PRED_ALL
+            (NLOGICAL:PRED_ALL
+              (not:PRED_ALL
+                (match_operand:PRED_ALL 2 "register_operand" "Upa"))
+              (not:PRED_ALL
+                (match_operand:PRED_ALL 3 "register_operand" "Upa")))
+            (match_dup 4))]
+         UNSPEC_PTEST))
+   (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+       (and:PRED_ALL (NLOGICAL:PRED_ALL
+                       (not:PRED_ALL (match_dup 2))
+                       (not:PRED_ALL (match_dup 3)))
+                     (match_dup 4)))]
+  "TARGET_SVE"
+  "<logical_nn>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
+;; Same with just the flags result.
+(define_insn "*<logical_nn><mode>3_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_operand 4)
+          (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+          (and:PRED_ALL
+            (NLOGICAL:PRED_ALL
+              (not:PRED_ALL
+                (match_operand:PRED_ALL 2 "register_operand" "Upa"))
+              (not:PRED_ALL
+                (match_operand:PRED_ALL 3 "register_operand" "Upa")))
+            (match_dup 4))]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+  "TARGET_SVE"
+  "<logical_nn>s\t%0.b, %1/z, %2.b, %3.b"
+)
+
 ;; =========================================================================
 ;; == Ternary arithmetic
 ;; =========================================================================
 )
 
 ;; Predicated integer addition of product.
-(define_insn "*fma<mode>4"
+(define_insn "@aarch64_pred_fma<mode>"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w")
        (plus:SVE_I
          (unspec:SVE_I
 )
 
 ;; Predicated integer subtraction of product.
-(define_insn "*fnma<mode>3"
+(define_insn "@aarch64_pred_fnma<mode>"
   [(set (match_operand:SVE_I 0 "register_operand" "=w, w, ?&w")
        (minus:SVE_I
          (match_operand:SVE_I 4 "register_operand" "w, 0, w")
   [(set_attr "movprfx" "*,yes")]
 )
 
+;; Four-element integer dot-product by selected lanes with accumulation.
+(define_insn "@aarch64_<sur>dot_prod_lane<vsi2qi>"
+  [(set (match_operand:SVE_SDI 0 "register_operand" "=w, ?&w")
+       (plus:SVE_SDI
+         (unspec:SVE_SDI
+           [(match_operand:<VSI2QI> 1 "register_operand" "w, w")
+            (unspec:<VSI2QI>
+              [(match_operand:<VSI2QI> 2 "register_operand" "<sve_lane_con>, <sve_lane_con>")
+               (match_operand:SI 3 "const_int_operand")]
+              UNSPEC_SVE_LANE_SELECT)]
+           DOTPROD)
+         (match_operand:SVE_SDI 4 "register_operand" "0, w")))]
+  "TARGET_SVE"
+  "@
+   <sur>dot\\t%0.<Vetype>, %1.<Vetype_fourth>, %2.<Vetype_fourth>[%3]
+   movprfx\t%0, %4\;<sur>dot\\t%0.<Vetype>, %1.<Vetype_fourth>, %2.<Vetype_fourth>[%3]"
+  [(set_attr "movprfx" "*,yes")]
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [INT] Sum of absolute differences
 ;; -------------------------------------------------------------------------
 )
 
 ;; Predicated floating-point ternary operations.
-(define_insn "*<optab><mode>4"
+(define_insn "@aarch64_pred_<optab><mode>"
   [(set (match_operand:SVE_F 0 "register_operand" "=w, w, ?&w")
        (unspec:SVE_F
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl")
 )
 
 ;; Predicated floating-point ternary operations with merging.
-(define_expand "cond_<optab><mode>"
+(define_expand "@cond_<optab><mode>"
   [(set (match_operand:SVE_F 0 "register_operand")
        (unspec:SVE_F
          [(match_operand:<VPRED> 1 "register_operand")
   [(set_attr "movprfx" "yes")]
 )
 
+;; Unpredicated FMLA and FMLS by selected lanes.  It doesn't seem worth using
+;; (fma ...) since target-independent code won't understand the indexing.
+(define_insn "@aarch64_<optab>_lane_<mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:SVE_F 1 "register_operand" "w, w")
+          (unspec:SVE_F
+            [(match_operand:SVE_F 2 "register_operand" "<sve_lane_con>, <sve_lane_con>")
+             (match_operand:SI 3 "const_int_operand")]
+            UNSPEC_SVE_LANE_SELECT)
+          (match_operand:SVE_F 4 "register_operand" "0, w")]
+         SVE_FP_TERNARY_LANE))]
+  "TARGET_SVE"
+  "@
+   <sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]
+   movprfx\t%0, %4\;<sve_fp_op>\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3]"
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [FP] Complex multiply-add
+;; -------------------------------------------------------------------------
+;; Includes merging patterns for:
+;; - FCMLA
+;; -------------------------------------------------------------------------
+
+;; Predicated FCMLA.
+(define_insn "@aarch64_pred_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (match_operand:SI 5 "aarch64_sve_gp_strictness")
+          (match_operand:SVE_F 2 "register_operand" "w, w")
+          (match_operand:SVE_F 3 "register_operand" "w, w")
+          (match_operand:SVE_F 4 "register_operand" "0, w")]
+         SVE_COND_FCMLA))]
+  "TARGET_SVE"
+  "@
+   fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+   movprfx\t%0, %4\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>"
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated FCMLA with merging.
+(define_expand "@cond_<optab><mode>"
+  [(set (match_operand:SVE_F 0 "register_operand")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand")
+          (unspec:SVE_F
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:SVE_F 2 "register_operand")
+             (match_operand:SVE_F 3 "register_operand")
+             (match_operand:SVE_F 4 "register_operand")]
+            SVE_COND_FCMLA)
+          (match_operand:SVE_F 5 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+)
+
+;; Predicated FCMLA, merging with the third input.
+(define_insn_and_rewrite "*cond_<optab><mode>_4"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+          (unspec:SVE_F
+            [(match_operand 5)
+             (match_operand:SI 6 "aarch64_sve_gp_strictness")
+             (match_operand:SVE_F 2 "register_operand" "w, w")
+             (match_operand:SVE_F 3 "register_operand" "w, w")
+             (match_operand:SVE_F 4 "register_operand" "0, w")]
+            SVE_COND_FCMLA)
+          (match_dup 4)]
+         UNSPEC_SEL))]
+  "TARGET_SVE && aarch64_sve_pred_dominates_p (&operands[5], operands[1])"
+  "@
+   fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+   movprfx\t%0, %4\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>"
+  "&& !rtx_equal_p (operands[1], operands[5])"
+  {
+    operands[5] = copy_rtx (operands[1]);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Predicated FCMLA, merging with an independent value.
+(define_insn_and_rewrite "*cond_<optab><mode>_any"
+  [(set (match_operand:SVE_F 0 "register_operand" "=&w, &w, &w, ?&w")
+       (unspec:SVE_F
+         [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl, Upl, Upl")
+          (unspec:SVE_F
+            [(match_operand 6)
+             (match_operand:SI 7 "aarch64_sve_gp_strictness")
+             (match_operand:SVE_F 2 "register_operand" "w, w, w, w")
+             (match_operand:SVE_F 3 "register_operand" "w, w, w, w")
+             (match_operand:SVE_F 4 "register_operand" "w, 0, w, w")]
+            SVE_COND_FCMLA)
+          (match_operand:SVE_F 5 "aarch64_simd_reg_or_zero" "Dz, Dz, 0, w")]
+         UNSPEC_SEL))]
+  "TARGET_SVE
+   && !rtx_equal_p (operands[4], operands[5])
+   && aarch64_sve_pred_dominates_p (&operands[6], operands[1])"
+  "@
+   movprfx\t%0.<Vetype>, %1/z, %4.<Vetype>\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+   movprfx\t%0.<Vetype>, %1/z, %0.<Vetype>\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+   movprfx\t%0.<Vetype>, %1/m, %4.<Vetype>\;fcmla\t%0.<Vetype>, %1/m, %2.<Vetype>, %3.<Vetype>, #<rot>
+   #"
+  "&& 1"
+  {
+    if (reload_completed
+        && register_operand (operands[5], <MODE>mode)
+        && !rtx_equal_p (operands[0], operands[5]))
+      {
+       emit_insn (gen_vcond_mask_<mode><vpred> (operands[0], operands[4],
+                                                operands[5], operands[1]));
+       operands[5] = operands[4] = operands[0];
+      }
+    else if (!rtx_equal_p (operands[1], operands[6]))
+      operands[6] = copy_rtx (operands[1]);
+    else
+      FAIL;
+  }
+  [(set_attr "movprfx" "yes")]
+)
+
+;; Unpredicated FCMLA with indexing.
+(define_insn "@aarch64_<optab>_lane_<mode>"
+  [(set (match_operand:SVE_HSF 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_HSF
+         [(match_operand:SVE_HSF 1 "register_operand" "w, w")
+          (unspec:SVE_HSF
+            [(match_operand:SVE_HSF 2 "register_operand" "<sve_lane_pair_con>, <sve_lane_pair_con>")
+             (match_operand:SI 3 "const_int_operand")]
+            UNSPEC_SVE_LANE_SELECT)
+          (match_operand:SVE_HSF 4 "register_operand" "0, w")]
+         FCMLA))]
+  "TARGET_SVE"
+  "@
+   fcmla\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3], #<rot>
+   movprfx\t%0, %4\;fcmla\t%0.<Vetype>, %1.<Vetype>, %2.<Vetype>[%3], #<rot>"
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [FP] Trigonometric multiply-add
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - FTMAD
+;; -------------------------------------------------------------------------
+
+(define_insn "@aarch64_sve_tmad<mode>"
+  [(set (match_operand:SVE_F 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_F [(match_operand:SVE_F 1 "register_operand" "0, w")
+                      (match_operand:SVE_F 2 "register_operand" "w, w")
+                      (match_operand:DI 3 "const_int_operand")]
+                     UNSPEC_FTMAD))]
+  "TARGET_SVE"
+  "@
+   ftmad\t%0.<Vetype>, %0.<Vetype>, %2.<Vetype>, #%3
+   movprfx\t%0, %1\;ftmad\t%0.<Vetype>, %0.<Vetype>, %2.<Vetype>, #%3"
+  [(set_attr "movprfx" "*,yes")]
+)
+
 ;; =========================================================================
 ;; == Comparisons and selects
 ;; =========================================================================
 ;; the latter of which can be a zero constant or a variable.  Treat duplicates
 ;; of GPRs as being more expensive than duplicates of FPRs, since they
 ;; involve a cross-file move.
-(define_insn "*aarch64_sel_dup<mode>"
+(define_insn "@aarch64_sel_dup<mode>"
   [(set (match_operand:SVE_ALL 0 "register_operand" "=?w, w, ??w, ?&w, ??&w, ?&w")
        (unspec:SVE_ALL
          [(match_operand:<VPRED> 3 "register_operand" "Upa, Upa, Upl, Upl, Upl, Upl")
 ;; -------------------------------------------------------------------------
 ;; ---- [INT] Comparisons
 ;; -------------------------------------------------------------------------
-;; Includes merging patterns for:
+;; Includes:
 ;; - CMPEQ
 ;; - CMPGE
 ;; - CMPGT
       (clobber (reg:CC_NZC CC_REGNUM))])]
 )
 
-;; -------------------------------------------------------------------------
-;; ---- [INT] While tests
-;; -------------------------------------------------------------------------
-;; Includes:
-;; - WHILELO
-;; -------------------------------------------------------------------------
-
-;; Set element I of the result if operand1 + J < operand2 for all J in [0, I],
-;; with the comparison being unsigned.
-(define_insn "@while_ult<GPI:mode><PRED_ALL:mode>"
-  [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
-       (unspec:PRED_ALL [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
-                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
-                        UNSPEC_WHILE_LO))
+;; Predicated integer wide comparisons.
+(define_insn "@aarch64_pred_cmp<cmp_op><mode>_wide"
+  [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
+       (unspec:<VPRED>
+         [(match_operand:VNx16BI 1 "register_operand" "Upl")
+          (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+          (unspec:<VPRED>
+            [(match_operand:SVE_BHSI 3 "register_operand" "w")
+             (match_operand:VNx2DI 4 "register_operand" "w")]
+            SVE_COND_INT_CMP_WIDE)]
+         UNSPEC_PRED_Z))
    (clobber (reg:CC_NZC CC_REGNUM))]
   "TARGET_SVE"
-  "whilelo\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
+  "cmp<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.d"
 )
 
-;; WHILELO sets the flags in the same way as a PTEST with a PTRUE GP.
-;; Handle the case in which both results are useful.  The GP operands
-;; to the PTEST aren't needed, so we allow them to be anything.
-(define_insn_and_rewrite "*while_ult<GPI:mode><PRED_ALL:mode>_cc"
+;; Predicated integer wide comparisons in which both the flag and
+;; predicate results are interesting.
+(define_insn "*aarch64_pred_cmp<cmp_op><mode>_wide_cc"
   [(set (reg:CC_NZC CC_REGNUM)
        (unspec:CC_NZC
-         [(match_operand 3)
+         [(match_operand:VNx16BI 1 "register_operand" "Upl")
           (match_operand 4)
-          (const_int SVE_KNOWN_PTRUE)
-          (unspec:PRED_ALL
-            [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
-             (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
-            UNSPEC_WHILE_LO)]
+          (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+          (unspec:<VPRED>
+            [(match_operand:VNx16BI 6 "register_operand" "Upl")
+             (match_operand:SI 7 "aarch64_sve_ptrue_flag")
+             (unspec:<VPRED>
+               [(match_operand:SVE_BHSI 2 "register_operand" "w")
+                (match_operand:VNx2DI 3 "register_operand" "w")]
+               SVE_COND_INT_CMP_WIDE)]
+            UNSPEC_PRED_Z)]
          UNSPEC_PTEST))
-   (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
-       (unspec:PRED_ALL [(match_dup 1)
-                         (match_dup 2)]
-                        UNSPEC_WHILE_LO))]
-  "TARGET_SVE"
-  "whilelo\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
-  ;; Force the compiler to drop the unused predicate operand, so that we
-  ;; don't have an unnecessary PTRUE.
-  "&& (!CONSTANT_P (operands[3]) || !CONSTANT_P (operands[4]))"
-  {
-    operands[3] = CONSTM1_RTX (VNx16BImode);
-    operands[4] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
-  }
-)
-
+   (set (match_operand:<VPRED> 0 "register_operand" "=Upa")
+       (unspec:<VPRED>
+         [(match_dup 6)
+          (match_dup 7)
+          (unspec:<VPRED>
+            [(match_dup 2)
+             (match_dup 3)]
+            SVE_COND_INT_CMP_WIDE)]
+         UNSPEC_PRED_Z))]
+  "TARGET_SVE
+   && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])"
+  "cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.d"
+)
+
+;; Predicated integer wide comparisons in which only the flags result
+;; is interesting.
+(define_insn "*aarch64_pred_cmp<cmp_op><mode>_wide_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upl")
+          (match_operand 4)
+          (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+          (unspec:<VPRED>
+            [(match_operand:VNx16BI 6 "register_operand" "Upl")
+             (match_operand:SI 7 "aarch64_sve_ptrue_flag")
+             (unspec:<VPRED>
+               [(match_operand:SVE_BHSI 2 "register_operand" "w")
+                (match_operand:VNx2DI 3 "register_operand" "w")]
+               SVE_COND_INT_CMP_WIDE)]
+            UNSPEC_PRED_Z)]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:<VPRED> 0 "=Upa"))]
+  "TARGET_SVE
+   && aarch64_sve_same_pred_for_ptest_p (&operands[4], &operands[6])"
+  "cmp<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.d"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] While tests
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - WHILELE
+;; - WHILELO
+;; - WHILELS
+;; - WHILELT
+;; -------------------------------------------------------------------------
+
+;; Set element I of the result if (cmp (plus operand1 J) operand2) is
+;; true for all J in [0, I].
+(define_insn "@while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>"
+  [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+       (unspec:PRED_ALL [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+                         (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+                        SVE_WHILE))
+   (clobber (reg:CC_NZC CC_REGNUM))]
+  "TARGET_SVE"
+  "while<cmp_op>\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
+)
+
+;; The WHILE instructions set the flags in the same way as a PTEST with
+;; a PTRUE GP.  Handle the case in which both results are useful.  The GP
+;; operands to the PTEST aren't needed, so we allow them to be anything.
+(define_insn_and_rewrite "*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand 3)
+          (match_operand 4)
+          (const_int SVE_KNOWN_PTRUE)
+          (unspec:PRED_ALL
+            [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+             (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+            SVE_WHILE)]
+         UNSPEC_PTEST))
+   (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+       (unspec:PRED_ALL [(match_dup 1)
+                         (match_dup 2)]
+                        SVE_WHILE))]
+  "TARGET_SVE"
+  "while<cmp_op>\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
+  ;; Force the compiler to drop the unused predicate operand, so that we
+  ;; don't have an unnecessary PTRUE.
+  "&& (!CONSTANT_P (operands[3]) || !CONSTANT_P (operands[4]))"
+  {
+    operands[3] = CONSTM1_RTX (VNx16BImode);
+    operands[4] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
+;; Same, but handle the case in which only the flags result is useful.
+(define_insn_and_rewrite "*while_<while_optab_cmp><GPI:mode><PRED_ALL:mode>_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand 3)
+          (match_operand 4)
+          (const_int SVE_KNOWN_PTRUE)
+          (unspec:PRED_ALL
+            [(match_operand:GPI 1 "aarch64_reg_or_zero" "rZ")
+             (match_operand:GPI 2 "aarch64_reg_or_zero" "rZ")]
+            SVE_WHILE)]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:PRED_ALL 0 "=Upa"))]
+  "TARGET_SVE"
+  "while<cmp_op>\t%0.<PRED_ALL:Vetype>, %<w>1, %<w>2"
+  ;; Force the compiler to drop the unused predicate operand, so that we
+  ;; don't have an unnecessary PTRUE.
+  "&& (!CONSTANT_P (operands[3]) || !CONSTANT_P (operands[4]))"
+  {
+    operands[3] = CONSTM1_RTX (VNx16BImode);
+    operands[4] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [FP] Direct comparisons
 ;; -------------------------------------------------------------------------
 )
 
 ;; Predicated floating-point comparisons.
-(define_insn "*fcm<cmp_op><mode>"
+(define_insn "@aarch64_pred_fcm<cmp_op><mode>"
   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa, Upa")
        (unspec:<VPRED>
          [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
-          (match_operand:SI 4 "aarch64_sve_ptrue_flag")
-          (match_operand:SVE_F 2 "register_operand" "w, w")
-          (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero" "Dz, w")]
+          (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+          (match_operand:SVE_F 3 "register_operand" "w, w")
+          (match_operand:SVE_F 4 "aarch64_simd_reg_or_zero" "Dz, w")]
          SVE_COND_FP_CMP_I0))]
   "TARGET_SVE"
   "@
-   fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, #0.0
-   fcm<cmp_op>\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
+   fcm<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, #0.0
+   fcm<cmp_op>\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>"
 )
 
 ;; Same for unordered comparisons.
-(define_insn "*fcmuo<mode>"
+(define_insn "@aarch64_pred_fcmuo<mode>"
   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
        (unspec:<VPRED>
          [(match_operand:<VPRED> 1 "register_operand" "Upl")
-          (match_operand:SI 4 "aarch64_sve_ptrue_flag")
-          (match_operand:SVE_F 2 "register_operand" "w")
-          (match_operand:SVE_F 3 "register_operand" "w")]
+          (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+          (match_operand:SVE_F 3 "register_operand" "w")
+          (match_operand:SVE_F 4 "register_operand" "w")]
          UNSPEC_COND_FCMUO))]
   "TARGET_SVE"
-  "fcmuo\t%0.<Vetype>, %1/z, %2.<Vetype>, %3.<Vetype>"
+  "fcmuo\t%0.<Vetype>, %1/z, %3.<Vetype>, %4.<Vetype>"
 )
 
 ;; Floating-point comparisons predicated on a PTRUE, with the results ANDed
 ;; -------------------------------------------------------------------------
 
 ;; Predicated floating-point absolute comparisons.
+(define_expand "@aarch64_pred_fac<cmp_op><mode>"
+  [(set (match_operand:<VPRED> 0 "register_operand")
+       (unspec:<VPRED>
+         [(match_operand:<VPRED> 1 "register_operand")
+          (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+          (unspec:SVE_F
+            [(match_dup 1)
+             (match_dup 2)
+             (match_operand:SVE_F 3 "register_operand")]
+            UNSPEC_COND_FABS)
+          (unspec:SVE_F
+            [(match_dup 1)
+             (match_dup 2)
+             (match_operand:SVE_F 4 "register_operand")]
+            UNSPEC_COND_FABS)]
+         SVE_COND_FP_ABS_CMP))]
+  "TARGET_SVE"
+)
+
 (define_insn_and_rewrite "*aarch64_pred_fac<cmp_op><mode>"
   [(set (match_operand:<VPRED> 0 "register_operand" "=Upa")
        (unspec:<VPRED>
   }
 )
 
+;; -------------------------------------------------------------------------
+;; ---- [PRED] Select
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - SEL
+;; -------------------------------------------------------------------------
+
+(define_insn "@vcond_mask_<mode><mode>"
+  [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+       (ior:PRED_ALL
+         (and:PRED_ALL
+           (match_operand:PRED_ALL 3 "register_operand" "Upa")
+           (match_operand:PRED_ALL 1 "register_operand" "Upa"))
+         (and:PRED_ALL
+           (not (match_dup 3))
+           (match_operand:PRED_ALL 2 "register_operand" "Upa"))))]
+  "TARGET_SVE"
+  "sel\t%0.b, %3, %1.b, %2.b"
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [PRED] Test bits
 ;; -------------------------------------------------------------------------
 ;; ---- [INT,FP] Conditional reductions
 ;; -------------------------------------------------------------------------
 ;; Includes:
+;; - CLASTA
 ;; - CLASTB
 ;; -------------------------------------------------------------------------
 
 ;; Set operand 0 to the last active element in operand 3, or to tied
 ;; operand 1 if no elements are active.
-(define_insn "fold_extract_last_<mode>"
+(define_insn "@fold_extract_<last_op>_<mode>"
   [(set (match_operand:<VEL> 0 "register_operand" "=?r, w")
        (unspec:<VEL>
          [(match_operand:<VEL> 1 "register_operand" "0, 0")
           (match_operand:<VPRED> 2 "register_operand" "Upl, Upl")
           (match_operand:SVE_ALL 3 "register_operand" "w, w")]
-         UNSPEC_CLASTB))]
+         CLAST))]
+  "TARGET_SVE"
+  "@
+   clast<ab>\t%<vwcore>0, %2, %<vwcore>0, %3.<Vetype>
+   clast<ab>\t%<Vetype>0, %2, %<Vetype>0, %3.<Vetype>"
+)
+
+(define_insn "@aarch64_fold_extract_vector_<last_op>_<mode>"
+  [(set (match_operand:SVE_ALL 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_ALL
+         [(match_operand:SVE_ALL 1 "register_operand" "0, w")
+          (match_operand:<VPRED> 2 "register_operand" "Upl, Upl")
+          (match_operand:SVE_ALL 3 "register_operand" "w, w")]
+         CLAST))]
   "TARGET_SVE"
   "@
-   clastb\t%<vwcore>0, %2, %<vwcore>0, %3.<Vetype>
-   clastb\t%<Vetype>0, %2, %<Vetype>0, %3.<Vetype>"
+   clast<ab>\t%0.<Vetype>, %2, %0.<Vetype>, %3.<Vetype>
+   movprfx\t%0, %1\;clast<ab>\t%0.<Vetype>, %2, %0.<Vetype>, %3.<Vetype>"
 )
 
 ;; -------------------------------------------------------------------------
 ;; - ANDV
 ;; - EORV
 ;; - ORV
+;; - SADDV
 ;; - SMAXV
 ;; - SMINV
 ;; - UADDV
 
 ;; Unpredicated integer add reduction.
 (define_expand "reduc_plus_scal_<mode>"
-  [(set (match_operand:<VEL> 0 "register_operand")
-       (unspec:<VEL> [(match_dup 2)
-                      (match_operand:SVE_I 1 "register_operand")]
-                     UNSPEC_ADDV))]
+  [(match_operand:<VEL> 0 "register_operand")
+   (match_operand:SVE_I 1 "register_operand")]
   "TARGET_SVE"
   {
-    operands[2] = aarch64_ptrue_reg (<VPRED>mode);
+    rtx pred = aarch64_ptrue_reg (<VPRED>mode);
+    rtx tmp = <VEL>mode == DImode ? operands[0] : gen_reg_rtx (DImode);
+    emit_insn (gen_aarch64_pred_reduc_uadd_<mode> (tmp, pred, operands[1]));
+    if (tmp != operands[0])
+      emit_move_insn (operands[0], gen_lowpart (<VEL>mode, tmp));
+    DONE;
   }
 )
 
 ;; Predicated integer add reduction.  The result is always 64-bits.
-(define_insn "*reduc_plus_scal_<mode>"
-  [(set (match_operand:<VEL> 0 "register_operand" "=w")
-       (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
-                      (match_operand:SVE_I 2 "register_operand" "w")]
-                     UNSPEC_ADDV))]
-  "TARGET_SVE"
-  "uaddv\t%d0, %1, %2.<Vetype>"
+(define_insn "@aarch64_pred_reduc_<optab>_<mode>"
+  [(set (match_operand:DI 0 "register_operand" "=w")
+       (unspec:DI [(match_operand:<VPRED> 1 "register_operand" "Upl")
+                   (match_operand:SVE_I 2 "register_operand" "w")]
+                  SVE_INT_ADDV))]
+  "TARGET_SVE && <max_elem_bits> >= <elem_bits>"
+  "<su>addv\t%d0, %1, %2.<Vetype>"
 )
 
 ;; Unpredicated integer reductions.
 )
 
 ;; Predicated integer reductions.
-(define_insn "*reduc_<optab>_scal_<mode>"
+(define_insn "@aarch64_pred_reduc_<optab>_<mode>"
   [(set (match_operand:<VEL> 0 "register_operand" "=w")
        (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
                       (match_operand:SVE_I 2 "register_operand" "w")]
 )
 
 ;; Predicated floating-point tree reductions.
-(define_insn "*reduc_<optab>_scal_<mode>"
+(define_insn "@aarch64_pred_reduc_<optab>_<mode>"
   [(set (match_operand:<VEL> 0 "register_operand" "=w")
        (unspec:<VEL> [(match_operand:<VPRED> 1 "register_operand" "Upl")
                       (match_operand:SVE_F 2 "register_operand" "w")]
   }
 )
 
-(define_insn "*aarch64_sve_tbl<mode>"
+(define_insn "@aarch64_sve_tbl<mode>"
   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
        (unspec:SVE_ALL
          [(match_operand:SVE_ALL 1 "register_operand" "w")
 ;; ---- [INT,FP] Special-purpose unary permutes
 ;; -------------------------------------------------------------------------
 ;; Includes:
+;; - COMPACT
 ;; - DUP
 ;; - REV
 ;; -------------------------------------------------------------------------
 
+;; Compact active elements and pad with zeros.
+(define_insn "@aarch64_sve_compact<mode>"
+  [(set (match_operand:SVE_SD 0 "register_operand" "=w")
+       (unspec:SVE_SD [(match_operand:<VPRED> 1 "register_operand" "Upl")
+                       (match_operand:SVE_SD 2 "register_operand" "w")]
+                      UNSPEC_SVE_COMPACT))]
+  "TARGET_SVE"
+  "compact\t%0.<Vetype>, %1, %2.<Vetype>"
+)
+
 ;; Duplicate one element of a vector.
-(define_insn "*aarch64_sve_dup_lane<mode>"
+(define_insn "@aarch64_sve_dup_lane<mode>"
   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
        (vec_duplicate:SVE_ALL
          (vec_select:<VEL>
   "dup\t%0.<Vetype>, %1.<Vetype>[%2]"
 )
 
+;; Use DUP.Q to duplicate a 128-bit segment of a register.
+;;
+;; The vec_select:<V128> sets memory lane number N of the V128 to lane
+;; number op2 + N of op1.  (We don't need to distinguish between memory
+;; and architectural register lane numbering for op1 or op0, since the
+;; two numbering schemes are the same for SVE.)
+;;
+;; The vec_duplicate:SVE_ALL then copies memory lane number N of the
+;; V128 (and thus lane number op2 + N of op1) to lane numbers N + I * STEP
+;; of op0.  We therefore get the correct result for both endiannesses.
+;;
+;; The wrinkle is that for big-endian V128 registers, memory lane numbering
+;; is in the opposite order to architectural register lane numbering.
+;; Thus if we were to do this operation via a V128 temporary register,
+;; the vec_select and vec_duplicate would both involve a reverse operation
+;; for big-endian targets.  In this fused pattern the two reverses cancel
+;; each other out.
+(define_insn "@aarch64_sve_dupq_lane<mode>"
+  [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
+       (vec_duplicate:SVE_ALL
+         (vec_select:<V128>
+           (match_operand:SVE_ALL 1 "register_operand" "w")
+           (match_operand 2 "ascending_int_parallel"))))]
+  "TARGET_SVE
+   && (INTVAL (XVECEXP (operands[2], 0, 0))
+       * GET_MODE_SIZE (<VEL>mode)) % 16 == 0
+   && IN_RANGE (INTVAL (XVECEXP (operands[2], 0, 0))
+               * GET_MODE_SIZE (<VEL>mode), 0, 63)"
+  {
+    unsigned int byte = (INTVAL (XVECEXP (operands[2], 0, 0))
+                        * GET_MODE_SIZE (<VEL>mode));
+    operands[2] = gen_int_mode (byte / 16, DImode);
+    return "dup\t%0.q, %1.q[%2]";
+  }
+)
+
 ;; Reverse the order of elements within a full vector.
 (define_insn "@aarch64_sve_rev<mode>"
   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
 ;; ---- [INT,FP] Special-purpose binary permutes
 ;; -------------------------------------------------------------------------
 ;; Includes:
+;; - SPLICE
 ;; - TRN1
 ;; - TRN2
 ;; - UZP1
 ;; - ZIP2
 ;; -------------------------------------------------------------------------
 
+;; Like EXT, but start at the first active element.
+(define_insn "@aarch64_sve_splice<mode>"
+  [(set (match_operand:SVE_ALL 0 "register_operand" "=w, ?&w")
+       (unspec:SVE_ALL [(match_operand:<VPRED> 1 "register_operand" "Upl, Upl")
+                        (match_operand:SVE_ALL 2 "register_operand" "0, w")
+                        (match_operand:SVE_ALL 3 "register_operand" "w, w")]
+                       UNSPEC_SVE_SPLICE))]
+  "TARGET_SVE"
+  "@
+   splice\t%0.<Vetype>, %1, %0.<Vetype>, %3.<Vetype>
+   movprfx\t%0, %2\;splice\t%0.<Vetype>, %1, %0.<Vetype>, %3.<Vetype>"
+  [(set_attr "movprfx" "*, yes")]
+)
+
 ;; Permutes that take half the elements from one vector and half the
 ;; elements from the other.
-(define_insn "aarch64_sve_<perm_insn><mode>"
+(define_insn "@aarch64_sve_<perm_insn><mode>"
   [(set (match_operand:SVE_ALL 0 "register_operand" "=w")
        (unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "w")
                         (match_operand:SVE_ALL 2 "register_operand" "w")]
 
 ;; Concatenate two vectors and extract a subvector.  Note that the
 ;; immediate (third) operand is the lane index not the byte index.
-(define_insn "*aarch64_sve_ext<mode>"
+(define_insn "@aarch64_sve_ext<mode>"
   [(set (match_operand:SVE_ALL 0 "register_operand" "=w, ?&w")
        (unspec:SVE_ALL [(match_operand:SVE_ALL 1 "register_operand" "0, w")
                         (match_operand:SVE_ALL 2 "register_operand" "w, w")
   }
 )
 
-(define_insn "aarch64_sve_<su>unpk<perm_hilo>_<SVE_BHSI:mode>"
+(define_insn "@aarch64_sve_<su>unpk<perm_hilo>_<SVE_BHSI:mode>"
   [(set (match_operand:<VWIDE> 0 "register_operand" "=w")
        (unspec:<VWIDE> [(match_operand:SVE_BHSI 1 "register_operand" "w")]
                        UNPACK))]
 )
 
 ;; Predicated float-to-integer conversion, either to the same width or wider.
-(define_insn "*aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>"
+(define_insn "@aarch64_sve_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>"
   [(set (match_operand:SVE_HSDI 0 "register_operand" "=w")
        (unspec:SVE_HSDI
          [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl")
 )
 
 ;; Predicated narrowing float-to-integer conversion.
-(define_insn "*aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
+(define_insn "@aarch64_sve_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
   [(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=w")
        (unspec:VNx4SI_ONLY
          [(match_operand:VNx2BI 1 "register_operand" "Upl")
 
 ;; Predicated float-to-integer conversion with merging, either to the same
 ;; width or wider.
-;;
+(define_expand "@cond_<optab>_nontrunc<SVE_F:mode><SVE_HSDI:mode>"
+  [(set (match_operand:SVE_HSDI 0 "register_operand")
+       (unspec:SVE_HSDI
+         [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand")
+          (unspec:SVE_HSDI
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:SVE_F 2 "register_operand")]
+            SVE_COND_FCVTI)
+          (match_operand:SVE_HSDI 3 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE && <SVE_HSDI:elem_bits> >= <SVE_F:elem_bits>"
+)
+
 ;; The first alternative doesn't need the earlyclobber, but the only case
 ;; it would help is the uninteresting one in which operands 2 and 3 are
 ;; the same register (despite having different modes).  Making all the
   [(set_attr "movprfx" "*,yes,yes")]
 )
 
+;; Predicated narrowing float-to-integer conversion with merging.
+(define_expand "@cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
+  [(set (match_operand:VNx4SI_ONLY 0 "register_operand")
+       (unspec:VNx4SI_ONLY
+         [(match_operand:VNx2BI 1 "register_operand")
+          (unspec:VNx4SI_ONLY
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:VNx2DF_ONLY 2 "register_operand")]
+            SVE_COND_FCVTI)
+          (match_operand:VNx4SI_ONLY 3 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+)
+
+(define_insn "*cond_<optab>_trunc<VNx2DF_ONLY:mode><VNx4SI_ONLY:mode>"
+  [(set (match_operand:VNx4SI_ONLY 0 "register_operand" "=&w, &w, ?&w")
+       (unspec:VNx4SI_ONLY
+         [(match_operand:VNx2BI 1 "register_operand" "Upl, Upl, Upl")
+          (unspec:VNx4SI_ONLY
+            [(match_dup 1)
+             (match_operand:SI 4 "aarch64_sve_gp_strictness")
+             (match_operand:VNx2DF_ONLY 2 "register_operand" "w, w, w")]
+            SVE_COND_FCVTI)
+          (match_operand:VNx4SI_ONLY 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+  "@
+   fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
+   movprfx\t%0.<VNx2DF_ONLY:Vetype>, %1/z, %2.<VNx2DF_ONLY:Vetype>\;fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>
+   movprfx\t%0, %3\;fcvtz<su>\t%0.<VNx4SI_ONLY:Vetype>, %1/m, %2.<VNx2DF_ONLY:Vetype>"
+  [(set_attr "movprfx" "*,yes,yes")]
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [INT<-FP] Packs
 ;; -------------------------------------------------------------------------
 
 ;; Predicated integer-to-float conversion, either to the same width or
 ;; narrower.
-(define_insn "*aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>"
+(define_insn "@aarch64_sve_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>"
   [(set (match_operand:SVE_F 0 "register_operand" "=w")
        (unspec:SVE_F
          [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand" "Upl")
 )
 
 ;; Predicated widening integer-to-float conversion.
-(define_insn "aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
+(define_insn "@aarch64_sve_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
   [(set (match_operand:VNx2DF_ONLY 0 "register_operand" "=w")
        (unspec:VNx2DF_ONLY
          [(match_operand:VNx2BI 1 "register_operand" "Upl")
 
 ;; Predicated integer-to-float conversion with merging, either to the same
 ;; width or narrower.
-;;
+(define_expand "@cond_<optab>_nonextend<SVE_HSDI:mode><SVE_F:mode>"
+  [(set (match_operand:SVE_F 0 "register_operand")
+       (unspec:SVE_F
+         [(match_operand:<SVE_HSDI:VPRED> 1 "register_operand")
+          (unspec:SVE_F
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:SVE_HSDI 2 "register_operand")]
+            SVE_COND_ICVTF)
+          (match_operand:SVE_F 3 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE && <SVE_HSDI:elem_bits> >= <SVE_F:elem_bits>"
+)
+
 ;; The first alternative doesn't need the earlyclobber, but the only case
 ;; it would help is the uninteresting one in which operands 2 and 3 are
 ;; the same register (despite having different modes).  Making all the
   [(set_attr "movprfx" "*,yes,yes")]
 )
 
+;; Predicated widening integer-to-float conversion with merging.
+(define_expand "@cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
+  [(set (match_operand:VNx2DF_ONLY 0 "register_operand")
+       (unspec:VNx2DF_ONLY
+         [(match_operand:VNx2BI 1 "register_operand")
+          (unspec:VNx2DF_ONLY
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:VNx4SI_ONLY 2 "register_operand")]
+            SVE_COND_ICVTF)
+          (match_operand:VNx2DF_ONLY 3 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+)
+
+(define_insn "*cond_<optab>_extend<VNx4SI_ONLY:mode><VNx2DF_ONLY:mode>"
+  [(set (match_operand:VNx2DF_ONLY 0 "register_operand" "=w, ?&w, ?&w")
+       (unspec:VNx2DF_ONLY
+         [(match_operand:VNx2BI 1 "register_operand" "Upl, Upl, Upl")
+          (unspec:VNx2DF_ONLY
+            [(match_dup 1)
+             (match_operand:SI 4 "aarch64_sve_gp_strictness")
+             (match_operand:VNx4SI_ONLY 2 "register_operand" "w, w, w")]
+            SVE_COND_ICVTF)
+          (match_operand:VNx2DF_ONLY 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+         UNSPEC_SEL))]
+  "TARGET_SVE"
+  "@
+   <su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>
+   movprfx\t%0.<VNx2DF_ONLY:Vetype>, %1/z, %2.<VNx2DF_ONLY:Vetype>\;<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>
+   movprfx\t%0, %3\;<su>cvtf\t%0.<VNx2DF_ONLY:Vetype>, %1/m, %2.<VNx4SI_ONLY:Vetype>"
+  [(set_attr "movprfx" "*,yes,yes")]
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [FP<-INT] Packs
 ;; -------------------------------------------------------------------------
 )
 
 ;; Predicated float-to-float truncation.
-(define_insn "*aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
+(define_insn "@aarch64_sve_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
   [(set (match_operand:SVE_HSF 0 "register_operand" "=w")
        (unspec:SVE_HSF
          [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl")
   "fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>"
 )
 
+;; Predicated float-to-float truncation with merging.
+(define_expand "@cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
+  [(set (match_operand:SVE_HSF 0 "register_operand")
+       (unspec:SVE_HSF
+         [(match_operand:<SVE_SDF:VPRED> 1 "register_operand")
+          (unspec:SVE_HSF
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:SVE_SDF 2 "register_operand")]
+            SVE_COND_FCVT)
+          (match_operand:SVE_HSF 3 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+)
+
+(define_insn "*cond_<optab>_trunc<SVE_SDF:mode><SVE_HSF:mode>"
+  [(set (match_operand:SVE_HSF 0 "register_operand" "=w, ?&w, ?&w")
+       (unspec:SVE_HSF
+         [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl, Upl, Upl")
+          (unspec:SVE_HSF
+            [(match_dup 1)
+             (match_operand:SI 4 "aarch64_sve_gp_strictness")
+             (match_operand:SVE_SDF 2 "register_operand" "w, w, w")]
+            SVE_COND_FCVT)
+          (match_operand:SVE_HSF 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+         UNSPEC_SEL))]
+  "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+  "@
+   fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>
+   movprfx\t%0.<SVE_SDF:Vetype>, %1/z, %2.<SVE_SDF:Vetype>\;fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>
+   movprfx\t%0, %3\;fcvt\t%0.<SVE_HSF:Vetype>, %1/m, %2.<SVE_SDF:Vetype>"
+  [(set_attr "movprfx" "*,yes,yes")]
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [FP<-FP] Unpacks
 ;; -------------------------------------------------------------------------
 )
 
 ;; Predicated float-to-float extension.
-(define_insn "aarch64_sve_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
+(define_insn "@aarch64_sve_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
   [(set (match_operand:SVE_SDF 0 "register_operand" "=w")
        (unspec:SVE_SDF
          [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl")
   "fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>"
 )
 
+;; Predicated float-to-float extension with merging.
+(define_expand "@cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
+  [(set (match_operand:SVE_SDF 0 "register_operand")
+       (unspec:SVE_SDF
+         [(match_operand:<SVE_SDF:VPRED> 1 "register_operand")
+          (unspec:SVE_SDF
+            [(match_dup 1)
+             (const_int SVE_STRICT_GP)
+             (match_operand:SVE_HSF 2 "register_operand")]
+            SVE_COND_FCVT)
+          (match_operand:SVE_SDF 3 "aarch64_simd_reg_or_zero")]
+         UNSPEC_SEL))]
+  "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+)
+
+(define_insn "*cond_<optab>_nontrunc<SVE_HSF:mode><SVE_SDF:mode>"
+  [(set (match_operand:SVE_SDF 0 "register_operand" "=w, ?&w, ?&w")
+       (unspec:SVE_SDF
+         [(match_operand:<SVE_SDF:VPRED> 1 "register_operand" "Upl, Upl, Upl")
+          (unspec:SVE_SDF
+            [(match_dup 1)
+             (match_operand:SI 4 "aarch64_sve_gp_strictness")
+             (match_operand:SVE_HSF 2 "register_operand" "w, w, w")]
+            SVE_COND_FCVT)
+          (match_operand:SVE_SDF 3 "aarch64_simd_reg_or_zero" "0, Dz, w")]
+         UNSPEC_SEL))]
+  "TARGET_SVE && <SVE_SDF:elem_bits> > <SVE_HSF:elem_bits>"
+  "@
+   fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>
+   movprfx\t%0.<SVE_SDF:Vetype>, %1/z, %2.<SVE_SDF:Vetype>\;fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>
+   movprfx\t%0, %3\;fcvt\t%0.<SVE_SDF:Vetype>, %1/m, %2.<SVE_HSF:Vetype>"
+  [(set_attr "movprfx" "*,yes,yes")]
+)
+
 ;; -------------------------------------------------------------------------
 ;; ---- [PRED<-PRED] Packs
 ;; -------------------------------------------------------------------------
   }
 )
 
-(define_insn "aarch64_sve_punpk<perm_hilo>_<mode>"
+(define_insn "@aarch64_sve_punpk<perm_hilo>_<mode>"
   [(set (match_operand:<VWIDE> 0 "register_operand" "=Upa")
        (unspec:<VWIDE> [(match_operand:PRED_BHS 1 "register_operand" "Upa")]
                        UNPACK_UNSIGNED))]
   "TARGET_SVE"
   "punpk<perm_hilo>\t%0.h, %1.b"
 )
+
+;; =========================================================================
+;; == Vector partitioning
+;; =========================================================================
+
+;; -------------------------------------------------------------------------
+;; ---- [PRED] Unary partitioning
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - BRKA
+;; - BRKAS
+;; - BRKB
+;; - BRKBS
+;; -------------------------------------------------------------------------
+
+;; Note that unlike most other instructions that have both merging and
+;; zeroing forms, these instructions don't operate elementwise and so
+;; don't fit the IFN_COND model.
+(define_insn "@aarch64_brk<brk_op>"
+  [(set (match_operand:VNx16BI 0 "register_operand" "=Upa, Upa")
+       (unspec:VNx16BI
+         [(match_operand:VNx16BI 1 "register_operand" "Upa, Upa")
+          (match_operand:VNx16BI 2 "register_operand" "Upa, Upa")
+          (match_operand:VNx16BI 3 "aarch64_simd_reg_or_zero" "Dz, 0")]
+         SVE_BRK_UNARY))]
+  "TARGET_SVE"
+  "@
+   brk<brk_op>\t%0.b, %1/z, %2.b
+   brk<brk_op>\t%0.b, %1/m, %2.b"
+)
+
+;; Same, but also producing a flags result.
+(define_insn "*aarch64_brk<brk_op>_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa, Upa")
+          (match_dup 1)
+          (match_operand:SI 4 "aarch64_sve_ptrue_flag")
+          (unspec:VNx16BI
+            [(match_dup 1)
+             (match_operand:VNx16BI 2 "register_operand" "Upa, Upa")
+             (match_operand:VNx16BI 3 "aarch64_simd_reg_or_zero" "Dz, 0")]
+            SVE_BRK_UNARY)]
+         UNSPEC_PTEST))
+   (set (match_operand:VNx16BI 0 "register_operand" "=Upa, Upa")
+       (unspec:VNx16BI
+         [(match_dup 1)
+          (match_dup 2)
+          (match_dup 3)]
+         SVE_BRK_UNARY))]
+  "TARGET_SVE"
+  "@
+   brk<brk_op>s\t%0.b, %1/z, %2.b
+   brk<brk_op>s\t%0.b, %1/m, %2.b"
+)
+
+;; Same, but with only the flags result being interesting.
+(define_insn "*aarch64_brk<brk_op>_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa, Upa")
+          (match_dup 1)
+          (match_operand:SI 4 "aarch64_sve_ptrue_flag")
+          (unspec:VNx16BI
+            [(match_dup 1)
+             (match_operand:VNx16BI 2 "register_operand" "Upa, Upa")
+             (match_operand:VNx16BI 3 "aarch64_simd_reg_or_zero" "Dz, 0")]
+            SVE_BRK_UNARY)]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:VNx16BI 0 "=Upa, Upa"))]
+  "TARGET_SVE"
+  "@
+   brk<brk_op>s\t%0.b, %1/z, %2.b
+   brk<brk_op>s\t%0.b, %1/m, %2.b"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [PRED] Binary partitioning
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - BRKN
+;; - BRKNS
+;; - BRKPA
+;; - BRKPAS
+;; - BRKPB
+;; - BRKPBS
+;; -------------------------------------------------------------------------
+
+;; Binary BRKs (BRKN, BRKPA, BRKPB).
+(define_insn "@aarch64_brk<brk_op>"
+  [(set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (unspec:VNx16BI
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_operand:VNx16BI 2 "register_operand" "Upa")
+          (match_operand:VNx16BI 3 "register_operand" "<brk_reg_con>")]
+         SVE_BRK_BINARY))]
+  "TARGET_SVE"
+  "brk<brk_op>\t%0.b, %1/z, %2.b, %<brk_reg_opno>.b"
+)
+
+;; Same, but also producing a flags result.
+(define_insn "*aarch64_brk<brk_op>_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_dup 1)
+          (match_operand:SI 4 "aarch64_sve_ptrue_flag")
+          (unspec:VNx16BI
+            [(match_dup 1)
+             (match_operand:VNx16BI 2 "register_operand" "Upa")
+             (match_operand:VNx16BI 3 "register_operand" "<brk_reg_con>")]
+            SVE_BRK_BINARY)]
+         UNSPEC_PTEST))
+   (set (match_operand:VNx16BI 0 "register_operand" "=Upa")
+       (unspec:VNx16BI
+         [(match_dup 1)
+          (match_dup 2)
+          (match_dup 3)]
+         SVE_BRK_BINARY))]
+  "TARGET_SVE"
+  "brk<brk_op>s\t%0.b, %1/z, %2.b, %<brk_reg_opno>.b"
+)
+
+;; Same, but with only the flags result being interesting.
+(define_insn "*aarch64_brk<brk_op>_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_dup 1)
+          (match_operand:SI 4 "aarch64_sve_ptrue_flag")
+          (unspec:VNx16BI
+            [(match_dup 1)
+             (match_operand:VNx16BI 2 "register_operand" "Upa")
+             (match_operand:VNx16BI 3 "register_operand" "<brk_reg_con>")]
+            SVE_BRK_BINARY)]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:VNx16BI 0 "=Upa"))]
+  "TARGET_SVE"
+  "brk<brk_op>s\t%0.b, %1/z, %2.b, %<brk_reg_opno>.b"
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [PRED] Scalarization
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - PFIRST
+;; - PNEXT
+;; -------------------------------------------------------------------------
+
+(define_insn "@aarch64_sve_<sve_pred_op><mode>"
+  [(set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+       (unspec:PRED_ALL
+         [(match_operand:PRED_ALL 1 "register_operand" "Upa")
+          (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+          (match_operand:PRED_ALL 3 "register_operand" "0")]
+         SVE_PITER))
+   (clobber (reg:CC_NZC CC_REGNUM))]
+  "TARGET_SVE && <max_elem_bits> >= <elem_bits>"
+  "<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
+)
+
+;; Same, but also producing a flags result.
+(define_insn_and_rewrite "*aarch64_sve_<sve_pred_op><mode>_cc"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_operand 2)
+          (match_operand:SI 3 "aarch64_sve_ptrue_flag")
+          (unspec:PRED_ALL
+            [(match_operand 4)
+             (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+             (match_operand:PRED_ALL 6 "register_operand" "0")]
+            SVE_PITER)]
+         UNSPEC_PTEST))
+   (set (match_operand:PRED_ALL 0 "register_operand" "=Upa")
+       (unspec:PRED_ALL
+         [(match_dup 4)
+          (match_dup 5)
+          (match_dup 6)]
+         SVE_PITER))]
+  "TARGET_SVE
+   && <max_elem_bits> >= <elem_bits>
+   && aarch64_sve_same_pred_for_ptest_p (&operands[2], &operands[4])"
+  "<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
+  "&& !rtx_equal_p (operands[2], operands[4])"
+  {
+    operands[4] = operands[2];
+    operands[5] = operands[3];
+  }
+)
+
+;; Same, but with only the flags result being interesting.
+(define_insn_and_rewrite "*aarch64_sve_<sve_pred_op><mode>_ptest"
+  [(set (reg:CC_NZC CC_REGNUM)
+       (unspec:CC_NZC
+         [(match_operand:VNx16BI 1 "register_operand" "Upa")
+          (match_operand 2)
+          (match_operand:SI 3 "aarch64_sve_ptrue_flag")
+          (unspec:PRED_ALL
+            [(match_operand 4)
+             (match_operand:SI 5 "aarch64_sve_ptrue_flag")
+             (match_operand:PRED_ALL 6 "register_operand" "0")]
+            SVE_PITER)]
+         UNSPEC_PTEST))
+   (clobber (match_scratch:PRED_ALL 0 "=Upa"))]
+  "TARGET_SVE
+   && <max_elem_bits> >= <elem_bits>
+   && aarch64_sve_same_pred_for_ptest_p (&operands[2], &operands[4])"
+  "<sve_pred_op>\t%0.<Vetype>, %1, %0.<Vetype>"
+  "&& !rtx_equal_p (operands[2], operands[4])"
+  {
+    operands[4] = operands[2];
+    operands[5] = operands[3];
+  }
+)
+
+;; =========================================================================
+;; == Counting elements
+;; =========================================================================
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Count elements in a pattern (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - CNTB
+;; - CNTD
+;; - CNTH
+;; - CNTW
+;; -------------------------------------------------------------------------
+
+;; Count the number of elements in an svpattern.  Operand 1 is the pattern,
+;; operand 2 is the number of elements that fit in a 128-bit block, and
+;; operand 3 is a multiplier in the range [1, 16].
+;;
+;; Note that this pattern isn't used for SV_ALL (but would work for that too).
+(define_insn "aarch64_sve_cnt_pat"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (unspec:SI [(match_operand:DI 1 "const_int_operand")
+                     (match_operand:DI 2 "const_int_operand")
+                     (match_operand:DI 3 "const_int_operand")]
+                    UNSPEC_SVE_CNT_PAT)))]
+  "TARGET_SVE"
+  {
+    return aarch64_output_sve_cnt_pat_immediate ("cnt", "%x0", operands + 1);
+  }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Increment by the number of elements in a pattern (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - INC
+;; - SQINC
+;; - UQINC
+;; -------------------------------------------------------------------------
+
+;; Increment a DImode register by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ANY_PLUS:DI (zero_extend:DI
+                      (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                                  (match_operand:DI 3 "const_int_operand")
+                                  (match_operand:DI 4 "const_int_operand")]
+                                 UNSPEC_SVE_CNT_PAT))
+                    (match_operand:DI_ONLY 1 "register_operand" "0")))]
+  "TARGET_SVE"
+  {
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%x0",
+                                                operands + 2);
+  }
+)
+
+;; Increment an SImode register by the number of elements in an svpattern
+;; using modular arithmetic.  See aarch64_sve_cnt_pat for the counting
+;; behavior.
+(define_insn "*aarch64_sve_incsi_pat"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                            (match_operand:DI 3 "const_int_operand")
+                            (match_operand:DI 4 "const_int_operand")]
+                           UNSPEC_SVE_CNT_PAT)
+                (match_operand:SI 1 "register_operand" "0")))]
+  "TARGET_SVE"
+  {
+    return aarch64_output_sve_cnt_pat_immediate ("inc", "%x0", operands + 2);
+  }
+)
+
+;; Increment an SImode register by the number of elements in an svpattern
+;; using saturating arithmetic, extending the result to 64 bits.
+;;
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (<paired_extend>:DI
+         (SAT_PLUS:SI
+           (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                       (match_operand:DI 3 "const_int_operand")
+                       (match_operand:DI 4 "const_int_operand")]
+                      UNSPEC_SVE_CNT_PAT)
+           (match_operand:SI_ONLY 1 "register_operand" "0"))))]
+  "TARGET_SVE"
+  {
+    const char *registers = (<CODE> == SS_PLUS ? "%x0, %w0" : "%w0");
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", registers,
+                                                operands + 2);
+  }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Increment by the number of elements in a pattern (vector)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - INC
+;; - SQINC
+;; - UQINC
+;; -------------------------------------------------------------------------
+
+;; Increment a vector of DIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:VNx2DI 0 "register_operand" "=w, ?&w")
+       (ANY_PLUS:VNx2DI
+         (vec_duplicate:VNx2DI
+           (zero_extend:DI
+             (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                         (match_operand:DI 3 "const_int_operand")
+                         (match_operand:DI 4 "const_int_operand")]
+                        UNSPEC_SVE_CNT_PAT)))
+         (match_operand:VNx2DI_ONLY 1 "register_operand" "0, w")))]
+  "TARGET_SVE"
+  {
+    if (which_alternative == 1)
+      output_asm_insn ("movprfx\t%0, %1", operands);
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+                                                operands + 2);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Increment a vector of SIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:VNx4SI 0 "register_operand" "=w, ?&w")
+       (ANY_PLUS:VNx4SI
+         (vec_duplicate:VNx4SI
+           (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                       (match_operand:DI 3 "const_int_operand")
+                       (match_operand:DI 4 "const_int_operand")]
+                      UNSPEC_SVE_CNT_PAT))
+         (match_operand:VNx4SI_ONLY 1 "register_operand" "0, w")))]
+  "TARGET_SVE"
+  {
+    if (which_alternative == 1)
+      output_asm_insn ("movprfx\t%0, %1", operands);
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+                                                operands + 2);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Increment a vector of HIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_expand "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:VNx8HI 0 "register_operand")
+       (ANY_PLUS:VNx8HI
+         (vec_duplicate:VNx8HI
+           (truncate:HI
+             (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                         (match_operand:DI 3 "const_int_operand")
+                         (match_operand:DI 4 "const_int_operand")]
+                        UNSPEC_SVE_CNT_PAT)))
+         (match_operand:VNx8HI_ONLY 1 "register_operand")))]
+  "TARGET_SVE"
+)
+
+(define_insn "*aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:VNx8HI 0 "register_operand" "=w, ?&w")
+       (ANY_PLUS:VNx8HI
+         (vec_duplicate:VNx8HI
+           (match_operator:HI 5 "subreg_lowpart_operator"
+             [(unspec:SI [(match_operand:DI 2 "const_int_operand")
+                          (match_operand:DI 3 "const_int_operand")
+                          (match_operand:DI 4 "const_int_operand")]
+                         UNSPEC_SVE_CNT_PAT)]))
+         (match_operand:VNx8HI_ONLY 1 "register_operand" "0, w")))]
+  "TARGET_SVE"
+  {
+    if (which_alternative == 1)
+      output_asm_insn ("movprfx\t%0, %1", operands);
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+                                                operands + 2);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Decrement by the number of elements in a pattern (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - DEC
+;; - SQDEC
+;; - UQDEC
+;; -------------------------------------------------------------------------
+
+;; Decrement a DImode register by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ANY_MINUS:DI (match_operand:DI_ONLY 1 "register_operand" "0")
+                     (zero_extend:DI
+                       (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                                   (match_operand:DI 3 "const_int_operand")
+                                   (match_operand:DI 4 "const_int_operand")]
+                                  UNSPEC_SVE_CNT_PAT))))]
+  "TARGET_SVE"
+  {
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%x0",
+                                                operands + 2);
+  }
+)
+
+;; Decrement an SImode register by the number of elements in an svpattern
+;; using modular arithmetic.  See aarch64_sve_cnt_pat for the counting
+;; behavior.
+(define_insn "*aarch64_sve_decsi_pat"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (minus:SI (match_operand:SI 1 "register_operand" "0")
+                 (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                             (match_operand:DI 3 "const_int_operand")
+                             (match_operand:DI 4 "const_int_operand")]
+                            UNSPEC_SVE_CNT_PAT)))]
+  "TARGET_SVE"
+  {
+    return aarch64_output_sve_cnt_pat_immediate ("dec", "%x0", operands + 2);
+  }
+)
+
+;; Decrement an SImode register by the number of elements in an svpattern
+;; using saturating arithmetic, extending the result to 64 bits.
+;;
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (<paired_extend>:DI
+         (SAT_MINUS:SI
+           (match_operand:SI_ONLY 1 "register_operand" "0")
+           (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                       (match_operand:DI 3 "const_int_operand")
+                       (match_operand:DI 4 "const_int_operand")]
+                      UNSPEC_SVE_CNT_PAT))))]
+  "TARGET_SVE"
+  {
+    const char *registers = (<CODE> == SS_MINUS ? "%x0, %w0" : "%w0");
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", registers,
+                                                operands + 2);
+  }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Decrement by the number of elements in a pattern (vector)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - DEC
+;; - SQDEC
+;; - UQDEC
+;; -------------------------------------------------------------------------
+
+;; Decrement a vector of DIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:VNx2DI 0 "register_operand" "=w, ?&w")
+       (ANY_MINUS:VNx2DI
+         (match_operand:VNx2DI_ONLY 1 "register_operand" "0, w")
+         (vec_duplicate:VNx2DI
+           (zero_extend:DI
+             (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                         (match_operand:DI 3 "const_int_operand")
+                         (match_operand:DI 4 "const_int_operand")]
+                        UNSPEC_SVE_CNT_PAT)))))]
+  "TARGET_SVE"
+  {
+    if (which_alternative == 1)
+      output_asm_insn ("movprfx\t%0, %1", operands);
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+                                                operands + 2);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Decrement a vector of SIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_insn "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:VNx4SI 0 "register_operand" "=w, ?&w")
+       (ANY_MINUS:VNx4SI
+         (match_operand:VNx4SI_ONLY 1 "register_operand" "0, w")
+         (vec_duplicate:VNx4SI
+           (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                       (match_operand:DI 3 "const_int_operand")
+                       (match_operand:DI 4 "const_int_operand")]
+                      UNSPEC_SVE_CNT_PAT))))]
+  "TARGET_SVE"
+  {
+    if (which_alternative == 1)
+      output_asm_insn ("movprfx\t%0, %1", operands);
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+                                                operands + 2);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Decrement a vector of HIs by the number of elements in an svpattern.
+;; See aarch64_sve_cnt_pat for the counting behavior.
+(define_expand "@aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:VNx8HI 0 "register_operand")
+       (ANY_MINUS:VNx8HI
+         (match_operand:VNx8HI_ONLY 1 "register_operand")
+         (vec_duplicate:VNx8HI
+           (truncate:HI
+             (unspec:SI [(match_operand:DI 2 "const_int_operand")
+                         (match_operand:DI 3 "const_int_operand")
+                         (match_operand:DI 4 "const_int_operand")]
+                        UNSPEC_SVE_CNT_PAT)))))]
+  "TARGET_SVE"
+)
+
+(define_insn "*aarch64_sve_<inc_dec><mode>_pat"
+  [(set (match_operand:VNx8HI 0 "register_operand" "=w, ?&w")
+       (ANY_MINUS:VNx8HI
+         (match_operand:VNx8HI_ONLY 1 "register_operand" "0, w")
+         (vec_duplicate:VNx8HI
+           (match_operator:HI 5 "subreg_lowpart_operator"
+             [(unspec:SI [(match_operand:DI 2 "const_int_operand")
+                          (match_operand:DI 3 "const_int_operand")
+                          (match_operand:DI 4 "const_int_operand")]
+                         UNSPEC_SVE_CNT_PAT)]))))]
+  "TARGET_SVE"
+  {
+    if (which_alternative == 1)
+      output_asm_insn ("movprfx\t%0, %1", operands);
+    return aarch64_output_sve_cnt_pat_immediate ("<inc_dec>", "%0.<Vetype>",
+                                                operands + 2);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Count elements in a predicate (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - CNTP
+;; -------------------------------------------------------------------------
+
+;; Count the number of set bits in a predicate.  Operand 3 is true if
+;; operand 1 is known to be all-true.
+(define_insn "@aarch64_pred_cntp<mode>"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (zero_extend:DI
+         (unspec:SI [(match_operand:PRED_ALL 1 "register_operand" "Upl")
+                     (match_operand:SI 2 "aarch64_sve_ptrue_flag")
+                     (match_operand:PRED_ALL 3 "register_operand" "Upa")]
+                    UNSPEC_CNTP)))]
+  "TARGET_SVE"
+  "cntp\t%x0, %1, %3.<Vetype>")
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Increment by the number of elements in a predicate (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - INCP
+;; - SQINCP
+;; - UQINCP
+;; -------------------------------------------------------------------------
+
+;; Increment a DImode register by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp"
+  [(set (match_operand:DI 0 "register_operand")
+       (ANY_PLUS:DI
+         (zero_extend:DI
+           (unspec:SI [(match_dup 3)
+                       (const_int SVE_KNOWN_PTRUE)
+                       (match_operand:PRED_ALL 2 "register_operand")]
+                      UNSPEC_CNTP))
+         (match_operand:DI_ONLY 1 "register_operand")))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ANY_PLUS:DI
+         (zero_extend:DI
+           (unspec:SI [(match_operand 3)
+                       (const_int SVE_KNOWN_PTRUE)
+                       (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+                      UNSPEC_CNTP))
+         (match_operand:DI_ONLY 1 "register_operand" "0")))]
+  "TARGET_SVE"
+  "<inc_dec>p\t%x0, %2.<PRED_ALL:Vetype>"
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
+;; Increment an SImode register by the number of set bits in a predicate
+;; using modular arithmetic.  See aarch64_sve_cntp for a description of
+;; the operands.
+(define_insn_and_rewrite "*aarch64_incsi<mode>_cntp"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (plus:SI
+         (unspec:SI [(match_operand 3)
+                     (const_int SVE_KNOWN_PTRUE)
+                     (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+                    UNSPEC_CNTP)
+         (match_operand:SI 1 "register_operand" "0")))]
+  "TARGET_SVE"
+  "incp\t%x0, %2.<Vetype>"
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<MODE>mode);
+  }
+)
+
+;; Increment an SImode register by the number of set bits in a predicate
+;; using saturating arithmetic, extending the result to 64 bits.
+;;
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp"
+  [(set (match_operand:DI 0 "register_operand")
+       (<paired_extend>:DI
+         (SAT_PLUS:SI
+           (unspec:SI [(match_dup 3)
+                       (const_int SVE_KNOWN_PTRUE)
+                       (match_operand:PRED_ALL 2 "register_operand")]
+                      UNSPEC_CNTP)
+           (match_operand:SI_ONLY 1 "register_operand"))))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (<paired_extend>:DI
+         (SAT_PLUS:SI
+           (unspec:SI [(match_operand 3)
+                       (const_int SVE_KNOWN_PTRUE)
+                       (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+                      UNSPEC_CNTP)
+           (match_operand:SI_ONLY 1 "register_operand" "0"))))]
+  "TARGET_SVE"
+  {
+    if (<CODE> == SS_PLUS)
+      return "<inc_dec>p\t%x0, %2.<PRED_ALL:Vetype>, %w0";
+    else
+      return "<inc_dec>p\t%w0, %2.<PRED_ALL:Vetype>";
+  }
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Increment by the number of elements in a predicate (vector)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - INCP
+;; - SQINCP
+;; - UQINCP
+;; -------------------------------------------------------------------------
+
+;; Increment a vector of DIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx2DI 0 "register_operand")
+       (ANY_PLUS:VNx2DI
+         (vec_duplicate:VNx2DI
+           (zero_extend:DI
+             (unspec:SI
+               [(match_dup 3)
+                (const_int SVE_KNOWN_PTRUE)
+                (match_operand:<VPRED> 2 "register_operand")]
+               UNSPEC_CNTP)))
+         (match_operand:VNx2DI_ONLY 1 "register_operand")))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx2DI 0 "register_operand" "=w, ?&w")
+       (ANY_PLUS:VNx2DI
+         (vec_duplicate:VNx2DI
+           (zero_extend:DI
+             (unspec:SI
+               [(match_operand 3)
+                (const_int SVE_KNOWN_PTRUE)
+                (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+               UNSPEC_CNTP)))
+         (match_operand:VNx2DI_ONLY 1 "register_operand" "0, w")))]
+  "TARGET_SVE"
+  "@
+   <inc_dec>p\t%0.d, %2
+   movprfx\t%0, %1\;<inc_dec>p\t%0.d, %2"
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Increment a vector of SIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx4SI 0 "register_operand")
+       (ANY_PLUS:VNx4SI
+         (vec_duplicate:VNx4SI
+           (unspec:SI
+             [(match_dup 3)
+              (const_int SVE_KNOWN_PTRUE)
+              (match_operand:<VPRED> 2 "register_operand")]
+             UNSPEC_CNTP))
+         (match_operand:VNx4SI_ONLY 1 "register_operand")))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx4SI 0 "register_operand" "=w, ?&w")
+       (ANY_PLUS:VNx4SI
+         (vec_duplicate:VNx4SI
+           (unspec:SI
+             [(match_operand 3)
+              (const_int SVE_KNOWN_PTRUE)
+              (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+             UNSPEC_CNTP))
+         (match_operand:VNx4SI_ONLY 1 "register_operand" "0, w")))]
+  "TARGET_SVE"
+  "@
+   <inc_dec>p\t%0.s, %2
+   movprfx\t%0, %1\;<inc_dec>p\t%0.s, %2"
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Increment a vector of HIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx8HI 0 "register_operand")
+       (ANY_PLUS:VNx8HI
+         (vec_duplicate:VNx8HI
+           (truncate:HI
+             (unspec:SI
+               [(match_dup 3)
+                (const_int SVE_KNOWN_PTRUE)
+                (match_operand:<VPRED> 2 "register_operand")]
+               UNSPEC_CNTP)))
+         (match_operand:VNx8HI_ONLY 1 "register_operand")))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx8HI 0 "register_operand" "=w, ?&w")
+       (ANY_PLUS:VNx8HI
+         (vec_duplicate:VNx8HI
+           (match_operator:HI 3 "subreg_lowpart_operator"
+             [(unspec:SI
+                [(match_operand 4)
+                 (const_int SVE_KNOWN_PTRUE)
+                 (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+                UNSPEC_CNTP)]))
+         (match_operand:VNx8HI_ONLY 1 "register_operand" "0, w")))]
+  "TARGET_SVE"
+  "@
+   <inc_dec>p\t%0.h, %2
+   movprfx\t%0, %1\;<inc_dec>p\t%0.h, %2"
+  "&& !CONSTANT_P (operands[4])"
+  {
+    operands[4] = CONSTM1_RTX (<VPRED>mode);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Decrement by the number of elements in a predicate (scalar)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - DECP
+;; - SQDECP
+;; - UQDECP
+;; -------------------------------------------------------------------------
+
+;; Decrement a DImode register by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp"
+  [(set (match_operand:DI 0 "register_operand")
+       (ANY_MINUS:DI
+         (match_operand:DI_ONLY 1 "register_operand")
+         (zero_extend:DI
+           (unspec:SI [(match_dup 3)
+                       (const_int SVE_KNOWN_PTRUE)
+                       (match_operand:PRED_ALL 2 "register_operand")]
+                      UNSPEC_CNTP))))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><DI_ONLY:mode><PRED_ALL:mode>_cntp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (ANY_MINUS:DI
+         (match_operand:DI_ONLY 1 "register_operand" "0")
+         (zero_extend:DI
+           (unspec:SI [(match_operand 3)
+                       (const_int SVE_KNOWN_PTRUE)
+                       (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+                      UNSPEC_CNTP))))]
+  "TARGET_SVE"
+  "<inc_dec>p\t%x0, %2.<PRED_ALL:Vetype>"
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
+;; Decrement an SImode register by the number of set bits in a predicate
+;; using modular arithmetic.  See aarch64_sve_cntp for a description of the
+;; operands.
+(define_insn_and_rewrite "*aarch64_decsi<mode>_cntp"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+       (minus:SI
+         (match_operand:SI 1 "register_operand" "0")
+         (unspec:SI [(match_operand 3)
+                     (const_int SVE_KNOWN_PTRUE)
+                     (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+                    UNSPEC_CNTP)))]
+  "TARGET_SVE"
+  "decp\t%x0, %2.<Vetype>"
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<MODE>mode);
+  }
+)
+
+;; Decrement an SImode register by the number of set bits in a predicate
+;; using saturating arithmetic, extending the result to 64 bits.
+;;
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp"
+  [(set (match_operand:DI 0 "register_operand")
+       (<paired_extend>:DI
+         (SAT_MINUS:SI
+           (match_operand:SI_ONLY 1 "register_operand")
+           (unspec:SI [(match_dup 3)
+                       (const_int SVE_KNOWN_PTRUE)
+                       (match_operand:PRED_ALL 2 "register_operand")]
+                      UNSPEC_CNTP))))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><SI_ONLY:mode><PRED_ALL:mode>_cntp"
+  [(set (match_operand:DI 0 "register_operand" "=r")
+       (<paired_extend>:DI
+         (SAT_MINUS:SI
+           (match_operand:SI_ONLY 1 "register_operand" "0")
+           (unspec:SI [(match_operand 3)
+                       (const_int SVE_KNOWN_PTRUE)
+                       (match_operand:PRED_ALL 2 "register_operand" "Upa")]
+                      UNSPEC_CNTP))))]
+  "TARGET_SVE"
+  {
+    if (<CODE> == SS_MINUS)
+      return "<inc_dec>p\t%x0, %2.<PRED_ALL:Vetype>, %w0";
+    else
+      return "<inc_dec>p\t%w0, %2.<PRED_ALL:Vetype>";
+  }
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<PRED_ALL:MODE>mode);
+  }
+)
+
+;; -------------------------------------------------------------------------
+;; ---- [INT] Decrement by the number of elements in a predicate (vector)
+;; -------------------------------------------------------------------------
+;; Includes:
+;; - DECP
+;; - SQDECP
+;; - UQDECP
+;; -------------------------------------------------------------------------
+
+;; Decrement a vector of DIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx2DI 0 "register_operand")
+       (ANY_MINUS:VNx2DI
+         (match_operand:VNx2DI_ONLY 1 "register_operand")
+         (vec_duplicate:VNx2DI
+           (zero_extend:DI
+             (unspec:SI
+               [(match_dup 3)
+                (const_int SVE_KNOWN_PTRUE)
+                (match_operand:<VPRED> 2 "register_operand")]
+               UNSPEC_CNTP)))))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx2DI 0 "register_operand" "=w, ?&w")
+       (ANY_MINUS:VNx2DI
+         (match_operand:VNx2DI_ONLY 1 "register_operand" "0, w")
+         (vec_duplicate:VNx2DI
+           (zero_extend:DI
+             (unspec:SI
+               [(match_operand 3)
+                (const_int SVE_KNOWN_PTRUE)
+                (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+               UNSPEC_CNTP)))))]
+  "TARGET_SVE"
+  "@
+   <inc_dec>p\t%0.d, %2
+   movprfx\t%0, %1\;<inc_dec>p\t%0.d, %2"
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Decrement a vector of SIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx4SI 0 "register_operand")
+       (ANY_MINUS:VNx4SI
+         (match_operand:VNx4SI_ONLY 1 "register_operand")
+         (vec_duplicate:VNx4SI
+           (unspec:SI
+             [(match_dup 3)
+              (const_int SVE_KNOWN_PTRUE)
+              (match_operand:<VPRED> 2 "register_operand")]
+             UNSPEC_CNTP))))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx4SI 0 "register_operand" "=w, ?&w")
+       (ANY_MINUS:VNx4SI
+         (match_operand:VNx4SI_ONLY 1 "register_operand" "0, w")
+         (vec_duplicate:VNx4SI
+           (unspec:SI
+             [(match_operand 3)
+              (const_int SVE_KNOWN_PTRUE)
+              (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+             UNSPEC_CNTP))))]
+  "TARGET_SVE"
+  "@
+   <inc_dec>p\t%0.s, %2
+   movprfx\t%0, %1\;<inc_dec>p\t%0.s, %2"
+  "&& !CONSTANT_P (operands[3])"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
+
+;; Decrement a vector of HIs by the number of set bits in a predicate.
+;; See aarch64_sve_cntp for a description of the operands.
+(define_expand "@aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx8HI 0 "register_operand")
+       (ANY_MINUS:VNx8HI
+         (match_operand:VNx8HI_ONLY 1 "register_operand")
+         (vec_duplicate:VNx8HI
+           (truncate:HI
+             (unspec:SI
+               [(match_dup 3)
+                (const_int SVE_KNOWN_PTRUE)
+                (match_operand:<VPRED> 2 "register_operand")]
+               UNSPEC_CNTP)))))]
+  "TARGET_SVE"
+  {
+    operands[3] = CONSTM1_RTX (<VPRED>mode);
+  }
+)
+
+(define_insn_and_rewrite "*aarch64_sve_<inc_dec><mode>_cntp"
+  [(set (match_operand:VNx8HI 0 "register_operand" "=w, ?&w")
+       (ANY_MINUS:VNx8HI
+         (match_operand:VNx8HI_ONLY 1 "register_operand" "0, w")
+         (vec_duplicate:VNx8HI
+           (match_operator:HI 3 "subreg_lowpart_operator"
+             [(unspec:SI
+                [(match_operand 4)
+                 (const_int SVE_KNOWN_PTRUE)
+                 (match_operand:<VPRED> 2 "register_operand" "Upa, Upa")]
+                UNSPEC_CNTP)]))))]
+  "TARGET_SVE"
+  "@
+   <inc_dec>p\t%0.h, %2
+   movprfx\t%0, %1\;<inc_dec>p\t%0.h, %2"
+  "&& !CONSTANT_P (operands[4])"
+  {
+    operands[4] = CONSTM1_RTX (<VPRED>mode);
+  }
+  [(set_attr "movprfx" "*,yes")]
+)
index 3b4290a9204b4b98b305a993198731c28cf6cfd8..9cafef46f38d71c6527d9fe39bd7638405bfb5c1 100644 (file)
@@ -1744,7 +1744,7 @@ aarch64_get_mask_mode (poly_uint64 nunits, poly_uint64 nbytes)
 
 /* Return the SVE vector mode that has NUNITS elements of mode INNER_MODE.  */
 
-static opt_machine_mode
+opt_machine_mode
 aarch64_sve_data_mode (scalar_mode inner_mode, poly_uint64 nunits)
 {
   enum mode_class mclass = (is_a <scalar_float_mode> (inner_mode)
@@ -1772,7 +1772,7 @@ aarch64_sve_element_int_mode (machine_mode mode)
    Unlike mode_for_int_vector, this can handle the case in which
    MODE is a predicate (and thus has a different total size).  */
 
-static machine_mode
+machine_mode
 aarch64_sve_int_mode (machine_mode mode)
 {
   scalar_int_mode int_mode = aarch64_sve_element_int_mode (mode);
@@ -2764,6 +2764,27 @@ aarch64_widest_sve_pred_elt_size (rtx_vector_builder &builder)
   return mask & -mask;
 }
 
+/* If VNx16BImode rtx X is a canonical PTRUE for a predicate mode,
+   return that predicate mode, otherwise return opt_machine_mode ().  */
+
+opt_machine_mode
+aarch64_ptrue_all_mode (rtx x)
+{
+  gcc_assert (GET_MODE (x) == VNx16BImode);
+  if (GET_CODE (x) != CONST_VECTOR
+      || !CONST_VECTOR_DUPLICATE_P (x)
+      || !CONST_INT_P (CONST_VECTOR_ENCODED_ELT (x, 0))
+      || INTVAL (CONST_VECTOR_ENCODED_ELT (x, 0)) == 0)
+    return opt_machine_mode ();
+
+  unsigned int nelts = const_vector_encoded_nelts (x);
+  for (unsigned int i = 1; i < nelts; ++i)
+    if (CONST_VECTOR_ENCODED_ELT (x, i) != const0_rtx)
+      return opt_machine_mode ();
+
+  return aarch64_sve_pred_mode (nelts);
+}
+
 /* BUILDER is a predicate constant of mode VNx16BI.  Consider the value
    that the constant would have with predicate element size ELT_SIZE
    (ignoring the upper bits in each element) and return:
@@ -2948,7 +2969,7 @@ aarch64_sve_emit_int_cmp (rtx target, machine_mode pred_mode, rtx_code cmp,
    the corresponding SVE predicate mode.  Use TARGET for the result
    if it's nonnull and convenient.  */
 
-static rtx
+rtx
 aarch64_convert_sve_data_to_pred (rtx target, machine_mode mode, rtx src)
 {
   machine_mode src_mode = GET_MODE (src);
@@ -2956,6 +2977,78 @@ aarch64_convert_sve_data_to_pred (rtx target, machine_mode mode, rtx src)
                                   src, CONST0_RTX (src_mode));
 }
 
+/* Return the assembly token for svprfop value PRFOP.  */
+
+static const char *
+svprfop_token (enum aarch64_svprfop prfop)
+{
+  switch (prfop)
+    {
+#define CASE(UPPER, LOWER, VALUE) case AARCH64_SV_##UPPER: return #LOWER;
+    AARCH64_FOR_SVPRFOP (CASE)
+#undef CASE
+    case AARCH64_NUM_SVPRFOPS:
+      break;
+    }
+  gcc_unreachable ();
+}
+
+/* Return the assembly string for an SVE prefetch operation with
+   mnemonic MNEMONIC, given that PRFOP_RTX is the prefetch operation
+   and that SUFFIX is the format for the remaining operands.  */
+
+char *
+aarch64_output_sve_prefetch (const char *mnemonic, rtx prfop_rtx,
+                            const char *suffix)
+{
+  static char buffer[128];
+  aarch64_svprfop prfop = (aarch64_svprfop) INTVAL (prfop_rtx);
+  unsigned int written = snprintf (buffer, sizeof (buffer), "%s\t%s, %s",
+                                  mnemonic, svprfop_token (prfop), suffix);
+  gcc_assert (written < sizeof (buffer));
+  return buffer;
+}
+
+/* Check whether we can calculate the number of elements in PATTERN
+   at compile time, given that there are NELTS_PER_VQ elements per
+   128-bit block.  Return the value if so, otherwise return -1.  */
+
+HOST_WIDE_INT
+aarch64_fold_sve_cnt_pat (aarch64_svpattern pattern, unsigned int nelts_per_vq)
+{
+  unsigned int vl, const_vg;
+  if (pattern >= AARCH64_SV_VL1 && pattern <= AARCH64_SV_VL8)
+    vl = 1 + (pattern - AARCH64_SV_VL1);
+  else if (pattern >= AARCH64_SV_VL16 && pattern <= AARCH64_SV_VL256)
+    vl = 16 << (pattern - AARCH64_SV_VL16);
+  else if (aarch64_sve_vg.is_constant (&const_vg))
+    {
+      /* There are two vector granules per quadword.  */
+      unsigned int nelts = (const_vg / 2) * nelts_per_vq;
+      switch (pattern)
+       {
+       case AARCH64_SV_POW2: return 1 << floor_log2 (nelts);
+       case AARCH64_SV_MUL4: return nelts & -4;
+       case AARCH64_SV_MUL3: return (nelts / 3) * 3;
+       case AARCH64_SV_ALL: return nelts;
+       default: gcc_unreachable ();
+       }
+    }
+  else
+    return -1;
+
+  /* There are two vector granules per quadword.  */
+  poly_uint64 nelts_all = exact_div (aarch64_sve_vg, 2) * nelts_per_vq;
+  if (known_le (vl, nelts_all))
+    return vl;
+
+  /* Requesting more elements than are available results in a PFALSE.  */
+  if (known_gt (vl, nelts_all))
+    return 0;
+
+  return -1;
+}
+
 /* Return true if we can move VALUE into a register using a single
    CNT[BHWD] instruction.  */
 
@@ -3038,6 +3131,24 @@ aarch64_output_sve_cnt_immediate (const char *prefix, const char *operands,
                                           value.coeffs[1], 0);
 }
 
+/* Return the asm string for an instruction with a CNT-like vector size
+   operand (a vector pattern followed by a multiplier in the range [1, 16]).
+   PREFIX is the mnemonic without the size suffix and OPERANDS is the
+   first part of the operands template (the part that comes before the
+   vector size itself).  CNT_PAT[0..2] are the operands of the
+   UNSPEC_SVE_CNT_PAT; see aarch64_sve_cnt_pat for details.  */
+
+char *
+aarch64_output_sve_cnt_pat_immediate (const char *prefix,
+                                     const char *operands, rtx *cnt_pat)
+{
+  aarch64_svpattern pattern = (aarch64_svpattern) INTVAL (cnt_pat[0]);
+  unsigned int nelts_per_vq = INTVAL (cnt_pat[1]);
+  unsigned int factor = INTVAL (cnt_pat[2]) * nelts_per_vq;
+  return aarch64_output_sve_cnt_immediate (prefix, operands, pattern,
+                                          factor, nelts_per_vq);
+}
+
 /* Return true if we can add X using a single SVE INC or DEC instruction.  */
 
 bool
@@ -3904,7 +4015,8 @@ aarch64_sve_move_pred_via_while (rtx target, machine_mode mode,
 {
   rtx limit = force_reg (DImode, gen_int_mode (vl, DImode));
   target = aarch64_target_reg (target, mode);
-  emit_insn (gen_while_ult (DImode, mode, target, const0_rtx, limit));
+  emit_insn (gen_while (UNSPEC_WHILE_LO, DImode, mode,
+                       target, const0_rtx, limit));
   return target;
 }
 
@@ -4416,7 +4528,7 @@ aarch64_maybe_expand_sve_subreg_move (rtx dest, rtx src)
    attributes.  Unlike gen_lowpart, this doesn't care whether the
    mode change is valid.  */
 
-static rtx
+rtx
 aarch64_replace_reg_mode (rtx x, machine_mode mode)
 {
   if (GET_MODE (x) == mode)
@@ -11718,6 +11830,7 @@ static void
 aarch64_init_builtins ()
 {
   aarch64_general_init_builtins ();
+  aarch64_sve::init_builtins ();
 }
 
 /* Implement TARGET_FOLD_BUILTIN.  */
@@ -11731,6 +11844,9 @@ aarch64_fold_builtin (tree fndecl, int nargs, tree *args, bool)
     {
     case AARCH64_BUILTIN_GENERAL:
       return aarch64_general_fold_builtin (subcode, type, nargs, args);
+
+    case AARCH64_BUILTIN_SVE:
+      return NULL_TREE;
     }
   gcc_unreachable ();
 }
@@ -11749,6 +11865,10 @@ aarch64_gimple_fold_builtin (gimple_stmt_iterator *gsi)
     case AARCH64_BUILTIN_GENERAL:
       new_stmt = aarch64_general_gimple_fold_builtin (subcode, stmt);
       break;
+
+    case AARCH64_BUILTIN_SVE:
+      new_stmt = aarch64_sve::gimple_fold_builtin (subcode, gsi, stmt);
+      break;
     }
 
   if (!new_stmt)
@@ -11769,6 +11889,9 @@ aarch64_expand_builtin (tree exp, rtx target, rtx, machine_mode, int ignore)
     {
     case AARCH64_BUILTIN_GENERAL:
       return aarch64_general_expand_builtin (subcode, exp, target, ignore);
+
+    case AARCH64_BUILTIN_SVE:
+      return aarch64_sve::expand_builtin (subcode, exp, target);
     }
   gcc_unreachable ();
 }
@@ -11782,6 +11905,9 @@ aarch64_builtin_decl (unsigned int code, bool initialize_p)
     {
     case AARCH64_BUILTIN_GENERAL:
       return aarch64_general_builtin_decl (subcode, initialize_p);
+
+    case AARCH64_BUILTIN_SVE:
+      return aarch64_sve::builtin_decl (subcode, initialize_p);
     }
   gcc_unreachable ();
 }
@@ -11815,6 +11941,9 @@ aarch64_builtin_reciprocal (tree fndecl)
     {
     case AARCH64_BUILTIN_GENERAL:
       return aarch64_general_builtin_rsqrt (subcode);
+
+    case AARCH64_BUILTIN_SVE:
+      return NULL_TREE;
     }
   gcc_unreachable ();
 }
@@ -15259,7 +15388,12 @@ aarch64_mangle_type (const_tree type)
   /* Mangle AArch64-specific internal types.  TYPE_NAME is non-NULL_TREE for
      builtin types.  */
   if (TYPE_NAME (type) != NULL)
-    return aarch64_general_mangle_builtin_type (type);
+    {
+      const char *res;
+      if ((res = aarch64_general_mangle_builtin_type (type))
+         || (res = aarch64_sve::mangle_builtin_type (type)))
+       return res;
+    }
 
   /* Use the default mangling.  */
   return NULL;
@@ -15417,6 +15551,27 @@ aarch64_sve_arith_immediate_p (rtx x, bool negate_p)
   return IN_RANGE (val, 0, 0xff00);
 }
 
+/* Return true if X is a valid immediate for the SVE SQADD and SQSUB
+   instructions.  Negate X first if NEGATE_P is true.  */
+
+bool
+aarch64_sve_sqadd_sqsub_immediate_p (rtx x, bool negate_p)
+{
+  rtx elt;
+
+  if (!const_vec_duplicate_p (x, &elt)
+      || !CONST_INT_P (elt))
+    return false;
+
+  if (!aarch64_sve_arith_immediate_p (x, negate_p))
+    return false;
+
+  /* After the optional negation, the immediate must be nonnegative.
+     E.g. a saturating add of -127 must be done via SQSUB Zn.B, Zn.B, #127
+     instead of SQADD Zn.B, Zn.B, #129.  */
+  return negate_p == (INTVAL (elt) < 0);
+}
+
 /* Return true if X is a valid immediate operand for an SVE logical
    instruction such as AND.  */
 
@@ -15649,12 +15804,45 @@ aarch64_sve_valid_immediate (unsigned HOST_WIDE_INT val64,
   return false;
 }
 
+/* Return true if X is an UNSPEC_PTRUE constant of the form:
+
+       (const (unspec [PATTERN ZERO] UNSPEC_PTRUE))
+
+   where PATTERN is the svpattern as a CONST_INT and where ZERO
+   is a zero constant of the required PTRUE mode (which can have
+   fewer elements than X's mode, if zero bits are significant).
+
+   If so, and if INFO is nonnull, describe the immediate in INFO.  */
+bool
+aarch64_sve_ptrue_svpattern_p (rtx x, struct simd_immediate_info *info)
+{
+  if (GET_CODE (x) != CONST)
+    return false;
+
+  x = XEXP (x, 0);
+  if (GET_CODE (x) != UNSPEC || XINT (x, 1) != UNSPEC_PTRUE)
+    return false;
+
+  if (info)
+    {
+      aarch64_svpattern pattern
+       = (aarch64_svpattern) INTVAL (XVECEXP (x, 0, 0));
+      machine_mode pred_mode = GET_MODE (XVECEXP (x, 0, 1));
+      scalar_int_mode int_mode = aarch64_sve_element_int_mode (pred_mode);
+      *info = simd_immediate_info (int_mode, pattern);
+    }
+  return true;
+}
+
 /* Return true if X is a valid SVE predicate.  If INFO is nonnull, use
    it to describe valid immediates.  */
 
 static bool
 aarch64_sve_pred_valid_immediate (rtx x, simd_immediate_info *info)
 {
+  if (aarch64_sve_ptrue_svpattern_p (x, info))
+    return true;
+
   if (x == CONST0_RTX (GET_MODE (x)))
     {
       if (info)
@@ -16063,6 +16251,35 @@ aarch64_sve_ld1rq_operand_p (rtx op)
   return false;
 }
 
+/* Return true if OP is a valid MEM operand for an SVE LDFF1 instruction.  */
+bool
+aarch64_sve_ldff1_operand_p (rtx op)
+{
+  if (!MEM_P (op))
+    return false;
+
+  struct aarch64_address_info addr;
+  if (!aarch64_classify_address (&addr, XEXP (op, 0), GET_MODE (op), false))
+    return false;
+
+  if (addr.type == ADDRESS_REG_IMM)
+    return known_eq (addr.const_offset, 0);
+
+  return addr.type == ADDRESS_REG_REG;
+}
+
+/* Return true if OP is a valid MEM operand for an SVE LDNF1 instruction.  */
+bool
+aarch64_sve_ldnf1_operand_p (rtx op)
+{
+  struct aarch64_address_info addr;
+
+  return (MEM_P (op)
+         && aarch64_classify_address (&addr, XEXP (op, 0),
+                                      GET_MODE (op), false)
+         && addr.type == ADDRESS_REG_IMM);
+}
+
 /* Return true if OP is a valid MEM operand for an SVE LDR instruction.
    The conditions for STR are the same.  */
 bool
@@ -16076,6 +16293,21 @@ aarch64_sve_ldr_operand_p (rtx op)
          && addr.type == ADDRESS_REG_IMM);
 }
 
+/* Return true if OP is a valid address for an SVE PRF[BHWD] instruction,
+   addressing memory of mode MODE.  */
+bool
+aarch64_sve_prefetch_operand_p (rtx op, machine_mode mode)
+{
+  struct aarch64_address_info addr;
+  if (!aarch64_classify_address (&addr, op, mode, false))
+    return false;
+
+  if (addr.type == ADDRESS_REG_IMM)
+    return known_eq (addr.const_offset, 0);
+
+  return addr.type == ADDRESS_REG_REG;
+}
+
 /* Return true if OP is a valid MEM operand for an SVE_STRUCT mode.
    We need to be able to access the individual pieces, so the range
    is different from LD[234] and ST[234].  */
@@ -17704,6 +17936,25 @@ aarch64_output_sve_mov_immediate (rtx const_vector)
   return templ;
 }
 
+/* Return the asm template for a PTRUES.  CONST_UNSPEC is the
+   aarch64_sve_ptrue_svpattern_immediate that describes the predicate
+   pattern.  */
+
+char *
+aarch64_output_sve_ptrues (rtx const_unspec)
+{
+  static char templ[40];
+
+  struct simd_immediate_info info;
+  bool is_valid = aarch64_simd_valid_immediate (const_unspec, &info);
+  gcc_assert (is_valid && info.insn == simd_immediate_info::PTRUE);
+
+  char element_char = sizetochar (GET_MODE_BITSIZE (info.elt_mode));
+  snprintf (templ, sizeof (templ), "ptrues\t%%0.%c, %s", element_char,
+           svpattern_token (info.u.pattern));
+  return templ;
+}
+
 /* Split operands into moves from op[1] + op[2] into op[0].  */
 
 void
index 3778109cb62d5b116e02397452b122c8226b2965..d1fe17366d2b663a09fb76c4ad87a76c9b700ec6 100644 (file)
     UNSPEC_XPACLRI
     UNSPEC_LD1_SVE
     UNSPEC_ST1_SVE
+    UNSPEC_LDNT1_SVE
+    UNSPEC_STNT1_SVE
     UNSPEC_LD1RQ
     UNSPEC_LD1_GATHER
+    UNSPEC_LDFF1_GATHER
     UNSPEC_ST1_SCATTER
     UNSPEC_PRED_X
     UNSPEC_PRED_Z
     UNSPEC_PTEST
+    UNSPEC_PTRUE
     UNSPEC_UNPACKSHI
     UNSPEC_UNPACKUHI
     UNSPEC_UNPACKSLO
     UNSPEC_UNPACKULO
     UNSPEC_PACK
+    UNSPEC_WHILE_LE
     UNSPEC_WHILE_LO
+    UNSPEC_WHILE_LS
+    UNSPEC_WHILE_LT
     UNSPEC_LDN
     UNSPEC_STN
     UNSPEC_INSR
+    UNSPEC_CLASTA
     UNSPEC_CLASTB
     UNSPEC_FADDA
     UNSPEC_REV_SUBREG
     UNSPEC_SPECULATION_TRACKER
     UNSPEC_COPYSIGN
     UNSPEC_TTEST               ; Represent transaction test.
+    UNSPEC_UPDATE_FFR
+    UNSPEC_UPDATE_FFRT
+    UNSPEC_RDFFR
+    UNSPEC_WRFFR
+    ;; Represents an SVE-style lane index, in which the indexing applies
+    ;; within the containing 128-bit block.
+    UNSPEC_SVE_LANE_SELECT
+    UNSPEC_SVE_CNT_PAT
+    UNSPEC_SVE_PREFETCH
+    UNSPEC_SVE_PREFETCH_GATHER
+    UNSPEC_SVE_COMPACT
+    UNSPEC_SVE_SPLICE
 ])
 
 (define_c_enum "unspecv" [
diff --git a/gcc/config/aarch64/arm_sve.h b/gcc/config/aarch64/arm_sve.h
new file mode 100644 (file)
index 0000000..b76d321
--- /dev/null
@@ -0,0 +1,36 @@
+/* AArch64 SVE intrinsics include file.
+   Copyright (C) 2018-2019 Free Software Foundation, Inc.
+
+   This file is part of GCC.
+
+   GCC is free software; you can redistribute it and/or modify it
+   under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GCC is distributed in the hope that it will be useful, but WITHOUT
+   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
+   License for more details.
+
+   Under Section 7 of GPL version 3, you are granted additional
+   permissions described in the GCC Runtime Library Exception, version
+   3.1, as published by the Free Software Foundation.
+
+   You should have received a copy of the GNU General Public License and
+   a copy of the GCC Runtime Library Exception along with this program;
+   see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _ARM_SVE_H_
+#define _ARM_SVE_H_
+
+#include <stdint.h>
+
+typedef __fp16 float16_t;
+typedef float float32_t;
+typedef double float64_t;
+
+#pragma GCC aarch64 "arm_sve.h"
+
+#endif
index 9326beca87d9ffa1d0b0977bcb556fdee861d2a1..d0c3dd5bc1f1b61457299b30241c02e3e101b608 100644 (file)
                                                  true,
                                                  ADDR_QUERY_LDP_STP_N)")))
 
+(define_address_constraint "UPb"
+  "@internal
+   An address valid for SVE PRFB instructions."
+  (match_test "aarch64_sve_prefetch_operand_p (op, VNx16QImode)"))
+
+(define_address_constraint "UPd"
+  "@internal
+   An address valid for SVE PRFD instructions."
+  (match_test "aarch64_sve_prefetch_operand_p (op, VNx2DImode)"))
+
+(define_address_constraint "UPh"
+  "@internal
+   An address valid for SVE PRFH instructions."
+  (match_test "aarch64_sve_prefetch_operand_p (op, VNx8HImode)"))
+
+(define_address_constraint "UPw"
+  "@internal
+   An address valid for SVE PRFW instructions."
+  (match_test "aarch64_sve_prefetch_operand_p (op, VNx4SImode)"))
+
+(define_memory_constraint "Utf"
+  "@internal
+   An address valid for SVE LDFF1 instructions."
+  (and (match_code "mem")
+       (match_test "aarch64_sve_ldff1_operand_p (op)")))
+
+(define_memory_constraint "Utn"
+  "@internal
+   An address valid for SVE LDNF1 instructions."
+  (and (match_code "mem")
+       (match_test "aarch64_sve_ldnf1_operand_p (op)")))
+
 (define_memory_constraint "Utr"
   "@internal
    An address valid for SVE LDR and STR instructions (as distinct from
  An address valid for a prefetch instruction."
  (match_test "aarch64_address_valid_for_prefetch_p (op, true)"))
 
+(define_constraint "vgb"
+  "@internal
+   A constraint that matches an immediate offset valid for SVE LD1B
+   gather instructions."
+ (match_operand 0 "aarch64_sve_gather_immediate_b"))
+
+(define_constraint "vgd"
+  "@internal
+   A constraint that matches an immediate offset valid for SVE LD1D
+   gather instructions."
+ (match_operand 0 "aarch64_sve_gather_immediate_d"))
+
+(define_constraint "vgh"
+  "@internal
+   A constraint that matches an immediate offset valid for SVE LD1H
+   gather instructions."
+ (match_operand 0 "aarch64_sve_gather_immediate_h"))
+
+(define_constraint "vgw"
+  "@internal
+   A constraint that matches an immediate offset valid for SVE LD1W
+   gather instructions."
+ (match_operand 0 "aarch64_sve_gather_immediate_w"))
+
 (define_constraint "vsa"
   "@internal
    A constraint that matches an immediate operand valid for SVE
    is valid for SVE SUB instructions."
  (match_operand 0 "aarch64_sve_sub_arith_immediate"))
 
+(define_constraint "vsQ"
+  "@internal
+   Like vsa, but additionally check that the immediate is nonnegative
+   when interpreted as a signed value."
+ (match_operand 0 "aarch64_sve_qadd_immediate"))
+
+(define_constraint "vsS"
+  "@internal
+   Like vsn, but additionally check that the immediate is negative
+   when interpreted as a signed value."
+ (match_operand 0 "aarch64_sve_qsub_immediate"))
+
 (define_constraint "vsl"
   "@internal
    A constraint that matches an immediate operand valid for SVE logical
index f879fadb007a23749a523edbe7fe247dee33fa94..d0ede24e9b042f584d9a04c9e7c1b716c59705ca 100644 (file)
 ;; Iterator for QI and HI modes
 (define_mode_iterator SHORT [QI HI])
 
+;; Iterators for single modes, for "@" patterns.
+(define_mode_iterator SI_ONLY [SI])
+(define_mode_iterator DI_ONLY [DI])
+
 ;; Iterator for all integer modes (up to 64-bit)
 (define_mode_iterator ALLI [QI HI SI DI])
 
                               VNx8HF VNx4SF VNx2DF])
 
 ;; Iterators for single modes, for "@" patterns.
+(define_mode_iterator VNx8HI_ONLY [VNx8HI])
 (define_mode_iterator VNx4SI_ONLY [VNx4SI])
+(define_mode_iterator VNx2DI_ONLY [VNx2DI])
 (define_mode_iterator VNx2DF_ONLY [VNx2DF])
 
 ;; All SVE vector structure modes.
 ;; All SVE floating-point vector modes.
 (define_mode_iterator SVE_F [VNx8HF VNx4SF VNx2DF])
 
+;; All partial SVE modes.
+(define_mode_iterator SVE_PARTIAL [VNx2QI
+                                  VNx4QI VNx2HI
+                                  VNx8QI VNx4HI VNx2SI])
+
+;; Modes involved in extending or truncating SVE data, for 8 elements per
+;; 128-bit block.
+(define_mode_iterator VNx8_NARROW [VNx8QI])
+(define_mode_iterator VNx8_WIDE [VNx8HI])
+
+;; ...same for 4 elements per 128-bit block.
+(define_mode_iterator VNx4_NARROW [VNx4QI VNx4HI])
+(define_mode_iterator VNx4_WIDE [VNx4SI])
+
+;; ...same for 2 elements per 128-bit block.
+(define_mode_iterator VNx2_NARROW [VNx2QI VNx2HI VNx2SI])
+(define_mode_iterator VNx2_WIDE [VNx2DI])
+
 ;; All SVE predicate modes.
 (define_mode_iterator PRED_ALL [VNx16BI VNx8BI VNx4BI VNx2BI])
 
 ;; SVE predicate modes that control 8-bit, 16-bit or 32-bit elements.
 (define_mode_iterator PRED_BHS [VNx16BI VNx8BI VNx4BI])
 
+;; SVE predicate modes that control 16-bit, 32-bit or 64-bit elements.
+(define_mode_iterator PRED_HSD [VNx8BI VNx4BI VNx2BI])
+
 ;; ------------------------------------------------------------------
 ;; Unspec enumerations for Advance SIMD. These could well go into
 ;; aarch64.md but for their use in int_iterators here.
     UNSPEC_FMLSL       ; Used in aarch64-simd.md.
     UNSPEC_FMLAL2      ; Used in aarch64-simd.md.
     UNSPEC_FMLSL2      ; Used in aarch64-simd.md.
+    UNSPEC_ADR         ; Used in aarch64-sve.md.
     UNSPEC_SEL         ; Used in aarch64-sve.md.
+    UNSPEC_BRKA                ; Used in aarch64-sve.md.
+    UNSPEC_BRKB                ; Used in aarch64-sve.md.
+    UNSPEC_BRKN                ; Used in aarch64-sve.md.
+    UNSPEC_BRKPA       ; Used in aarch64-sve.md.
+    UNSPEC_BRKPB       ; Used in aarch64-sve.md.
+    UNSPEC_PFIRST      ; Used in aarch64-sve.md.
+    UNSPEC_PNEXT       ; Used in aarch64-sve.md.
+    UNSPEC_CNTP                ; Used in aarch64-sve.md.
+    UNSPEC_SADDV       ; Used in aarch64-sve.md.
+    UNSPEC_UADDV       ; Used in aarch64-sve.md.
     UNSPEC_ANDV                ; Used in aarch64-sve.md.
     UNSPEC_IORV                ; Used in aarch64-sve.md.
     UNSPEC_XORV                ; Used in aarch64-sve.md.
     UNSPEC_REVW                ; Used in aarch64-sve.md.
     UNSPEC_SMUL_HIGHPART ; Used in aarch64-sve.md.
     UNSPEC_UMUL_HIGHPART ; Used in aarch64-sve.md.
+    UNSPEC_FMLA                ; Used in aarch64-sve.md.
+    UNSPEC_FMLS                ; Used in aarch64-sve.md.
+    UNSPEC_FEXPA       ; Used in aarch64-sve.md.
+    UNSPEC_FTMAD       ; Used in aarch64-sve.md.
+    UNSPEC_FTSMUL      ; Used in aarch64-sve.md.
+    UNSPEC_FTSSEL      ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPEQ_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPGE_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPGT_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPHI_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPHS_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPLE_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPLO_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPLS_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPLT_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_COND_CMPNE_WIDE ; Used in aarch64-sve.md.
     UNSPEC_COND_FABS   ; Used in aarch64-sve.md.
     UNSPEC_COND_FADD   ; Used in aarch64-sve.md.
+    UNSPEC_COND_FCADD90        ; Used in aarch64-sve.md.
+    UNSPEC_COND_FCADD270 ; Used in aarch64-sve.md.
     UNSPEC_COND_FCMEQ  ; Used in aarch64-sve.md.
     UNSPEC_COND_FCMGE  ; Used in aarch64-sve.md.
     UNSPEC_COND_FCMGT  ; Used in aarch64-sve.md.
+    UNSPEC_COND_FCMLA  ; Used in aarch64-sve.md.
+    UNSPEC_COND_FCMLA90        ; Used in aarch64-sve.md.
+    UNSPEC_COND_FCMLA180 ; Used in aarch64-sve.md.
+    UNSPEC_COND_FCMLA270 ; Used in aarch64-sve.md.
     UNSPEC_COND_FCMLE  ; Used in aarch64-sve.md.
     UNSPEC_COND_FCMLT  ; Used in aarch64-sve.md.
     UNSPEC_COND_FCMNE  ; Used in aarch64-sve.md.
     UNSPEC_COND_FCVTZS ; Used in aarch64-sve.md.
     UNSPEC_COND_FCVTZU ; Used in aarch64-sve.md.
     UNSPEC_COND_FDIV   ; Used in aarch64-sve.md.
+    UNSPEC_COND_FMAX   ; Used in aarch64-sve.md.
     UNSPEC_COND_FMAXNM ; Used in aarch64-sve.md.
+    UNSPEC_COND_FMIN   ; Used in aarch64-sve.md.
     UNSPEC_COND_FMINNM ; Used in aarch64-sve.md.
     UNSPEC_COND_FMLA   ; Used in aarch64-sve.md.
     UNSPEC_COND_FMLS   ; Used in aarch64-sve.md.
     UNSPEC_COND_FMUL   ; Used in aarch64-sve.md.
+    UNSPEC_COND_FMULX  ; Used in aarch64-sve.md.
     UNSPEC_COND_FNEG   ; Used in aarch64-sve.md.
     UNSPEC_COND_FNMLA  ; Used in aarch64-sve.md.
     UNSPEC_COND_FNMLS  ; Used in aarch64-sve.md.
+    UNSPEC_COND_FRECPX ; Used in aarch64-sve.md.
     UNSPEC_COND_FRINTA ; Used in aarch64-sve.md.
     UNSPEC_COND_FRINTI ; Used in aarch64-sve.md.
     UNSPEC_COND_FRINTM ; Used in aarch64-sve.md.
     UNSPEC_COND_FRINTP ; Used in aarch64-sve.md.
     UNSPEC_COND_FRINTX ; Used in aarch64-sve.md.
     UNSPEC_COND_FRINTZ ; Used in aarch64-sve.md.
+    UNSPEC_COND_FSCALE ; Used in aarch64-sve.md.
     UNSPEC_COND_FSQRT  ; Used in aarch64-sve.md.
     UNSPEC_COND_FSUB   ; Used in aarch64-sve.md.
     UNSPEC_COND_SCVTF  ; Used in aarch64-sve.md.
     UNSPEC_COND_UCVTF  ; Used in aarch64-sve.md.
+    UNSPEC_LASTA       ; Used in aarch64-sve.md.
     UNSPEC_LASTB       ; Used in aarch64-sve.md.
+    UNSPEC_ASHIFT_WIDE  ; Used in aarch64-sve.md.
+    UNSPEC_ASHIFTRT_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_LSHIFTRT_WIDE ; Used in aarch64-sve.md.
+    UNSPEC_LDFF1       ; Used in aarch64-sve.md.
+    UNSPEC_LDNF1       ; Used in aarch64-sve.md.
     UNSPEC_FCADD90     ; Used in aarch64-simd.md.
     UNSPEC_FCADD270    ; Used in aarch64-simd.md.
     UNSPEC_FCMLA       ; Used in aarch64-simd.md.
 (define_mode_attr Vetype_fourth [(VNx4SI "b") (VNx2DI "h")])
 
 ;; Equivalent of "size" for a vector element.
-(define_mode_attr Vesize [(VNx16QI "b")
-                         (VNx8HI  "h") (VNx8HF  "h")
-                         (VNx4SI  "w") (VNx4SF  "w")
+(define_mode_attr Vesize [(VNx16QI "b") (VNx8QI  "b")
+                         (VNx4QI  "b") (VNx2QI  "b")
+                         (VNx8HI  "h") (VNx4HI  "h")
+                         (VNx2HI  "h") (VNx8HF  "h")
+                         (VNx4SI  "w") (VNx2SI  "w") (VNx4SF  "w")
                          (VNx2DI  "d") (VNx2DF  "d")
                          (VNx32QI "b") (VNx48QI "b") (VNx64QI "b")
                          (VNx16HI "h") (VNx24HI "h") (VNx32HI "h")
 (define_mode_attr data_bytes [(VNx16BI "1") (VNx8BI "2")
                              (VNx4BI "4") (VNx2BI "8")])
 
+;; Two-nybble mask for partial vector modes: nunits, byte size.
+(define_mode_attr self_mask [(VNx8QI "0x81")
+                            (VNx4QI "0x41")
+                            (VNx2QI "0x21")
+                            (VNx4HI "0x42")
+                            (VNx2HI "0x22")
+                            (VNx2SI "0x24")])
+
+;; For full vector modes, the mask of narrower modes, encoded as above.
+(define_mode_attr narrower_mask [(VNx8HI "0x81")
+                                (VNx4SI "0x43")
+                                (VNx2DI "0x27")])
+
+;; The constraint to use for an SVE [SU]DOT, FMUL, FMLA or FMLS lane index.
+(define_mode_attr sve_lane_con [(VNx4SI "y") (VNx2DI "x")
+                               (VNx8HF "y") (VNx4SF "y") (VNx2DF "x")])
+
+;; The constraint to use for an SVE FCMLA lane index.
+(define_mode_attr sve_lane_pair_con [(VNx8HF "y") (VNx4SF "x")])
+
 ;; -------------------------------------------------------------------
 ;; Code Iterators
 ;; -------------------------------------------------------------------
 ;; Code iterator for signed variants of vector saturating binary ops.
 (define_code_iterator SBINQOPS [ss_plus ss_minus])
 
+;; Code iterator for unsigned variants of vector saturating binary ops.
+(define_code_iterator UBINQOPS [us_plus us_minus])
+
+;; Modular and saturating addition.
+(define_code_iterator ANY_PLUS [plus ss_plus us_plus])
+
+;; Saturating addition.
+(define_code_iterator SAT_PLUS [ss_plus us_plus])
+
+;; Modular and saturating subtraction.
+(define_code_iterator ANY_MINUS [minus ss_minus us_minus])
+
+;; Saturating subtraction.
+(define_code_iterator SAT_MINUS [ss_minus us_minus])
+
 ;; Comparison operators for <F>CM.
 (define_code_iterator COMPARISONS [lt le eq ge gt])
 
                      (smax "s") (umax "u")
                      (smin "s") (umin "u")])
 
+;; "s" for signed ops, empty for unsigned ones.
+(define_code_attr s [(sign_extend "s") (zero_extend "")])
+
+;; Map signed/unsigned ops to the corresponding extension.
+(define_code_attr paired_extend [(ss_plus "sign_extend")
+                                (us_plus "zero_extend")
+                                (ss_minus "sign_extend")
+                                (us_minus "zero_extend")])
+
 ;; Whether a shift is left or right.
 (define_code_attr lr [(ashift "l") (ashiftrt "r") (lshiftrt "r")])
 
    (ior "register_operand")
    (xor "register_operand")])
 
+(define_code_attr inc_dec [(minus "dec") (ss_minus "sqdec") (us_minus "uqdec")
+                          (plus "inc") (ss_plus "sqinc") (us_plus "uqinc")])
+
 ;; -------------------------------------------------------------------
 ;; Int Iterators.
 ;; -------------------------------------------------------------------
 (define_int_iterator FMAXMINV [UNSPEC_FMAXV UNSPEC_FMINV
                               UNSPEC_FMAXNMV UNSPEC_FMINNMV])
 
+(define_int_iterator SVE_INT_ADDV [UNSPEC_SADDV UNSPEC_UADDV])
+
 (define_int_iterator LOGICALF [UNSPEC_ANDF UNSPEC_IORF UNSPEC_XORF])
 
 (define_int_iterator HADDSUB [UNSPEC_SHADD UNSPEC_UHADD
 
 (define_int_iterator MUL_HIGHPART [UNSPEC_SMUL_HIGHPART UNSPEC_UMUL_HIGHPART])
 
-(define_int_iterator SVE_INT_UNARY [UNSPEC_REVB UNSPEC_REVH UNSPEC_REVW])
+(define_int_iterator CLAST [UNSPEC_CLASTA UNSPEC_CLASTB])
+
+(define_int_iterator LAST [UNSPEC_LASTA UNSPEC_LASTB])
+
+(define_int_iterator SVE_INT_UNARY [UNSPEC_RBIT UNSPEC_REVB
+                                   UNSPEC_REVH UNSPEC_REVW])
+
+(define_int_iterator SVE_FP_UNARY [UNSPEC_FRECPE UNSPEC_RSQRTE])
+
+(define_int_iterator SVE_FP_UNARY_INT [UNSPEC_FEXPA])
+
+(define_int_iterator SVE_FP_BINARY [UNSPEC_FRECPS UNSPEC_RSQRTS])
+
+(define_int_iterator SVE_FP_BINARY_INT [UNSPEC_FTSMUL UNSPEC_FTSSEL])
 
 (define_int_iterator SVE_INT_REDUCTION [UNSPEC_ANDV
                                        UNSPEC_IORV
 
 (define_int_iterator SVE_COND_FP_UNARY [UNSPEC_COND_FABS
                                        UNSPEC_COND_FNEG
+                                       UNSPEC_COND_FRECPX
                                        UNSPEC_COND_FRINTA
                                        UNSPEC_COND_FRINTI
                                        UNSPEC_COND_FRINTM
 
 (define_int_iterator SVE_COND_FP_BINARY [UNSPEC_COND_FADD
                                         UNSPEC_COND_FDIV
+                                        UNSPEC_COND_FMAX
                                         UNSPEC_COND_FMAXNM
+                                        UNSPEC_COND_FMIN
                                         UNSPEC_COND_FMINNM
                                         UNSPEC_COND_FMUL
+                                        UNSPEC_COND_FMULX
                                         UNSPEC_COND_FSUB])
 
-(define_int_iterator SVE_COND_FP_BINARY_I1 [UNSPEC_COND_FMAXNM
+(define_int_iterator SVE_COND_FP_BINARY_INT [UNSPEC_COND_FSCALE])
+
+(define_int_iterator SVE_COND_FP_ADD [UNSPEC_COND_FADD])
+(define_int_iterator SVE_COND_FP_SUB [UNSPEC_COND_FSUB])
+(define_int_iterator SVE_COND_FP_MUL [UNSPEC_COND_FMUL])
+
+(define_int_iterator SVE_COND_FP_BINARY_I1 [UNSPEC_COND_FMAX
+                                           UNSPEC_COND_FMAXNM
+                                           UNSPEC_COND_FMIN
                                            UNSPEC_COND_FMINNM
                                            UNSPEC_COND_FMUL])
 
-(define_int_iterator SVE_COND_FP_BINARY_REG [UNSPEC_COND_FDIV])
+(define_int_iterator SVE_COND_FP_BINARY_REG [UNSPEC_COND_FDIV
+                                            UNSPEC_COND_FMULX])
+
+(define_int_iterator SVE_COND_FCADD [UNSPEC_COND_FCADD90
+                                    UNSPEC_COND_FCADD270])
+
+(define_int_iterator SVE_COND_FP_MAXMIN [UNSPEC_COND_FMAX
+                                        UNSPEC_COND_FMAXNM
+                                        UNSPEC_COND_FMIN
+                                        UNSPEC_COND_FMINNM])
 
 ;; Floating-point max/min operations that correspond to optabs,
 ;; as opposed to those that are internal to the port.
                                          UNSPEC_COND_FNMLA
                                          UNSPEC_COND_FNMLS])
 
+(define_int_iterator SVE_COND_FCMLA [UNSPEC_COND_FCMLA
+                                    UNSPEC_COND_FCMLA90
+                                    UNSPEC_COND_FCMLA180
+                                    UNSPEC_COND_FCMLA270])
+
+(define_int_iterator SVE_COND_INT_CMP_WIDE [UNSPEC_COND_CMPEQ_WIDE
+                                           UNSPEC_COND_CMPGE_WIDE
+                                           UNSPEC_COND_CMPGT_WIDE
+                                           UNSPEC_COND_CMPHI_WIDE
+                                           UNSPEC_COND_CMPHS_WIDE
+                                           UNSPEC_COND_CMPLE_WIDE
+                                           UNSPEC_COND_CMPLO_WIDE
+                                           UNSPEC_COND_CMPLS_WIDE
+                                           UNSPEC_COND_CMPLT_WIDE
+                                           UNSPEC_COND_CMPNE_WIDE])
+
 ;; SVE FP comparisons that accept #0.0.
 (define_int_iterator SVE_COND_FP_CMP_I0 [UNSPEC_COND_FCMEQ
                                         UNSPEC_COND_FCMGE
                                          UNSPEC_COND_FCMLE
                                          UNSPEC_COND_FCMLT])
 
+(define_int_iterator SVE_FP_TERNARY_LANE [UNSPEC_FMLA UNSPEC_FMLS])
+
+(define_int_iterator SVE_CFP_TERNARY_LANE [UNSPEC_FCMLA UNSPEC_FCMLA90
+                                          UNSPEC_FCMLA180 UNSPEC_FCMLA270])
+
+(define_int_iterator SVE_WHILE [UNSPEC_WHILE_LE UNSPEC_WHILE_LO
+                               UNSPEC_WHILE_LS UNSPEC_WHILE_LT])
+
+(define_int_iterator SVE_SHIFT_WIDE [UNSPEC_ASHIFT_WIDE
+                                    UNSPEC_ASHIFTRT_WIDE
+                                    UNSPEC_LSHIFTRT_WIDE])
+
+(define_int_iterator SVE_LDFF1_LDNF1 [UNSPEC_LDFF1 UNSPEC_LDNF1])
+
 (define_int_iterator FCADD [UNSPEC_FCADD90
                            UNSPEC_FCADD270])
 
 (define_int_iterator FRINTNZX [UNSPEC_FRINT32Z UNSPEC_FRINT32X
                               UNSPEC_FRINT64Z UNSPEC_FRINT64X])
 
+(define_int_iterator SVE_BRK_UNARY [UNSPEC_BRKA UNSPEC_BRKB])
+
+(define_int_iterator SVE_BRK_BINARY [UNSPEC_BRKN UNSPEC_BRKPA UNSPEC_BRKPB])
+
+(define_int_iterator SVE_PITER [UNSPEC_PFIRST UNSPEC_PNEXT])
+
 ;; Iterators for atomic operations.
 
 (define_int_iterator ATOMIC_LDOP
 (define_int_attr optab [(UNSPEC_ANDF "and")
                        (UNSPEC_IORF "ior")
                        (UNSPEC_XORF "xor")
+                       (UNSPEC_SADDV "sadd")
+                       (UNSPEC_UADDV "uadd")
                        (UNSPEC_ANDV "and")
                        (UNSPEC_IORV "ior")
                        (UNSPEC_XORV "xor")
+                       (UNSPEC_FRECPE "frecpe")
+                       (UNSPEC_FRECPS "frecps")
+                       (UNSPEC_RSQRTE "frsqrte")
+                       (UNSPEC_RSQRTS "frsqrts")
+                       (UNSPEC_RBIT "rbit")
                        (UNSPEC_REVB "revb")
                        (UNSPEC_REVH "revh")
                        (UNSPEC_REVW "revw")
                        (UNSPEC_FMAXV "smax_nan")
                        (UNSPEC_FMINNMV "smin")
                        (UNSPEC_FMINV "smin_nan")
+                       (UNSPEC_SMUL_HIGHPART "smulh")
+                       (UNSPEC_UMUL_HIGHPART "umulh")
+                       (UNSPEC_FMLA "fma")
+                       (UNSPEC_FMLS "fnma")
+                       (UNSPEC_FCMLA "fcmla")
+                       (UNSPEC_FCMLA90 "fcmla90")
+                       (UNSPEC_FCMLA180 "fcmla180")
+                       (UNSPEC_FCMLA270 "fcmla270")
+                       (UNSPEC_FEXPA "fexpa")
+                       (UNSPEC_FTSMUL "ftsmul")
+                       (UNSPEC_FTSSEL "ftssel")
                        (UNSPEC_COND_FABS "abs")
                        (UNSPEC_COND_FADD "add")
+                       (UNSPEC_COND_FCADD90 "cadd90")
+                       (UNSPEC_COND_FCADD270 "cadd270")
+                       (UNSPEC_COND_FCMLA "fcmla")
+                       (UNSPEC_COND_FCMLA90 "fcmla90")
+                       (UNSPEC_COND_FCMLA180 "fcmla180")
+                       (UNSPEC_COND_FCMLA270 "fcmla270")
                        (UNSPEC_COND_FCVT "fcvt")
                        (UNSPEC_COND_FCVTZS "fix_trunc")
                        (UNSPEC_COND_FCVTZU "fixuns_trunc")
                        (UNSPEC_COND_FDIV "div")
+                       (UNSPEC_COND_FMAX "smax_nan")
                        (UNSPEC_COND_FMAXNM "smax")
+                       (UNSPEC_COND_FMIN "smin_nan")
                        (UNSPEC_COND_FMINNM "smin")
                        (UNSPEC_COND_FMLA "fma")
                        (UNSPEC_COND_FMLS "fnma")
                        (UNSPEC_COND_FMUL "mul")
+                       (UNSPEC_COND_FMULX "mulx")
                        (UNSPEC_COND_FNEG "neg")
                        (UNSPEC_COND_FNMLA "fnms")
                        (UNSPEC_COND_FNMLS "fms")
+                       (UNSPEC_COND_FRECPX "frecpx")
                        (UNSPEC_COND_FRINTA "round")
                        (UNSPEC_COND_FRINTI "nearbyint")
                        (UNSPEC_COND_FRINTM "floor")
                        (UNSPEC_COND_FRINTP "ceil")
                        (UNSPEC_COND_FRINTX "rint")
                        (UNSPEC_COND_FRINTZ "btrunc")
+                       (UNSPEC_COND_FSCALE "fscale")
                        (UNSPEC_COND_FSQRT "sqrt")
                        (UNSPEC_COND_FSUB "sub")
                        (UNSPEC_COND_SCVTF "float")
                              (UNSPEC_FMINV "smin_nan")
                              (UNSPEC_FMAXNM "fmax")
                              (UNSPEC_FMINNM "fmin")
+                             (UNSPEC_COND_FMAX "fmax_nan")
                              (UNSPEC_COND_FMAXNM "fmax")
+                             (UNSPEC_COND_FMIN "fmin_nan")
                              (UNSPEC_COND_FMINNM "fmin")])
 
 (define_int_attr  maxmin_uns_op [(UNSPEC_UMAXV "umax")
                                 (UNSPEC_FMAXNM "fmaxnm")
                                 (UNSPEC_FMINNM "fminnm")])
 
+(define_code_attr binqops_op [(ss_plus "sqadd")
+                             (us_plus "uqadd")
+                             (ss_minus "sqsub")
+                             (us_minus "uqsub")])
+
+(define_code_attr binqops_op_rev [(ss_plus "sqsub")
+                                 (ss_minus "sqadd")])
+
 ;; The SVE logical instruction that implements an unspec.
 (define_int_attr logicalf_op [(UNSPEC_ANDF "and")
                              (UNSPEC_IORF "orr")
                              (UNSPEC_XORF "eor")])
 
+(define_int_attr last_op [(UNSPEC_CLASTA "after_last")
+                         (UNSPEC_CLASTB "last")
+                         (UNSPEC_LASTA "after_last")
+                         (UNSPEC_LASTB "last")])
+
 ;; "s" for signed operations and "u" for unsigned ones.
-(define_int_attr su [(UNSPEC_UNPACKSHI "s")
+(define_int_attr su [(UNSPEC_SADDV "s")
+                    (UNSPEC_UADDV "u")
+                    (UNSPEC_UNPACKSHI "s")
                     (UNSPEC_UNPACKUHI "u")
                     (UNSPEC_UNPACKSLO "s")
                     (UNSPEC_UNPACKULO "u")
 (define_int_attr bt [(UNSPEC_SMULLB "b") (UNSPEC_UMULLB "b")
                     (UNSPEC_SMULLT "t") (UNSPEC_UMULLT "t")])
 
+(define_int_attr fn [(UNSPEC_LDFF1 "f") (UNSPEC_LDNF1 "n")])
+
+(define_int_attr ab [(UNSPEC_CLASTA "a") (UNSPEC_CLASTB "b")
+                    (UNSPEC_LASTA "a") (UNSPEC_LASTB "b")])
+
 (define_int_attr addsub [(UNSPEC_SHADD "add")
                         (UNSPEC_UHADD "add")
                         (UNSPEC_SRHADD "add")
                              (UNSPEC_FRINT64Z "frint64z") (UNSPEC_FRINT64X "frint64x")])
 
 ;; The condition associated with an UNSPEC_COND_<xx>.
-(define_int_attr cmp_op [(UNSPEC_COND_FCMEQ "eq")
+(define_int_attr cmp_op [(UNSPEC_COND_CMPEQ_WIDE "eq")
+                        (UNSPEC_COND_CMPGE_WIDE "ge")
+                        (UNSPEC_COND_CMPGT_WIDE "gt")
+                        (UNSPEC_COND_CMPHI_WIDE "hi")
+                        (UNSPEC_COND_CMPHS_WIDE "hs")
+                        (UNSPEC_COND_CMPLE_WIDE "le")
+                        (UNSPEC_COND_CMPLO_WIDE "lo")
+                        (UNSPEC_COND_CMPLS_WIDE "ls")
+                        (UNSPEC_COND_CMPLT_WIDE "lt")
+                        (UNSPEC_COND_CMPNE_WIDE "ne")
+                        (UNSPEC_COND_FCMEQ "eq")
                         (UNSPEC_COND_FCMGE "ge")
                         (UNSPEC_COND_FCMGT "gt")
                         (UNSPEC_COND_FCMLE "le")
                         (UNSPEC_COND_FCMLT "lt")
                         (UNSPEC_COND_FCMNE "ne")
-                        (UNSPEC_COND_FCMUO "uo")])
+                        (UNSPEC_WHILE_LE "le")
+                        (UNSPEC_WHILE_LO "lo")
+                        (UNSPEC_WHILE_LS "ls")
+                        (UNSPEC_WHILE_LT "lt")])
+
+(define_int_attr while_optab_cmp [(UNSPEC_WHILE_LE "le")
+                                 (UNSPEC_WHILE_LO "ult")
+                                 (UNSPEC_WHILE_LS "ule")
+                                 (UNSPEC_WHILE_LT "lt")])
+
+(define_int_attr brk_op [(UNSPEC_BRKA "a") (UNSPEC_BRKB "b")
+                        (UNSPEC_BRKN "n")
+                        (UNSPEC_BRKPA "pa") (UNSPEC_BRKPB "pb")])
+
+(define_int_attr sve_pred_op [(UNSPEC_PFIRST "pfirst") (UNSPEC_PNEXT "pnext")])
 
 (define_int_attr sve_int_op [(UNSPEC_ANDV "andv")
                             (UNSPEC_IORV "orv")
                             (UNSPEC_UMINV "uminv")
                             (UNSPEC_SMAXV "smaxv")
                             (UNSPEC_SMINV "sminv")
+                            (UNSPEC_SMUL_HIGHPART "smulh")
+                            (UNSPEC_UMUL_HIGHPART "umulh")
+                            (UNSPEC_ASHIFT_WIDE "lsl")
+                            (UNSPEC_ASHIFTRT_WIDE "asr")
+                            (UNSPEC_LSHIFTRT_WIDE "lsr")
+                            (UNSPEC_RBIT "rbit")
                             (UNSPEC_REVB "revb")
                             (UNSPEC_REVH "revh")
                             (UNSPEC_REVW "revw")])
 
-(define_int_attr sve_fp_op [(UNSPEC_FADDV "faddv")
+(define_int_attr sve_fp_op [(UNSPEC_FRECPE "frecpe")
+                           (UNSPEC_FRECPS "frecps")
+                           (UNSPEC_RSQRTE "frsqrte")
+                           (UNSPEC_RSQRTS "frsqrts")
+                           (UNSPEC_FADDV "faddv")
                            (UNSPEC_FMAXNMV "fmaxnmv")
                            (UNSPEC_FMAXV "fmaxv")
                            (UNSPEC_FMINNMV "fminnmv")
                            (UNSPEC_FMINV "fminv")
+                           (UNSPEC_FMLA "fmla")
+                           (UNSPEC_FMLS "fmls")
+                           (UNSPEC_FEXPA "fexpa")
+                           (UNSPEC_FTSMUL "ftsmul")
+                           (UNSPEC_FTSSEL "ftssel")
                            (UNSPEC_COND_FABS "fabs")
                            (UNSPEC_COND_FADD "fadd")
                            (UNSPEC_COND_FDIV "fdiv")
+                           (UNSPEC_COND_FMAX "fmax")
                            (UNSPEC_COND_FMAXNM "fmaxnm")
+                           (UNSPEC_COND_FMIN "fmin")
                            (UNSPEC_COND_FMINNM "fminnm")
                            (UNSPEC_COND_FMUL "fmul")
+                           (UNSPEC_COND_FMULX "fmulx")
                            (UNSPEC_COND_FNEG "fneg")
+                           (UNSPEC_COND_FRECPX "frecpx")
                            (UNSPEC_COND_FRINTA "frinta")
                            (UNSPEC_COND_FRINTI "frinti")
                            (UNSPEC_COND_FRINTM "frintm")
                            (UNSPEC_COND_FRINTP "frintp")
                            (UNSPEC_COND_FRINTX "frintx")
                            (UNSPEC_COND_FRINTZ "frintz")
+                           (UNSPEC_COND_FSCALE "fscale")
                            (UNSPEC_COND_FSQRT "fsqrt")
                            (UNSPEC_COND_FSUB "fsub")])
 
 (define_int_attr sve_fp_op_rev [(UNSPEC_COND_FADD "fadd")
                                (UNSPEC_COND_FDIV "fdivr")
+                               (UNSPEC_COND_FMAX "fmax")
                                (UNSPEC_COND_FMAXNM "fmaxnm")
+                               (UNSPEC_COND_FMIN "fmin")
                                (UNSPEC_COND_FMINNM "fminnm")
                                (UNSPEC_COND_FMUL "fmul")
+                               (UNSPEC_COND_FMULX "fmulx")
                                (UNSPEC_COND_FSUB "fsubr")])
 
 (define_int_attr rot [(UNSPEC_FCADD90 "90")
                      (UNSPEC_FCMLA "0")
                      (UNSPEC_FCMLA90 "90")
                      (UNSPEC_FCMLA180 "180")
-                     (UNSPEC_FCMLA270 "270")])
+                     (UNSPEC_FCMLA270 "270")
+                     (UNSPEC_COND_FCADD90 "90")
+                     (UNSPEC_COND_FCADD270 "270")
+                     (UNSPEC_COND_FCMLA "0")
+                     (UNSPEC_COND_FCMLA90 "90")
+                     (UNSPEC_COND_FCMLA180 "180")
+                     (UNSPEC_COND_FCMLA270 "270")])
 
 (define_int_attr sve_fmla_op [(UNSPEC_COND_FMLA "fmla")
                              (UNSPEC_COND_FMLS "fmls")
                              (UNSPEC_COND_FNMLA "fnmad")
                              (UNSPEC_COND_FNMLS "fnmsb")])
 
+;; The register constraint to use for the final operand in a binary BRK.
+(define_int_attr brk_reg_con [(UNSPEC_BRKN "0")
+                             (UNSPEC_BRKPA "Upa") (UNSPEC_BRKPB "Upa")])
+
+;; The register number to print for the above.
+(define_int_attr brk_reg_opno [(UNSPEC_BRKN "0")
+                              (UNSPEC_BRKPA "3") (UNSPEC_BRKPB "3")])
+
 ;; The predicate to use for the first input operand in a floating-point
 ;; <optab><mode>3 pattern.
 (define_int_attr sve_pred_fp_rhs1_operand
   [(UNSPEC_COND_FADD "register_operand")
    (UNSPEC_COND_FDIV "register_operand")
+   (UNSPEC_COND_FMAX "register_operand")
    (UNSPEC_COND_FMAXNM "register_operand")
+   (UNSPEC_COND_FMIN "register_operand")
    (UNSPEC_COND_FMINNM "register_operand")
    (UNSPEC_COND_FMUL "register_operand")
+   (UNSPEC_COND_FMULX "register_operand")
    (UNSPEC_COND_FSUB "aarch64_sve_float_arith_operand")])
 
 ;; The predicate to use for the second input operand in a floating-point
 (define_int_attr sve_pred_fp_rhs2_operand
   [(UNSPEC_COND_FADD "aarch64_sve_float_arith_with_sub_operand")
    (UNSPEC_COND_FDIV "register_operand")
+   (UNSPEC_COND_FMAX "aarch64_sve_float_maxmin_operand")
    (UNSPEC_COND_FMAXNM "aarch64_sve_float_maxmin_operand")
+   (UNSPEC_COND_FMIN "aarch64_sve_float_maxmin_operand")
    (UNSPEC_COND_FMINNM "aarch64_sve_float_maxmin_operand")
    (UNSPEC_COND_FMUL "aarch64_sve_float_mul_operand")
+   (UNSPEC_COND_FMULX "register_operand")
    (UNSPEC_COND_FSUB "register_operand")])
 
 ;; Likewise for immediates only.
 (define_int_attr sve_pred_fp_rhs2_immediate
-  [(UNSPEC_COND_FMAXNM "aarch64_sve_float_maxmin_immediate")
+  [(UNSPEC_COND_FMAX "aarch64_sve_float_maxmin_immediate")
+   (UNSPEC_COND_FMAXNM "aarch64_sve_float_maxmin_immediate")
+   (UNSPEC_COND_FMIN "aarch64_sve_float_maxmin_immediate")
    (UNSPEC_COND_FMINNM "aarch64_sve_float_maxmin_immediate")
    (UNSPEC_COND_FMUL "aarch64_sve_float_mul_immediate")])
 
+;; The maximum number of element bits that an instruction can handle.
+(define_int_attr max_elem_bits [(UNSPEC_UADDV "64") (UNSPEC_SADDV "32")
+                               (UNSPEC_PFIRST "8") (UNSPEC_PNEXT "64")])
+
 ;; The minimum number of element bits that an instruction can handle.
-(define_int_attr min_elem_bits [(UNSPEC_REVB "16")
+(define_int_attr min_elem_bits [(UNSPEC_RBIT "8")
+                               (UNSPEC_REVB "16")
                                (UNSPEC_REVH "32")
                                (UNSPEC_REVW "64")])
index 2b9aa4a2959743bd3cca70924991b0ef4f3eb0bb..2c5c53c716d98036192b9d97f0a4cf99a7c885f0 100644 (file)
   return CONST_INT_P (op) && IN_RANGE (INTVAL (op), 1, 3);
 })
 
-(define_special_predicate "subreg_lowpart_operator"
-  (and (match_code "subreg")
-       (match_test "subreg_lowpart_p (op)")))
+(define_predicate "subreg_lowpart_operator"
+  (ior (match_code "truncate")
+       (and (match_code "subreg")
+           (match_test "subreg_lowpart_p (op)"))))
 
 (define_predicate "aarch64_ccmp_immediate"
   (and (match_code "const_int")
   return aarch64_stepped_int_parallel_p (op, -1);
 })
 
+(define_predicate "ascending_int_parallel"
+  (match_code "parallel")
+{
+  return aarch64_stepped_int_parallel_p (op, 1);
+})
+
 (define_special_predicate "aarch64_simd_lshift_imm"
   (match_code "const,const_vector")
 {
            (match_test "op == const0_rtx")
            (match_operand 0 "aarch64_simd_or_scalar_imm_zero"))))
 
+(define_predicate "aarch64_simd_reg_or_minus_one"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "aarch64_simd_imm_minus_one")))
+
 (define_predicate "aarch64_simd_struct_operand"
   (and (match_code "mem")
        (match_test "TARGET_SIMD && aarch64_simd_mem_operand_p (op)")))
   (and (match_code "mem")
        (match_test "aarch64_sve_ld1rq_operand_p (op)")))
 
+(define_predicate "aarch64_sve_ldff1_operand"
+  (and (match_code "mem")
+       (match_test "aarch64_sve_ldff1_operand_p (op)")))
+
+(define_predicate "aarch64_sve_ldnf1_operand"
+  (and (match_code "mem")
+       (match_test "aarch64_sve_ldnf1_operand_p (op)")))
+
 ;; Like memory_operand, but restricted to addresses that are valid for
 ;; SVE LDR and STR instructions.
 (define_predicate "aarch64_sve_ldr_operand"
   (and (match_code "mem")
        (match_test "aarch64_sve_ldr_operand_p (op)")))
 
+(define_special_predicate "aarch64_sve_prefetch_operand"
+  (and (match_code "reg, plus")
+       (match_test "aarch64_sve_prefetch_operand_p (op, mode)")))
+
 (define_predicate "aarch64_sve_nonimmediate_operand"
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "aarch64_sve_ldr_operand")))
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "aarch64_sve_ld1r_operand")))
 
+(define_predicate "aarch64_sve_ptrue_svpattern_immediate"
+  (and (match_code "const")
+       (match_test "aarch64_sve_ptrue_svpattern_p (op, NULL)")))
+
 (define_predicate "aarch64_sve_arith_immediate"
   (and (match_code "const,const_vector")
        (match_test "aarch64_sve_arith_immediate_p (op, false)")))
   (and (match_code "const,const_vector")
        (match_test "aarch64_sve_arith_immediate_p (op, true)")))
 
+(define_predicate "aarch64_sve_qadd_immediate"
+  (and (match_code "const,const_vector")
+       (match_test "aarch64_sve_sqadd_sqsub_immediate_p (op, false)")))
+
+(define_predicate "aarch64_sve_qsub_immediate"
+  (and (match_code "const,const_vector")
+       (match_test "aarch64_sve_sqadd_sqsub_immediate_p (op, true)")))
+
 (define_predicate "aarch64_sve_vector_inc_dec_immediate"
   (and (match_code "const,const_vector")
        (match_test "aarch64_sve_vector_inc_dec_immediate_p (op)")))
 
+(define_predicate "aarch64_sve_gather_immediate_b"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 0, 31)")))
+
+(define_predicate "aarch64_sve_gather_immediate_h"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 0, 62)")
+       (match_test "(INTVAL (op) & 1) == 0")))
+
+(define_predicate "aarch64_sve_gather_immediate_w"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 0, 124)")
+       (match_test "(INTVAL (op) & 3) == 0")))
+
+(define_predicate "aarch64_sve_gather_immediate_d"
+  (and (match_code "const_int")
+       (match_test "IN_RANGE (INTVAL (op), 0, 248)")
+       (match_test "(INTVAL (op) & 7) == 0")))
+
 (define_predicate "aarch64_sve_uxtb_immediate"
   (and (match_code "const_vector")
        (match_test "GET_MODE_UNIT_BITSIZE (GET_MODE (op)) > 8")
        (match_operand 0 "aarch64_sve_sub_arith_immediate")
        (match_operand 0 "aarch64_sve_vector_inc_dec_immediate")))
 
+(define_predicate "aarch64_sve_sqadd_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "aarch64_sve_qadd_immediate")
+       (match_operand 0 "aarch64_sve_qsub_immediate")))
+
 (define_predicate "aarch64_sve_pred_and_operand"
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "aarch64_sve_uxt_immediate")))
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "aarch64_sve_logical_immediate")))
 
+(define_predicate "aarch64_sve_gather_offset_b"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "aarch64_sve_gather_immediate_b")))
+
+(define_predicate "aarch64_sve_gather_offset_h"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "aarch64_sve_gather_immediate_h")))
+
+(define_predicate "aarch64_sve_gather_offset_w"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "aarch64_sve_gather_immediate_w")))
+
+(define_predicate "aarch64_sve_gather_offset_d"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "aarch64_sve_gather_immediate_d")))
+
 (define_predicate "aarch64_sve_lshift_operand"
   (ior (match_operand 0 "register_operand")
        (match_operand 0 "aarch64_simd_lshift_imm")))
        (ior (match_test "INTVAL (op) == SVE_RELAXED_GP")
            (match_test "INTVAL (op) == SVE_STRICT_GP"))))
 
+(define_predicate "aarch64_gather_scale_operand_b"
+  (and (match_code "const_int")
+       (match_test "INTVAL (op) == 1")))
+
+(define_predicate "aarch64_gather_scale_operand_h"
+  (and (match_code "const_int")
+       (match_test "INTVAL (op) == 1 || INTVAL (op) == 2")))
+
 (define_predicate "aarch64_gather_scale_operand_w"
   (and (match_code "const_int")
        (match_test "INTVAL (op) == 1 || INTVAL (op) == 4")))
index 391b4a2f7fced9c9b19a8377cd050bee91e452a3..28e1c7aecdd68bbac2ce3a875c3df416650aa8e1 100644 (file)
@@ -40,6 +40,43 @@ aarch64-builtins.o: $(srcdir)/config/aarch64/aarch64-builtins.c $(CONFIG_H) \
        $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
                $(srcdir)/config/aarch64/aarch64-builtins.c
 
+aarch64-sve-builtins.o: $(srcdir)/config/aarch64/aarch64-sve-builtins.cc \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins.def \
+  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+  $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) $(DIAGNOSTIC_H) \
+  $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \
+  gimple-iterator.h gimplify.h explow.h $(EMIT_RTL_H) tree-vector-builder.h \
+  stor-layout.h $(REG_H) alias.h gimple-fold.h langhooks.h \
+  stringpool.h \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins.h \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.h \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins-base.h
+       $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+               $(srcdir)/config/aarch64/aarch64-sve-builtins.cc
+
+aarch64-sve-builtins-shapes.o: \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.cc \
+  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+  $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins.h \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.h
+       $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+               $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.cc
+
+aarch64-sve-builtins-base.o: \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins-base.cc \
+  $(CONFIG_H) $(SYSTEM_H) coretypes.h $(TM_H) $(TREE_H) $(RTL_H) \
+  $(TM_P_H) memmodel.h insn-codes.h $(OPTABS_H) $(RECOG_H) \
+  $(EXPR_H) $(BASIC_BLOCK_H) $(FUNCTION_H) fold-const.h $(GIMPLE_H) \
+  gimple-iterator.h gimplify.h explow.h $(EMIT_RTL_H) tree-vector-builder.h \
+  rtx-vector-builder.h vec-perm-indices.h \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins.h \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins-shapes.h \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins-base.h \
+  $(srcdir)/config/aarch64/aarch64-sve-builtins-functions.h
+       $(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
+               $(srcdir)/config/aarch64/aarch64-sve-builtins-base.cc
+
 aarch64-builtin-iterators.h: $(srcdir)/config/aarch64/geniterators.sh \
        $(srcdir)/config/aarch64/iterators.md
        $(SHELL) $(srcdir)/config/aarch64/geniterators.sh \
index bbb5f1b19550833bebe5d83b5d0f2f1b5f3c3035..0507477512ec25baa6117bf010aba0154a229318 100644 (file)
@@ -1,3 +1,13 @@
+2019-10-29  Richard Sandiford  <richard.sandiford@arm.com>
+           Kugan Vivekanandarajah  <kugan.vivekanandarajah@linaro.org>
+           Prathamesh Kulkarni  <prathamesh.kulkarni@linaro.org>
+
+       * g++.target/aarch64/sve/acle/aarch64-sve-acle.exp: New file.
+       * g++.target/aarch64/sve/acle/general-c++: New test directory.
+       * gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp: New file.
+       * gcc.target/aarch64/sve/acle/general: New test directory.
+       * gcc.target/aarch64/sve/acle/general-c: Likewise.
+
 2019-10-29  Richard Biener  <rguenther@suse.de>
 
        PR tree-optimization/92241
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle.exp b/gcc/testsuite/g++.target/aarch64/sve/acle/aarch64-sve-acle.exp
new file mode 100644 (file)
index 0000000..54c43a3
--- /dev/null
@@ -0,0 +1,55 @@
+#  Specific regression driver for AArch64 SVE.
+#  Copyright (C) 2009-2019 Free Software Foundation, Inc.
+#  Contributed by ARM Ltd.
+#
+#  This file is part of GCC.
+#
+#  GCC is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3, or (at your option)
+#  any later version.
+#
+#  GCC is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with GCC; see the file COPYING3.  If not see
+#  <http://www.gnu.org/licenses/>.  */
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an AArch64 target.
+if {![istarget aarch64*-*-*] } {
+    return
+}
+
+# Load support procs.
+load_lib g++-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CXXFLAGS
+if ![info exists DEFAULT_CXXFLAGS] then {
+    set DEFAULT_CXXFLAGS " -pedantic-errors -Wno-long-long"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Force SVE if we're not testing it already.
+if { [check_effective_target_aarch64_sve] } {
+    set sve_flags ""
+} else {
+    set sve_flags "-march=armv8.2-a+sve"
+}
+
+# Main loop.
+set gcc_subdir [string replace $subdir 0 2 gcc]
+set files [glob -nocomplain \
+              "$srcdir/$gcc_subdir/general/*.c" \
+              "$srcdir/$subdir/general-c++/*.\[cC\]"]
+dg-runtest [lsort $files] "$sve_flags" $DEFAULT_CXXFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_1.C
new file mode 100644 (file)
index 0000000..44aa10e
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+#include "add_1.h"
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t x, svint8_t y)
+{
+  return svadd_u8_x (pg, x, y); /* { dg-error "cannot convert 'svint8_t' to 'svuint8_t'" } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_1.h b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_1.h
new file mode 100644 (file)
index 0000000..d441328
--- /dev/null
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma GCC aarch64 "arm_sve.h" /* { dg-message "initializing argument 3" } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_2.C
new file mode 100644 (file)
index 0000000..fcfb0f4
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+#include "add_2.h"
+
+void
+f1 (svbool_t pg, svuint8_t x, svint8_t y)
+{
+  svadd_x (pg, x); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, svuint8_t&\)'} } */
+  svadd_x (pg, x, x, x); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, svuint8_t&, svuint8_t&, svuint8_t&\)'} } */
+  svadd_x (x, x, x); /* { dg-error {no matching function for call to 'svadd_x\(svuint8_t&, svuint8_t&, svuint8_t&\)'} } */
+  svadd_x (pg, pg, pg); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, svbool_t&, svbool_t&\)'} } */
+  svadd_x (pg, 1, x); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, int, svuint8_t&\)'} } */
+  svadd_x (pg, x, y); /* { dg-error {no matching function for call to 'svadd_x\(svbool_t&, svuint8_t&, svint8_t&\)'} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_2.h b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_2.h
new file mode 100644 (file)
index 0000000..2b3a520
--- /dev/null
@@ -0,0 +1,9 @@
+#pragma GCC system_header
+#pragma GCC aarch64 "arm_sve.h"
+/* { dg-message {note: candidate: 'svfloat16_t svadd_x\(svbool_t, svfloat16_t, svfloat16_t\)'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *candidate expects 3 arguments, 2 provided} "" { target *-*-* } 3 } */
+/* { dg-message {note: *candidate expects 3 arguments, 4 provided} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 1 from 'svuint8_t' to 'svbool_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'svbool_t' to 'svfloat16_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'int' to 'svfloat16_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'svuint8_t' to 'svfloat16_t'} "" { target *-*-* } 3 } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_3.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/add_3.C
new file mode 100644 (file)
index 0000000..1d811fc
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized -fnon-call-exceptions" } */
+
+#include <arm_sve.h>
+
+svint8_t
+foo (svbool_t pg, svint8_t a, svint8_t b)
+{
+  try
+    {
+      a = svadd_m (pg, a, b);
+    }
+  catch (...)
+    {
+      a = b;
+    }
+  return a;
+}
+
+/* { dg-final { scan-tree-dump-not {__cxa_begin_catch} "optimized" } } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/asrd_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/asrd_1.C
new file mode 100644 (file)
index 0000000..a73934f
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_add (uint64_t a, uint64_t b) { return a + b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+void
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint16_t s16,
+    svint32_t s32, svint64_t s64, int x)
+{
+  const int one = 1;
+  u8 = svasrd_x (pg, u8, 1); /* { dg-error {no matching function for call to 'svasrd_x\(svbool_t&, svuint8_t&, [^)]*\)'} } */
+  s8 = svasrd_x (pg, s8, x); /* { dg-error "argument 3 of 'svasrd_x' must be an integer constant expression" } */
+  s8 = svasrd_x (pg, s8, one);
+  s8 = svasrd_x (pg, s8, 0.4); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_x (pg, s8, 1.0);
+  s8 = svasrd_x (pg, s8, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_x (pg, s8, 1);
+  s8 = svasrd_x (pg, s8, 1 + 1);
+  s8 = svasrd_x (pg, s8, const_add (1, 1));
+  s8 = svasrd_x (pg, s8, add (1, 1)); /* { dg-error "argument 3 of 'svasrd_x' must be an integer constant expression" } */
+  s8 = svasrd_x (pg, s8, 8);
+  s8 = svasrd_x (pg, s8, 9); /* { dg-error {passing 9 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_x (pg, s8, (uint64_t (1) << 62) + 1); /* { dg-error {passing [^ ]* to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+  s16 = svasrd_x (pg, s16, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} } */
+  s16 = svasrd_x (pg, s16, 1);
+  s16 = svasrd_x (pg, s16, 16);
+  s16 = svasrd_x (pg, s16, 17); /* { dg-error {passing 17 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} } */
+  s32 = svasrd_x (pg, s32, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} } */
+  s32 = svasrd_x (pg, s32, 1);
+  s32 = svasrd_x (pg, s32, 32);
+  s32 = svasrd_x (pg, s32, 33); /* { dg-error {passing 33 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} } */
+  s64 = svasrd_x (pg, s64, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} } */
+  s64 = svasrd_x (pg, s64, 1);
+  s64 = svasrd_x (pg, s64, 64);
+  s64 = svasrd_x (pg, s64, 65); /* { dg-error {passing 65 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/asrd_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/asrd_2.C
new file mode 100644 (file)
index 0000000..bbe7ba7
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_add (uint64_t a, uint64_t b) { return a + b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+void
+f1 (svbool_t pg, svint8_t s8, svint16_t s16, svint32_t s32, svint64_t s64,
+    int x)
+{
+  const int one = 1;
+  s8 = svasrd_n_s8_x (pg, s8, x); /* { dg-error "argument 3 of 'svasrd_n_s8_x' must be an integer constant expression" } */
+  s8 = svasrd_n_s8_x (pg, s8, one);
+  s8 = svasrd_n_s8_x (pg, s8, 0.4); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_n_s8_x (pg, s8, 1.0);
+  s8 = svasrd_n_s8_x (pg, s8, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_n_s8_x (pg, s8, 1);
+  s8 = svasrd_n_s8_x (pg, s8, 1 + 1);
+  s8 = svasrd_n_s8_x (pg, s8, const_add (1, 1));
+  s8 = svasrd_n_s8_x (pg, s8, add (1, 1)); /* { dg-error "argument 3 of 'svasrd_n_s8_x' must be an integer constant expression" } */
+  s8 = svasrd_n_s8_x (pg, s8, 8);
+  s8 = svasrd_n_s8_x (pg, s8, 9); /* { dg-error {passing 9 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_n_s8_x (pg, s8, (uint64_t (1) << 62) + 1); /* { dg-error {passing [^ ]* to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+  s16 = svasrd_n_s16_x (pg, s16, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s16_x', which expects a value in the range \[1, 16\]} } */
+  s16 = svasrd_n_s16_x (pg, s16, 1);
+  s16 = svasrd_n_s16_x (pg, s16, 16);
+  s16 = svasrd_n_s16_x (pg, s16, 17); /* { dg-error {passing 17 to argument 3 of 'svasrd_n_s16_x', which expects a value in the range \[1, 16\]} } */
+  s32 = svasrd_n_s32_x (pg, s32, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s32_x', which expects a value in the range \[1, 32\]} } */
+  s32 = svasrd_n_s32_x (pg, s32, 1);
+  s32 = svasrd_n_s32_x (pg, s32, 32);
+  s32 = svasrd_n_s32_x (pg, s32, 33); /* { dg-error {passing 33 to argument 3 of 'svasrd_n_s32_x', which expects a value in the range \[1, 32\]} } */
+  s64 = svasrd_n_s64_x (pg, s64, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s64_x', which expects a value in the range \[1, 64\]} } */
+  s64 = svasrd_n_s64_x (pg, s64, 1);
+  s64 = svasrd_n_s64_x (pg, s64, 64);
+  s64 = svasrd_n_s64_x (pg, s64, 65); /* { dg-error {passing 65 to argument 3 of 'svasrd_n_s64_x', which expects a value in the range \[1, 64\]} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/asrd_3.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/asrd_3.C
new file mode 100644 (file)
index 0000000..5ebd770
--- /dev/null
@@ -0,0 +1,51 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_add (uint64_t a, uint64_t b) { return a + b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+template<uint64_t N, typename T>
+T shift (svbool_t pg, T v) { return svasrd_x (pg, v, N); }
+/* { dg-error {no matching function for call to 'svasrd_x\(svbool_t&,} "" { target *-*-* } .-1 } */
+/* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} "" { target *-*-* } .-2 } */
+/* { dg-error {passing 9 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} "" { target *-*-* } .-3 } */
+/* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} "" { target *-*-* } .-4 } */
+/* { dg-error {passing 17 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} "" { target *-*-* } .-5 } */
+/* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} "" { target *-*-* } .-6 } */
+/* { dg-error {passing 33 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} "" { target *-*-* } .-7 } */
+/* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} "" { target *-*-* } .-8 } */
+/* { dg-error {passing 65 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} "" { target *-*-* } .-9 } */
+
+template<typename T>
+T shift1 (svbool_t pg, T v, uint64_t n) { return svasrd_x (pg, v, n); }
+
+template<typename T>
+T shift2 (svbool_t pg, T v, uint64_t n) { return svasrd_x (pg, v, n); }
+/* { dg-error {argument 3 of 'svasrd_x' must be an integer constant expression} "" { target *-*-* } .-1 } */
+
+void
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint16_t s16,
+    svint32_t s32, svint64_t s64)
+{
+  u8 = shift <1> (pg, u8);
+  s8 = shift <0> (pg, s8);
+  s8 = shift <1> (pg, s8);
+  s8 = shift <8> (pg, s8);
+  s8 = shift <9> (pg, s8);
+  s16 = shift <0> (pg, s16);
+  s16 = shift <1> (pg, s16);
+  s16 = shift <16> (pg, s16);
+  s16 = shift <17> (pg, s16);
+  s32 = shift <0> (pg, s32);
+  s32 = shift <1> (pg, s32);
+  s32 = shift <32> (pg, s32);
+  s32 = shift <33> (pg, s32);
+  s64 = shift <0> (pg, s64);
+  s64 = shift <1> (pg, s64);
+  s64 = shift <64> (pg, s64);
+  s64 = shift <65> (pg, s64);
+
+  s8 = shift2 (pg, s8, 1);
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/cntb_pat.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/cntb_pat.c
new file mode 100644 (file)
index 0000000..bbc9f90
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+test (svpattern pat, int i)
+{
+  svcntb_pat (pat); /* { dg-error "argument 1 of 'svcntb_pat' must be an integer constant expression" } */
+  svcntb_pat (i); /* { dg-error "invalid conversion from 'int' to 'svpattern'" } */
+   /* { dg-error "argument 1 of 'svcntb_pat' must be an integer constant expression" "" { target *-*-* } .-1 } */
+  svcntb_pat ((svpattern) -1); /* { dg-error "passing 4294967295 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 0);
+  svcntb_pat ((svpattern) 1);
+  svcntb_pat ((svpattern) 2);
+  svcntb_pat ((svpattern) 3);
+  svcntb_pat ((svpattern) 4);
+  svcntb_pat ((svpattern) 5);
+  svcntb_pat ((svpattern) 6);
+  svcntb_pat ((svpattern) 7);
+  svcntb_pat ((svpattern) 8);
+  svcntb_pat ((svpattern) 9);
+  svcntb_pat ((svpattern) 10);
+  svcntb_pat ((svpattern) 11);
+  svcntb_pat ((svpattern) 12);
+  svcntb_pat ((svpattern) 13);
+  svcntb_pat ((svpattern) 14); /* { dg-error "passing 14 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 15); /* { dg-error "passing 15 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 16); /* { dg-error "passing 16 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 17); /* { dg-error "passing 17 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 18); /* { dg-error "passing 18 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 19); /* { dg-error "passing 19 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 20); /* { dg-error "passing 20 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 21); /* { dg-error "passing 21 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 22); /* { dg-error "passing 22 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 23); /* { dg-error "passing 23 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 24); /* { dg-error "passing 24 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 25); /* { dg-error "passing 25 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 26); /* { dg-error "passing 26 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 27); /* { dg-error "passing 27 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 28); /* { dg-error "passing 28 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+  svcntb_pat ((svpattern) 29);
+  svcntb_pat ((svpattern) 30);
+  svcntb_pat ((svpattern) 31);
+  svcntb_pat ((svpattern) 32); /* { dg-error "passing 32 to argument 1 of 'svcntb_pat', which expects a valid 'svpattern' value" } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/conversion_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/conversion_1.C
new file mode 100644 (file)
index 0000000..1b939cd
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+template<typename T>
+struct S
+{
+  S(T);
+  operator T() const;
+  void *base;
+};
+
+void f(svbool_t pg, const S<svuint8_t> &u8a, const S<svuint8_t> &u8b,
+       const S<svint8_t> &s8a)
+{
+  svadd_x(pg, u8a, u8b);
+  svadd_x(pg, u8a, 1);
+  svadd_x(pg, s8a, u8b); // { dg-error "no matching function for call" }
+  svadd_x(pg, s8a, 1);
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create2_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create2_1.C
new file mode 100644 (file)
index 0000000..247fd85
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+    svuint8x2_t u8x2)
+{
+  *ptr = svcreate2 (u8); /* { dg-error {no matching function for call to 'svcreate2\(svuint8_t\&\)'} } */
+  *ptr = svcreate2 (u8, u8, u8); /* { dg-error {no matching function for call to 'svcreate2\(svuint8_t\&, svuint8_t\&, svuint8_t\&\)'} } */
+  *ptr = svcreate2 (u8x2, u8x2); /* { dg-error {no matching function for call to 'svcreate2\(svuint8x2_t\&, svuint8x2_t\&\)'} } */
+  *ptr = svcreate2 (u8, f64); /* { dg-error {no matching function for call to 'svcreate2\(svuint8_t\&, svfloat64_t\&\)'} } */
+  *ptr = svcreate2 (u8, pg); /* { dg-error {no matching function for call to 'svcreate2\(svuint8_t\&, svbool_t\&\)'} } */
+  *ptr = svcreate2 (u8, u8);
+  *ptr = svcreate2 (f64, f64); /* { dg-error {cannot convert 'svfloat64x2_t' to 'svuint8x2_t' in assignment} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create2_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create2_2.C
new file mode 100644 (file)
index 0000000..10f3231
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+    svuint8x2_t u8x2)
+{
+  *ptr = svcreate2_u8 (u8); /* { dg-error {too few arguments to function '[^']*'} } */
+  *ptr = svcreate2_u8 (u8, u8, u8); /* { dg-error {too many arguments to function '[^']*'} } */
+  *ptr = svcreate2_u8 (u8x2, u8x2); /* { dg-error {cannot convert 'svuint8x2_t' to 'svuint8_t'} } */
+  *ptr = svcreate2_u8 (u8, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svuint8_t'} } */
+  *ptr = svcreate2_u8 (pg, u8); /* { dg-error {cannot convert 'svbool_t' to 'svuint8_t'} } */
+  *ptr = svcreate2_u8 (u8, u8);
+  *ptr = svcreate2_f64 (f64, f64); /* { dg-error {cannot convert 'svfloat64x2_t' to 'svuint8x2_t' in assignment} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create3_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create3_1.C
new file mode 100644 (file)
index 0000000..ff01363
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+    svfloat16x3_t f16x3)
+{
+  *ptr = svcreate3 (f16); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&\)'} } */
+  *ptr = svcreate3 (f16, f16); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&, svfloat16_t\&\)'} } */
+  *ptr = svcreate3 (f16, f16, f16, f16); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&, svfloat16_t\&, svfloat16_t\&, svfloat16_t\&\)'} } */
+  *ptr = svcreate3 (f16x3, f16x3, f16x3); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16x3_t\&, svfloat16x3_t\&, svfloat16x3_t\&\)'} } */
+  *ptr = svcreate3 (f16, f16, f64); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&, svfloat16_t\&, svfloat64_t\&\)'} } */
+  *ptr = svcreate3 (f16, pg, f16); /* { dg-error {no matching function for call to 'svcreate3\(svfloat16_t\&, svbool_t\&, svfloat16_t\&\)'} } */
+  *ptr = svcreate3 (f16, f16, f16);
+  *ptr = svcreate3 (f64, f64, f64); /* { dg-error {cannot convert 'svfloat64x3_t' to 'svfloat16x3_t' in assignment} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create3_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create3_2.C
new file mode 100644 (file)
index 0000000..07a72b1
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+    svfloat16x3_t f16x3)
+{
+  *ptr = svcreate3_f16 (f16); /* { dg-error {too few arguments to function '[^']*'} } */
+  *ptr = svcreate3_f16 (f16, f16); /* { dg-error {too few arguments to function '[^']*'} } */
+  *ptr = svcreate3_f16 (f16, f16, f16, f16); /* { dg-error {too many arguments to function '[^']*'} } */
+  *ptr = svcreate3_f16 (f16x3, f16x3, f16x3); /* { dg-error {cannot convert 'svfloat16x3_t' to 'svfloat16_t'} } */
+  *ptr = svcreate3_f16 (f16, f16, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svfloat16_t'} } */
+  *ptr = svcreate3_f16 (f16, pg, f16); /* { dg-error {cannot convert 'svbool_t' to 'svfloat16_t'} } */
+  *ptr = svcreate3_f16 (f16, f16, f16);
+  *ptr = svcreate3_f64 (f64, f64, f64); /* { dg-error {cannot convert 'svfloat64x3_t' to 'svfloat16x3_t' in assignment} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create4_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create4_1.C
new file mode 100644 (file)
index 0000000..2785d90
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+    svint32x4_t s32x4)
+{
+  *ptr = svcreate4 (s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&\)'} } */
+  *ptr = svcreate4 (s32, s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svint32_t\&\)'} } */
+  *ptr = svcreate4 (s32, s32, s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svint32_t\&, svint32_t\&\)'} } */
+  *ptr = svcreate4 (s32, s32, s32, s32, s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svint32_t\&, svint32_t\&, svint32_t\&, svint32_t\&\)'} } */
+  *ptr = svcreate4 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {no matching function for call to 'svcreate4\(svint32x4_t\&, svint32x4_t\&, svint32x4_t\&, svint32x4_t\&\)'} } */
+  *ptr = svcreate4 (s32, s32, s32, f64); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svint32_t\&, svint32_t\&, svfloat64_t\&\)'} } */
+  *ptr = svcreate4 (s32, pg, s32, s32); /* { dg-error {no matching function for call to 'svcreate4\(svint32_t\&, svbool_t\&, svint32_t\&, svint32_t\&\)'} } */
+  *ptr = svcreate4 (s32, s32, s32, s32);
+  *ptr = svcreate4 (f64, f64, f64, f64); /* { dg-error {cannot convert 'svfloat64x4_t' to 'svint32x4_t' in assignment} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create4_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/create4_2.C
new file mode 100644 (file)
index 0000000..68f21a1
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+    svint32x4_t s32x4)
+{
+  *ptr = svcreate4_s32 (s32); /* { dg-error {too few arguments to function '[^']*'} } */
+  *ptr = svcreate4_s32 (s32, s32); /* { dg-error {too few arguments to function '[^']*'} } */
+  *ptr = svcreate4_s32 (s32, s32, s32); /* { dg-error {too few arguments to function '[^']*'} } */
+  *ptr = svcreate4_s32 (s32, s32, s32, s32, s32); /* { dg-error {too many arguments to function '[^']*'} } */
+  *ptr = svcreate4_s32 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {cannot convert 'svint32x4_t' to 'svint32_t'} } */
+  *ptr = svcreate4_s32 (s32, s32, s32, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svint32_t'} } */
+  *ptr = svcreate4_s32 (s32, pg, s32, s32); /* { dg-error {cannot convert 'svbool_t' to 'svint32_t'} } */
+  *ptr = svcreate4_s32 (s32, s32, s32, s32);
+  *ptr = svcreate4_f64 (f64, f64, f64, f64); /* { dg-error {cannot convert 'svfloat64x4_t' to 'svint32x4_t' in assignment} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_1.C
new file mode 100644 (file)
index 0000000..93397c8
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+#include "dot_1.h"
+
+svuint32_t
+f1 (svuint32_t x, svint8_t y, svuint8_t z)
+{
+  return svdot_u32 (x, y, z); /* { dg-error "cannot convert 'svint8_t' to 'svuint8_t'" } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_1.h b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_1.h
new file mode 100644 (file)
index 0000000..aef02f2
--- /dev/null
@@ -0,0 +1,2 @@
+#pragma GCC system_header
+#pragma GCC aarch64 "arm_sve.h" /* { dg-message "initializing argument 2" } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_2.C
new file mode 100644 (file)
index 0000000..2084ed8
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+#include "dot_2.h"
+
+void
+f1 (svuint32_t x, svint8_t y, svuint8_t z)
+{
+  svdot (x, y); /* { dg-error {no matching function for call to 'svdot\(svuint32_t&, svint8_t&\)'} } */
+  svdot (x, x, x); /* { dg-error {no matching function for call to 'svdot\(svuint32_t&, svuint32_t&, svuint32_t&\)'} } */
+  svdot (1, z, z); /* { dg-error {no matching function for call to 'svdot\(int, svuint8_t&, svuint8_t&\)'} } */
+  svdot (x, y, z); /* { dg-error {no matching function for call to 'svdot\(svuint32_t&, svint8_t&, svuint8_t&\)'} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_2.h b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/dot_2.h
new file mode 100644 (file)
index 0000000..3e4a9c7
--- /dev/null
@@ -0,0 +1,7 @@
+#pragma GCC system_header
+#pragma GCC aarch64 "arm_sve.h"
+/* { dg-message {note: candidate: 'svuint32_t svdot\(svuint32_t, svuint8_t, svuint8_t\)'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *candidate expects 3 arguments, 2 provided} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'svuint32_t' to 'svuint8_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 1 from 'int' to 'svuint32_t'} "" { target *-*-* } 3 } */
+/* { dg-message {note: *no known conversion for argument 2 from 'svint8_t' to 'svuint8_t'} "" { target *-*-* } 3 } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_1.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_1.c
new file mode 100644 (file)
index 0000000..8f18810
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svadd_n_u8_x; /* { dg-message "note: previous declaration 'int svadd_n_u8_x'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svuint8_t svadd_n_u8_x\(svbool_t, svuint8_t, [^)\n]*\)' redeclared as different kind of entity} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_2.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_2.c
new file mode 100644 (file)
index 0000000..a67f9f7
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svadd_n_u8_x = 1; /* { dg-message "note: previous declaration 'int svadd_n_u8_x'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svuint8_t svadd_n_u8_x\(svbool_t, svuint8_t, [^)\n]*\)' redeclared as different kind of entity} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_3.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_3.c
new file mode 100644 (file)
index 0000000..74b820f
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+
+/* Although not supported, there's nothing to stop the user overloading
+   the sv* functions.  */
+extern __SVInt8_t svadd_u8_x (__SVBool_t, __SVInt8_t, __SVInt8_t);
+
+#pragma GCC aarch64 "arm_sve.h"
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_4.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_4.c
new file mode 100644 (file)
index 0000000..9591e3d
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+/* Although somewhat suspect, this isn't actively wrong, and doesn't need
+   to be diagnosed.  Any attempt to call the function before including
+   arm_sve.h will lead to a link failure.  (Same for taking its address,
+   etc.)  */
+extern __SVUint8_t svadd_u8_x (__SVBool_t, __SVUint8_t, __SVUint8_t);
+
+#pragma GCC aarch64 "arm_sve.h"
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_5.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_5.c
new file mode 100644 (file)
index 0000000..f872019
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+__SVUint8_t
+svadd_u8_x (__SVBool_t pg, __SVUint8_t x, __SVUint8_t y)
+{
+  return x;
+}
+
+#pragma GCC aarch64 "arm_sve.h"
+
+svuint8_t
+f (svbool_t pg, svuint8_t x, svuint8_t y)
+{
+  return svadd_u8_x (pg, x, y);
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_6.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_6.c
new file mode 100644 (file)
index 0000000..a65e0d6
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+typedef int svadd_u8_x; /* { dg-message "note: previous declaration 'typedef int svadd_u8_x'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svuint8_t svadd_u8_x\(svbool_t, svuint8_t, svuint8_t\)' redeclared as different kind of entity} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_7.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/func_redef_7.c
new file mode 100644 (file)
index 0000000..1f2e4bf
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+__SVUint8_t
+svadd_x (__SVBool_t pg, __SVUint8_t x, __SVUint8_t y)
+{
+  return x;
+}
+
+#pragma GCC aarch64 "arm_sve.h"
+
+svuint8_t
+f (svbool_t pg, svuint8_t x, svuint8_t y)
+{
+  return svadd_x (pg, x, y);
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get2_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get2_1.C
new file mode 100644 (file)
index 0000000..8d6bb23
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svuint8x3_t u8x3, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  u8 = svget2 (u8x2); /* { dg-error {no matching function for call to 'svget2\(svuint8x2_t\&\)'} } */
+  u8 = svget2 (u8x2, 1, 2); /* { dg-error {no matching function for call to 'svget2\(svuint8x2_t\&, int, int\)'} } */
+  u8 = svget2 (u8, 0); /* { dg-error {no matching function for call to 'svget2\(svuint8_t\&, int\)'} } */
+  u8 = svget2 (u8x3, 0); /* { dg-error {no matching function for call to 'svget2\(svuint8x3_t\&, int\)'} } */
+  u8 = svget2 (pg, 0); /* { dg-error {no matching function for call to 'svget2\(svbool_t\&, int\)'} } */
+  u8 = svget2 (u8x2, x); /* { dg-error "argument 2 of 'svget2' must be an integer constant expression" } */
+  u8 = svget2 (u8x2, 0);
+  f64 = svget2 (u8x2, 0); /* { dg-error "cannot convert 'svuint8_t' to 'svfloat64_t' in assignment" } */
+  u8 = svget2 (u8x2, 1);
+  u8 = svget2 (u8x2, 2); /* { dg-error {passing 2 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, 3); /* { dg-error {passing 3 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, 4); /* { dg-error {passing 4 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, 5); /* { dg-error {passing 5 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, one);
+  u8 = svget2 (u8x2, 3 - 2);
+  u8 = svget2 (u8x2, 1.0);
+  u8 = svget2 (u8x2, const_sub (5, 4));
+  u8 = svget2 (u8x2, const_sub (6, 4)); /* { dg-error {passing 2 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, const_sub (7, 4)); /* { dg-error {passing 3 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, add (0, 0)); /* { dg-error "argument 2 of 'svget2' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get2_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get2_2.C
new file mode 100644 (file)
index 0000000..9c7674b
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svuint8x3_t u8x3, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  u8 = svget2_u8 (u8x2); /* { dg-error {too few arguments to function '[^']*'} } */
+  u8 = svget2_u8 (u8x2, 1, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+  u8 = svget2_u8 (u8, 0); /* { dg-error {cannot convert 'svuint8_t' to 'svuint8x2_t'} } */
+  u8 = svget2_u8 (u8x3, 0); /* { dg-error {cannot convert 'svuint8x3_t' to 'svuint8x2_t'} } */
+  u8 = svget2_u8 (pg, 0); /* { dg-error {cannot convert 'svbool_t' to 'svuint8x2_t'} } */
+  u8 = svget2_u8 (u8x2, x); /* { dg-error "argument 2 of 'svget2_u8' must be an integer constant expression" } */
+  u8 = svget2_u8 (u8x2, 0);
+  f64 = svget2_u8 (u8x2, 0); /* { dg-error "cannot convert 'svuint8_t' to 'svfloat64_t' in assignment" } */
+  u8 = svget2_u8 (u8x2, 1);
+  u8 = svget2_u8 (u8x2, 2); /* { dg-error {passing 2 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, 3); /* { dg-error {passing 3 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, 4); /* { dg-error {passing 4 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, 5); /* { dg-error {passing 5 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, one);
+  u8 = svget2_u8 (u8x2, 3 - 2);
+  u8 = svget2_u8 (u8x2, 1.0);
+  u8 = svget2_u8 (u8x2, const_sub (5, 4));
+  u8 = svget2_u8 (u8x2, const_sub (6, 4)); /* { dg-error {passing 2 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, const_sub (7, 4)); /* { dg-error {passing 3 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, add (0, 0)); /* { dg-error "argument 2 of 'svget2_u8' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get3_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get3_1.C
new file mode 100644 (file)
index 0000000..bd8808a
--- /dev/null
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat16x4_t f16x4,
+    int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  f16 = svget3 (f16x3); /* { dg-error {no matching function for call to 'svget3\(svfloat16x3_t\&\)'} } */
+  f16 = svget3 (f16x3, 1, 2); /* { dg-error {no matching function for call to 'svget3\(svfloat16x3_t\&, int, int\)'} } */
+  f16 = svget3 (f16, 0); /* { dg-error {no matching function for call to 'svget3\(svfloat16_t\&, int\)'} } */
+  f16 = svget3 (f16x4, 0); /* { dg-error {no matching function for call to 'svget3\(svfloat16x4_t\&, int\)'} } */
+  f16 = svget3 (pg, 0); /* { dg-error {no matching function for call to 'svget3\(svbool_t\&, int\)'} } */
+  f16 = svget3 (f16x3, x); /* { dg-error "argument 2 of 'svget3' must be an integer constant expression" } */
+  f16 = svget3 (f16x3, 0);
+  f64 = svget3 (f16x3, 0); /* { dg-error "cannot convert 'svfloat16_t' to 'svfloat64_t' in assignment" } */
+  f16 = svget3 (f16x3, 1);
+  f16 = svget3 (f16x3, 2);
+  f16 = svget3 (f16x3, 3); /* { dg-error {passing 3 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, 4); /* { dg-error {passing 4 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, 5); /* { dg-error {passing 5 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, one);
+  f16 = svget3 (f16x3, 3 - 2);
+  f16 = svget3 (f16x3, 1.0);
+  f16 = svget3 (f16x3, const_sub (5, 4));
+  f16 = svget3 (f16x3, const_sub (6, 4));
+  f16 = svget3 (f16x3, const_sub (7, 4)); /* { dg-error {passing 3 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, add (0, 0)); /* { dg-error "argument 2 of 'svget3' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get3_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get3_2.C
new file mode 100644 (file)
index 0000000..d526947
--- /dev/null
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat16x4_t f16x4,
+    int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  f16 = svget3_f16 (f16x3); /* { dg-error {too few arguments to function '[^']*'} } */
+  f16 = svget3_f16 (f16x3, 1, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+  f16 = svget3_f16 (f16, 0); /* { dg-error {cannot convert 'svfloat16_t' to 'svfloat16x3_t'} } */
+  f16 = svget3_f16 (f16x4, 0); /* { dg-error {cannot convert 'svfloat16x4_t' to 'svfloat16x3_t'} } */
+  f16 = svget3_f16 (pg, 0); /* { dg-error {cannot convert 'svbool_t' to 'svfloat16x3_t'} } */
+  f16 = svget3_f16 (f16x3, x); /* { dg-error "argument 2 of 'svget3_f16' must be an integer constant expression" } */
+  f16 = svget3_f16 (f16x3, 0);
+  f64 = svget3_f16 (f16x3, 0); /* { dg-error "cannot convert 'svfloat16_t' to 'svfloat64_t' in assignment" } */
+  f16 = svget3_f16 (f16x3, 1);
+  f16 = svget3_f16 (f16x3, 2);
+  f16 = svget3_f16 (f16x3, 3); /* { dg-error {passing 3 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, 4); /* { dg-error {passing 4 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, 5); /* { dg-error {passing 5 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, one);
+  f16 = svget3_f16 (f16x3, 3 - 2);
+  f16 = svget3_f16 (f16x3, 1.0);
+  f16 = svget3_f16 (f16x3, const_sub (5, 4));
+  f16 = svget3_f16 (f16x3, const_sub (6, 4));
+  f16 = svget3_f16 (f16x3, const_sub (7, 4)); /* { dg-error {passing 3 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, add (0, 0)); /* { dg-error "argument 2 of 'svget3_f16' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get4_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get4_1.C
new file mode 100644 (file)
index 0000000..19853de
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svint32x2_t s32x2, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  s32 = svget4 (s32x4); /* { dg-error {no matching function for call to 'svget4\(svint32x4_t\&\)'} } */
+  s32 = svget4 (s32x4, 1, 2); /* { dg-error {no matching function for call to 'svget4\(svint32x4_t\&, int, int\)'} } */
+  s32 = svget4 (s32, 0); /* { dg-error {no matching function for call to 'svget4\(svint32_t\&, int\)'} } */
+  s32 = svget4 (s32x2, 0); /* { dg-error {no matching function for call to 'svget4\(svint32x2_t\&, int\)'} } */
+  s32 = svget4 (pg, 0); /* { dg-error {no matching function for call to 'svget4\(svbool_t\&, int\)'} } */
+  s32 = svget4 (s32x4, x); /* { dg-error "argument 2 of 'svget4' must be an integer constant expression" } */
+  s32 = svget4 (s32x4, 0);
+  f64 = svget4 (s32x4, 0); /* { dg-error "cannot convert 'svint32_t' to 'svfloat64_t' in assignment" } */
+  s32 = svget4 (s32x4, 1);
+  s32 = svget4 (s32x4, 2);
+  s32 = svget4 (s32x4, 3);
+  s32 = svget4 (s32x4, 4); /* { dg-error {passing 4 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4 (s32x4, 5); /* { dg-error {passing 5 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4 (s32x4, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4 (s32x4, one);
+  s32 = svget4 (s32x4, 3 - 2);
+  s32 = svget4 (s32x4, 1.0);
+  s32 = svget4 (s32x4, const_sub (5, 4));
+  s32 = svget4 (s32x4, const_sub (6, 4));
+  s32 = svget4 (s32x4, const_sub (7, 4));
+  s32 = svget4 (s32x4, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4 (s32x4, add (0, 0)); /* { dg-error "argument 2 of 'svget4' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get4_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/get4_2.C
new file mode 100644 (file)
index 0000000..7a09792
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svint32x2_t s32x2, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  s32 = svget4_s32 (s32x4); /* { dg-error {too few arguments to function '[^']*'} } */
+  s32 = svget4_s32 (s32x4, 1, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+  s32 = svget4_s32 (s32, 0); /* { dg-error {cannot convert 'svint32_t' to 'svint32x4_t'} } */
+  s32 = svget4_s32 (s32x2, 0); /* { dg-error {cannot convert 'svint32x2_t' to 'svint32x4_t'} } */
+  s32 = svget4_s32 (pg, 0); /* { dg-error {cannot convert 'svbool_t' to 'svint32x4_t'} } */
+  s32 = svget4_s32 (s32x4, x); /* { dg-error "argument 2 of 'svget4_s32' must be an integer constant expression" } */
+  s32 = svget4_s32 (s32x4, 0);
+  f64 = svget4_s32 (s32x4, 0); /* { dg-error "cannot convert 'svint32_t' to 'svfloat64_t' in assignment" } */
+  s32 = svget4_s32 (s32x4, 1);
+  s32 = svget4_s32 (s32x4, 2);
+  s32 = svget4_s32 (s32x4, 3);
+  s32 = svget4_s32 (s32x4, 4); /* { dg-error {passing 4 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4_s32 (s32x4, 5); /* { dg-error {passing 5 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4_s32 (s32x4, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4_s32 (s32x4, one);
+  s32 = svget4_s32 (s32x4, 3 - 2);
+  s32 = svget4_s32 (s32x4, 1.0);
+  s32 = svget4_s32 (s32x4, const_sub (5, 4));
+  s32 = svget4_s32 (s32x4, const_sub (6, 4));
+  s32 = svget4_s32 (s32x4, const_sub (7, 4));
+  s32 = svget4_s32 (s32x4, const_sub (8, 4)); /* { dg-error {passing 4 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4_s32 (s32x4, add (0, 0)); /* { dg-error "argument 2 of 'svget4_s32' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/lsl_wide_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/lsl_wide_1.C
new file mode 100644 (file)
index 0000000..fb31e94
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t x, svint8_t w, svuint64_t y)
+{
+  svlsl_wide_u8_x (pg, x, x); /* { dg-error "cannot convert 'svuint8_t' to 'svuint64_t'" } */
+  svlsl_wide_u8_x (pg, x); /* { dg-error {too few arguments to function 'svuint8_t svlsl_wide_u8_x\(svbool_t, svuint8_t, svuint64_t\)'} } */
+  svlsl_wide_u8_x (pg, x, y, x); /* { dg-error {too many arguments to function 'svuint8_t svlsl_wide_u8_x\(svbool_t, svuint8_t, svuint64_t\)'} } */
+  return svlsl_wide_s8_x (pg, w, y); /* { dg-error {cannot convert 'svint8_t' to 'svuint8_t' in return} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/lsl_wide_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/lsl_wide_2.C
new file mode 100644 (file)
index 0000000..95d341d
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void
+f1 (svbool_t pg, svuint8_t x, svuint64_t y)
+{
+  svlsl_wide_x (pg, x); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, svuint8_t&\)'} } */
+  svlsl_wide_x (pg, x, x, x, x); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, svuint8_t&, svuint8_t&, svuint8_t&, svuint8_t&\)'} } */
+  svlsl_wide_x (x, x, y); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svuint8_t&, svuint8_t&, svuint64_t&\)'} } */
+  svlsl_wide_x (pg, 1, y); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, int, svuint64_t&\)'} } */
+  svlsl_wide_x (pg, x, x); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, svuint8_t&, svuint8_t&\)'} } */
+  svlsl_wide_x (pg, y, y); /* { dg-error {no matching function for call to 'svlsl_wide_x\(svbool_t&, svuint64_t&, svuint64_t&\)'} } */
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_1.C
new file mode 100644 (file)
index 0000000..1138f2e
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void f1(svbool_t) {}
+void f2(svint8_t) {}
+void f3(svint16_t) {}
+void f4(svint32_t) {}
+void f5(svint64_t) {}
+void f6(svuint8_t) {}
+void f7(svuint16_t) {}
+void f8(svuint32_t) {}
+void f9(svuint64_t) {}
+void f10(svfloat16_t) {}
+void f11(svfloat32_t) {}
+void f12(svfloat64_t) {}
+
+/* { dg-final { scan-assembler "_Z2f110__SVBool_t:" } } */
+/* { dg-final { scan-assembler "_Z2f210__SVInt8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f311__SVInt16_t:" } } */
+/* { dg-final { scan-assembler "_Z2f411__SVInt32_t:" } } */
+/* { dg-final { scan-assembler "_Z2f511__SVInt64_t:" } } */
+/* { dg-final { scan-assembler "_Z2f611__SVUint8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f712__SVUint16_t:" } } */
+/* { dg-final { scan-assembler "_Z2f812__SVUint32_t:" } } */
+/* { dg-final { scan-assembler "_Z2f912__SVUint64_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1013__SVFloat16_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1113__SVFloat32_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1213__SVFloat64_t:" } } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_2.C
new file mode 100644 (file)
index 0000000..575b262
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+
+void f1(__SVBool_t) {}
+void f2(__SVInt8_t) {}
+void f3(__SVInt16_t) {}
+void f4(__SVInt32_t) {}
+void f5(__SVInt64_t) {}
+void f6(__SVUint8_t) {}
+void f7(__SVUint16_t) {}
+void f8(__SVUint32_t) {}
+void f9(__SVUint64_t) {}
+void f10(__SVFloat16_t) {}
+void f11(__SVFloat32_t) {}
+void f12(__SVFloat64_t) {}
+
+/* { dg-final { scan-assembler "_Z2f110__SVBool_t:" } } */
+/* { dg-final { scan-assembler "_Z2f210__SVInt8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f311__SVInt16_t:" } } */
+/* { dg-final { scan-assembler "_Z2f411__SVInt32_t:" } } */
+/* { dg-final { scan-assembler "_Z2f511__SVInt64_t:" } } */
+/* { dg-final { scan-assembler "_Z2f611__SVUint8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f712__SVUint16_t:" } } */
+/* { dg-final { scan-assembler "_Z2f812__SVUint32_t:" } } */
+/* { dg-final { scan-assembler "_Z2f912__SVUint64_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1013__SVFloat16_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1113__SVFloat32_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1213__SVFloat64_t:" } } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_3.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_3.C
new file mode 100644 (file)
index 0000000..8f64f7c
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-msve-vector-bits=256" } */
+
+#include <arm_sve.h>
+
+typedef __SVInt8_t t1;
+typedef svint8_t t2;
+/* Distinct from svint8_t, but compatible with it.  */
+typedef int8_t t3 __attribute__((vector_size(32)));
+
+void f1(t1) {}
+void f2(t2) {}
+void f3(t3) {}
+void f4(t1 &a, t2 &b, t3 &c) { a = b = c; }
+
+/* { dg-final { scan-assembler "_Z2f110__SVInt8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f210__SVInt8_t:" } } */
+/* { dg-final { scan-assembler "_Z2f3Dv32_a:" } } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_4.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/mangle_4.C
new file mode 100644 (file)
index 0000000..7cdc6cb
--- /dev/null
@@ -0,0 +1,75 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void f1(svint8x2_t) {}
+void f2(svint16x2_t) {}
+void f3(svint32x2_t) {}
+void f4(svint64x2_t) {}
+void f5(svuint8x2_t) {}
+void f6(svuint16x2_t) {}
+void f7(svuint32x2_t) {}
+void f8(svuint64x2_t) {}
+void f9(svfloat16x2_t) {}
+void f10(svfloat32x2_t) {}
+void f11(svfloat64x2_t) {}
+
+void g1(svint8x3_t) {}
+void g2(svint16x3_t) {}
+void g3(svint32x3_t) {}
+void g4(svint64x3_t) {}
+void g5(svuint8x3_t) {}
+void g6(svuint16x3_t) {}
+void g7(svuint32x3_t) {}
+void g8(svuint64x3_t) {}
+void g9(svfloat16x3_t) {}
+void g10(svfloat32x3_t) {}
+void g11(svfloat64x3_t) {}
+
+void h1(svint8x4_t) {}
+void h2(svint16x4_t) {}
+void h3(svint32x4_t) {}
+void h4(svint64x4_t) {}
+void h5(svuint8x4_t) {}
+void h6(svuint16x4_t) {}
+void h7(svuint32x4_t) {}
+void h8(svuint64x4_t) {}
+void h9(svfloat16x4_t) {}
+void h10(svfloat32x4_t) {}
+void h11(svfloat64x4_t) {}
+
+/* { dg-final { scan-assembler "_Z2f110svint8x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f211svint16x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f311svint32x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f411svint64x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f511svuint8x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f612svuint16x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f712svuint32x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f812svuint64x2_t:" } } */
+/* { dg-final { scan-assembler "_Z2f913svfloat16x2_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1013svfloat32x2_t:" } } */
+/* { dg-final { scan-assembler "_Z3f1113svfloat64x2_t:" } } */
+
+/* { dg-final { scan-assembler "_Z2g110svint8x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g211svint16x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g311svint32x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g411svint64x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g511svuint8x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g612svuint16x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g712svuint32x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g812svuint64x3_t:" } } */
+/* { dg-final { scan-assembler "_Z2g913svfloat16x3_t:" } } */
+/* { dg-final { scan-assembler "_Z3g1013svfloat32x3_t:" } } */
+/* { dg-final { scan-assembler "_Z3g1113svfloat64x3_t:" } } */
+
+/* { dg-final { scan-assembler "_Z2h110svint8x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h211svint16x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h311svint32x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h411svint64x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h511svuint8x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h612svuint16x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h712svuint32x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h812svuint64x4_t:" } } */
+/* { dg-final { scan-assembler "_Z2h913svfloat16x4_t:" } } */
+/* { dg-final { scan-assembler "_Z3h1013svfloat32x4_t:" } } */
+/* { dg-final { scan-assembler "_Z3h1113svfloat64x4_t:" } } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set2_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set2_1.C
new file mode 100644 (file)
index 0000000..80c3ad7
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svint8x2_t s8x2,
+    svuint8x3_t u8x3, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  u8x2 = svset2 (u8x2); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&\)'} } */
+  u8x2 = svset2 (u8x2, 1); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int\)'} } */
+  u8x2 = svset2 (u8x2, 1, u8, 2); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int, svuint8_t\&, int\)'} } */
+  u8x2 = svset2 (u8, 0, u8); /* { dg-error {no matching function for call to 'svset2\(svuint8_t\&, int, svuint8_t\&\)'} } */
+  u8x2 = svset2 (s8x2, 0, u8); /* { dg-error {no matching function for call to 'svset2\(svint8x2_t\&, int, svuint8_t\&\)'} } */
+  u8x2 = svset2 (u8x3, 0, u8); /* { dg-error {no matching function for call to 'svset2\(svuint8x3_t\&, int, svuint8_t\&\)'} } */
+  u8x2 = svset2 (pg, 0, u8); /* { dg-error {no matching function for call to 'svset2\(svbool_t\&, int, svuint8_t\&\)'} } */
+  u8x2 = svset2 (u8x2, 0, f64); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int, svfloat64_t\&\)'} } */
+  u8x2 = svset2 (u8x2, 0, u8x2); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int, svuint8x2_t\&\)'} } */
+  u8x2 = svset2 (u8x2, 0, pg); /* { dg-error {no matching function for call to 'svset2\(svuint8x2_t\&, int, svbool_t\&\)'} } */
+  u8x2 = svset2 (u8x2, x, u8); /* { dg-error "argument 2 of 'svset2' must be an integer constant expression" } */
+  u8x2 = svset2 (u8x2, 0, u8);
+  s8x2 = svset2 (u8x2, 0, u8); /* { dg-error {cannot convert 'svuint8x2_t' to 'svint8x2_t' in assignment} } */
+  u8x2 = svset2 (u8x2, 1, u8);
+  u8x2 = svset2 (u8x2, 2, u8); /* { dg-error {passing 2 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, 3, u8); /* { dg-error {passing 3 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, 4, u8); /* { dg-error {passing 4 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, 5, u8); /* { dg-error {passing 5 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, ~0U, u8); /* { dg-error {passing [^ ]* to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, one, u8);
+  u8x2 = svset2 (u8x2, 3 - 2, u8);
+  u8x2 = svset2 (u8x2, 1.0, u8);
+  u8x2 = svset2 (u8x2, const_sub (5, 4), u8);
+  u8x2 = svset2 (u8x2, const_sub (6, 4), u8); /* { dg-error {passing 2 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, const_sub (7, 4), u8); /* { dg-error {passing 3 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, const_sub (8, 4), u8); /* { dg-error {passing 4 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, add (0, 0), u8); /* { dg-error "argument 2 of 'svset2' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set2_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set2_2.C
new file mode 100644 (file)
index 0000000..1433b78
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svint8x2_t s8x2,
+    svuint8x3_t u8x3, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  u8x2 = svset2_u8 (u8x2); /* { dg-error {too few arguments to function '[^']*'} } */
+  u8x2 = svset2_u8 (u8x2, 1); /* { dg-error {too few arguments to function '[^']*'} } */
+  u8x2 = svset2_u8 (u8x2, 1, u8, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+  u8x2 = svset2_u8 (u8, 0, u8); /* { dg-error {cannot convert 'svuint8_t' to 'svuint8x2_t'} } */
+  u8x2 = svset2_u8 (s8x2, 0, u8); /* { dg-error {cannot convert 'svint8x2_t' to 'svuint8x2_t'} } */
+  u8x2 = svset2_u8 (u8x3, 0, u8); /* { dg-error {cannot convert 'svuint8x3_t' to 'svuint8x2_t'} } */
+  u8x2 = svset2_u8 (pg, 0, u8); /* { dg-error {cannot convert 'svbool_t' to 'svuint8x2_t'} } */
+  u8x2 = svset2_u8 (u8x2, 0, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svuint8_t'} } */
+  u8x2 = svset2_u8 (u8x2, 0, u8x2); /* { dg-error {cannot convert 'svuint8x2_t' to 'svuint8_t'} } */
+  u8x2 = svset2_u8 (u8x2, 0, pg); /* { dg-error {cannot convert 'svbool_t' to 'svuint8_t'} } */
+  u8x2 = svset2_u8 (u8x2, x, u8); /* { dg-error "argument 2 of 'svset2_u8' must be an integer constant expression" } */
+  u8x2 = svset2_u8 (u8x2, 0, u8);
+  s8x2 = svset2_u8 (u8x2, 0, u8); /* { dg-error {cannot convert 'svuint8x2_t' to 'svint8x2_t' in assignment} } */
+  u8x2 = svset2_u8 (u8x2, 1, u8);
+  u8x2 = svset2_u8 (u8x2, 2, u8); /* { dg-error {passing 2 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, 3, u8); /* { dg-error {passing 3 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, 4, u8); /* { dg-error {passing 4 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, 5, u8); /* { dg-error {passing 5 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, ~0U, u8); /* { dg-error {passing [^ ]* to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, one, u8);
+  u8x2 = svset2_u8 (u8x2, 3 - 2, u8);
+  u8x2 = svset2_u8 (u8x2, 1.0, u8);
+  u8x2 = svset2_u8 (u8x2, const_sub (5, 4), u8);
+  u8x2 = svset2_u8 (u8x2, const_sub (6, 4), u8); /* { dg-error {passing 2 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, const_sub (7, 4), u8); /* { dg-error {passing 3 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, const_sub (8, 4), u8); /* { dg-error {passing 4 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, add (0, 0), u8); /* { dg-error "argument 2 of 'svset2_u8' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set3_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set3_1.C
new file mode 100644 (file)
index 0000000..9bb4f7a
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svuint16x3_t u16x3,
+    svfloat16x4_t f16x4, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  f16x3 = svset3 (f16x3); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&\)'} } */
+  f16x3 = svset3 (f16x3, 1); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int\)'} } */
+  f16x3 = svset3 (f16x3, 1, f16, 2); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int, svfloat16_t\&, int\)'} } */
+  f16x3 = svset3 (f16, 0, f16); /* { dg-error {no matching function for call to 'svset3\(svfloat16_t\&, int, svfloat16_t\&\)'} } */
+  f16x3 = svset3 (u16x3, 0, f16); /* { dg-error {no matching function for call to 'svset3\(svuint16x3_t\&, int, svfloat16_t\&\)'} } */
+  f16x3 = svset3 (f16x4, 0, f16); /* { dg-error {no matching function for call to 'svset3\(svfloat16x4_t\&, int, svfloat16_t\&\)'} } */
+  f16x3 = svset3 (pg, 0, f16); /* { dg-error {no matching function for call to 'svset3\(svbool_t\&, int, svfloat16_t\&\)'} } */
+  f16x3 = svset3 (f16x3, 0, f64); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int, svfloat64_t\&\)'} } */
+  f16x3 = svset3 (f16x3, 0, f16x3); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int, svfloat16x3_t\&\)'} } */
+  f16x3 = svset3 (f16x3, 0, pg); /* { dg-error {no matching function for call to 'svset3\(svfloat16x3_t\&, int, svbool_t\&\)'} } */
+  f16x3 = svset3 (f16x3, x, f16); /* { dg-error "argument 2 of 'svset3' must be an integer constant expression" } */
+  f16x3 = svset3 (f16x3, 0, f16);
+  u16x3 = svset3 (f16x3, 0, f16); /* { dg-error {cannot convert 'svfloat16x3_t' to 'svuint16x3_t' in assignment} } */
+  f16x3 = svset3 (f16x3, 1, f16);
+  f16x3 = svset3 (f16x3, 2, f16);
+  f16x3 = svset3 (f16x3, 3, f16); /* { dg-error {passing 3 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, 4, f16); /* { dg-error {passing 4 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, 5, f16); /* { dg-error {passing 5 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, ~0U, f16); /* { dg-error {passing [^ ]* to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, one, f16);
+  f16x3 = svset3 (f16x3, 3 - 2, f16);
+  f16x3 = svset3 (f16x3, 1.0, f16);
+  f16x3 = svset3 (f16x3, const_sub (5, 4), f16);
+  f16x3 = svset3 (f16x3, const_sub (6, 4), f16);
+  f16x3 = svset3 (f16x3, const_sub (7, 4), f16); /* { dg-error {passing 3 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, const_sub (8, 4), f16); /* { dg-error {passing 4 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, add (0, 0), f16); /* { dg-error "argument 2 of 'svset3' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set3_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set3_2.C
new file mode 100644 (file)
index 0000000..0bb6049
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svuint16x3_t u16x3,
+    svfloat16x4_t f16x4, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  f16x3 = svset3_f16 (f16x3); /* { dg-error {too few arguments to function '[^']*'} } */
+  f16x3 = svset3_f16 (f16x3, 1); /* { dg-error {too few arguments to function '[^']*'} } */
+  f16x3 = svset3_f16 (f16x3, 1, f16, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+  f16x3 = svset3_f16 (f16, 0, f16); /* { dg-error {cannot convert 'svfloat16_t' to 'svfloat16x3_t'} } */
+  f16x3 = svset3_f16 (u16x3, 0, f16); /* { dg-error {cannot convert 'svuint16x3_t' to 'svfloat16x3_t'} } */
+  f16x3 = svset3_f16 (f16x4, 0, f16); /* { dg-error {cannot convert 'svfloat16x4_t' to 'svfloat16x3_t'} } */
+  f16x3 = svset3_f16 (pg, 0, f16); /* { dg-error {cannot convert 'svbool_t' to 'svfloat16x3_t'} } */
+  f16x3 = svset3_f16 (f16x3, 0, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svfloat16_t'} } */
+  f16x3 = svset3_f16 (f16x3, 0, f16x3); /* { dg-error {cannot convert 'svfloat16x3_t' to 'svfloat16_t'} } */
+  f16x3 = svset3_f16 (f16x3, 0, pg); /* { dg-error {cannot convert 'svbool_t' to 'svfloat16_t'} } */
+  f16x3 = svset3_f16 (f16x3, x, f16); /* { dg-error "argument 2 of 'svset3_f16' must be an integer constant expression" } */
+  f16x3 = svset3_f16 (f16x3, 0, f16);
+  u16x3 = svset3_f16 (f16x3, 0, f16); /* { dg-error {cannot convert 'svfloat16x3_t' to 'svuint16x3_t' in assignment} } */
+  f16x3 = svset3_f16 (f16x3, 1, f16);
+  f16x3 = svset3_f16 (f16x3, 2, f16);
+  f16x3 = svset3_f16 (f16x3, 3, f16); /* { dg-error {passing 3 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, 4, f16); /* { dg-error {passing 4 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, 5, f16); /* { dg-error {passing 5 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, ~0U, f16); /* { dg-error {passing [^ ]* to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, one, f16);
+  f16x3 = svset3_f16 (f16x3, 3 - 2, f16);
+  f16x3 = svset3_f16 (f16x3, 1.0, f16);
+  f16x3 = svset3_f16 (f16x3, const_sub (5, 4), f16);
+  f16x3 = svset3_f16 (f16x3, const_sub (6, 4), f16);
+  f16x3 = svset3_f16 (f16x3, const_sub (7, 4), f16); /* { dg-error {passing 3 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, const_sub (8, 4), f16); /* { dg-error {passing 4 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, add (0, 0), f16); /* { dg-error "argument 2 of 'svset3_f16' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set4_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set4_1.C
new file mode 100644 (file)
index 0000000..dc5dae8
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svfloat32x4_t f32x4,
+    svint32x2_t s32x2, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  s32x4 = svset4 (s32x4); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&\)'} } */
+  s32x4 = svset4 (s32x4, 1); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int\)'} } */
+  s32x4 = svset4 (s32x4, 1, s32, 2); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int, svint32_t\&, int\)'} } */
+  s32x4 = svset4 (s32, 0, s32); /* { dg-error {no matching function for call to 'svset4\(svint32_t\&, int, svint32_t\&\)'} } */
+  s32x4 = svset4 (f32x4, 0, s32); /* { dg-error {no matching function for call to 'svset4\(svfloat32x4_t\&, int, svint32_t\&\)'} } */
+  s32x4 = svset4 (s32x2, 0, s32); /* { dg-error {no matching function for call to 'svset4\(svint32x2_t\&, int, svint32_t\&\)'} } */
+  s32x4 = svset4 (pg, 0, s32); /* { dg-error {no matching function for call to 'svset4\(svbool_t\&, int, svint32_t\&\)'} } */
+  s32x4 = svset4 (s32x4, 0, f64); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int, svfloat64_t\&\)'} } */
+  s32x4 = svset4 (s32x4, 0, s32x4); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int, svint32x4_t\&\)'} } */
+  s32x4 = svset4 (s32x4, 0, pg); /* { dg-error {no matching function for call to 'svset4\(svint32x4_t\&, int, svbool_t\&\)'} } */
+  s32x4 = svset4 (s32x4, x, s32); /* { dg-error "argument 2 of 'svset4' must be an integer constant expression" } */
+  s32x4 = svset4 (s32x4, 0, s32);
+  f32x4 = svset4 (s32x4, 0, s32); /* { dg-error {cannot convert 'svint32x4_t' to 'svfloat32x4_t' in assignment} } */
+  s32x4 = svset4 (s32x4, 1, s32);
+  s32x4 = svset4 (s32x4, 2, s32);
+  s32x4 = svset4 (s32x4, 3, s32);
+  s32x4 = svset4 (s32x4, 4, s32); /* { dg-error {passing 4 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4 (s32x4, 5, s32); /* { dg-error {passing 5 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4 (s32x4, ~0U, s32); /* { dg-error {passing [^ ]* to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4 (s32x4, one, s32);
+  s32x4 = svset4 (s32x4, 3 - 2, s32);
+  s32x4 = svset4 (s32x4, 1.0, s32);
+  s32x4 = svset4 (s32x4, const_sub (5, 4), s32);
+  s32x4 = svset4 (s32x4, const_sub (6, 4), s32);
+  s32x4 = svset4 (s32x4, const_sub (7, 4), s32);
+  s32x4 = svset4 (s32x4, const_sub (8, 4), s32); /* { dg-error {passing 4 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4 (s32x4, add (0, 0), s32); /* { dg-error "argument 2 of 'svset4' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set4_2.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/set4_2.C
new file mode 100644 (file)
index 0000000..762a6db
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c++11 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+constexpr uint64_t const_sub (uint64_t a, uint64_t b) { return a - b; }
+uint64_t add (uint64_t a, uint64_t b) { return a + b; }
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svfloat32x4_t f32x4,
+    svint32x2_t s32x2, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  s32x4 = svset4_s32 (s32x4); /* { dg-error {too few arguments to function '[^']*'} } */
+  s32x4 = svset4_s32 (s32x4, 1); /* { dg-error {too few arguments to function '[^']*'} } */
+  s32x4 = svset4_s32 (s32x4, 1, s32, 2); /* { dg-error {too many arguments to function '[^']*'} } */
+  s32x4 = svset4_s32 (s32, 0, s32); /* { dg-error {cannot convert 'svint32_t' to 'svint32x4_t'} } */
+  s32x4 = svset4_s32 (f32x4, 0, s32); /* { dg-error {cannot convert 'svfloat32x4_t' to 'svint32x4_t'} } */
+  s32x4 = svset4_s32 (s32x2, 0, s32); /* { dg-error {cannot convert 'svint32x2_t' to 'svint32x4_t'} } */
+  s32x4 = svset4_s32 (pg, 0, s32); /* { dg-error {cannot convert 'svbool_t' to 'svint32x4_t'} } */
+  s32x4 = svset4_s32 (s32x4, 0, f64); /* { dg-error {cannot convert 'svfloat64_t' to 'svint32_t'} } */
+  s32x4 = svset4_s32 (s32x4, 0, s32x4); /* { dg-error {cannot convert 'svint32x4_t' to 'svint32_t'} } */
+  s32x4 = svset4_s32 (s32x4, 0, pg); /* { dg-error {cannot convert 'svbool_t' to 'svint32_t'} } */
+  s32x4 = svset4_s32 (s32x4, x, s32); /* { dg-error "argument 2 of 'svset4_s32' must be an integer constant expression" } */
+  s32x4 = svset4_s32 (s32x4, 0, s32);
+  f32x4 = svset4_s32 (s32x4, 0, s32); /* { dg-error {cannot convert 'svint32x4_t' to 'svfloat32x4_t' in assignment} } */
+  s32x4 = svset4_s32 (s32x4, 1, s32);
+  s32x4 = svset4_s32 (s32x4, 2, s32);
+  s32x4 = svset4_s32 (s32x4, 3, s32);
+  s32x4 = svset4_s32 (s32x4, 4, s32); /* { dg-error {passing 4 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4_s32 (s32x4, 5, s32); /* { dg-error {passing 5 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4_s32 (s32x4, ~0U, s32); /* { dg-error {passing [^ ]* to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4_s32 (s32x4, one, s32);
+  s32x4 = svset4_s32 (s32x4, 3 - 2, s32);
+  s32x4 = svset4_s32 (s32x4, 1.0, s32);
+  s32x4 = svset4_s32 (s32x4, const_sub (5, 4), s32);
+  s32x4 = svset4_s32 (s32x4, const_sub (6, 4), s32);
+  s32x4 = svset4_s32 (s32x4, const_sub (7, 4), s32);
+  s32x4 = svset4_s32 (s32x4, const_sub (8, 4), s32); /* { dg-error {passing 4 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4_s32 (s32x4, add (0, 0), s32); /* { dg-error "argument 2 of 'svset4_s32' must be an integer constant expression" } */
+
+  return f64;
+}
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_1.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_1.c
new file mode 100644 (file)
index 0000000..ff25900
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svbool_t; /* { dg-message "note: previous declaration 'int svbool_t'" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'typedef [^'\n]* svbool_t' redeclared as different kind of entity} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_10.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_10.c
new file mode 100644 (file)
index 0000000..86d87fa
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+typedef int svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_11.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_11.c
new file mode 100644 (file)
index 0000000..741d10e
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+
+struct svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
+
+svint8_t f (svint8x2_t x) { return x.__val[0]; } /* { dg-error {'x' has incomplete type} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_12.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_12.c
new file mode 100644 (file)
index 0000000..fc6a07a
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+
+typedef struct svint8x2_t svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
+
+svint8_t f (svint8x2_t x) { return x.__val[0]; } /* { dg-error {'x' has incomplete type} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_13.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_13.c
new file mode 100644 (file)
index 0000000..161aacb
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+struct svint8x2_t {};
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_14.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_14.c
new file mode 100644 (file)
index 0000000..8319111
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+enum svpattern { FOO }; /* { dg-message "note: previous definition here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error "multiple definition of 'enum svpattern'" } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_15.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_15.c
new file mode 100644 (file)
index 0000000..71e35a4
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+enum svpattern { FOO }; /* { dg-error "multiple definition of 'enum svpattern'" } */
+enum foo { SV_ALL }; /* { dg-error "'SV_ALL' conflicts with a previous declaration" } */
+typedef int SV_POW2; /* { dg-error "'typedef int SV_POW2' redeclared as different kind of entity" } */
+int SV_VL3; /* { dg-error "'int SV_VL3' redeclared as different kind of entity" } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_16.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_16.c
new file mode 100644 (file)
index 0000000..277064d
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+struct svpattern { int x; };
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error "'svpattern' referred to as enum" } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_17.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_17.c
new file mode 100644 (file)
index 0000000..e4bcda6
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+struct svpattern { int x; }; /* { dg-error "'svpattern' referred to as 'struct'" } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_18.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_18.c
new file mode 100644 (file)
index 0000000..b670615
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svpattern; /* OK in C.  */
+
+#pragma GCC aarch64 "arm_sve.h"
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_19.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_19.c
new file mode 100644 (file)
index 0000000..c6379f7
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+int svpattern; /* OK in C.  */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_2.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_2.c
new file mode 100644 (file)
index 0000000..5baf599
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svint8_t; /* { dg-message "note: previous declaration 'int svint8_t" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'typedef [^'\n]* svint8_t' redeclared as different kind of entity} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_20.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_20.c
new file mode 100644 (file)
index 0000000..3ba19f5
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+enum foo { SV_VL4 };
+typedef int SV_POW2;
+int SV_ALL;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error "'SV_VL4' conflicts with a previous declaration" } */
+/* { dg-error "'SV_POW2' redeclared as different kind of entity" "" { target *-*-* } .-1 } */
+/* { dg-error "'SV_ALL' redeclared as different kind of entity" "" { target *-*-* } .-2 } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_3.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_3.c
new file mode 100644 (file)
index 0000000..a8d7bdc
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svuint16_t; /* { dg-message "note: previous declaration 'int svuint16_t'" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'typedef [^'\n]* svuint16_t' redeclared as different kind of entity} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_4.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_4.c
new file mode 100644 (file)
index 0000000..c0563d0
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svfloat32_t; /* { dg-message "note: previous declaration 'int svfloat32_t'" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'typedef [^'\n]* svfloat32_t' redeclared as different kind of entity} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_5.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_5.c
new file mode 100644 (file)
index 0000000..ee28e95
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+typedef int svbool_t; /* { dg-message "note: previous declaration as 'typedef int svbool_t'" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {conflicting declaration '[^'\n]* svbool_t'} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_6.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_6.c
new file mode 100644 (file)
index 0000000..85c17ea
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+
+typedef __SVBool_t svbool_t;
+
+#pragma GCC aarch64 "arm_sve.h"
+
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_7.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_7.c
new file mode 100644 (file)
index 0000000..3a0dfb1
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+
+int svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'typedef struct svint8x2_t svint8x2_t' redeclared as different kind of entity} } */
+
+void f (struct svint8x2_t) {} /* { dg-error {incomplete type} } */
+void g () { int &x = svint8x2_t; }
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_8.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_8.c
new file mode 100644 (file)
index 0000000..9b0df91
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+
+struct svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {conflicting declaration 'typedef struct svint8x2_t svint8x2_t'} } */
+
+void f (svint8x2_t) {} /* { dg-error {incomplete type} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_9.c b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/type_redef_9.c
new file mode 100644 (file)
index 0000000..43068da
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+int svint8x2_t; /* { dg-error {'int svint8x2_t' redeclared as different kind of entity} } */
+
+void f (struct svint8x2_t) {} /* { dg-error {using typedef-name 'svint8x2_t' after 'struct'} } */
+void g () { int &x = svint8x2_t; } /* { dg-error {expected primary-expression before ';' token} } */
diff --git a/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/whilele_1.C b/gcc/testsuite/g++.target/aarch64/sve/acle/general-c++/whilele_1.C
new file mode 100644 (file)
index 0000000..9571e66
--- /dev/null
@@ -0,0 +1,81 @@
+// { dg-do compile }
+
+#include <arm_sve.h>
+
+enum foo { A, B };
+
+void
+test (int8_t s8, int16_t s16, int32_t s32, int64_t s64,
+      uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64,
+      bool b, foo e, int *ptr, float f32, svbool_t pg,
+      svint32_t vec)
+{
+  svwhilele_b8 (s32); // { dg-error {no matching function for call to 'svwhilele_b8\(int32_t&\)'} }
+  svwhilele_b8 (s32, s32, s32); // { dg-error {no matching function for call to 'svwhilele_b8\(int32_t&, int32_t&, int32_t&\)'} }
+
+  svwhilele_b8 (b, b);
+  svwhilele_b8 (e, e);
+  svwhilele_b8 (s8, s8);
+  svwhilele_b8 (u8, u8);
+  svwhilele_b8 (s16, s16);
+  svwhilele_b8 (u16, u16);
+  svwhilele_b8 (ptr, ptr); // { dg-error {no matching function for call to 'svwhilele_b8\(int\*&, int\*&\)'} }
+  // { dg-error {invalid conversion from 'int\*' to '[^']*'} "" { target *-*-* } .-1 }
+  svwhilele_b8 (f32, f32); // { dg-error {call of overloaded 'svwhilele_b8\(float&, float&\)' is ambiguous} }
+  svwhilele_b8 (pg, pg); // { dg-error {no matching function for call to 'svwhilele_b8\(svbool_t&, svbool_t&\)'} }
+  svwhilele_b8 (vec, vec); // { dg-error {no matching function for call to 'svwhilele_b8\(svint32_t&, svint32_t&\)'} }
+
+  svwhilele_b8 (s32, b);
+  svwhilele_b8 (s32, e);
+  svwhilele_b8 (s32, s8);
+  svwhilele_b8 (s32, u8);
+  svwhilele_b8 (s32, s16);
+  svwhilele_b8 (s32, u16);
+
+  svwhilele_b8 (u32, b); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, bool&\)' is ambiguous} }
+  svwhilele_b8 (u32, e); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, foo&\)' is ambiguous} }
+  svwhilele_b8 (u32, s8); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int8_t&\)' is ambiguous} }
+  svwhilele_b8 (u32, u8); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, uint8_t&\)' is ambiguous} }
+  svwhilele_b8 (u32, s16); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int16_t&\)' is ambiguous} }
+  svwhilele_b8 (u32, u16); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, uint16_t&\)' is ambiguous} }
+
+  svwhilele_b8 (s32, s32);
+  svwhilele_b8 (s32, u32); // { dg-error {call of overloaded 'svwhilele_b8\(int32_t&, uint32_t&\)' is ambiguous} }
+  svwhilele_b8 (s32, s64); // { dg-error {call of overloaded 'svwhilele_b8\(int32_t&, int64_t&\)' is ambiguous} }
+  svwhilele_b8 (s32, u64); // { dg-error {call of overloaded 'svwhilele_b8\(int32_t&, uint64_t&\)' is ambiguous} }
+
+  svwhilele_b8 (u32, s32); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int32_t&\)' is ambiguous} }
+  svwhilele_b8 (u32, u32);
+  svwhilele_b8 (u32, s64); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int64_t&\)' is ambiguous} }
+  svwhilele_b8 (u32, u64); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, uint64_t&\)' is ambiguous} }
+
+  svwhilele_b8 (s64, s32); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, int32_t&\)' is ambiguous} }
+  svwhilele_b8 (s64, u32); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, uint32_t&\)' is ambiguous} }
+  svwhilele_b8 (s64, s64);
+  svwhilele_b8 (s64, u64); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, uint64_t&\)' is ambiguous} }
+
+  svwhilele_b8 (u64, s32); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, int32_t&\)' is ambiguous} }
+  svwhilele_b8 (u64, u32); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, uint32_t&\)' is ambiguous} }
+  svwhilele_b8 (u64, s64); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, int64_t&\)' is ambiguous} }
+  svwhilele_b8 (u64, u64);
+
+  svwhilele_b8 (0, s32);
+  svwhilele_b8 (0, u32); // { dg-error {call of overloaded 'svwhilele_b8\(int, uint32_t&\)' is ambiguous} }
+  svwhilele_b8 (0, s64); // { dg-error {call of overloaded 'svwhilele_b8\(int, int64_t&\)' is ambiguous} }
+  svwhilele_b8 (0, u64); // { dg-error {call of overloaded 'svwhilele_b8\(int, uint64_t&\)' is ambiguous} }
+
+  svwhilele_b8 (s32, 0);
+  svwhilele_b8 (u32, 0); // { dg-error {call of overloaded 'svwhilele_b8\(uint32_t&, int\)' is ambiguous} }
+  svwhilele_b8 (s64, 0); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, int\)' is ambiguous} }
+  svwhilele_b8 (u64, 0); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, int\)' is ambiguous} }
+
+  svwhilele_b8 (0U, s32); // { dg-error {call of overloaded 'svwhilele_b8\(unsigned int, int32_t&\)' is ambiguous} }
+  svwhilele_b8 (0U, u32);
+  svwhilele_b8 (0U, s64); // { dg-error {call of overloaded 'svwhilele_b8\(unsigned int, int64_t&\)' is ambiguous} }
+  svwhilele_b8 (0U, u64); // { dg-error {call of overloaded 'svwhilele_b8\(unsigned int, uint64_t&\)' is ambiguous} }
+
+  svwhilele_b8 (s32, 0U); // { dg-error {call of overloaded 'svwhilele_b8\(int32_t&, unsigned int\)' is ambiguous} }
+  svwhilele_b8 (u32, 0U);
+  svwhilele_b8 (s64, 0U); // { dg-error {call of overloaded 'svwhilele_b8\(int64_t&, unsigned int\)' is ambiguous} }
+  svwhilele_b8 (u64, 0U); // { dg-error {call of overloaded 'svwhilele_b8\(uint64_t&, unsigned int\)' is ambiguous} }
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp b/gcc/testsuite/gcc.target/aarch64/sve/acle/aarch64-sve-acle.exp
new file mode 100644 (file)
index 0000000..34d9dfd
--- /dev/null
@@ -0,0 +1,54 @@
+#  Specific regression driver for AArch64 SVE.
+#  Copyright (C) 2009-2019 Free Software Foundation, Inc.
+#  Contributed by ARM Ltd.
+#
+#  This file is part of GCC.
+#
+#  GCC is free software; you can redistribute it and/or modify it
+#  under the terms of the GNU General Public License as published by
+#  the Free Software Foundation; either version 3, or (at your option)
+#  any later version.
+#
+#  GCC is distributed in the hope that it will be useful, but
+#  WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+#  General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with GCC; see the file COPYING3.  If not see
+#  <http://www.gnu.org/licenses/>.  */
+
+# GCC testsuite that uses the `dg.exp' driver.
+
+# Exit immediately if this isn't an AArch64 target.
+if {![istarget aarch64*-*-*] } {
+    return
+}
+
+# Load support procs.
+load_lib gcc-dg.exp
+
+# If a testcase doesn't have special options, use these.
+global DEFAULT_CFLAGS
+if ![info exists DEFAULT_CFLAGS] then {
+    set DEFAULT_CFLAGS " -ansi -pedantic-errors"
+}
+
+# Initialize `dg'.
+dg-init
+
+# Force SVE if we're not testing it already.
+if { [check_effective_target_aarch64_sve] } {
+    set sve_flags ""
+} else {
+    set sve_flags "-march=armv8.2-a+sve"
+}
+
+# Main loop.
+# FIXME: This should include general/*.c too, but leave that until the
+# C frontend allows initialization of SVE vectors.
+set files [glob -nocomplain $srcdir/$subdir/general-c/*.c]
+dg-runtest [lsort $files] "$sve_flags" $DEFAULT_CFLAGS
+
+# All done.
+dg-finish
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_index_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_index_1.c
new file mode 100644 (file)
index 0000000..714265e
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, uint32_t *u32_ptr, svuint8_t u8, svuint16_t u16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+  svadrh_index (u32); /* { dg-error {too few arguments to function 'svadrh_index'} } */
+  svadrh_index (u32, u32, u32); /* { dg-error {too many arguments to function 'svadrh_index'} } */
+  svadrh_index (u32_ptr, s32); /* { dg-error {passing '[^']*\*'[^\n]* to argument 1 of 'svadrh_index', which expects an SVE vector type} } */
+  svadrh_index (0, s32); /* { dg-error {passing 'int' to argument 1 of 'svadrh_index', which expects an SVE vector type} } */
+  svadrh_index (u16, u16); /* { dg-error {passing 'svuint16_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svadrh_index (s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svadrh_index (f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svadrh_index (pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svadrh_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+  svadrh_index (u32, 0); /* { dg-error {passing 'int' to argument 2 of 'svadrh_index', which expects an SVE vector type} } */
+  svadrh_index (u32, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svadrh_index', which expects a vector of 32-bit or 64-bit integers} } */
+  svadrh_index (u32, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svadrh_index', which expects a vector of 32-bit or 64-bit integers} } */
+  svadrh_index (u32, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+
+  svadrh_index (u32, s32);
+  svadrh_index (u32, u32);
+  svadrh_index (u32, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+  svadrh_index (u32, s64); /* { dg-error {cannot combine a base of type 'svuint32_t' with an index of type 'svint64_t'} } */
+  svadrh_index (u32, u64); /* { dg-error {cannot combine a base of type 'svuint32_t' with an index of type 'svuint64_t'} } */
+  svadrh_index (u32, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+
+  svadrh_index (u64, s32); /* { dg-error {cannot combine a base of type 'svuint64_t' with an index of type 'svint32_t'} } */
+  svadrh_index (u64, u32); /* { dg-error {cannot combine a base of type 'svuint64_t' with an index of type 'svuint32_t'} } */
+  svadrh_index (u64, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+  svadrh_index (u64, s64);
+  svadrh_index (u64, u64);
+  svadrh_index (u64, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svadrh_index', which expects a vector of integers} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_offset_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/adr_offset_1.c
new file mode 100644 (file)
index 0000000..528d7ac
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, uint32_t *u32_ptr, svuint8_t u8, svuint16_t u16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+  svadrb_offset (u32); /* { dg-error {too few arguments to function 'svadrb_offset'} } */
+  svadrb_offset (u32, u32, u32); /* { dg-error {too many arguments to function 'svadrb_offset'} } */
+  svadrb_offset (u32_ptr, s32); /* { dg-error {passing '[^']*\*'[^\n]* to argument 1 of 'svadrb_offset', which expects an SVE vector type} } */
+  svadrb_offset (0, s32); /* { dg-error {passing 'int' to argument 1 of 'svadrb_offset', which expects an SVE vector type} } */
+  svadrb_offset (u16, u16); /* { dg-error {passing 'svuint16_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svadrb_offset (s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svadrb_offset (f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svadrb_offset (pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svadrb_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+  svadrb_offset (u32, 0); /* { dg-error {passing 'int' to argument 2 of 'svadrb_offset', which expects an SVE vector type} } */
+  svadrb_offset (u32, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svadrb_offset', which expects a vector of 32-bit or 64-bit integers} } */
+  svadrb_offset (u32, u16); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svadrb_offset', which expects a vector of 32-bit or 64-bit integers} } */
+  svadrb_offset (u32, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+
+  svadrb_offset (u32, s32);
+  svadrb_offset (u32, u32);
+  svadrb_offset (u32, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+  svadrb_offset (u32, s64); /* { dg-error {cannot combine a base of type 'svuint32_t' with an offset of type 'svint64_t'} } */
+  svadrb_offset (u32, u64); /* { dg-error {cannot combine a base of type 'svuint32_t' with an offset of type 'svuint64_t'} } */
+  svadrb_offset (u32, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+
+  svadrb_offset (u64, s32); /* { dg-error {cannot combine a base of type 'svuint64_t' with an offset of type 'svint32_t'} } */
+  svadrb_offset (u64, u32); /* { dg-error {cannot combine a base of type 'svuint64_t' with an offset of type 'svuint32_t'} } */
+  svadrb_offset (u64, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+  svadrb_offset (u64, s64);
+  svadrb_offset (u64, u64);
+  svadrb_offset (u64, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svadrb_offset', which expects a vector of integers} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_1.c
new file mode 100644 (file)
index 0000000..8ce89fa
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t u8, svint16_t s16)
+{
+  svzip1 (pg); /* { dg-error {too few arguments to function 'svzip1'} } */
+  svzip1 (pg, u8, u8); /* { dg-error {too many arguments to function 'svzip1'} } */
+  svzip1 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svzip1', but previous arguments had type 'svbool_t'} } */
+  svzip1 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svzip1', but previous arguments had type 'svuint8_t'} } */
+  svzip1 (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svzip1', but previous arguments had type 'svuint8_t'} } */
+  svzip1 (u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svzip1', which expects an SVE vector type} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_int_opt_n.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_int_opt_n.c
new file mode 100644 (file)
index 0000000..965e9a1
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svint16_t s16, svuint16_t u16,
+    svfloat32_t f32, svint32_t s32, svuint32_t u32)
+{
+  svscale_x (pg, f16); /* { dg-error {too few arguments to function 'svscale_x'} } */
+  svscale_x (pg, f16, s16, s16); /* { dg-error {too many arguments to function 'svscale_x'} } */
+  svscale_x (s32, f16, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svscale_x', which expects 'svbool_t'} } */
+  svscale_x (1, f16, s32); /* { dg-error {passing 'int' to argument 1 of 'svscale_x', which expects 'svbool_t'} } */
+  svscale_x (pg, pg, s16); /* { dg-error {'svscale_x' has no form that takes 'svbool_t' arguments} } */
+  svscale_x (pg, 1, s16); /* { dg-error {passing 'int' to argument 2 of 'svscale_x', which expects an SVE vector type} } */
+  svscale_x (pg, f16, s16);
+  svscale_x (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+  svscale_x (pg, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+  svscale_x (pg, f16, s32); /* { dg-error {arguments 2 and 3 of 'svscale_x' must have the same element size, but the values passed here have type 'svfloat16_t' and 'svint32_t' respectively} } */
+  svscale_x (pg, f16, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+  svscale_x (pg, f16, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+  svscale_x (pg, f16, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+  svscale_x (pg, f16, 0);
+  svscale_x (pg, s16, s16); /* { dg-error {'svscale_x' has no form that takes 'svint16_t' arguments} } */
+  svscale_x (pg, s16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+  svscale_x (pg, s16, s32); /* { dg-error {'svscale_x' has no form that takes 'svint16_t' arguments} } */
+  svscale_x (pg, s16, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svscale_x', which expects a vector of signed integers} } */
+  svscale_x (pg, u16, s16); /* { dg-error {'svscale_x' has no form that takes 'svuint16_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_lane_1.c
new file mode 100644 (file)
index 0000000..f1879ca
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+    svint32_t s32, int i)
+{
+  svmul_lane (f32, f32); /* { dg-error {too few arguments to function 'svmul_lane'} } */
+  svmul_lane (f32, f32, 0, 0); /* { dg-error {too many arguments to function 'svmul_lane'} } */
+  svmul_lane (pg, pg, 0); /* { dg-error {'svmul_lane' has no form that takes 'svbool_t' arguments} } */
+  svmul_lane (s32, s32, 0); /* { dg-error {'svmul_lane' has no form that takes 'svint32_t' arguments} } */
+  svmul_lane (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmul_lane', which expects an SVE vector type} } */
+  svmul_lane (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svmul_lane', which expects an SVE vector type} } */
+  svmul_lane (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmul_lane', but previous arguments had type 'svfloat32_t'} } */
+  svmul_lane (f32, f32, s32); /* { dg-error {argument 3 of 'svmul_lane' must be an integer constant expression} } */
+  svmul_lane (f32, f32, i); /* { dg-error {argument 3 of 'svmul_lane' must be an integer constant expression} } */
+
+  svmul_lane (f16, f16, 0);
+  svmul_lane (f16, f16, 7);
+  svmul_lane (f16, f16, 8); /* { dg-error {passing 8 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 7\]} } */
+  svmul_lane (f16, f16, -1); /* { dg-error {passing -1 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 7\]} } */
+
+  svmul_lane (f32, f32, 0);
+  svmul_lane (f32, f32, 3);
+  svmul_lane (f32, f32, 4); /* { dg-error {passing 4 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 3\]} } */
+  svmul_lane (f32, f32, -1); /* { dg-error {passing -1 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 3\]} } */
+
+  svmul_lane (f64, f64, 0);
+  svmul_lane (f64, f64, 1);
+  svmul_lane (f64, f64, 2); /* { dg-error {passing 2 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 1\]} } */
+  svmul_lane (f64, f64, -1); /* { dg-error {passing -1 to argument 3 of 'svmul_lane', which expects a value in the range \[0, 1\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_n_1.c
new file mode 100644 (file)
index 0000000..0c69e66
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, svfloat16_t f16, int i, float f)
+{
+  svinsr (u8); /* { dg-error {too few arguments to function 'svinsr'} } */
+  svinsr (u8, 0, 0); /* { dg-error {too many arguments to function 'svinsr'} } */
+  svinsr (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svinsr', which expects an SVE vector type} } */
+  svinsr (u8, 0);
+  svinsr (u8, -1);
+  svinsr (u8, i);
+  svinsr (u8, f);
+  svinsr (u8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svinsr', which expects a scalar element} } */
+  svinsr (pg, 0); /* { dg-error {'svinsr' has no form that takes 'svbool_t' arguments} } */
+  svinsr (f16, f);
+  svinsr (f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svinsr', which expects a scalar element} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_1.c
new file mode 100644 (file)
index 0000000..29615e5
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8)
+{
+  svadd_u8_x (pg, u8, s8); /* { dg-error {incompatible type for argument 3 of 'svadd_u8_x'} } */
+  svadd_u8_x (pg, u8); /* { dg-error {too few arguments to function 'svadd_u8_x'} } */
+  svadd_u8_x (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svadd_u8_x'} } */
+  return svadd_s8_x (pg, s8, s8); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_2.c
new file mode 100644 (file)
index 0000000..9fa83ca
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+    svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+  svadd_x (pg, u8); /* { dg-error {too few arguments to function 'svadd_x'} } */
+  svadd_x (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svadd_x'} } */
+  svadd_x (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svadd_x', which expects 'svbool_t'} } */
+  svadd_x (pg, pg, pg); /* { dg-error {'svadd_x' has no form that takes 'svbool_t' arguments} } */
+  svadd_x (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svadd_x', which expects an SVE vector type} } */
+  svadd_x (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+  svadd_x (pg, u8, u8);
+  svadd_x (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+  svadd_x (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+  svadd_x (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+  svadd_x (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svadd_x', but previous arguments had type 'svuint8_t'} } */
+  svadd_x (pg, u8, 0);
+
+  svadd_x (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svfloat16_t'} } */
+  svadd_x (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svadd_x', but previous arguments had type 'svfloat16_t'} } */
+  svadd_x (pg, f16, f16);
+  svadd_x (pg, f16, 1);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_opt_n_3.c
new file mode 100644 (file)
index 0000000..4d0b253
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+    svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+  svand_z (pg, u8); /* { dg-error {too few arguments to function 'svand_z'} } */
+  svand_z (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svand_z'} } */
+  svand_z (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svand_z', which expects 'svbool_t'} } */
+  svand_z (pg, pg, pg);
+  svand_z (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svand_z', which expects an SVE vector type} } */
+  svand_z (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+  svand_z (pg, u8, u8);
+  svand_z (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+  svand_z (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+  svand_z (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+  svand_z (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svand_z', but previous arguments had type 'svuint8_t'} } */
+  svand_z (pg, u8, 0);
+
+  svand_z (pg, pg, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svand_z', but previous arguments had type 'svbool_t'} } */
+  svand_z (pg, pg, 0); /* { dg-error {passing 'int' to argument 3 of 'svand_z', but its 'svbool_t' form does not accept scalars} } */
+
+  svand_z (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svfloat16_t'} } */
+  svand_z (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svand_z', but previous arguments had type 'svfloat16_t'} } */
+  svand_z (pg, f16, f16); /* { dg-error {'svand_z' has no form that takes 'svfloat16_t' arguments} } */
+  svand_z (pg, f16, 1); /* { dg-error {'svand_z' has no form that takes 'svfloat16_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_rotate_1.c
new file mode 100644 (file)
index 0000000..8ffe91b
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+{
+  svcadd_x (pg, f32, f32); /* { dg-error {too few arguments to function 'svcadd_x'} } */
+  svcadd_x (pg, f32, f32, 90, 90); /* { dg-error {too many arguments to function 'svcadd_x'} } */
+  svcadd_x (f32, f32, f32, 90); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svcadd_x', which expects 'svbool_t'} } */
+  svcadd_x (pg, pg, pg, 90); /* { dg-error {'svcadd_x' has no form that takes 'svbool_t' arguments} } */
+  svcadd_x (pg, s32, s32, 90); /* { dg-error {'svcadd_x' has no form that takes 'svint32_t' arguments} } */
+  svcadd_x (pg, 1, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcadd_x', which expects an SVE vector type} } */
+  svcadd_x (pg, f32, 1, 90); /* { dg-error {passing 'int' to argument 3 of 'svcadd_x', which expects an SVE vector type} } */
+  svcadd_x (pg, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcadd_x', but previous arguments had type 'svfloat32_t'} } */
+  svcadd_x (pg, f32, f32, s32); /* { dg-error {argument 4 of 'svcadd_x' must be an integer constant expression} } */
+  svcadd_x (pg, f32, f32, i); /* { dg-error {argument 4 of 'svcadd_x' must be an integer constant expression} } */
+  svcadd_x (pg, f32, f32, -90); /* { dg-error {passing -90 to argument 4 of 'svcadd_x', which expects either 90 or 270} } */
+  svcadd_x (pg, f32, f32, 0); /* { dg-error {passing 0 to argument 4 of 'svcadd_x', which expects either 90 or 270} } */
+  svcadd_x (pg, f32, f32, 1); /* { dg-error {passing 1 to argument 4 of 'svcadd_x', which expects either 90 or 270} } */
+  svcadd_x (pg, f32, f32, 90);
+  svcadd_x (pg, f32, f32, 180); /* { dg-error {passing 180 to argument 4 of 'svcadd_x', which expects either 90 or 270} } */
+  svcadd_x (pg, f32, f32, 270);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_n_1.c
new file mode 100644 (file)
index 0000000..c8ca5f7
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, int i, float f)
+{
+  svdupq_lane (u8); /* { dg-error {too few arguments to function 'svdupq_lane'} } */
+  svdupq_lane (u8, 0, 0); /* { dg-error {too many arguments to function 'svdupq_lane'} } */
+  svdupq_lane (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svdupq_lane', which expects an SVE vector type} } */
+  svdupq_lane (u8, 0);
+  svdupq_lane (u8, -1);
+  svdupq_lane (u8, i);
+  svdupq_lane (u8, f);
+  svdupq_lane (u8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svdupq_lane', which expects 'uint64_t'} } */
+  svdupq_lane (pg, 0); /* { dg-error {'svdupq_lane' has no form that takes 'svbool_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_1.c
new file mode 100644 (file)
index 0000000..27726a8
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svuint64_t u64)
+{
+  svlsl_wide_u8_x (pg, u8, u8); /* { dg-error {incompatible type for argument 3 of 'svlsl_wide_u8_x'} } */
+  svlsl_wide_u8_x (pg, u8); /* { dg-error {too few arguments to function 'svlsl_wide_u8_x'} } */
+  svlsl_wide_u8_x (pg, u8, u64, u8); /* { dg-error {too many arguments to function 'svlsl_wide_u8_x'} } */
+  return svlsl_wide_s8_x (pg, s8, u64); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint64_opt_n_2.c
new file mode 100644 (file)
index 0000000..be21739
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, svuint64_t u64)
+{
+  svlsl_wide_x (pg, u8); /* { dg-error {too few arguments to function 'svlsl_wide_x'} } */
+  svlsl_wide_x (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svlsl_wide_x'} } */
+  svlsl_wide_x (u8, u8, u64); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svlsl_wide_x', which expects 'svbool_t'} } */
+  svlsl_wide_x (pg, 1, u64); /* { dg-error {passing 'int' to argument 2 of 'svlsl_wide_x', which expects an SVE vector type} } */
+  svlsl_wide_x (pg, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svlsl_wide_x', which expects 'svuint64_t'} } */
+  svlsl_wide_x (pg, u64, u64); /* { dg-error {'svlsl_wide_x' has no form that takes 'svuint64_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_1.c
new file mode 100644 (file)
index 0000000..8f86c50
--- /dev/null
@@ -0,0 +1,44 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svuint16_t u16, svint16_t s16,
+    svfloat16_t f16)
+{
+  svtbl (u8); /* { dg-error {too few arguments to function 'svtbl'} } */
+  svtbl (u8, u8, u8); /* { dg-error {too many arguments to function 'svtbl'} } */
+  svtbl (pg, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (pg, u8); /* { dg-error {'svtbl' has no form that takes 'svbool_t' arguments} } */
+
+  svtbl (u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svtbl', which expects an SVE vector type} } */
+  svtbl (u8, u8);
+  svtbl (u8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (u8, u16); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svuint8_t' and 'svuint16_t' respectively} } */
+  svtbl (u8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+
+  svtbl (s8, u8);
+  svtbl (s8, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (s8, u16); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svint8_t' and 'svuint16_t' respectively} } */
+  svtbl (s8, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (s8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+
+  svtbl (u16, u8); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svuint16_t' and 'svuint8_t' respectively} } */
+  svtbl (u16, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (u16, u16);
+  svtbl (u16, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (u16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+
+  svtbl (s16, u8); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svint16_t' and 'svuint8_t' respectively} } */
+  svtbl (s16, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (s16, u16);
+  svtbl (s16, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (s16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+
+  svtbl (f16, u8); /* { dg-error {arguments 1 and 2 of 'svtbl' must have the same element size, but the values passed here have type 'svfloat16_t' and 'svuint8_t' respectively} } */
+  svtbl (f16, s8); /* { dg-error {passing 'svint8_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (f16, u16);
+  svtbl (f16, s16); /* { dg-error {passing 'svint16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+  svtbl (f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svtbl', which expects a vector of unsigned integers} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_n_1.c
new file mode 100644 (file)
index 0000000..36a902e
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, int i, float f)
+{
+  svdup_lane (u8); /* { dg-error {too few arguments to function 'svdup_lane'} } */
+  svdup_lane (u8, 0, 0); /* { dg-error {too many arguments to function 'svdup_lane'} } */
+  svdup_lane (0, 0); /* { dg-error {passing 'int' to argument 1 of 'svdup_lane', which expects an SVE vector type} } */
+  svdup_lane (u8, 0);
+  svdup_lane (u8, -1);
+  svdup_lane (u8, i);
+  svdup_lane (u8, f);
+  svdup_lane (u8, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svdup_lane', which expects a scalar integer} } */
+  svdup_lane (pg, 0); /* { dg-error {'svdup_lane' has no form that takes 'svbool_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/binary_uint_opt_n_1.c
new file mode 100644 (file)
index 0000000..b162ab4
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svint16_t s16, svuint16_t u16,
+    svfloat32_t f32, svint32_t s32, svuint32_t u32)
+{
+  svlsl_x (pg, s16); /* { dg-error {too few arguments to function 'svlsl_x'} } */
+  svlsl_x (pg, s16, u16, u16); /* { dg-error {too many arguments to function 'svlsl_x'} } */
+  svlsl_x (s32, s32, u32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svlsl_x', which expects 'svbool_t'} } */
+  svlsl_x (1, s32, u32); /* { dg-error {passing 'int' to argument 1 of 'svlsl_x', which expects 'svbool_t'} } */
+  svlsl_x (pg, pg, u16); /* { dg-error {'svlsl_x' has no form that takes 'svbool_t' arguments} } */
+  svlsl_x (pg, 1, s16); /* { dg-error {passing 'int' to argument 2 of 'svlsl_x', which expects an SVE vector type} } */
+  svlsl_x (pg, s16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+  svlsl_x (pg, s16, u16);
+  svlsl_x (pg, s16, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+  svlsl_x (pg, s16, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+  svlsl_x (pg, s16, u32); /* { dg-error {arguments 2 and 3 of 'svlsl_x' must have the same element size, but the values passed here have type 'svint16_t' and 'svuint32_t' respectively} } */
+  svlsl_x (pg, s16, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+  svlsl_x (pg, s16, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+  svlsl_x (pg, s16, 0);
+  svlsl_x (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+  svlsl_x (pg, f16, u16); /* { dg-error {'svlsl_x' has no form that takes 'svfloat16_t' arguments} } */
+  svlsl_x (pg, f16, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svlsl_x', which expects a vector of unsigned integers} } */
+  svlsl_x (pg, f16, u32); /* { dg-error {'svlsl_x' has no form that takes 'svfloat16_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/clast_1.c
new file mode 100644 (file)
index 0000000..cb9ac94
--- /dev/null
@@ -0,0 +1,15 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint32_t s32, svint64_t s64, int i)
+{
+  svclasta (pg, 1); /* { dg-error {too few arguments to function 'svclasta'} } */
+  svclasta (pg, 1, s32, 1); /* { dg-error {too many arguments to function 'svclasta'} } */
+  svclasta (1, 1, s32); /* { dg-error {passing 'int' to argument 1 of 'svclasta', which expects 'svbool_t'} } */
+  svclasta (pg, 1, 1); /* { dg-error {passing 'int' to argument 3 of 'svclasta', which expects an SVE vector type} } */
+  svclasta (pg, 1, pg); /* { dg-error {'svclasta' has no form that takes 'svbool_t' arguments} } */
+  svclasta (pg, i, s32);
+  svclasta (pg, s32, 1); /* { dg-error {passing 'int' to argument 3 of 'svclasta', which expects an SVE vector type} } */
+  svclasta (pg, s32, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svclasta', but previous arguments had type 'svint32_t'} } */
+  svclasta (pg, pg, pg); /* { dg-error {'svclasta' has no form that takes 'svbool_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_opt_n_1.c
new file mode 100644 (file)
index 0000000..71c8e86
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+    svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+  svcmpeq (pg, u8); /* { dg-error {too few arguments to function 'svcmpeq'} } */
+  svcmpeq (pg, u8, u8, u8); /* { dg-error {too many arguments to function 'svcmpeq'} } */
+  svcmpeq (u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svcmpeq', which expects 'svbool_t'} } */
+  svcmpeq (pg, pg, pg); /* { dg-error {'svcmpeq' has no form that takes 'svbool_t' arguments} } */
+  svcmpeq (pg, 1, u8); /* { dg-error {passing 'int' to argument 2 of 'svcmpeq', which expects an SVE vector type} } */
+  svcmpeq (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+  svcmpeq (pg, u8, u8);
+  svcmpeq (pg, u8, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+  svcmpeq (pg, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+  svcmpeq (pg, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+  svcmpeq (pg, u8, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svuint8_t'} } */
+  svcmpeq (pg, u8, 0);
+
+  svcmpeq (pg, f16, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svfloat16_t'} } */
+  svcmpeq (pg, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svcmpeq', but previous arguments had type 'svfloat16_t'} } */
+  svcmpeq (pg, f16, f16);
+  svcmpeq (pg, f16, 1);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_scalar_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_scalar_1.c
new file mode 100644 (file)
index 0000000..d5a60f8
--- /dev/null
@@ -0,0 +1,85 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+#include <stdbool.h>
+
+enum signed_enum { SA = -1, SB };
+enum unsigned_enum { UA, UB };
+
+void
+test (int8_t s8, int16_t s16, int32_t s32, int64_t s64,
+      uint8_t u8, uint16_t u16, uint32_t u32, uint64_t u64,
+      bool b, enum signed_enum se, enum unsigned_enum ue,
+      int *ptr, float f32, svbool_t pg, svint32_t vec)
+{
+  svwhilele_b8 (s32); /* { dg-error {too few arguments to function 'svwhilele_b8'} } */
+  svwhilele_b8 (s32, s32, s32); /* { dg-error {too many arguments to function 'svwhilele_b8'} } */
+
+  svwhilele_b8 (b, b);
+  svwhilele_b8 (se, se);
+  svwhilele_b8 (ue, ue);
+  svwhilele_b8 (s8, s8);
+  svwhilele_b8 (u8, u8);
+  svwhilele_b8 (s16, s16);
+  svwhilele_b8 (u16, u16);
+  svwhilele_b8 (ptr, ptr); /* { dg-error {passing 'int \*' to argument 1 of 'svwhilele_b8', which expects a 32-bit or 64-bit integer type} } */
+  svwhilele_b8 (f32, f32); /* { dg-error {passing 'float' to argument 1 of 'svwhilele_b8', which expects a 32-bit or 64-bit integer type} } */
+  svwhilele_b8 (pg, pg); /* { dg-error {passing 'svbool_t' to argument 1 of 'svwhilele_b8', which expects a 32-bit or 64-bit integer type} } */
+  svwhilele_b8 (vec, vec); /* { dg-error {passing 'svint32_t' to argument 1 of 'svwhilele_b8', which expects a 32-bit or 64-bit integer type} } */
+
+  svwhilele_b8 (s32, b);
+  svwhilele_b8 (s32, se);
+  svwhilele_b8 (s32, ue); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint32_t'} } */
+  svwhilele_b8 (s32, s8);
+  svwhilele_b8 (s32, u8);
+  svwhilele_b8 (s32, s16);
+  svwhilele_b8 (s32, u16);
+
+  svwhilele_b8 (u32, b); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (u32, se); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (u32, ue);
+  svwhilele_b8 (u32, s8); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (u32, u8); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (u32, s16); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (u32, u16); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+
+  svwhilele_b8 (s32, s32);
+  svwhilele_b8 (s32, u32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint32_t'} } */
+  svwhilele_b8 (s32, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'int64_t'} } */
+  svwhilele_b8 (s32, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint64_t'} } */
+
+  svwhilele_b8 (u32, s32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (u32, u32);
+  svwhilele_b8 (u32, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int64_t'} } */
+  svwhilele_b8 (u32, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'uint64_t'} } */
+
+  svwhilele_b8 (s64, s32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (s64, u32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'uint32_t'} } */
+  svwhilele_b8 (s64, s64);
+  svwhilele_b8 (s64, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'uint64_t'} } */
+
+  svwhilele_b8 (u64, s32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (u64, u32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'uint32_t'} } */
+  svwhilele_b8 (u64, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'int64_t'} } */
+  svwhilele_b8 (u64, u64);
+
+  svwhilele_b8 (0, s32);
+  svwhilele_b8 (0, u32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint32_t'} } */
+  svwhilele_b8 (0, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'int64_t'} } */
+  svwhilele_b8 (0, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint64_t'} } */
+
+  svwhilele_b8 (s32, 0);
+  svwhilele_b8 (u32, 0); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (s64, 0); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (u64, 0); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'int32_t'} } */
+
+  svwhilele_b8 (0U, s32); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int32_t'} } */
+  svwhilele_b8 (0U, u32);
+  svwhilele_b8 (0U, s64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'int64_t'} } */
+  svwhilele_b8 (0U, u64); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint32_t' but argument 2 has type 'uint64_t'} } */
+
+  svwhilele_b8 (s32, 0U); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int32_t' but argument 2 has type 'uint32_t'} } */
+  svwhilele_b8 (u32, 0U);
+  svwhilele_b8 (s64, 0U); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'int64_t' but argument 2 has type 'uint32_t'} } */
+  svwhilele_b8 (u64, 0U); /* { dg-error {call to 'svwhilele_b8' is ambiguous; argument 1 has type 'uint64_t' but argument 2 has type 'uint32_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_wide_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/compare_wide_opt_n_1.c
new file mode 100644 (file)
index 0000000..fc5e456
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint64_t s64, svuint64_t u64,
+    svfloat32_t f32, svfloat64_t f64, unsigned int x)
+{
+  svcmpeq_wide (pg, s8); /* { dg-error {too few arguments to function 'svcmpeq_wide'} } */
+  svcmpeq_wide (pg, s8, s64, s8); /* { dg-error {too many arguments to function 'svcmpeq_wide'} } */
+  svcmpeq_wide (s8, s8, s64); /* { dg-error {passing 'svint8_t' to argument 1 of 'svcmpeq_wide', which expects 'svbool_t'} } */
+  svcmpeq_wide (pg, 0, s64); /* { dg-error {passing 'int' to argument 2 of 'svcmpeq_wide', which expects an SVE vector type} } */
+  svcmpeq_wide (pg, s8, 0);
+  svcmpeq_wide (pg, s8, x);
+  svcmpeq_wide (pg, s8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+  svcmpeq_wide (pg, s8, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+  svcmpeq_wide (pg, s8, s64);
+  svcmpeq_wide (pg, s8, u64); /* { dg-error {arguments 2 and 3 of 'svcmpeq_wide' must have the same signedness, but the values passed here have type 'svint8_t' and 'svuint64_t' respectively} } */
+  svcmpeq_wide (pg, u8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+  svcmpeq_wide (pg, u8, u64); /* { dg-error {'svcmpeq_wide' has no form that takes 'svuint8_t' arguments} } */
+  svcmpeq_wide (pg, s64, s64); /* { dg-error {'svcmpeq_wide' has no form that takes 'svint64_t' arguments} } */
+  svcmpeq_wide (pg, f32, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+  svcmpeq_wide (pg, f32, f64); /* { dg-error {'svcmpeq_wide' has no form that takes 'svfloat32_t' arguments} } */
+  svcmpeq_wide (pg, f64, f64); /* { dg-error {'svcmpeq_wide' has no form that takes 'svfloat64_t' arguments} } */
+  svcmpeq_wide (pg, pg, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcmpeq_wide', which expects a vector of 64-bit elements} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_pat_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_pat_1.c
new file mode 100644 (file)
index 0000000..8dd76a5
--- /dev/null
@@ -0,0 +1,42 @@
+#include <arm_sve.h>
+
+void
+test (enum svpattern pat, int i)
+{
+  svcntb_pat (pat); /* { dg-error {argument 1 of 'svcntb_pat' must be an integer constant expression} } */
+  svcntb_pat (i); /* { dg-error {argument 1 of 'svcntb_pat' must be an integer constant expression} } */
+  svcntb_pat ((enum svpattern) -1); /* { dg-error {passing 4294967295 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 0);
+  svcntb_pat ((enum svpattern) 1);
+  svcntb_pat ((enum svpattern) 2);
+  svcntb_pat ((enum svpattern) 3);
+  svcntb_pat ((enum svpattern) 4);
+  svcntb_pat ((enum svpattern) 5);
+  svcntb_pat ((enum svpattern) 6);
+  svcntb_pat ((enum svpattern) 7);
+  svcntb_pat ((enum svpattern) 8);
+  svcntb_pat ((enum svpattern) 9);
+  svcntb_pat ((enum svpattern) 10);
+  svcntb_pat ((enum svpattern) 11);
+  svcntb_pat ((enum svpattern) 12);
+  svcntb_pat ((enum svpattern) 13);
+  svcntb_pat ((enum svpattern) 14); /* { dg-error {passing 14 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 15); /* { dg-error {passing 15 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 16); /* { dg-error {passing 16 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 17); /* { dg-error {passing 17 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 18); /* { dg-error {passing 18 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 19); /* { dg-error {passing 19 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 20); /* { dg-error {passing 20 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 21); /* { dg-error {passing 21 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 22); /* { dg-error {passing 22 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 23); /* { dg-error {passing 23 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 24); /* { dg-error {passing 24 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 25); /* { dg-error {passing 25 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 26); /* { dg-error {passing 26 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 27); /* { dg-error {passing 27 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 28); /* { dg-error {passing 28 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+  svcntb_pat ((enum svpattern) 29);
+  svcntb_pat ((enum svpattern) 30);
+  svcntb_pat ((enum svpattern) 31);
+  svcntb_pat ((enum svpattern) 32); /* { dg-error {passing 32 to argument 1 of 'svcntb_pat', which expects a valid 'enum svpattern' value} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_vector_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/count_vector_1.c
new file mode 100644 (file)
index 0000000..daf9e0d
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint32_t u32, svuint32x2_t u32x2)
+{
+  svlen (); /* { dg-error {too few arguments to function 'svlen'} } */
+  svlen (u32, u32); /* { dg-error {too many arguments to function 'svlen'} } */
+  svlen (0); /* { dg-error {passing 'int' to argument 1 of 'svlen', which expects an SVE vector type} } */
+  svlen (pg); /* { dg-error {'svlen' has no form that takes 'svbool_t' arguments} } */
+  svlen (u32x2); /* { dg-error {passing 'svuint32x2_t' to argument 1 of 'svlen', which expects a single SVE vector rather than a tuple} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_1.c
new file mode 100644 (file)
index 0000000..31321a0
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+    svuint8x2_t u8x2, int x)
+{
+  *ptr = svcreate2 (u8); /* { dg-error {too few arguments to function 'svcreate2'} } */
+  *ptr = svcreate2 (u8, u8, u8); /* { dg-error {too many arguments to function 'svcreate2'} } */
+  *ptr = svcreate2 (u8x2, u8x2); /* { dg-error {passing 'svuint8x2_t' to argument 1 of 'svcreate2', which expects a single SVE vector rather than a tuple} } */
+  *ptr = svcreate2 (u8, f64); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcreate2', but previous arguments had type 'svuint8_t'} } */
+  *ptr = svcreate2 (u8, pg); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate2', but previous arguments had type 'svuint8_t'} } */
+  *ptr = svcreate2 (u8, x); /* { dg-error {passing 'int' to argument 2 of 'svcreate2', which expects an SVE vector type} } */
+  *ptr = svcreate2 (x, u8); /* { dg-error {passing 'int' to argument 1 of 'svcreate2', which expects an SVE vector type} } */
+  *ptr = svcreate2 (pg, u8); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svcreate2', but previous arguments had type 'svbool_t'} } */
+  *ptr = svcreate2 (pg, pg); /* { dg-error {'svcreate2' has no form that takes 'svbool_t' arguments} } */
+  *ptr = svcreate2 (u8, u8);
+  *ptr = svcreate2 (f64, f64); /* { dg-error {incompatible types when assigning to type 'svuint8x2_t' from type 'svfloat64x2_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_2.c
new file mode 100644 (file)
index 0000000..28ad16c
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svuint8x2_t *ptr, svbool_t pg, svuint8_t u8, svfloat64_t f64,
+    svuint8x2_t u8x2, int x)
+{
+  *ptr = svcreate2_u8 (u8); /* { dg-error {too few arguments to function 'svcreate2_u8'} } */
+  *ptr = svcreate2_u8 (u8, u8, u8); /* { dg-error {too many arguments to function 'svcreate2_u8'} } */
+  *ptr = svcreate2_u8 (u8x2, u8x2); /* { dg-error {incompatible type for argument 1 of 'svcreate2_u8'} } */
+  /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} "" { target *-*-* } .-1 } */
+  *ptr = svcreate2_u8 (u8, f64); /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} } */
+  *ptr = svcreate2_u8 (u8, pg); /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} } */
+  *ptr = svcreate2_u8 (u8, x); /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} } */
+  *ptr = svcreate2_u8 (x, u8); /* { dg-error {incompatible type for argument 1 of 'svcreate2_u8'} } */
+  *ptr = svcreate2_u8 (pg, u8); /* { dg-error {incompatible type for argument 1 of 'svcreate2_u8'} } */
+  *ptr = svcreate2_u8 (pg, pg); /* { dg-error {incompatible type for argument 1 of 'svcreate2_u8'} } */
+  /* { dg-error {incompatible type for argument 2 of 'svcreate2_u8'} "" { target *-*-* } .-1 } */
+  *ptr = svcreate2_u8 (u8, u8);
+  *ptr = svcreate2_f64 (f64, f64); /* { dg-error {incompatible types when assigning to type 'svuint8x2_t' from type 'svfloat64x2_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_3.c
new file mode 100644 (file)
index 0000000..a88e56b
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+    svfloat16x3_t f16x3, int x)
+{
+  *ptr = svcreate3 (f16); /* { dg-error {too few arguments to function 'svcreate3'} } */
+  *ptr = svcreate3 (f16, f16); /* { dg-error {too few arguments to function 'svcreate3'} } */
+  *ptr = svcreate3 (f16, f16, f16, f16); /* { dg-error {too many arguments to function 'svcreate3'} } */
+  *ptr = svcreate3 (f16x3, f16x3, f16x3); /* { dg-error {passing 'svfloat16x3_t' to argument 1 of 'svcreate3', which expects a single SVE vector rather than a tuple} } */
+  *ptr = svcreate3 (f16, f16, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcreate3', but previous arguments had type 'svfloat16_t'} } */
+  *ptr = svcreate3 (f16, pg, f16); /* { dg-error {passing 'svbool_t' to argument 2 of 'svcreate3', but previous arguments had type 'svfloat16_t'} } */
+  *ptr = svcreate3 (f16, x, f16); /* { dg-error {passing 'int' to argument 2 of 'svcreate3', which expects an SVE vector type} } */
+  *ptr = svcreate3 (x, f16, f16); /* { dg-error {passing 'int' to argument 1 of 'svcreate3', which expects an SVE vector type} } */
+  *ptr = svcreate3 (pg, f16, f16); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svcreate3', but previous arguments had type 'svbool_t'} } */
+  *ptr = svcreate3 (pg, pg, pg); /* { dg-error {'svcreate3' has no form that takes 'svbool_t' arguments} } */
+  *ptr = svcreate3 (f16, f16, f16);
+  *ptr = svcreate3 (f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svfloat16x3_t' from type 'svfloat64x3_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_4.c
new file mode 100644 (file)
index 0000000..c111e9f
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svfloat16x3_t *ptr, svbool_t pg, svfloat16_t f16, svfloat64_t f64,
+    svfloat16x3_t f16x3, int x)
+{
+  *ptr = svcreate3_f16 (f16); /* { dg-error {too few arguments to function 'svcreate3_f16'} } */
+  *ptr = svcreate3_f16 (f16, f16); /* { dg-error {too few arguments to function 'svcreate3_f16'} } */
+  *ptr = svcreate3_f16 (f16, f16, f16, f16); /* { dg-error {too many arguments to function 'svcreate3_f16'} } */
+  *ptr = svcreate3_f16 (f16x3, f16x3, f16x3); /* { dg-error {incompatible type for argument 1 of 'svcreate3_f16'} } */
+  /* { dg-error {incompatible type for argument 2 of 'svcreate3_f16'} "" { target *-*-* } .-1 } */
+  /* { dg-error {incompatible type for argument 3 of 'svcreate3_f16'} "" { target *-*-* } .-2 } */
+  *ptr = svcreate3_f16 (f16, f16, f64); /* { dg-error {incompatible type for argument 3 of 'svcreate3_f16'} } */
+  *ptr = svcreate3_f16 (f16, pg, f16); /* { dg-error {incompatible type for argument 2 of 'svcreate3_f16'} } */
+  *ptr = svcreate3_f16 (f16, x, f16); /* { dg-error {incompatible type for argument 2 of 'svcreate3_f16'} } */
+  *ptr = svcreate3_f16 (x, f16, f16); /* { dg-error {incompatible type for argument 1 of 'svcreate3_f16'} } */
+  *ptr = svcreate3_f16 (pg, f16, f16); /* { dg-error {incompatible type for argument 1 of 'svcreate3_f16'} } */
+  *ptr = svcreate3_f16 (pg, pg, pg); /* { dg-error {incompatible type for argument 1 of 'svcreate3_f16'} } */
+  /* { dg-error {incompatible type for argument 2 of 'svcreate3_f16'} "" { target *-*-* } .-1 } */
+  /* { dg-error {incompatible type for argument 3 of 'svcreate3_f16'} "" { target *-*-* } .-2 } */
+  *ptr = svcreate3_f16 (f16, f16, f16);
+  *ptr = svcreate3_f64 (f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svfloat16x3_t' from type 'svfloat64x3_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_5.c
new file mode 100644 (file)
index 0000000..fed1245
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+    svint32x4_t s32x4, int x)
+{
+  *ptr = svcreate4 (s32); /* { dg-error {too few arguments to function 'svcreate4'} } */
+  *ptr = svcreate4 (s32, s32); /* { dg-error {too few arguments to function 'svcreate4'} } */
+  *ptr = svcreate4 (s32, s32, s32); /* { dg-error {too few arguments to function 'svcreate4'} } */
+  *ptr = svcreate4 (s32, s32, s32, s32, s32); /* { dg-error {too many arguments to function 'svcreate4'} } */
+  *ptr = svcreate4 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {passing 'svint32x4_t' to argument 1 of 'svcreate4', which expects a single SVE vector rather than a tuple} } */
+  *ptr = svcreate4 (s32, s32, s32, f64); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcreate4', but previous arguments had type 'svint32_t'} } */
+  *ptr = svcreate4 (s32, s32, pg, s32); /* { dg-error {passing 'svbool_t' to argument 3 of 'svcreate4', but previous arguments had type 'svint32_t'} } */
+  *ptr = svcreate4 (s32, x, s32, s32); /* { dg-error {passing 'int' to argument 2 of 'svcreate4', which expects an SVE vector type} } */
+  *ptr = svcreate4 (x, s32, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svcreate4', which expects an SVE vector type} } */
+  *ptr = svcreate4 (pg, s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svcreate4', but previous arguments had type 'svbool_t'} } */
+  *ptr = svcreate4 (pg, pg, pg, pg); /* { dg-error {'svcreate4' has no form that takes 'svbool_t' arguments} } */
+  *ptr = svcreate4 (s32, s32, s32, s32);
+  *ptr = svcreate4 (f64, f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svint32x4_t' from type 'svfloat64x4_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/create_6.c
new file mode 100644 (file)
index 0000000..b9e298a
--- /dev/null
@@ -0,0 +1,29 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svint32x4_t *ptr, svbool_t pg, svint32_t s32, svfloat64_t f64,
+    svint32x4_t s32x4, int x)
+{
+  *ptr = svcreate4_s32 (s32); /* { dg-error {too few arguments to function 'svcreate4_s32'} } */
+  *ptr = svcreate4_s32 (s32, s32); /* { dg-error {too few arguments to function 'svcreate4_s32'} } */
+  *ptr = svcreate4_s32 (s32, s32, s32); /* { dg-error {too few arguments to function 'svcreate4_s32'} } */
+  *ptr = svcreate4_s32 (s32, s32, s32, s32, s32); /* { dg-error {too many arguments to function 'svcreate4_s32'} } */
+  *ptr = svcreate4_s32 (s32x4, s32x4, s32x4, s32x4); /* { dg-error {incompatible type for argument 1 of 'svcreate4_s32'} } */
+  /* { dg-error {incompatible type for argument 2 of 'svcreate4_s32'} "" { target *-*-* } .-1 } */
+  /* { dg-error {incompatible type for argument 3 of 'svcreate4_s32'} "" { target *-*-* } .-2 } */
+  /* { dg-error {incompatible type for argument 4 of 'svcreate4_s32'} "" { target *-*-* } .-3 } */
+  *ptr = svcreate4_s32 (s32, s32, s32, f64); /* { dg-error {incompatible type for argument 4 of 'svcreate4_s32'} } */
+  *ptr = svcreate4_s32 (s32, s32, pg, s32); /* { dg-error {incompatible type for argument 3 of 'svcreate4_s32'} } */
+  *ptr = svcreate4_s32 (s32, x, s32, s32); /* { dg-error {incompatible type for argument 2 of 'svcreate4_s32'} } */
+  *ptr = svcreate4_s32 (x, s32, s32, s32); /* { dg-error {incompatible type for argument 1 of 'svcreate4_s32'} } */
+  *ptr = svcreate4_s32 (pg, s32, s32, s32); /* { dg-error {incompatible type for argument 1 of 'svcreate4_s32'} } */
+  *ptr = svcreate4_s32 (pg, pg, pg, pg); /* { dg-error {incompatible type for argument 1 of 'svcreate4_s32'} } */
+  /* { dg-error {incompatible type for argument 2 of 'svcreate4_s32'} "" { target *-*-* } .-1 } */
+  /* { dg-error {incompatible type for argument 3 of 'svcreate4_s32'} "" { target *-*-* } .-2 } */
+  /* { dg-error {incompatible type for argument 4 of 'svcreate4_s32'} "" { target *-*-* } .-3 } */
+  *ptr = svcreate4_s32 (s32, s32, s32, s32);
+  *ptr = svcreate4_f64 (f64, f64, f64, f64); /* { dg-error {incompatible types when assigning to type 'svint32x4_t' from type 'svfloat64x4_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ext_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ext_1.c
new file mode 100644 (file)
index 0000000..bdce392
--- /dev/null
@@ -0,0 +1,67 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+    svfloat16_t f16, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, int i)
+{
+  svext (pg, pg, 0); /* { dg-error {'svext' has no form that takes 'svbool_t' arguments} } */
+  svext (s8, s8, i); /* { dg-error {argument 3 of 'svext' must be an integer constant expression} } */
+
+  svext (s8, s8, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 255\]} } */
+  svext (s8, s8, 0);
+  svext (s8, s8, 255);
+  svext (s8, s8, 256); /* { dg-error {passing 256 to argument 3 of 'svext', which expects a value in the range \[0, 255\]} } */
+
+  svext (u8, u8, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 255\]} } */
+  svext (u8, u8, 0);
+  svext (u8, u8, 255);
+  svext (u8, u8, 256); /* { dg-error {passing 256 to argument 3 of 'svext', which expects a value in the range \[0, 255\]} } */
+
+  svext (s16, s16, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+  svext (s16, s16, 0);
+  svext (s16, s16, 127);
+  svext (s16, s16, 128); /* { dg-error {passing 128 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+
+  svext (u16, u16, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+  svext (u16, u16, 0);
+  svext (u16, u16, 127);
+  svext (u16, u16, 128); /* { dg-error {passing 128 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+
+  svext (f16, f16, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+  svext (f16, f16, 0);
+  svext (f16, f16, 127);
+  svext (f16, f16, 128); /* { dg-error {passing 128 to argument 3 of 'svext', which expects a value in the range \[0, 127\]} } */
+
+  svext (s32, s32, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+  svext (s32, s32, 0);
+  svext (s32, s32, 63);
+  svext (s32, s32, 64); /* { dg-error {passing 64 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+
+  svext (u32, u32, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+  svext (u32, u32, 0);
+  svext (u32, u32, 63);
+  svext (u32, u32, 64); /* { dg-error {passing 64 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+
+  svext (f32, f32, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+  svext (f32, f32, 0);
+  svext (f32, f32, 63);
+  svext (f32, f32, 64); /* { dg-error {passing 64 to argument 3 of 'svext', which expects a value in the range \[0, 63\]} } */
+
+  svext (s64, s64, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+  svext (s64, s64, 0);
+  svext (s64, s64, 31);
+  svext (s64, s64, 32); /* { dg-error {passing 32 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+
+  svext (u64, u64, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+  svext (u64, u64, 0);
+  svext (u64, u64, 31);
+  svext (u64, u64, 32); /* { dg-error {passing 32 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+
+  svext (f64, f64, -1); /* { dg-error {passing -1 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+  svext (f64, f64, 0);
+  svext (f64, f64, 31);
+  svext (f64, f64, 32); /* { dg-error {passing 32 to argument 3 of 'svext', which expects a value in the range \[0, 31\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/fold_left_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/fold_left_1.c
new file mode 100644 (file)
index 0000000..1d29278
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svuint8_t
+f1 (svbool_t pg, int i, float f, double d, void *ptr, svfloat32_t f32,
+    svint32_t i32)
+{
+  svadda (pg, f); /* { dg-error {too few arguments to function 'svadda'} } */
+  svadda (pg, f, f32, f32); /* { dg-error {too many arguments to function 'svadda'} } */
+  svadda (f32, f, f32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svadda', which expects 'svbool_t'} } */
+  svadda (pg, i, f32);
+  svadda (pg, f, f32);
+  svadda (pg, d, f32);
+  svadda (pg, ptr, f32); /* { dg-error {incompatible type for argument 2 of 'svadda_f32'} } */
+  svadda (pg, pg, f32); /* { dg-error {passing 'svbool_t' to argument 2 of 'svadda', which expects a scalar element} } */
+  svadda (pg, f32, f32); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svadda', which expects a scalar element} } */
+  svadda (pg, f, f); /* { dg-error {passing 'float' to argument 3 of 'svadda', which expects an SVE vector type} } */
+  svadda (pg, i, i32); /* { dg-error {'svadda' has no form that takes 'svint32_t' arguments} } */
+  svadda (pg, i, i); /* { dg-error {passing 'int' to argument 3 of 'svadda', which expects an SVE vector type} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_1.c
new file mode 100644 (file)
index 0000000..e1b99fa
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svadd_n_u8_x; /* { dg-message "note: previous declaration of 'svadd_n_u8_x' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'svadd_n_u8_x' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_2.c
new file mode 100644 (file)
index 0000000..7f653f1
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svadd_n_u8_x = 1; /* { dg-message "note: previous definition of 'svadd_n_u8_x' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'svadd_n_u8_x' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_3.c
new file mode 100644 (file)
index 0000000..d9ff15a
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+extern __SVInt8_t svadd_u8_x (__SVBool_t, __SVInt8_t, __SVInt8_t); /* { dg-message "note: previous declaration of 'svadd_u8_x' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {conflicting types for 'svadd_u8_x'} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_4.c
new file mode 100644 (file)
index 0000000..9591e3d
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+/* Although somewhat suspect, this isn't actively wrong, and doesn't need
+   to be diagnosed.  Any attempt to call the function before including
+   arm_sve.h will lead to a link failure.  (Same for taking its address,
+   etc.)  */
+extern __SVUint8_t svadd_u8_x (__SVBool_t, __SVUint8_t, __SVUint8_t);
+
+#pragma GCC aarch64 "arm_sve.h"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_5.c
new file mode 100644 (file)
index 0000000..8592361
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+/* There's no requirement to diagnose this.  In particular, arm_sve.h
+   is allowed to use macros to implement the functions, and defining
+   a macro that matches an existing symbol would not be diagnosed.
+
+   At the moment this works like other built-ins in the sense that the
+   explicit definition "wins".  This isn't supported behavior though.  */
+__SVUint8_t
+svadd_u8_x (__SVBool_t pg, __SVUint8_t x, __SVUint8_t y)
+{
+  return x;
+}
+
+#pragma GCC aarch64 "arm_sve.h"
+
+svuint8_t
+f (svbool_t pg, svuint8_t x, svuint8_t y)
+{
+  return svadd_u8_x (pg, x, y);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/func_redef_6.c
new file mode 100644 (file)
index 0000000..1f04e46
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+typedef int svadd_u8_x; /* { dg-message "note: previous declaration of 'svadd_u8_x' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'svadd_u8_x' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_1.c
new file mode 100644 (file)
index 0000000..a3ac08f
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svuint8x3_t u8x3, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  u8 = svget2 (u8x2); /* { dg-error {too few arguments to function 'svget2'} } */
+  u8 = svget2 (u8x2, 1, 2); /* { dg-error {too many arguments to function 'svget2'} } */
+  u8 = svget2 (u8, 0); /* { dg-error {passing single vector 'svuint8_t' to argument 1 of 'svget2', which expects a tuple of 2 vectors} } */
+  u8 = svget2 (u8x3, 0); /* { dg-error {passing 'svuint8x3_t' to argument 1 of 'svget2', which expects a tuple of 2 vectors} } */
+  u8 = svget2 (pg, 0); /* { dg-error {passing 'svbool_t' to argument 1 of 'svget2', which expects a tuple of 2 vectors} } */
+  u8 = svget2 (u8x2, x); /* { dg-error {argument 2 of 'svget2' must be an integer constant expression} } */
+  u8 = svget2 (u8x2, 0);
+  f64 = svget2 (u8x2, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svuint8_t'} } */
+  u8 = svget2 (u8x2, 1);
+  u8 = svget2 (u8x2, 2); /* { dg-error {passing 2 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, 3); /* { dg-error {passing 3 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, 4); /* { dg-error {passing 4 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, 5); /* { dg-error {passing 5 to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget2', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2 (u8x2, one); /* { dg-error {argument 2 of 'svget2' must be an integer constant expression} } */
+  u8 = svget2 (u8x2, 3 - 2);
+  u8 = svget2 (u8x2, 1.0);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_2.c
new file mode 100644 (file)
index 0000000..4eee243
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svint8x2_t s8x2,
+    svuint8x3_t u8x3, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  u8 = svget2_u8 (u8x2); /* { dg-error {too few arguments to function 'svget2_u8'} } */
+  u8 = svget2_u8 (u8x2, 1, 2); /* { dg-error {too many arguments to function 'svget2_u8'} } */
+  u8 = svget2_u8 (u8, 0); /* { dg-error {incompatible type for argument 1 of 'svget2_u8'} } */
+  u8 = svget2_u8 (s8x2, 0); /* { dg-error {incompatible type for argument 1 of 'svget2_u8'} } */
+  u8 = svget2_u8 (u8x3, 0); /* { dg-error {incompatible type for argument 1 of 'svget2_u8'} } */
+  u8 = svget2_u8 (pg, 0); /* { dg-error {incompatible type for argument 1 of 'svget2_u8'} } */
+  u8 = svget2_u8 (u8x2, x); /* { dg-error {argument 2 of 'svget2_u8' must be an integer constant expression} } */
+  u8 = svget2_u8 (u8x2, 0);
+  f64 = svget2_u8 (u8x2, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svuint8_t'} } */
+  u8 = svget2_u8 (u8x2, 1);
+  u8 = svget2_u8 (u8x2, 2); /* { dg-error {passing 2 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, 3); /* { dg-error {passing 3 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, 4); /* { dg-error {passing 4 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, 5); /* { dg-error {passing 5 to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget2_u8', which expects a value in the range \[0, 1\]} } */
+  u8 = svget2_u8 (u8x2, one); /* { dg-error {argument 2 of 'svget2_u8' must be an integer constant expression} } */
+  u8 = svget2_u8 (u8x2, 3 - 2);
+  u8 = svget2_u8 (u8x2, 1.0);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_3.c
new file mode 100644 (file)
index 0000000..0e7b2e2
--- /dev/null
@@ -0,0 +1,32 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat16x4_t f16x4,
+    int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  f16 = svget3 (f16x3); /* { dg-error {too few arguments to function 'svget3'} } */
+  f16 = svget3 (f16x3, 1, 2); /* { dg-error {too many arguments to function 'svget3'} } */
+  f16 = svget3 (f16, 0); /* { dg-error {passing single vector 'svfloat16_t' to argument 1 of 'svget3', which expects a tuple of 3 vectors} } */
+  f16 = svget3 (f16x4, 0); /* { dg-error {passing 'svfloat16x4_t' to argument 1 of 'svget3', which expects a tuple of 3 vectors} } */
+  f16 = svget3 (pg, 0); /* { dg-error {passing 'svbool_t' to argument 1 of 'svget3', which expects a tuple of 3 vectors} } */
+  f16 = svget3 (f16x3, x); /* { dg-error {argument 2 of 'svget3' must be an integer constant expression} } */
+  f16 = svget3 (f16x3, 0);
+  f64 = svget3 (f16x3, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svfloat16_t'} } */
+  f16 = svget3 (f16x3, 1);
+  f16 = svget3 (f16x3, 2);
+  f16 = svget3 (f16x3, 3); /* { dg-error {passing 3 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, 4); /* { dg-error {passing 4 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, 5); /* { dg-error {passing 5 to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget3', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3 (f16x3, one); /* { dg-error {argument 2 of 'svget3' must be an integer constant expression} } */
+  f16 = svget3 (f16x3, 3 - 2);
+  f16 = svget3 (f16x3, 1.0);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_4.c
new file mode 100644 (file)
index 0000000..72b4f82
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat32x3_t f32x3,
+    svfloat16x4_t f16x4, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  f16 = svget3_f16 (f16x3); /* { dg-error {too few arguments to function 'svget3_f16'} } */
+  f16 = svget3_f16 (f16x3, 1, 2); /* { dg-error {too many arguments to function 'svget3_f16'} } */
+  f16 = svget3_f16 (f16, 0); /* { dg-error {incompatible type for argument 1 of 'svget3_f16'} } */
+  f16 = svget3_f16 (f32x3, 0); /* { dg-error {incompatible type for argument 1 of 'svget3_f16'} } */
+  f16 = svget3_f16 (f16x4, 0); /* { dg-error {incompatible type for argument 1 of 'svget3_f16'} } */
+  f16 = svget3_f16 (pg, 0); /* { dg-error {incompatible type for argument 1 of 'svget3_f16'} } */
+  f16 = svget3_f16 (f16x3, x); /* { dg-error {argument 2 of 'svget3_f16' must be an integer constant expression} } */
+  f16 = svget3_f16 (f16x3, 0);
+  f64 = svget3_f16 (f16x3, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svfloat16_t'} } */
+  f16 = svget3_f16 (f16x3, 1);
+  f16 = svget3_f16 (f16x3, 2);
+  f16 = svget3_f16 (f16x3, 3); /* { dg-error {passing 3 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, 4); /* { dg-error {passing 4 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, 5); /* { dg-error {passing 5 to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget3_f16', which expects a value in the range \[0, 2\]} } */
+  f16 = svget3_f16 (f16x3, one); /* { dg-error {argument 2 of 'svget3_f16' must be an integer constant expression} } */
+  f16 = svget3_f16 (f16x3, 3 - 2);
+  f16 = svget3_f16 (f16x3, 1.0);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_5.c
new file mode 100644 (file)
index 0000000..b0b69b9
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svint32x2_t s32x2, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  s32 = svget4 (s32x4); /* { dg-error {too few arguments to function 'svget4'} } */
+  s32 = svget4 (s32x4, 1, 2); /* { dg-error {too many arguments to function 'svget4'} } */
+  s32 = svget4 (s32, 0); /* { dg-error {passing single vector 'svint32_t' to argument 1 of 'svget4', which expects a tuple of 4 vectors} } */
+  s32 = svget4 (s32x2, 0); /* { dg-error {passing 'svint32x2_t' to argument 1 of 'svget4', which expects a tuple of 4 vectors} } */
+  s32 = svget4 (pg, 0); /* { dg-error {passing 'svbool_t' to argument 1 of 'svget4', which expects a tuple of 4 vectors} } */
+  s32 = svget4 (s32x4, x); /* { dg-error {argument 2 of 'svget4' must be an integer constant expression} } */
+  s32 = svget4 (s32x4, 0);
+  f64 = svget4 (s32x4, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svint32_t'} } */
+  s32 = svget4 (s32x4, 1);
+  s32 = svget4 (s32x4, 2);
+  s32 = svget4 (s32x4, 3);
+  s32 = svget4 (s32x4, 4); /* { dg-error {passing 4 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4 (s32x4, 5); /* { dg-error {passing 5 to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4 (s32x4, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget4', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4 (s32x4, one); /* { dg-error {argument 2 of 'svget4' must be an integer constant expression} } */
+  s32 = svget4 (s32x4, 3 - 2);
+  s32 = svget4 (s32x4, 1.0);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/get_6.c
new file mode 100644 (file)
index 0000000..3801c0c
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svfloat32x4_t f32x4,
+    svint32x2_t s32x2, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  s32 = svget4_s32 (s32x4); /* { dg-error {too few arguments to function 'svget4_s32'} } */
+  s32 = svget4_s32 (s32x4, 1, 2); /* { dg-error {too many arguments to function 'svget4_s32'} } */
+  s32 = svget4_s32 (s32, 0); /* { dg-error {incompatible type for argument 1 of 'svget4_s32'} } */
+  s32 = svget4_s32 (f32x4, 0); /* { dg-error {incompatible type for argument 1 of 'svget4_s32'} } */
+  s32 = svget4_s32 (s32x2, 0); /* { dg-error {incompatible type for argument 1 of 'svget4_s32'} } */
+  s32 = svget4_s32 (pg, 0); /* { dg-error {incompatible type for argument 1 of 'svget4_s32'} } */
+  s32 = svget4_s32 (s32x4, x); /* { dg-error {argument 2 of 'svget4_s32' must be an integer constant expression} } */
+  s32 = svget4_s32 (s32x4, 0);
+  f64 = svget4_s32 (s32x4, 0); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svint32_t'} } */
+  s32 = svget4_s32 (s32x4, 1);
+  s32 = svget4_s32 (s32x4, 2);
+  s32 = svget4_s32 (s32x4, 3);
+  s32 = svget4_s32 (s32x4, 4); /* { dg-error {passing 4 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4_s32 (s32x4, 5); /* { dg-error {passing 5 to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4_s32 (s32x4, ~0U); /* { dg-error {passing [^ ]* to argument 2 of 'svget4_s32', which expects a value in the range \[0, 3\]} } */
+  s32 = svget4_s32 (s32x4, one); /* { dg-error {argument 2 of 'svget4_s32' must be an integer constant expression} } */
+  s32 = svget4_s32 (s32x4, 3 - 2);
+  s32 = svget4_s32 (s32x4, 1.0);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_1.c
new file mode 100644 (file)
index 0000000..dcd291d
--- /dev/null
@@ -0,0 +1,37 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+      int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+      float f, int i)
+{
+  svqincb (sw); /* { dg-error {too few arguments to function 'svqincb'} } */
+  svqincb (sw, 1, 1); /* { dg-error {too many arguments to function 'svqincb'} } */
+
+  svqincb (pg, 1); /* { dg-error {'svqincb' has no form that takes 'svbool_t' arguments} } */
+  svqincb (s8, 1); /* { dg-error {'svqincb' has no form that takes 'svint8_t' arguments} } */
+  svqincb (u8, 1); /* { dg-error {'svqincb' has no form that takes 'svuint8_t' arguments} } */
+  svqincb (s16, 1); /* { dg-error {'svqincb' has no form that takes 'svint16_t' arguments} } */
+  svqincb (u16, 1); /* { dg-error {'svqincb' has no form that takes 'svuint16_t' arguments} } */
+  svqincb (s32, 1); /* { dg-error {'svqincb' has no form that takes 'svint32_t' arguments} } */
+  svqincb (u32, 1); /* { dg-error {'svqincb' has no form that takes 'svuint32_t' arguments} } */
+  svqincb (s64, 1); /* { dg-error {'svqincb' has no form that takes 'svint64_t' arguments} } */
+  svqincb (u64, 1); /* { dg-error {'svqincb' has no form that takes 'svuint64_t' arguments} } */
+  svqincb (sh, 1);
+  svqincb (sw, 1);
+  svqincb (sd, 1);
+  svqincb (uh, 1);
+  svqincb (uw, 1);
+  svqincb (ud, 1);
+  svqincb (f, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincb', which expects a 32-bit or 64-bit integer type} } */
+  svqincb (ud, i); /* { dg-error {argument 2 of 'svqincb' must be an integer constant expression} } */
+
+  svqincb (sw, -1); /* { dg-error {passing -1 to argument 2 of 'svqincb', which expects a value in the range \[1, 16\]} } */
+  svqincb (sw, 0); /* { dg-error {passing 0 to argument 2 of 'svqincb', which expects a value in the range \[1, 16\]} } */
+  svqincb (sw, 1);
+  svqincb (sw, 2);
+  svqincb (sw, 16);
+  svqincb (sw, 17); /* { dg-error {passing 17 to argument 2 of 'svqincb', which expects a value in the range \[1, 16\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_2.c
new file mode 100644 (file)
index 0000000..e5acad1
--- /dev/null
@@ -0,0 +1,13 @@
+#include <arm_sve.h>
+
+void
+test (int32_t sw, int i)
+{
+  svqincb_n_s32 (sw, -1); /* { dg-error {passing -1 to argument 2 of 'svqincb_n_s32', which expects a value in the range \[1, 16\]} } */
+  svqincb_n_s32 (sw, 0); /* { dg-error {passing 0 to argument 2 of 'svqincb_n_s32', which expects a value in the range \[1, 16\]} } */
+  svqincb_n_s32 (sw, 1);
+  svqincb_n_s32 (sw, 2);
+  svqincb_n_s32 (sw, 16);
+  svqincb_n_s32 (sw, 17); /* { dg-error {passing 17 to argument 2 of 'svqincb_n_s32', which expects a value in the range \[1, 16\]} } */
+  svqincb_n_s32 (sw, i); /* { dg-error {argument 2 of 'svqincb_n_s32' must be an integer constant expression} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_3.c
new file mode 100644 (file)
index 0000000..351e775
--- /dev/null
@@ -0,0 +1,26 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+      int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+      float f)
+{
+  svqinch (pg, 1); /* { dg-error {'svqinch' has no form that takes 'svbool_t' arguments} } */
+  svqinch (s8, 1); /* { dg-error {'svqinch' has no form that takes 'svint8_t' arguments} } */
+  svqinch (u8, 1); /* { dg-error {'svqinch' has no form that takes 'svuint8_t' arguments} } */
+  svqinch (s16, 1);
+  svqinch (u16, 1);
+  svqinch (s32, 1); /* { dg-error {'svqinch' has no form that takes 'svint32_t' arguments} } */
+  svqinch (u32, 1); /* { dg-error {'svqinch' has no form that takes 'svuint32_t' arguments} } */
+  svqinch (s64, 1); /* { dg-error {'svqinch' has no form that takes 'svint64_t' arguments} } */
+  svqinch (u64, 1); /* { dg-error {'svqinch' has no form that takes 'svuint64_t' arguments} } */
+  svqinch (sh, 1);
+  svqinch (sw, 1);
+  svqinch (sd, 1);
+  svqinch (uh, 1);
+  svqinch (uw, 1);
+  svqinch (ud, 1);
+  svqinch (f, 1); /* { dg-error {passing 'float' to argument 1 of 'svqinch', which expects a 32-bit or 64-bit integer type} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_4.c
new file mode 100644 (file)
index 0000000..e071c02
--- /dev/null
@@ -0,0 +1,26 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+      int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+      float f)
+{
+  svqincw (pg, 1); /* { dg-error {'svqincw' has no form that takes 'svbool_t' arguments} } */
+  svqincw (s8, 1); /* { dg-error {'svqincw' has no form that takes 'svint8_t' arguments} } */
+  svqincw (u8, 1); /* { dg-error {'svqincw' has no form that takes 'svuint8_t' arguments} } */
+  svqincw (s16, 1); /* { dg-error {'svqincw' has no form that takes 'svint16_t' arguments} } */
+  svqincw (u16, 1); /* { dg-error {'svqincw' has no form that takes 'svuint16_t' arguments} } */
+  svqincw (s32, 1);
+  svqincw (u32, 1);
+  svqincw (s64, 1); /* { dg-error {'svqincw' has no form that takes 'svint64_t' arguments} } */
+  svqincw (u64, 1); /* { dg-error {'svqincw' has no form that takes 'svuint64_t' arguments} } */
+  svqincw (sh, 1);
+  svqincw (sw, 1);
+  svqincw (sd, 1);
+  svqincw (uh, 1);
+  svqincw (uw, 1);
+  svqincw (ud, 1);
+  svqincw (f, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincw', which expects a 32-bit or 64-bit integer type} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_5.c
new file mode 100644 (file)
index 0000000..be9c769
--- /dev/null
@@ -0,0 +1,26 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+      int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+      float f)
+{
+  svqincd (pg, 1); /* { dg-error {'svqincd' has no form that takes 'svbool_t' arguments} } */
+  svqincd (s8, 1); /* { dg-error {'svqincd' has no form that takes 'svint8_t' arguments} } */
+  svqincd (u8, 1); /* { dg-error {'svqincd' has no form that takes 'svuint8_t' arguments} } */
+  svqincd (s16, 1); /* { dg-error {'svqincd' has no form that takes 'svint16_t' arguments} } */
+  svqincd (u16, 1); /* { dg-error {'svqincd' has no form that takes 'svuint16_t' arguments} } */
+  svqincd (s32, 1); /* { dg-error {'svqincd' has no form that takes 'svint32_t' arguments} } */
+  svqincd (u32, 1); /* { dg-error {'svqincd' has no form that takes 'svuint32_t' arguments} } */
+  svqincd (s64, 1);
+  svqincd (u64, 1);
+  svqincd (sh, 1);
+  svqincd (sw, 1);
+  svqincd (sd, 1);
+  svqincd (uh, 1);
+  svqincd (uw, 1);
+  svqincd (ud, 1);
+  svqincd (f, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincd', which expects a 32-bit or 64-bit integer type} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_1.c
new file mode 100644 (file)
index 0000000..f2e5841
--- /dev/null
@@ -0,0 +1,47 @@
+#include <arm_sve.h>
+
+void
+test (enum svpattern pat, svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+      int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+      float f, int i)
+{
+  svqincb_pat (sw, pat); /* { dg-error {too few arguments to function 'svqincb_pat'} } */
+  svqincb_pat (sw, pat, 1, 1); /* { dg-error {too many arguments to function 'svqincb_pat'} } */
+
+  svqincb_pat (pg, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svbool_t' arguments} } */
+  svqincb_pat (s8, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svint8_t' arguments} } */
+  svqincb_pat (u8, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svuint8_t' arguments} } */
+  svqincb_pat (s16, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svint16_t' arguments} } */
+  svqincb_pat (u16, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svuint16_t' arguments} } */
+  svqincb_pat (s32, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svint32_t' arguments} } */
+  svqincb_pat (u32, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svuint32_t' arguments} } */
+  svqincb_pat (s64, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svint64_t' arguments} } */
+  svqincb_pat (u64, SV_ALL, 1); /* { dg-error {'svqincb_pat' has no form that takes 'svuint64_t' arguments} } */
+  svqincb_pat (sh, SV_ALL, 1);
+  svqincb_pat (sw, SV_ALL, 1);
+  svqincb_pat (sd, SV_ALL, 1);
+  svqincb_pat (uh, SV_ALL, 1);
+  svqincb_pat (uw, SV_ALL, 1);
+  svqincb_pat (ud, SV_ALL, 1);
+  svqincb_pat (f, SV_ALL, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincb_pat', which expects a 32-bit or 64-bit integer type} } */
+
+  svqincb_pat (sw, pat, 1); /* { dg-error {argument 2 of 'svqincb_pat' must be an integer constant expression} } */
+  svqincb_pat (sw, i, 1); /* { dg-error {argument 2 of 'svqincb_pat' must be an integer constant expression} } */
+  svqincb_pat (sw, (enum svpattern) -1, 1); /* { dg-error {passing 4294967295 to argument 2 of 'svqincb_pat', which expects a valid 'enum svpattern' value} } */
+  svqincb_pat (sw, (enum svpattern) 0, 1);
+  svqincb_pat (sw, (enum svpattern) 13, 1);
+  svqincb_pat (sw, (enum svpattern) 14, 1); /* { dg-error {passing 14 to argument 2 of 'svqincb_pat', which expects a valid 'enum svpattern' value} } */
+  svqincb_pat (sw, (enum svpattern) 28, 1); /* { dg-error {passing 28 to argument 2 of 'svqincb_pat', which expects a valid 'enum svpattern' value} } */
+  svqincb_pat (sw, (enum svpattern) 29, 1);
+  svqincb_pat (sw, (enum svpattern) 31, 1);
+  svqincb_pat (sw, (enum svpattern) 32, 1); /* { dg-error {passing 32 to argument 2 of 'svqincb_pat', which expects a valid 'enum svpattern' value} } */
+
+  svqincb_pat (sw, SV_POW2, -1); /* { dg-error {passing -1 to argument 3 of 'svqincb_pat', which expects a value in the range \[1, 16\]} } */
+  svqincb_pat (sw, SV_POW2, 0); /* { dg-error {passing 0 to argument 3 of 'svqincb_pat', which expects a value in the range \[1, 16\]} } */
+  svqincb_pat (sw, SV_POW2, 1);
+  svqincb_pat (sw, SV_POW2, 2);
+  svqincb_pat (sw, SV_POW2, 16);
+  svqincb_pat (sw, SV_POW2, 17); /* { dg-error {passing 17 to argument 3 of 'svqincb_pat', which expects a value in the range \[1, 16\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_2.c
new file mode 100644 (file)
index 0000000..c1c1ab9
--- /dev/null
@@ -0,0 +1,23 @@
+#include <arm_sve.h>
+
+void
+test (int32_t sw, enum svpattern pat, int i)
+{
+  svqincb_pat_n_s32 (sw, pat, 1); /* { dg-error {argument 2 of 'svqincb_pat_n_s32' must be an integer constant expression} } */
+  svqincb_pat_n_s32 (sw, i, 1); /* { dg-error {argument 2 of 'svqincb_pat_n_s32' must be an integer constant expression} } */
+  svqincb_pat_n_s32 (sw, (enum svpattern) -1, 1); /* { dg-error {passing 4294967295 to argument 2 of 'svqincb_pat_n_s32', which expects a valid 'enum svpattern' value} } */
+  svqincb_pat_n_s32 (sw, (enum svpattern) 0, 1);
+  svqincb_pat_n_s32 (sw, (enum svpattern) 13, 1);
+  svqincb_pat_n_s32 (sw, (enum svpattern) 14, 1); /* { dg-error {passing 14 to argument 2 of 'svqincb_pat_n_s32', which expects a valid 'enum svpattern' value} } */
+  svqincb_pat_n_s32 (sw, (enum svpattern) 28, 1); /* { dg-error {passing 28 to argument 2 of 'svqincb_pat_n_s32', which expects a valid 'enum svpattern' value} } */
+  svqincb_pat_n_s32 (sw, (enum svpattern) 29, 1);
+  svqincb_pat_n_s32 (sw, (enum svpattern) 31, 1);
+  svqincb_pat_n_s32 (sw, (enum svpattern) 32, 1); /* { dg-error {passing 32 to argument 2 of 'svqincb_pat_n_s32', which expects a valid 'enum svpattern' value} } */
+
+  svqincb_pat_n_s32 (sw, SV_POW2, -1); /* { dg-error {passing -1 to argument 3 of 'svqincb_pat_n_s32', which expects a value in the range \[1, 16\]} } */
+  svqincb_pat_n_s32 (sw, SV_POW2, 0); /* { dg-error {passing 0 to argument 3 of 'svqincb_pat_n_s32', which expects a value in the range \[1, 16\]} } */
+  svqincb_pat_n_s32 (sw, SV_POW2, 1);
+  svqincb_pat_n_s32 (sw, SV_POW2, 2);
+  svqincb_pat_n_s32 (sw, SV_POW2, 16);
+  svqincb_pat_n_s32 (sw, SV_POW2, 17); /* { dg-error {passing 17 to argument 3 of 'svqincb_pat_n_s32', which expects a value in the range \[1, 16\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_3.c
new file mode 100644 (file)
index 0000000..4126b24
--- /dev/null
@@ -0,0 +1,26 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+      int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+      float f)
+{
+  svqinch_pat (pg, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svbool_t' arguments} } */
+  svqinch_pat (s8, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svint8_t' arguments} } */
+  svqinch_pat (u8, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svuint8_t' arguments} } */
+  svqinch_pat (s16, SV_ALL, 1);
+  svqinch_pat (u16, SV_ALL, 1);
+  svqinch_pat (s32, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svint32_t' arguments} } */
+  svqinch_pat (u32, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svuint32_t' arguments} } */
+  svqinch_pat (s64, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svint64_t' arguments} } */
+  svqinch_pat (u64, SV_ALL, 1); /* { dg-error {'svqinch_pat' has no form that takes 'svuint64_t' arguments} } */
+  svqinch_pat (sh, SV_ALL, 1);
+  svqinch_pat (sw, SV_ALL, 1);
+  svqinch_pat (sd, SV_ALL, 1);
+  svqinch_pat (uh, SV_ALL, 1);
+  svqinch_pat (uw, SV_ALL, 1);
+  svqinch_pat (ud, SV_ALL, 1);
+  svqinch_pat (f, SV_ALL, 1); /* { dg-error {passing 'float' to argument 1 of 'svqinch_pat', which expects a 32-bit or 64-bit integer type} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_4.c
new file mode 100644 (file)
index 0000000..9aabbd7
--- /dev/null
@@ -0,0 +1,26 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+      int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+      float f)
+{
+  svqincw_pat (pg, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svbool_t' arguments} } */
+  svqincw_pat (s8, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svint8_t' arguments} } */
+  svqincw_pat (u8, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svuint8_t' arguments} } */
+  svqincw_pat (s16, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svint16_t' arguments} } */
+  svqincw_pat (u16, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svuint16_t' arguments} } */
+  svqincw_pat (s32, SV_ALL, 1);
+  svqincw_pat (u32, SV_ALL, 1);
+  svqincw_pat (s64, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svint64_t' arguments} } */
+  svqincw_pat (u64, SV_ALL, 1); /* { dg-error {'svqincw_pat' has no form that takes 'svuint64_t' arguments} } */
+  svqincw_pat (sh, SV_ALL, 1);
+  svqincw_pat (sw, SV_ALL, 1);
+  svqincw_pat (sd, SV_ALL, 1);
+  svqincw_pat (uh, SV_ALL, 1);
+  svqincw_pat (uw, SV_ALL, 1);
+  svqincw_pat (ud, SV_ALL, 1);
+  svqincw_pat (f, SV_ALL, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincw_pat', which expects a 32-bit or 64-bit integer type} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pat_5.c
new file mode 100644 (file)
index 0000000..5df88c6
--- /dev/null
@@ -0,0 +1,26 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, int16_t sh, uint16_t uh,
+      int32_t sw, uint32_t uw, int64_t sd, uint64_t ud,
+      float f)
+{
+  svqincd_pat (pg, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svbool_t' arguments} } */
+  svqincd_pat (s8, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svint8_t' arguments} } */
+  svqincd_pat (u8, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svuint8_t' arguments} } */
+  svqincd_pat (s16, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svint16_t' arguments} } */
+  svqincd_pat (u16, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svuint16_t' arguments} } */
+  svqincd_pat (s32, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svint32_t' arguments} } */
+  svqincd_pat (u32, SV_ALL, 1); /* { dg-error {'svqincd_pat' has no form that takes 'svuint32_t' arguments} } */
+  svqincd_pat (s64, SV_ALL, 1);
+  svqincd_pat (u64, SV_ALL, 1);
+  svqincd_pat (sh, SV_ALL, 1);
+  svqincd_pat (sw, SV_ALL, 1);
+  svqincd_pat (sd, SV_ALL, 1);
+  svqincd_pat (uh, SV_ALL, 1);
+  svqincd_pat (uw, SV_ALL, 1);
+  svqincd_pat (ud, SV_ALL, 1);
+  svqincd_pat (f, SV_ALL, 1); /* { dg-error {passing 'float' to argument 1 of 'svqincd_pat', which expects a 32-bit or 64-bit integer type} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_1.c
new file mode 100644 (file)
index 0000000..a61afcd
--- /dev/null
@@ -0,0 +1,22 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, int i)
+{
+  svqincp (s32); /* { dg-error {too few arguments to function 'svqincp'} } */
+  svqincp (s32, pg, pg); /* { dg-error {too many arguments to function 'svqincp'} } */
+  svqincp (i, pg); /* { dg-error {passing 'int' to argument 1 of 'svqincp', which expects an SVE vector type} } */
+  svqincp (pg, pg); /* { dg-error {'svqincp' has no form that takes 'svbool_t' arguments} } */
+  svqincp (s8, pg); /* { dg-error {'svqincp' has no form that takes 'svint8_t' arguments} } */
+  svqincp (u8, pg); /* { dg-error {'svqincp' has no form that takes 'svuint8_t' arguments} } */
+  svqincp (s16, pg);
+  svqincp (u16, pg);
+  svqincp (s32, pg);
+  svqincp (u32, pg);
+  svqincp (s64, pg);
+  svqincp (u64, pg);
+  svqincp (u64, 0); /* { dg-error {passing 'int' to argument 2 of 'svqincp', which expects 'svbool_t'} } */
+  svqincp (u64, u64); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svqincp', which expects 'svbool_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_scalar_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/inc_dec_pred_scalar_1.c
new file mode 100644 (file)
index 0000000..94ebe7e
--- /dev/null
@@ -0,0 +1,19 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint32_t s32, svuint64_t u64, int16_t sh, uint16_t uh,
+      int32_t sw, uint32_t uw, int64_t sd, uint64_t ud)
+{
+  svqincp_b8 (s32); /* { dg-error {too few arguments to function 'svqincp_b8'} } */
+  svqincp_b8 (s32, pg, pg); /* { dg-error {too many arguments to function 'svqincp_b8'} } */
+  svqincp_b8 (pg, pg); /* { dg-error {passing 'svbool_t' to argument 1 of 'svqincp_b8', which expects a 32-bit or 64-bit integer type} } */
+  svqincp_b8 (s32, pg); /* { dg-error {passing 'svint32_t' to argument 1 of 'svqincp_b8', which expects a 32-bit or 64-bit integer type} } */
+  svqincp_b8 (sh, pg);
+  svqincp_b8 (uh, pg);
+  svqincp_b8 (sw, pg);
+  svqincp_b8 (uw, pg);
+  svqincp_b8 (sd, pg);
+  svqincp_b8 (ud, pg);
+  svqincp_b8 (ud, 0); /* { dg-error {passing 'int' to argument 2 of 'svqincp_b8', which expects 'svbool_t'} } */
+  svqincp_b8 (ud, u64); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svqincp_b8', which expects 'svbool_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ld1sh_gather_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ld1sh_gather_1.c
new file mode 100644 (file)
index 0000000..91f37f6
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -Wpointer-sign" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, short *s16_ptr, unsigned short *u16_ptr,
+    svint8_t s8, svint16_t s16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+  svld1sh_gather_index (pg, s16_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1sh_gather_index'; did you mean 'svld1_gather_index'} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr); /* { dg-error {too few arguments to function 'svld1sh_gather_index_u32'} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1sh_gather_index_u32'} } */
+  svld1sh_gather_index_u32 (pg, u16_ptr, s32); /* { dg-warning {pointer targets in passing argument 2 of 'svld1sh_gather_s32index_u32' differ in signedness} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s32);
+  svld1sh_gather_index_u32 (pg, s16_ptr, u32);
+  svld1sh_gather_index_u32 (pg, s16_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+
+  svld1sh_gather_index_u32 (pg, 0, s32);
+  svld1sh_gather_index_u32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1sh_gather_index_u32', which expects a vector or pointer base address} } */
+
+  svld1sh_gather_index_u32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+  svld1sh_gather_index_u32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+  svld1sh_gather_index_u32 (pg, u32, 0);
+  svld1sh_gather_index_u32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_1.c
new file mode 100644 (file)
index 0000000..34f989b
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+    float *f32_ptr, _Complex float *cf32_ptr, int **ptr_ptr)
+{
+  svld1 (pg); /* { dg-error {too few arguments to function 'svld1'} } */
+  svld1 (pg, s8_ptr, 0); /* { dg-error {too many arguments to function 'svld1'} } */
+  svld1 (0, s8_ptr); /* { dg-error {passing 'int' to argument 1 of 'svld1', which expects 'svbool_t'} } */
+  svld1 (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svld1', which expects a pointer type} } */
+  svld1 (pg, (int *) 0);
+  svld1 (pg, void_ptr); /* { dg-error {passing 'void \*' to argument 2 of 'svld1', but 'void' is not a valid SVE element type} } */
+  svld1 (pg, s_ptr); /* { dg-error {passing 'struct s \*' to argument 2 of 'svld1', but 'struct s' is not a valid SVE element type} } */
+  svld1 (pg, f32_ptr);
+  svld1 (pg, cf32_ptr); /* { dg-error {passing '_Complex float \*' to argument 2 of 'svld1', but 'complex float' is not a valid SVE element type} } */
+  svld1 (pg, ptr_ptr); /* { dg-error {passing 'int \*\*' to argument 2 of 'svld1', but 'int \*' is not a valid SVE element type} } */
+  return svld1 (pg, s8_ptr); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_2.c
new file mode 100644 (file)
index 0000000..beb07f1
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+    float *f32_ptr, _Complex float *cf32_ptr)
+{
+  svld1_s8 (pg); /* { dg-error {too few arguments to function 'svld1_s8'} } */
+  svld1_s8 (pg, s8_ptr, 0); /* { dg-error {too many arguments to function 'svld1_s8'} } */
+  svld1_s8 (0, 0); /* { dg-error {incompatible type for argument 1 of 'svld1_s8'} } */
+  svld1_s8 (pg, 0);
+  svld1_s32 (pg, (int *) 0);
+  svld1_s8 (pg, void_ptr);
+  svld1_s8 (pg, s_ptr); /* { dg-warning {passing argument 2 of 'svld1_s8' from incompatible pointer type} } */
+  svld1_f32 (pg, f32_ptr);
+  svld1_f32 (pg, cf32_ptr); /* { dg-warning {passing argument 2 of 'svld1_f32' from incompatible pointer type} } */
+  return svld1_s8 (pg, s8_ptr); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_3.c
new file mode 100644 (file)
index 0000000..770203f
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, svint8_t s8)
+{
+  svld1_vnum (pg); /* { dg-error {too few arguments to function 'svld1_vnum'} } */
+  svld1_vnum (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1_vnum'} } */
+  svld1_vnum (pg, s8_ptr, 0, 0); /* { dg-error {too many arguments to function 'svld1_vnum'} } */
+  svld1_vnum (0, s8_ptr, 0); /* { dg-error {passing 'int' to argument 1 of 'svld1_vnum', which expects 'svbool_t'} } */
+  svld1_vnum (pg, 0, 0); /* { dg-error {passing 'int' to argument 2 of 'svld1_vnum', which expects a pointer type} } */
+  svld1_vnum (pg, s8_ptr, s8_ptr); /* { dg-warning "passing argument 3 of 'svld1_vnum_s8' makes integer from pointer without a cast" } */
+  svld1_vnum (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1_vnum', which expects 'int64_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_index_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_index_1.c
new file mode 100644 (file)
index 0000000..91f37f6
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99 -Wpointer-sign" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, short *s16_ptr, unsigned short *u16_ptr,
+    svint8_t s8, svint16_t s16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+  svld1sh_gather_index (pg, s16_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1sh_gather_index'; did you mean 'svld1_gather_index'} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr); /* { dg-error {too few arguments to function 'svld1sh_gather_index_u32'} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1sh_gather_index_u32'} } */
+  svld1sh_gather_index_u32 (pg, u16_ptr, s32); /* { dg-warning {pointer targets in passing argument 2 of 'svld1sh_gather_s32index_u32' differ in signedness} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s32);
+  svld1sh_gather_index_u32 (pg, s16_ptr, u32);
+  svld1sh_gather_index_u32 (pg, s16_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+  svld1sh_gather_index_u32 (pg, s16_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sh_gather_index_u32', which expects a vector of 32-bit integers} } */
+
+  svld1sh_gather_index_u32 (pg, 0, s32);
+  svld1sh_gather_index_u32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1sh_gather_index_u32', which expects a vector or pointer base address} } */
+
+  svld1sh_gather_index_u32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+  svld1sh_gather_index_u32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+  svld1sh_gather_index_u32 (pg, u32, 0);
+  svld1sh_gather_index_u32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1sh_gather_index_u32', which expects 'svuint32_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_1.c
new file mode 100644 (file)
index 0000000..dae4d0c
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+    svint8_t s8, svint16_t s16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+  svld1sb_gather_offset (pg, s8_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1sb_gather_offset'; did you mean 'svld1_gather_offset'} } */
+  svld1sb_gather_offset_s32 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1sb_gather_offset_s32'} } */
+  svld1sb_gather_offset_s32 (pg, s8_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1sb_gather_offset_s32'} } */
+  svld1sb_gather_offset_s32 (pg, s16_ptr, s32); /* { dg-warning {passing argument 2 of 'svld1sb_gather_s32offset_s32' from incompatible pointer type} } */
+  svld1sb_gather_offset_s32 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_s32 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_s32 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_s32 (pg, s8_ptr, s32);
+  svld1sb_gather_offset_s32 (pg, s8_ptr, u32);
+  svld1sb_gather_offset_s32 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_s32 (pg, s8_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_s32 (pg, s8_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_s32 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sb_gather_offset_s32', which expects a vector of 32-bit integers} } */
+
+  svld1sb_gather_offset_s32 (pg, 0, s32);
+  svld1sb_gather_offset_s32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1sb_gather_offset_s32', which expects a vector or pointer base address} } */
+
+  svld1sb_gather_offset_s32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sb_gather_offset_s32', which expects 'svuint32_t'} } */
+  svld1sb_gather_offset_s32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sb_gather_offset_s32', which expects 'svuint32_t'} } */
+  svld1sb_gather_offset_s32 (pg, u32, 0);
+  svld1sb_gather_offset_s32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1sb_gather_offset_s32', which expects 'svuint32_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_2.c
new file mode 100644 (file)
index 0000000..1bc6697
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+    svint8_t s8, svint16_t s16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+  svld1sb_gather_offset (pg, s8_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1sb_gather_offset'; did you mean 'svld1_gather_offset'} } */
+  svld1sb_gather_offset_u32 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1sb_gather_offset_u32'} } */
+  svld1sb_gather_offset_u32 (pg, s8_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1sb_gather_offset_u32'} } */
+  svld1sb_gather_offset_u32 (pg, s16_ptr, s32); /* { dg-warning {passing argument 2 of 'svld1sb_gather_s32offset_u32' from incompatible pointer type} } */
+  svld1sb_gather_offset_u32 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_u32 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_u32 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_u32 (pg, s8_ptr, s32);
+  svld1sb_gather_offset_u32 (pg, s8_ptr, u32);
+  svld1sb_gather_offset_u32 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_u32 (pg, s8_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_u32 (pg, s8_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+  svld1sb_gather_offset_u32 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sb_gather_offset_u32', which expects a vector of 32-bit integers} } */
+
+  svld1sb_gather_offset_u32 (pg, 0, s32);
+  svld1sb_gather_offset_u32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1sb_gather_offset_u32', which expects a vector or pointer base address} } */
+
+  svld1sb_gather_offset_u32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sb_gather_offset_u32', which expects 'svuint32_t'} } */
+  svld1sb_gather_offset_u32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sb_gather_offset_u32', which expects 'svuint32_t'} } */
+  svld1sb_gather_offset_u32 (pg, u32, 0);
+  svld1sb_gather_offset_u32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1sb_gather_offset_u32', which expects 'svuint32_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_3.c
new file mode 100644 (file)
index 0000000..6522889
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+    svint8_t s8, svint16_t s16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+  svld1sb_gather_offset (pg, s8_ptr, s64); /* { dg-warning {implicit declaration of function 'svld1sb_gather_offset'; did you mean 'svld1_gather_offset'} } */
+  svld1sb_gather_offset_s64 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1sb_gather_offset_s64'} } */
+  svld1sb_gather_offset_s64 (pg, s8_ptr, s64, 0); /* { dg-error {too many arguments to function 'svld1sb_gather_offset_s64'} } */
+  svld1sb_gather_offset_s64 (pg, s16_ptr, s64); /* { dg-warning {passing argument 2 of 'svld1sb_gather_s64offset_s64' from incompatible pointer type} } */
+  svld1sb_gather_offset_s64 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_s64 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_s64 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_s64 (pg, s8_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_s64 (pg, s8_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_s64 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_s64 (pg, s8_ptr, s64);
+  svld1sb_gather_offset_s64 (pg, s8_ptr, u64);
+  svld1sb_gather_offset_s64 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sb_gather_offset_s64', which expects a vector of 64-bit integers} } */
+
+  svld1sb_gather_offset_s64 (pg, 0, s64);
+  svld1sb_gather_offset_s64 (pg, s, s64); /* { dg-error {'struct s' to argument 2 of 'svld1sb_gather_offset_s64', which expects a vector or pointer base address} } */
+
+  svld1sb_gather_offset_s64 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sb_gather_offset_s64', which expects 'svuint64_t'} } */
+  svld1sb_gather_offset_s64 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sb_gather_offset_s64', which expects 'svuint64_t'} } */
+  svld1sb_gather_offset_s64 (pg, u32, 0); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svld1sb_gather_offset_s64', which expects 'svuint64_t'} } */
+  svld1sb_gather_offset_s64 (pg, u64, 0);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_4.c
new file mode 100644 (file)
index 0000000..0256219
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+    svint8_t s8, svint16_t s16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+  svld1sb_gather_offset (pg, s8_ptr, s64); /* { dg-warning {implicit declaration of function 'svld1sb_gather_offset'; did you mean 'svld1_gather_offset'} } */
+  svld1sb_gather_offset_u64 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1sb_gather_offset_u64'} } */
+  svld1sb_gather_offset_u64 (pg, s8_ptr, s64, 0); /* { dg-error {too many arguments to function 'svld1sb_gather_offset_u64'} } */
+  svld1sb_gather_offset_u64 (pg, s16_ptr, s64); /* { dg-warning {passing argument 2 of 'svld1sb_gather_s64offset_u64' from incompatible pointer type} } */
+  svld1sb_gather_offset_u64 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_u64 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_u64 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_u64 (pg, s8_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_u64 (pg, s8_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_u64 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+  svld1sb_gather_offset_u64 (pg, s8_ptr, s64);
+  svld1sb_gather_offset_u64 (pg, s8_ptr, u64);
+  svld1sb_gather_offset_u64 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1sb_gather_offset_u64', which expects a vector of 64-bit integers} } */
+
+  svld1sb_gather_offset_u64 (pg, 0, s64);
+  svld1sb_gather_offset_u64 (pg, s, s64); /* { dg-error {'struct s' to argument 2 of 'svld1sb_gather_offset_u64', which expects a vector or pointer base address} } */
+
+  svld1sb_gather_offset_u64 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1sb_gather_offset_u64', which expects 'svuint64_t'} } */
+  svld1sb_gather_offset_u64 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1sb_gather_offset_u64', which expects 'svuint64_t'} } */
+  svld1sb_gather_offset_u64 (pg, u32, 0); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svld1sb_gather_offset_u64', which expects 'svuint64_t'} } */
+  svld1sb_gather_offset_u64 (pg, u64, 0);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_ext_gather_offset_5.c
new file mode 100644 (file)
index 0000000..8d57aa0
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, unsigned char *s8_ptr, unsigned short *s16_ptr,
+    svint8_t s8, svint16_t s16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+  svld1ub_gather_offset (pg, s8_ptr, s32); /* { dg-warning {implicit declaration of function 'svld1ub_gather_offset'; did you mean 'svld1_gather_offset'} } */
+  svld1ub_gather_offset_s32 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svld1ub_gather_offset_s32'} } */
+  svld1ub_gather_offset_s32 (pg, s8_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1ub_gather_offset_s32'} } */
+  svld1ub_gather_offset_s32 (pg, s16_ptr, s32); /* { dg-warning {passing argument 2 of 'svld1ub_gather_s32offset_s32' from incompatible pointer type} } */
+  svld1ub_gather_offset_s32 (pg, s8_ptr, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1ub_gather_offset_s32 (pg, s8_ptr, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1ub_gather_offset_s32 (pg, s8_ptr, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1ub_gather_offset_s32 (pg, s8_ptr, s32);
+  svld1ub_gather_offset_s32 (pg, s8_ptr, u32);
+  svld1ub_gather_offset_s32 (pg, s8_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1ub_gather_offset_s32 (pg, s8_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1ub_gather_offset_s32 (pg, s8_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+  svld1ub_gather_offset_s32 (pg, s8_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1ub_gather_offset_s32', which expects a vector of 32-bit integers} } */
+
+  svld1ub_gather_offset_s32 (pg, 0, s32);
+  svld1ub_gather_offset_s32 (pg, s, s32); /* { dg-error {'struct s' to argument 2 of 'svld1ub_gather_offset_s32', which expects a vector or pointer base address} } */
+
+  svld1ub_gather_offset_s32 (pg, pg, 0); /* { dg-error {passing 'svbool_t' to argument 2 of 'svld1ub_gather_offset_s32', which expects 'svuint32_t'} } */
+  svld1ub_gather_offset_s32 (pg, s32, 0); /* { dg-error {passing 'svint32_t' to argument 2 of 'svld1ub_gather_offset_s32', which expects 'svuint32_t'} } */
+  svld1ub_gather_offset_s32 (pg, u32, 0);
+  svld1ub_gather_offset_s32 (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1ub_gather_offset_s32', which expects 'svuint32_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_gather_sv_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_gather_sv_1.c
new file mode 100644 (file)
index 0000000..21566a9
--- /dev/null
@@ -0,0 +1,80 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+    int32_t *s32_ptr, uint32_t *u32_ptr, float *f32_ptr,
+    int64_t *s64_ptr, uint64_t *u64_ptr, double *f64_ptr,
+    void *void_ptr, struct s *s_ptr, _Complex float *cf32_ptr, int **ptr_ptr,
+    svint8_t s8, svint16_t s16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+  svld1_gather_offset (pg, s32_ptr); /* { dg-error {too few arguments to function 'svld1_gather_offset'} } */
+  svld1_gather_offset (pg, s32_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1_gather_offset'} } */
+  svld1_gather_offset (0, s32_ptr, s32); /* { dg-error {passing 'int' to argument 1 of 'svld1_gather_offset', which expects 'svbool_t'} } */
+  svld1_gather_offset (pg, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svld1_gather_offset', which expects a pointer type} } */
+  svld1_gather_offset (pg, (int *) 0, s32);
+  svld1_gather_offset (pg, void_ptr, s32); /* { dg-error {passing 'void \*' to argument 2 of 'svld1_gather_offset', but 'void' is not a valid SVE element type} } */
+  svld1_gather_offset (pg, s_ptr, s32); /* { dg-error {passing 'struct s \*' to argument 2 of 'svld1_gather_offset', but 'struct s' is not a valid SVE element type} } */
+  svld1_gather_offset (pg, f32_ptr, s32);
+  svld1_gather_offset (pg, cf32_ptr, s32); /* { dg-error {passing '_Complex float \*' to argument 2 of 'svld1_gather_offset', but 'complex float' is not a valid SVE element type} } */
+  svld1_gather_offset (pg, ptr_ptr, u64); /* { dg-error {passing 'int \*\*' to argument 2 of 'svld1_gather_offset', but 'int \*' is not a valid SVE element type} } */
+  svld1_gather_offset (pg, u32, 0); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svld1_gather_offset', which expects a pointer type} } */
+  /* { dg-message {an explicit type suffix is needed when using a vector of base addresses} "" { target *-*-* } .-1 } */
+  svld1_gather_offset (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1_gather_offset', which expects a pointer type} } */
+  /* { dg-message {an explicit type suffix is needed when using a vector of base addresses} "" { target *-*-* } .-1 } */
+
+  svld1_gather_offset (pg, s8_ptr, s8); /* { dg-error {passing 'signed char \*' to argument 2 of 'svld1_gather_offset', which expects a pointer to 32-bit or 64-bit elements} } */
+  svld1_gather_offset (pg, s8_ptr, s32); /* { dg-error {passing 'signed char \*' to argument 2 of 'svld1_gather_offset', which expects a pointer to 32-bit or 64-bit elements} } */
+  svld1_gather_offset (pg, s16_ptr, s16); /* { dg-error {passing 'short( int)? \*' to argument 2 of 'svld1_gather_offset', which expects a pointer to 32-bit or 64-bit elements} } */
+  svld1_gather_offset (pg, s16_ptr, s32); /* { dg-error {passing 'short( int)? \*' to argument 2 of 'svld1_gather_offset', which expects a pointer to 32-bit or 64-bit elements} } */
+
+  svld1_gather_offset (pg, s32_ptr, s32);
+  svld1_gather_offset (pg, s32_ptr, u32);
+  svld1_gather_offset (pg, s32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_offset (pg, s32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_offset (pg, s32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_offset (pg, s32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+
+  svld1_gather_offset (pg, u32_ptr, s32);
+  svld1_gather_offset (pg, u32_ptr, u32);
+  svld1_gather_offset (pg, u32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_offset (pg, u32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_offset (pg, u32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_offset (pg, u32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+
+  svld1_gather_offset (pg, f32_ptr, s32);
+  svld1_gather_offset (pg, f32_ptr, u32);
+  svld1_gather_offset (pg, f32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_offset (pg, f32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_offset (pg, f32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_offset (pg, f32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+
+  svld1_gather_offset (pg, s64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_offset (pg, s64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_offset (pg, s64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_offset (pg, s64_ptr, s64);
+  svld1_gather_offset (pg, s64_ptr, u64);
+  svld1_gather_offset (pg, s64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+
+  svld1_gather_offset (pg, u64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_offset (pg, u64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_offset (pg, u64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_offset (pg, u64_ptr, s64);
+  svld1_gather_offset (pg, u64_ptr, u64);
+  svld1_gather_offset (pg, u64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+
+  svld1_gather_offset (pg, f64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_offset (pg, f64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_offset (pg, f64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_offset (pg, f64_ptr, s64);
+  svld1_gather_offset (pg, f64_ptr, u64);
+  svld1_gather_offset (pg, f64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_offset', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+
+  return svld1_gather_offset (pg, s32_ptr, s32); /* { dg-error {incompatible types when returning type 'svint32_t' but 'svuint32_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_gather_sv_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_gather_sv_2.c
new file mode 100644 (file)
index 0000000..4c15fc4
--- /dev/null
@@ -0,0 +1,80 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+    int32_t *s32_ptr, uint32_t *u32_ptr, float *f32_ptr,
+    int64_t *s64_ptr, uint64_t *u64_ptr, double *f64_ptr,
+    void *void_ptr, struct s *s_ptr, _Complex float *cf32_ptr, int **ptr_ptr,
+    svint8_t s8, svint16_t s16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+  svld1_gather_index (pg, s32_ptr); /* { dg-error {too few arguments to function 'svld1_gather_index'} } */
+  svld1_gather_index (pg, s32_ptr, s32, 0); /* { dg-error {too many arguments to function 'svld1_gather_index'} } */
+  svld1_gather_index (0, s32_ptr, s32); /* { dg-error {passing 'int' to argument 1 of 'svld1_gather_index', which expects 'svbool_t'} } */
+  svld1_gather_index (pg, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svld1_gather_index', which expects a pointer type} } */
+  svld1_gather_index (pg, (int *) 0, s32);
+  svld1_gather_index (pg, void_ptr, s32); /* { dg-error {passing 'void \*' to argument 2 of 'svld1_gather_index', but 'void' is not a valid SVE element type} } */
+  svld1_gather_index (pg, s_ptr, s32); /* { dg-error {passing 'struct s \*' to argument 2 of 'svld1_gather_index', but 'struct s' is not a valid SVE element type} } */
+  svld1_gather_index (pg, f32_ptr, s32);
+  svld1_gather_index (pg, cf32_ptr, s32); /* { dg-error {passing '_Complex float \*' to argument 2 of 'svld1_gather_index', but 'complex float' is not a valid SVE element type} } */
+  svld1_gather_index (pg, ptr_ptr, u64); /* { dg-error {passing 'int \*\*' to argument 2 of 'svld1_gather_index', but 'int \*' is not a valid SVE element type} } */
+  svld1_gather_index (pg, u32, 0); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svld1_gather_index', which expects a pointer type} } */
+  /* { dg-message {an explicit type suffix is needed when using a vector of base addresses} "" { target *-*-* } .-1 } */
+  svld1_gather_index (pg, u64, 0); /* { dg-error {passing 'svuint64_t' to argument 2 of 'svld1_gather_index', which expects a pointer type} } */
+  /* { dg-message {an explicit type suffix is needed when using a vector of base addresses} "" { target *-*-* } .-1 } */
+
+  svld1_gather_index (pg, s8_ptr, s8); /* { dg-error {passing 'signed char \*' to argument 2 of 'svld1_gather_index', which expects a pointer to 32-bit or 64-bit elements} } */
+  svld1_gather_index (pg, s8_ptr, s32); /* { dg-error {passing 'signed char \*' to argument 2 of 'svld1_gather_index', which expects a pointer to 32-bit or 64-bit elements} } */
+  svld1_gather_index (pg, s16_ptr, s16); /* { dg-error {passing 'short( int)? \*' to argument 2 of 'svld1_gather_index', which expects a pointer to 32-bit or 64-bit elements} } */
+  svld1_gather_index (pg, s16_ptr, s32); /* { dg-error {passing 'short( int)? \*' to argument 2 of 'svld1_gather_index', which expects a pointer to 32-bit or 64-bit elements} } */
+
+  svld1_gather_index (pg, s32_ptr, s32);
+  svld1_gather_index (pg, s32_ptr, u32);
+  svld1_gather_index (pg, s32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_index (pg, s32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_index (pg, s32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_index (pg, s32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svint32_t' expects a vector of 32-bit integers} } */
+
+  svld1_gather_index (pg, u32_ptr, s32);
+  svld1_gather_index (pg, u32_ptr, u32);
+  svld1_gather_index (pg, u32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_index (pg, u32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_index (pg, u32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_index (pg, u32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint32_t' expects a vector of 32-bit integers} } */
+
+  svld1_gather_index (pg, f32_ptr, s32);
+  svld1_gather_index (pg, f32_ptr, u32);
+  svld1_gather_index (pg, f32_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_index (pg, f32_ptr, s64); /* { dg-error {passing 'svint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_index (pg, f32_ptr, u64); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svld1_gather_index (pg, f32_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat32_t' expects a vector of 32-bit integers} } */
+
+  svld1_gather_index (pg, s64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_index (pg, s64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_index (pg, s64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_index (pg, s64_ptr, s64);
+  svld1_gather_index (pg, s64_ptr, u64);
+  svld1_gather_index (pg, s64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svint64_t' expects a vector of 64-bit integers} } */
+
+  svld1_gather_index (pg, u64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_index (pg, u64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_index (pg, u64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_index (pg, u64_ptr, s64);
+  svld1_gather_index (pg, u64_ptr, u64);
+  svld1_gather_index (pg, u64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svuint64_t' expects a vector of 64-bit integers} } */
+
+  svld1_gather_index (pg, f64_ptr, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_index (pg, f64_ptr, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_index (pg, f64_ptr, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svld1_gather_index (pg, f64_ptr, s64);
+  svld1_gather_index (pg, f64_ptr, u64);
+  svld1_gather_index (pg, f64_ptr, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svld1_gather_index', which when loading 'svfloat64_t' expects a vector of 64-bit integers} } */
+
+  return svld1_gather_index (pg, s32_ptr, s32); /* { dg-error {incompatible types when returning type 'svint32_t' but 'svuint32_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_replicate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/load_replicate_1.c
new file mode 100644 (file)
index 0000000..d4ff76e
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+    float *f32_ptr, _Complex float *cf32_ptr, int **ptr_ptr)
+{
+  svld1rq (pg); /* { dg-error {too few arguments to function 'svld1rq'} } */
+  svld1rq (pg, s8_ptr, 0); /* { dg-error {too many arguments to function 'svld1rq'} } */
+  svld1rq (0, s8_ptr); /* { dg-error {passing 'int' to argument 1 of 'svld1rq', which expects 'svbool_t'} } */
+  svld1rq (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svld1rq', which expects a pointer type} } */
+  svld1rq (pg, (int *) 0);
+  svld1rq (pg, void_ptr); /* { dg-error {passing 'void \*' to argument 2 of 'svld1rq', but 'void' is not a valid SVE element type} } */
+  svld1rq (pg, s_ptr); /* { dg-error {passing 'struct s \*' to argument 2 of 'svld1rq', but 'struct s' is not a valid SVE element type} } */
+  svld1rq (pg, f32_ptr);
+  svld1rq (pg, cf32_ptr); /* { dg-error {passing '_Complex float \*' to argument 2 of 'svld1rq', but 'complex float' is not a valid SVE element type} } */
+  svld1rq (pg, ptr_ptr); /* { dg-error {passing 'int \*\*' to argument 2 of 'svld1rq', but 'int \*' is not a valid SVE element type} } */
+  return svld1rq (pg, s8_ptr); /* { dg-error {incompatible types when returning type 'svint8_t' but 'svuint8_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pattern_pred_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/pattern_pred_1.c
new file mode 100644 (file)
index 0000000..99b61bd
--- /dev/null
@@ -0,0 +1,14 @@
+#include <arm_sve.h>
+
+void
+test ()
+{
+  svptrue_pat_b16 ((enum svpattern) -1); /* { dg-error {passing 4294967295 to argument 1 of 'svptrue_pat_b16', which expects a valid 'enum svpattern' value} } */
+  svptrue_pat_b16 ((enum svpattern) 0);
+  svptrue_pat_b16 ((enum svpattern) 13);
+  svptrue_pat_b16 ((enum svpattern) 14); /* { dg-error {passing 14 to argument 1 of 'svptrue_pat_b16', which expects a valid 'enum svpattern' value} } */
+  svptrue_pat_b16 ((enum svpattern) 28); /* { dg-error {passing 28 to argument 1 of 'svptrue_pat_b16', which expects a valid 'enum svpattern' value} } */
+  svptrue_pat_b16 ((enum svpattern) 29);
+  svptrue_pat_b16 ((enum svpattern) 31);
+  svptrue_pat_b16 ((enum svpattern) 32); /* { dg-error {passing 32 to argument 1 of 'svptrue_pat_b16', which expects a valid 'enum svpattern' value} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_1.c
new file mode 100644 (file)
index 0000000..316f77f
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, enum svprfop op)
+{
+  svprfb (pg, s32_ptr, op); /* { dg-error {argument 3 of 'svprfb' must be an integer constant expression} } */
+  svprfb (pg, s32_ptr, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 3 of 'svprfb', which expects a valid 'enum svprfop' value} } */
+  svprfb (pg, s32_ptr, (enum svprfop) 0);
+  svprfb (pg, s32_ptr, (enum svprfop) 5);
+  svprfb (pg, s32_ptr, (enum svprfop) 6); /* { dg-error {passing 6 to argument 3 of 'svprfb', which expects a valid 'enum svprfop' value} } */
+  svprfb (pg, s32_ptr, (enum svprfop) 7); /* { dg-error {passing 7 to argument 3 of 'svprfb', which expects a valid 'enum svprfop' value} } */
+  svprfb (pg, s32_ptr, (enum svprfop) 8);
+  svprfb (pg, s32_ptr, (enum svprfop) 14); /* { dg-error {passing 14 to argument 3 of 'svprfb', which expects a valid 'enum svprfop' value} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_index_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_index_1.c
new file mode 100644 (file)
index 0000000..c33c954
--- /dev/null
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, void *void_ptr, void **ptr_ptr,
+    svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16, svfloat16_t f16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, enum svprfop op,
+    struct s s)
+{
+  svprfh_gather_index (pg, s32_ptr, s32); /* { dg-error {too few arguments to function 'svprfh_gather_index'} } */
+  svprfh_gather_index (pg, s32_ptr, s32, SV_PLDL1KEEP, 0); /* { dg-error {too many arguments to function 'svprfh_gather_index'} } */
+  svprfh_gather_index (0, s32_ptr, s32, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 1 of 'svprfh_gather_index', which expects 'svbool_t'} } */
+  svprfh_gather_index (pg, 0, s32, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, (int *) 0, s32, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, void_ptr, s32, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, ptr_ptr, s32, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, s, s32, SV_PLDL1KEEP); /* { dg-error {passing 'struct s' to argument 2 of 'svprfh_gather_index', which expects a vector or pointer base address} } */
+
+  svprfh_gather_index (pg, s32_ptr, s8, SV_PLDL1KEEP); /* { dg-error {passing 'svint8_t' to argument 3 of 'svprfh_gather_index', which expects a vector of 32-bit or 64-bit integers} } */
+  svprfh_gather_index (pg, s32_ptr, u8, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svprfh_gather_index', which expects a vector of 32-bit or 64-bit integers} } */
+  svprfh_gather_index (pg, s32_ptr, s16, SV_PLDL1KEEP); /* { dg-error {passing 'svint16_t' to argument 3 of 'svprfh_gather_index', which expects a vector of 32-bit or 64-bit integers} } */
+  svprfh_gather_index (pg, s32_ptr, u16, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svprfh_gather_index', which expects a vector of 32-bit or 64-bit integers} } */
+  svprfh_gather_index (pg, s32_ptr, f16, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svprfh_gather_index', which expects a vector of integers} } */
+  svprfh_gather_index (pg, s32_ptr, s32, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, s32_ptr, u32, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, s32_ptr, f32, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svprfh_gather_index', which expects a vector of integers} } */
+  svprfh_gather_index (pg, s32_ptr, s64, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, s32_ptr, u64, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, s32_ptr, f64, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svprfh_gather_index', which expects a vector of integers} } */
+
+  svprfh_gather_index (pg, u8, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfh_gather_index (pg, u16, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfh_gather_index (pg, s32, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svint32_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfh_gather_index (pg, u32, 0, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, f32, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfh_gather_index (pg, s64, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svint64_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfh_gather_index (pg, u64, 0, SV_PLDL1KEEP);
+  svprfh_gather_index (pg, f64, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svprfh_gather_index', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+  svprfh_gather_index (pg, s32_ptr, s32, op); /* { dg-error {argument 4 of 'svprfh_gather_index' must be an integer constant expression} } */
+  svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 4 of 'svprfh_gather_index', which expects a valid 'enum svprfop' value} } */
+  svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 0);
+  svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 5);
+  svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 4 of 'svprfh_gather_index', which expects a valid 'enum svprfop' value} } */
+  svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 4 of 'svprfh_gather_index', which expects a valid 'enum svprfop' value} } */
+  svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 8);
+  svprfh_gather_index (pg, s32_ptr, s32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 4 of 'svprfh_gather_index', which expects a valid 'enum svprfop' value} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_index_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_index_2.c
new file mode 100644 (file)
index 0000000..3d77973
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, svint32_t s32, enum svprfop op)
+{
+  svprfh_gather_s32index (pg, s32_ptr, s32, op); /* { dg-error {argument 4 of 'svprfh_gather_s32index' must be an integer constant expression} } */
+  svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 4 of 'svprfh_gather_s32index', which expects a valid 'enum svprfop' value} } */
+  svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 0);
+  svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 5);
+  svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 4 of 'svprfh_gather_s32index', which expects a valid 'enum svprfop' value} } */
+  svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 4 of 'svprfh_gather_s32index', which expects a valid 'enum svprfop' value} } */
+  svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 8);
+  svprfh_gather_s32index (pg, s32_ptr, s32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 4 of 'svprfh_gather_s32index', which expects a valid 'enum svprfop' value} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_1.c
new file mode 100644 (file)
index 0000000..cc61901
--- /dev/null
@@ -0,0 +1,53 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { int i; };
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, void *void_ptr, void **ptr_ptr,
+    svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16, svfloat16_t f16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, enum svprfop op,
+    struct s s)
+{
+  svprfb_gather_offset (pg, s32_ptr, s32); /* { dg-error {too few arguments to function 'svprfb_gather_offset'} } */
+  svprfb_gather_offset (pg, s32_ptr, s32, SV_PLDL1KEEP, 0); /* { dg-error {too many arguments to function 'svprfb_gather_offset'} } */
+  svprfb_gather_offset (0, s32_ptr, s32, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 1 of 'svprfb_gather_offset', which expects 'svbool_t'} } */
+  svprfb_gather_offset (pg, 0, s32, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, (int *) 0, s32, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, void_ptr, s32, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, ptr_ptr, s32, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, s, s32, SV_PLDL1KEEP); /* { dg-error {passing 'struct s' to argument 2 of 'svprfb_gather_offset', which expects a vector or pointer base address} } */
+
+  svprfb_gather_offset (pg, s32_ptr, s8, SV_PLDL1KEEP); /* { dg-error {passing 'svint8_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of 32-bit or 64-bit integers} } */
+  svprfb_gather_offset (pg, s32_ptr, u8, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of 32-bit or 64-bit integers} } */
+  svprfb_gather_offset (pg, s32_ptr, s16, SV_PLDL1KEEP); /* { dg-error {passing 'svint16_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of 32-bit or 64-bit integers} } */
+  svprfb_gather_offset (pg, s32_ptr, u16, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of 32-bit or 64-bit integers} } */
+  svprfb_gather_offset (pg, s32_ptr, f16, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of integers} } */
+  svprfb_gather_offset (pg, s32_ptr, s32, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, s32_ptr, u32, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, s32_ptr, f32, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of integers} } */
+  svprfb_gather_offset (pg, s32_ptr, s64, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, s32_ptr, u64, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, s32_ptr, f64, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svprfb_gather_offset', which expects a vector of integers} } */
+
+  svprfb_gather_offset (pg, u8, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather_offset (pg, u16, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather_offset (pg, s32, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svint32_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather_offset (pg, u32, 0, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, f32, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather_offset (pg, s64, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svint64_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather_offset (pg, u64, 0, SV_PLDL1KEEP);
+  svprfb_gather_offset (pg, f64, 0, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svprfb_gather_offset', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+  svprfb_gather_offset (pg, s32_ptr, s32, op); /* { dg-error {argument 4 of 'svprfb_gather_offset' must be an integer constant expression} } */
+  svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 4 of 'svprfb_gather_offset', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 0);
+  svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 5);
+  svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 4 of 'svprfb_gather_offset', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 4 of 'svprfb_gather_offset', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 8);
+  svprfb_gather_offset (pg, s32_ptr, s32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 4 of 'svprfb_gather_offset', which expects a valid 'enum svprfop' value} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_2.c
new file mode 100644 (file)
index 0000000..b74721f
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+    svint16_t s16, svuint16_t u16, svfloat16_t f16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, enum svprfop op)
+{
+  svprfb_gather (pg, u32); /* { dg-error {too few arguments to function 'svprfb_gather'} } */
+  svprfb_gather (pg, u32, SV_PLDL1KEEP, 0); /* { dg-error {too many arguments to function 'svprfb_gather'} } */
+  svprfb_gather (0, u32, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 1 of 'svprfb_gather', which expects 'svbool_t'} } */
+  svprfb_gather (pg, 0, SV_PLDL1KEEP); /* { dg-error {passing 'int' to argument 2 of 'svprfb_gather', which expects an SVE vector type} } */
+
+  svprfb_gather (pg, s8, SV_PLDL1KEEP); /* { dg-error {passing 'svint8_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather (pg, u8, SV_PLDL1KEEP); /* { dg-error {passing 'svuint8_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather (pg, s16, SV_PLDL1KEEP); /* { dg-error {passing 'svint16_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather (pg, u16, SV_PLDL1KEEP); /* { dg-error {passing 'svuint16_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather (pg, f16, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat16_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather (pg, s32, SV_PLDL1KEEP); /* { dg-error {passing 'svint32_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather (pg, u32, SV_PLDL1KEEP);
+  svprfb_gather (pg, f32, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat32_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather (pg, s64, SV_PLDL1KEEP); /* { dg-error {passing 'svint64_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+  svprfb_gather (pg, u64, SV_PLDL1KEEP);
+  svprfb_gather (pg, f64, SV_PLDL1KEEP); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svprfb_gather', which expects 'svuint32_t' or 'svuint64_t'} } */
+
+  svprfb_gather (pg, u32, op); /* { dg-error {argument 3 of 'svprfb_gather' must be an integer constant expression} } */
+  svprfb_gather (pg, u32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 3 of 'svprfb_gather', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather (pg, u32, (enum svprfop) 0);
+  svprfb_gather (pg, u32, (enum svprfop) 5);
+  svprfb_gather (pg, u32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 3 of 'svprfb_gather', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather (pg, u32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 3 of 'svprfb_gather', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather (pg, u32, (enum svprfop) 8);
+  svprfb_gather (pg, u32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 3 of 'svprfb_gather', which expects a valid 'enum svprfop' value} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_3.c
new file mode 100644 (file)
index 0000000..24b4aa1
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, int32_t *s32_ptr, svint32_t s32, enum svprfop op)
+{
+  svprfb_gather_s32offset (pg, s32_ptr, s32, op); /* { dg-error {argument 4 of 'svprfb_gather_s32offset' must be an integer constant expression} } */
+  svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 4 of 'svprfb_gather_s32offset', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 0);
+  svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 5);
+  svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 4 of 'svprfb_gather_s32offset', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 4 of 'svprfb_gather_s32offset', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 8);
+  svprfb_gather_s32offset (pg, s32_ptr, s32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 4 of 'svprfb_gather_s32offset', which expects a valid 'enum svprfop' value} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/prefetch_gather_offset_4.c
new file mode 100644 (file)
index 0000000..63ccdc5
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint32_t u32, enum svprfop op)
+{
+  svprfb_gather_u32base (pg, u32, op); /* { dg-error {argument 3 of 'svprfb_gather_u32base' must be an integer constant expression} } */
+  svprfb_gather_u32base (pg, u32, (enum svprfop) -1); /* { dg-error {passing 4294967295 to argument 3 of 'svprfb_gather_u32base', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather_u32base (pg, u32, (enum svprfop) 0);
+  svprfb_gather_u32base (pg, u32, (enum svprfop) 5);
+  svprfb_gather_u32base (pg, u32, (enum svprfop) 6); /* { dg-error {passing 6 to argument 3 of 'svprfb_gather_u32base', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather_u32base (pg, u32, (enum svprfop) 7); /* { dg-error {passing 7 to argument 3 of 'svprfb_gather_u32base', which expects a valid 'enum svprfop' value} } */
+  svprfb_gather_u32base (pg, u32, (enum svprfop) 8);
+  svprfb_gather_u32base (pg, u32, (enum svprfop) 14); /* { dg-error {passing 14 to argument 3 of 'svprfb_gather_u32base', which expects a valid 'enum svprfop' value} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_1.c
new file mode 100644 (file)
index 0000000..ab0ef30
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svuint32x2_t u32x2)
+{
+  svorv (pg); /* { dg-error {too few arguments to function 'svorv'} } */
+  svorv (pg, u32, u32); /* { dg-error {too many arguments to function 'svorv'} } */
+  svorv (0, u32); /* { dg-error {passing 'int' to argument 1 of 'svorv', which expects 'svbool_t'} } */
+  svorv (u32, u32); /* { dg-error {passing 'svuint32_t' to argument 1 of 'svorv', which expects 'svbool_t'} } */
+  svorv (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svorv', which expects an SVE vector type} } */
+  svorv (pg, pg); /* { dg-error {'svorv' has no form that takes 'svbool_t' arguments} } */
+  svorv (pg, s32);
+  svorv (pg, u32);
+  svorv (pg, f32); /* { dg-error {'svorv' has no form that takes 'svfloat32_t' arguments} } */
+  svorv (pg, u32x2); /* { dg-error {passing 'svuint32x2_t' to argument 2 of 'svorv', which expects a single SVE vector rather than a tuple} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_wide_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/reduction_wide_1.c
new file mode 100644 (file)
index 0000000..f99a288
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svuint32x2_t u32x2)
+{
+  svaddv (pg); /* { dg-error {too few arguments to function 'svaddv'} } */
+  svaddv (pg, u32, u32); /* { dg-error {too many arguments to function 'svaddv'} } */
+  svaddv (0, u32); /* { dg-error {passing 'int' to argument 1 of 'svaddv', which expects 'svbool_t'} } */
+  svaddv (u32, u32); /* { dg-error {passing 'svuint32_t' to argument 1 of 'svaddv', which expects 'svbool_t'} } */
+  svaddv (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svaddv', which expects an SVE vector type} } */
+  svaddv (pg, pg); /* { dg-error {'svaddv' has no form that takes 'svbool_t' arguments} } */
+  svaddv (pg, s32);
+  svaddv (pg, u32);
+  svaddv (pg, f32);
+  svaddv (pg, u32x2); /* { dg-error {passing 'svuint32x2_t' to argument 2 of 'svaddv', which expects a single SVE vector rather than a tuple} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_1.c
new file mode 100644 (file)
index 0000000..f07c761
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svuint8x3_t u8x3, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  u8x2 = svset2 (u8x2); /* { dg-error {too few arguments to function 'svset2'} } */
+  u8x2 = svset2 (u8x2, 1); /* { dg-error {too few arguments to function 'svset2'} } */
+  u8x2 = svset2 (u8x2, 1, u8, 3); /* { dg-error {too many arguments to function 'svset2'} } */
+  u8x2 = svset2 (u8, 0, u8); /* { dg-error {passing single vector 'svuint8_t' to argument 1 of 'svset2', which expects a tuple of 2 vectors} } */
+  u8x2 = svset2 (u8x3, 0, u8); /* { dg-error {passing 'svuint8x3_t' to argument 1 of 'svset2', which expects a tuple of 2 vectors} } */
+  u8x2 = svset2 (pg, 0, u8); /* { dg-error {passing 'svbool_t' to argument 1 of 'svset2', which expects a tuple of 2 vectors} } */
+  u8x2 = svset2 (u8x2, 0, u8x2); /* { dg-error {passing 'svuint8x2_t' to argument 3 of 'svset2', which expects a single SVE vector rather than a tuple} } */
+  u8x2 = svset2 (u8x2, 0, f64); /* { dg-error {passing 'svfloat64_t' instead of the expected 'svuint8_t' to argument 3 of 'svset2', after passing 'svuint8x2_t' to argument 1} } */
+  u8x2 = svset2 (u8x2, 0, pg); /* { dg-error {passing 'svbool_t' instead of the expected 'svuint8_t' to argument 3 of 'svset2', after passing 'svuint8x2_t' to argument 1} } */
+  u8x2 = svset2 (u8x2, x, u8); /* { dg-error {argument 2 of 'svset2' must be an integer constant expression} } */
+  u8x2 = svset2 (u8x2, 0, u8);
+  f64 = svset2 (u8x2, 0, u8); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svuint8x2_t'} } */
+  u8x2 = svset2 (u8x2, 1, u8);
+  u8x2 = svset2 (u8x2, 2, u8); /* { dg-error {passing 2 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, 3, u8); /* { dg-error {passing 3 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, 4, u8); /* { dg-error {passing 4 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, 5, u8); /* { dg-error {passing 5 to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, ~0U, u8); /* { dg-error {passing [^ ]* to argument 2 of 'svset2', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2 (u8x2, one, u8); /* { dg-error {argument 2 of 'svset2' must be an integer constant expression} } */
+  u8x2 = svset2 (u8x2, 3 - 2, u8);
+  u8x2 = svset2 (u8x2, 1.0, u8);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_2.c
new file mode 100644 (file)
index 0000000..ae277ea
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svuint8_t u8, svuint8x2_t u8x2, svint8x2_t s8x2,
+    svuint8x3_t u8x3, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  u8x2 = svset2_u8 (u8x2); /* { dg-error {too few arguments to function 'svset2_u8'} } */
+  u8x2 = svset2_u8 (u8x2, 1); /* { dg-error {too few arguments to function 'svset2_u8'} } */
+  u8x2 = svset2_u8 (u8x2, 1, u8, 3); /* { dg-error {too many arguments to function 'svset2_u8'} } */
+  u8x2 = svset2_u8 (u8, 0, u8); /* { dg-error {incompatible type for argument 1 of 'svset2_u8'} } */
+  u8x2 = svset2_u8 (s8x2, 0, u8); /* { dg-error {incompatible type for argument 1 of 'svset2_u8'} } */
+  u8x2 = svset2_u8 (u8x3, 0, u8); /* { dg-error {incompatible type for argument 1 of 'svset2_u8'} } */
+  u8x2 = svset2_u8 (pg, 0, u8); /* { dg-error {incompatible type for argument 1 of 'svset2_u8'} } */
+  u8x2 = svset2_u8 (u8x2, 0, u8x2); /* { dg-error {incompatible type for argument 3 of 'svset2_u8'} } */
+  u8x2 = svset2_u8 (u8x2, 0, f64); /* { dg-error {incompatible type for argument 3 of 'svset2_u8'} } */
+  u8x2 = svset2_u8 (u8x2, 0, pg); /* { dg-error {incompatible type for argument 3 of 'svset2_u8'} } */
+  u8x2 = svset2_u8 (u8x2, x, u8); /* { dg-error {argument 2 of 'svset2_u8' must be an integer constant expression} } */
+  u8x2 = svset2_u8 (u8x2, 0, u8);
+  f64 = svset2_u8 (u8x2, 0, u8); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svuint8x2_t'} } */
+  u8x2 = svset2_u8 (u8x2, 1, u8);
+  u8x2 = svset2_u8 (u8x2, 2, u8); /* { dg-error {passing 2 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, 3, u8); /* { dg-error {passing 3 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, 4, u8); /* { dg-error {passing 4 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, 5, u8); /* { dg-error {passing 5 to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, ~0U, u8); /* { dg-error {passing [^ ]* to argument 2 of 'svset2_u8', which expects a value in the range \[0, 1\]} } */
+  u8x2 = svset2_u8 (u8x2, one, u8); /* { dg-error {argument 2 of 'svset2_u8' must be an integer constant expression} } */
+  u8x2 = svset2_u8 (u8x2, 3 - 2, u8);
+  u8x2 = svset2_u8 (u8x2, 1.0, u8);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_3.c
new file mode 100644 (file)
index 0000000..543a1be
--- /dev/null
@@ -0,0 +1,36 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svfloat16x4_t f16x4,
+    int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  f16x3 = svset3 (f16x3); /* { dg-error {too few arguments to function 'svset3'} } */
+  f16x3 = svset3 (f16x3, 1); /* { dg-error {too few arguments to function 'svset3'} } */
+  f16x3 = svset3 (f16x3, 1, f16, 3); /* { dg-error {too many arguments to function 'svset3'} } */
+  f16x3 = svset3 (f16, 0, f16); /* { dg-error {passing single vector 'svfloat16_t' to argument 1 of 'svset3', which expects a tuple of 3 vectors} } */
+  f16x3 = svset3 (f16x4, 0, f16); /* { dg-error {passing 'svfloat16x4_t' to argument 1 of 'svset3', which expects a tuple of 3 vectors} } */
+  f16x3 = svset3 (pg, 0, f16); /* { dg-error {passing 'svbool_t' to argument 1 of 'svset3', which expects a tuple of 3 vectors} } */
+  f16x3 = svset3 (f16x3, 0, f16x3); /* { dg-error {passing 'svfloat16x3_t' to argument 3 of 'svset3', which expects a single SVE vector rather than a tuple} } */
+  f16x3 = svset3 (f16x3, 0, f64); /* { dg-error {passing 'svfloat64_t' instead of the expected 'svfloat16_t' to argument 3 of 'svset3', after passing 'svfloat16x3_t' to argument 1} } */
+  f16x3 = svset3 (f16x3, 0, pg); /* { dg-error {passing 'svbool_t' instead of the expected 'svfloat16_t' to argument 3 of 'svset3', after passing 'svfloat16x3_t' to argument 1} } */
+  f16x3 = svset3 (f16x3, x, f16); /* { dg-error {argument 2 of 'svset3' must be an integer constant expression} } */
+  f16x3 = svset3 (f16x3, 0, f16);
+  f64 = svset3 (f16x3, 0, f16); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svfloat16x3_t'} } */
+  f16x3 = svset3 (f16x3, 1, f16);
+  f16x3 = svset3 (f16x3, 2, f16);
+  f16x3 = svset3 (f16x3, 3, f16); /* { dg-error {passing 3 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, 4, f16); /* { dg-error {passing 4 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, 5, f16); /* { dg-error {passing 5 to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, ~0U, f16); /* { dg-error {passing [^ ]* to argument 2 of 'svset3', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3 (f16x3, one, f16); /* { dg-error {argument 2 of 'svset3' must be an integer constant expression} } */
+  f16x3 = svset3 (f16x3, 3 - 2, f16);
+  f16x3 = svset3 (f16x3, 1.0, f16);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_4.c
new file mode 100644 (file)
index 0000000..198b034
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svfloat16_t f16, svfloat16x3_t f16x3, svuint16x3_t u16x3,
+    svfloat16x4_t f16x4, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  f16x3 = svset3_f16 (f16x3); /* { dg-error {too few arguments to function 'svset3_f16'} } */
+  f16x3 = svset3_f16 (f16x3, 1); /* { dg-error {too few arguments to function 'svset3_f16'} } */
+  f16x3 = svset3_f16 (f16x3, 1, f16, 3); /* { dg-error {too many arguments to function 'svset3_f16'} } */
+  f16x3 = svset3_f16 (f16, 0, f16); /* { dg-error {incompatible type for argument 1 of 'svset3_f16'} } */
+  f16x3 = svset3_f16 (u16x3, 0, f16); /* { dg-error {incompatible type for argument 1 of 'svset3_f16'} } */
+  f16x3 = svset3_f16 (f16x4, 0, f16); /* { dg-error {incompatible type for argument 1 of 'svset3_f16'} } */
+  f16x3 = svset3_f16 (pg, 0, f16); /* { dg-error {incompatible type for argument 1 of 'svset3_f16'} } */
+  f16x3 = svset3_f16 (f16x3, 0, f16x3); /* { dg-error {incompatible type for argument 3 of 'svset3_f16'} } */
+  f16x3 = svset3_f16 (f16x3, 0, f64); /* { dg-error {incompatible type for argument 3 of 'svset3_f16'} } */
+  f16x3 = svset3_f16 (f16x3, 0, pg); /* { dg-error {incompatible type for argument 3 of 'svset3_f16'} } */
+  f16x3 = svset3_f16 (f16x3, x, f16); /* { dg-error {argument 2 of 'svset3_f16' must be an integer constant expression} } */
+  f16x3 = svset3_f16 (f16x3, 0, f16);
+  f64 = svset3_f16 (f16x3, 0, f16); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svfloat16x3_t'} } */
+  f16x3 = svset3_f16 (f16x3, 1, f16);
+  f16x3 = svset3_f16 (f16x3, 2, f16);
+  f16x3 = svset3_f16 (f16x3, 3, f16); /* { dg-error {passing 3 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, 4, f16); /* { dg-error {passing 4 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, 5, f16); /* { dg-error {passing 5 to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, ~0U, f16); /* { dg-error {passing [^ ]* to argument 2 of 'svset3_f16', which expects a value in the range \[0, 2\]} } */
+  f16x3 = svset3_f16 (f16x3, one, f16); /* { dg-error {argument 2 of 'svset3_f16' must be an integer constant expression} } */
+  f16x3 = svset3_f16 (f16x3, 3 - 2, f16);
+  f16x3 = svset3_f16 (f16x3, 1.0, f16);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_5.c
new file mode 100644 (file)
index 0000000..be911a7
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svint32x2_t s32x2, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  s32x4 = svset4 (s32x4); /* { dg-error {too few arguments to function 'svset4'} } */
+  s32x4 = svset4 (s32x4, 1); /* { dg-error {too few arguments to function 'svset4'} } */
+  s32x4 = svset4 (s32x4, 1, s32, 3); /* { dg-error {too many arguments to function 'svset4'} } */
+  s32x4 = svset4 (s32, 0, s32); /* { dg-error {passing single vector 'svint32_t' to argument 1 of 'svset4', which expects a tuple of 4 vectors} } */
+  s32x4 = svset4 (s32x2, 0, s32); /* { dg-error {passing 'svint32x2_t' to argument 1 of 'svset4', which expects a tuple of 4 vectors} } */
+  s32x4 = svset4 (pg, 0, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svset4', which expects a tuple of 4 vectors} } */
+  s32x4 = svset4 (s32x4, 0, s32x4); /* { dg-error {passing 'svint32x4_t' to argument 3 of 'svset4', which expects a single SVE vector rather than a tuple} } */
+  s32x4 = svset4 (s32x4, 0, f64); /* { dg-error {passing 'svfloat64_t' instead of the expected 'svint32_t' to argument 3 of 'svset4', after passing 'svint32x4_t' to argument 1} } */
+  s32x4 = svset4 (s32x4, 0, pg); /* { dg-error {passing 'svbool_t' instead of the expected 'svint32_t' to argument 3 of 'svset4', after passing 'svint32x4_t' to argument 1} } */
+  s32x4 = svset4 (s32x4, x, s32); /* { dg-error {argument 2 of 'svset4' must be an integer constant expression} } */
+  s32x4 = svset4 (s32x4, 0, s32);
+  f64 = svset4 (s32x4, 0, s32); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svint32x4_t'} } */
+  s32x4 = svset4 (s32x4, 1, s32);
+  s32x4 = svset4 (s32x4, 2, s32);
+  s32x4 = svset4 (s32x4, 3, s32);
+  s32x4 = svset4 (s32x4, 4, s32); /* { dg-error {passing 4 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4 (s32x4, 5, s32); /* { dg-error {passing 5 to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4 (s32x4, ~0U, s32); /* { dg-error {passing [^ ]* to argument 2 of 'svset4', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4 (s32x4, one, s32); /* { dg-error {argument 2 of 'svset4' must be an integer constant expression} } */
+  s32x4 = svset4 (s32x4, 3 - 2, s32);
+  s32x4 = svset4 (s32x4, 1.0, s32);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/set_6.c
new file mode 100644 (file)
index 0000000..cec4354
--- /dev/null
@@ -0,0 +1,37 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+svfloat64_t
+f1 (svbool_t pg, svint32_t s32, svint32x4_t s32x4, svfloat32x4_t f32x4,
+    svint32x2_t s32x2, int x)
+{
+  const int one = 1;
+  svfloat64_t f64;
+
+  s32x4 = svset4_s32 (s32x4); /* { dg-error {too few arguments to function 'svset4_s32'} } */
+  s32x4 = svset4_s32 (s32x4, 1); /* { dg-error {too few arguments to function 'svset4_s32'} } */
+  s32x4 = svset4_s32 (s32x4, 1, s32, 3); /* { dg-error {too many arguments to function 'svset4_s32'} } */
+  s32x4 = svset4_s32 (s32, 0, s32); /* { dg-error {incompatible type for argument 1 of 'svset4_s32'} } */
+  s32x4 = svset4_s32 (f32x4, 0, s32); /* { dg-error {incompatible type for argument 1 of 'svset4_s32'} } */
+  s32x4 = svset4_s32 (s32x2, 0, s32); /* { dg-error {incompatible type for argument 1 of 'svset4_s32'} } */
+  s32x4 = svset4_s32 (pg, 0, s32); /* { dg-error {incompatible type for argument 1 of 'svset4_s32'} } */
+  s32x4 = svset4_s32 (s32x4, 0, s32x4); /* { dg-error {incompatible type for argument 3 of 'svset4_s32'} } */
+  s32x4 = svset4_s32 (s32x4, 0, f64); /* { dg-error {incompatible type for argument 3 of 'svset4_s32'} } */
+  s32x4 = svset4_s32 (s32x4, 0, pg); /* { dg-error {incompatible type for argument 3 of 'svset4_s32'} } */
+  s32x4 = svset4_s32 (s32x4, x, s32); /* { dg-error {argument 2 of 'svset4_s32' must be an integer constant expression} } */
+  s32x4 = svset4_s32 (s32x4, 0, s32);
+  f64 = svset4_s32 (s32x4, 0, s32); /* { dg-error {incompatible types when assigning to type 'svfloat64_t' from type 'svint32x4_t'} } */
+  s32x4 = svset4_s32 (s32x4, 1, s32);
+  s32x4 = svset4_s32 (s32x4, 2, s32);
+  s32x4 = svset4_s32 (s32x4, 3, s32);
+  s32x4 = svset4_s32 (s32x4, 4, s32); /* { dg-error {passing 4 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4_s32 (s32x4, 5, s32); /* { dg-error {passing 5 to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4_s32 (s32x4, ~0U, s32); /* { dg-error {passing [^ ]* to argument 2 of 'svset4_s32', which expects a value in the range \[0, 3\]} } */
+  s32x4 = svset4_s32 (s32x4, one, s32); /* { dg-error {argument 2 of 'svset4_s32' must be an integer constant expression} } */
+  s32x4 = svset4_s32 (s32x4, 3 - 2, s32);
+  s32x4 = svset4_s32 (s32x4, 1.0, s32);
+
+  return f64;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_1.c
new file mode 100644 (file)
index 0000000..4dd9a9c
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8, svint8_t s8, svint16_t s16,
+    svint32_t s32, svint64_t s64, int x)
+{
+  const int one = 1;
+  u8 = svasrd_x (pg, u8, 1); /* { dg-error {'svasrd_x' has no form that takes 'svuint8_t' arguments} } */
+  s8 = svasrd_x (pg, s8, x); /* { dg-error {argument 3 of 'svasrd_x' must be an integer constant expression} } */
+  s8 = svasrd_x (pg, s8, one); /* { dg-error {argument 3 of 'svasrd_x' must be an integer constant expression} } */
+  s8 = svasrd_x (pg, s8, 0.4); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_x (pg, s8, 1.0);
+  s8 = svasrd_x (pg, s8, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_x (pg, s8, 1);
+  s8 = svasrd_x (pg, s8, 1 + 1);
+  s8 = svasrd_x (pg, s8, 8);
+  s8 = svasrd_x (pg, s8, 9); /* { dg-error {passing 9 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_x (pg, s8, (1ULL << 62) + 1); /* { dg-error {passing [^ ]* to argument 3 of 'svasrd_x', which expects a value in the range \[1, 8\]} } */
+  s16 = svasrd_x (pg, s16, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} } */
+  s16 = svasrd_x (pg, s16, 1);
+  s16 = svasrd_x (pg, s16, 16);
+  s16 = svasrd_x (pg, s16, 17); /* { dg-error {passing 17 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 16\]} } */
+  s32 = svasrd_x (pg, s32, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} } */
+  s32 = svasrd_x (pg, s32, 1);
+  s32 = svasrd_x (pg, s32, 32);
+  s32 = svasrd_x (pg, s32, 33); /* { dg-error {passing 33 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 32\]} } */
+  s64 = svasrd_x (pg, s64, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} } */
+  s64 = svasrd_x (pg, s64, 1);
+  s64 = svasrd_x (pg, s64, 64);
+  s64 = svasrd_x (pg, s64, 65); /* { dg-error {passing 65 to argument 3 of 'svasrd_x', which expects a value in the range \[1, 64\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/shift_right_imm_2.c
new file mode 100644 (file)
index 0000000..4970689
--- /dev/null
@@ -0,0 +1,33 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-std=c99 -Wall -Wextra" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svint16_t s16, svint32_t s32, svint64_t s64,
+    int x)
+{
+  const int one = 1;
+  s8 = svasrd_n_s8_x (pg, s8, x); /* { dg-error {argument 3 of 'svasrd_n_s8_x' must be an integer constant expression} } */
+  s8 = svasrd_n_s8_x (pg, s8, one); /* { dg-error {argument 3 of 'svasrd_n_s8_x' must be an integer constant expression} } */
+  s8 = svasrd_n_s8_x (pg, s8, 0.4); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_n_s8_x (pg, s8, 1.0);
+  s8 = svasrd_n_s8_x (pg, s8, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_n_s8_x (pg, s8, 1);
+  s8 = svasrd_n_s8_x (pg, s8, 1 + 1);
+  s8 = svasrd_n_s8_x (pg, s8, 8);
+  s8 = svasrd_n_s8_x (pg, s8, 9); /* { dg-error {passing 9 to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+  s8 = svasrd_n_s8_x (pg, s8, (1ULL << 62) + 1); /* { dg-error {passing [^ ]* to argument 3 of 'svasrd_n_s8_x', which expects a value in the range \[1, 8\]} } */
+  s16 = svasrd_n_s16_x (pg, s16, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s16_x', which expects a value in the range \[1, 16\]} } */
+  s16 = svasrd_n_s16_x (pg, s16, 1);
+  s16 = svasrd_n_s16_x (pg, s16, 16);
+  s16 = svasrd_n_s16_x (pg, s16, 17); /* { dg-error {passing 17 to argument 3 of 'svasrd_n_s16_x', which expects a value in the range \[1, 16\]} } */
+  s32 = svasrd_n_s32_x (pg, s32, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s32_x', which expects a value in the range \[1, 32\]} } */
+  s32 = svasrd_n_s32_x (pg, s32, 1);
+  s32 = svasrd_n_s32_x (pg, s32, 32);
+  s32 = svasrd_n_s32_x (pg, s32, 33); /* { dg-error {passing 33 to argument 3 of 'svasrd_n_s32_x', which expects a value in the range \[1, 32\]} } */
+  s64 = svasrd_n_s64_x (pg, s64, 0); /* { dg-error {passing 0 to argument 3 of 'svasrd_n_s64_x', which expects a value in the range \[1, 64\]} } */
+  s64 = svasrd_n_s64_x (pg, s64, 1);
+  s64 = svasrd_n_s64_x (pg, s64, 64);
+  s64 = svasrd_n_s64_x (pg, s64, 65); /* { dg-error {passing 65 to argument 3 of 'svasrd_n_s64_x', which expects a value in the range \[1, 64\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_1.c
new file mode 100644 (file)
index 0000000..267db83
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+    float *f32_ptr, _Complex float *cf32_ptr, svint8_t s8, svfloat32_t f32,
+    struct s s)
+{
+  svst1 (pg, s8_ptr); /* { dg-error {too few arguments to function 'svst1'} } */
+  svst1 (pg, s8_ptr, s8, 0); /* { dg-error {too many arguments to function 'svst1'} } */
+  svst1 (0, s8_ptr, s8); /* { dg-error {passing 'int' to argument 1 of 'svst1', which expects 'svbool_t'} } */
+  svst1 (pg, void_ptr, 0); /* { dg-error {passing 'int' to argument 3 of 'svst1', which expects an SVE vector type} } */
+  svst1 (pg, void_ptr, pg); /* { dg-error {'svst1' has no form that takes 'svbool_t' arguments} } */
+  svst1 (pg, 0, s8);
+  svst1 (pg, (int *) 0, s8); /* { dg-warning "passing argument 2 of 'svst1_s8' from incompatible pointer type" } */
+  svst1 (pg, void_ptr, s8);
+  svst1 (pg, s_ptr, s8); /* { dg-warning "passing argument 2 of 'svst1_s8' from incompatible pointer type" } */
+  svst1 (pg, f32_ptr, s8); /* { dg-warning "passing argument 2 of 'svst1_s8' from incompatible pointer type" } */
+  svst1 (pg, f32_ptr, f32);
+  svst1 (pg, cf32_ptr, f32); /* { dg-warning "passing argument 2 of 'svst1_f32' from incompatible pointer type" } */
+  svst1 (pg, s, s8); /* { dg-error {passing 'struct s' to argument 2 of 'svst1', which expects a scalar pointer} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_2.c
new file mode 100644 (file)
index 0000000..4e4fb3c
--- /dev/null
@@ -0,0 +1,27 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint8_t
+f1 (svbool_t pg, signed char *s8_ptr, void *void_ptr, struct s *s_ptr,
+    float *f32_ptr, _Complex float *cf32_ptr, svint8_t s8, svfloat32_t f32)
+{
+  svst1_vnum (pg, s8_ptr, 0); /* { dg-error {too few arguments to function 'svst1_vnum'} } */
+  svst1_vnum (pg, s8_ptr, 0, s8, 0); /* { dg-error {too many arguments to function 'svst1_vnum'} } */
+  svst1_vnum (0, s8_ptr, 0, s8); /* { dg-error {passing 'int' to argument 1 of 'svst1_vnum', which expects 'svbool_t'} } */
+  svst1_vnum (pg, s8_ptr, pg, s8); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_vnum', which expects 'int64_t'} } */
+  svst1_vnum (pg, s8_ptr, s8, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svst1_vnum', which expects 'int64_t'} } */
+  svst1_vnum (pg, s8_ptr, void_ptr, s8); /* { dg-warning "passing argument 3 of 'svst1_vnum_s8' makes integer from pointer without a cast" } */
+  svst1_vnum (pg, void_ptr, 0, 0); /* { dg-error {passing 'int' to argument 4 of 'svst1_vnum', which expects an SVE vector type} } */
+  svst1_vnum (pg, void_ptr, 0, pg); /* { dg-error {'svst1_vnum' has no form that takes 'svbool_t' arguments} } */
+  svst1_vnum (pg, 0, 0, s8);
+  svst1_vnum (pg, (int *) 0, 0, s8); /* { dg-warning "passing argument 2 of 'svst1_vnum_s8' from incompatible pointer type" } */
+  svst1_vnum (pg, void_ptr, 0, s8);
+  svst1_vnum (pg, s_ptr, 0, s8); /* { dg-warning "passing argument 2 of 'svst1_vnum_s8' from incompatible pointer type" } */
+  svst1_vnum (pg, f32_ptr, 0, s8); /* { dg-warning "passing argument 2 of 'svst1_vnum_s8' from incompatible pointer type" } */
+  svst1_vnum (pg, f32_ptr, 0, f32);
+  svst1_vnum (pg, cf32_ptr, 0, f32); /* { dg-warning "passing argument 2 of 'svst1_vnum_f32' from incompatible pointer type" } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_index_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_index_1.c
new file mode 100644 (file)
index 0000000..3209149
--- /dev/null
@@ -0,0 +1,101 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+    int32_t *s32_ptr, uint32_t *u32_ptr, float *f32_ptr,
+    int64_t *s64_ptr, uint64_t *u64_ptr, double *f64_ptr,
+    void *void_ptr, struct s *s_ptr, _Complex float *cf32_ptr,
+    svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16, svfloat16_t f16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+  svst1_scatter_index (pg, s32_ptr, s32); /* { dg-error {too few arguments to function 'svst1_scatter_index'} } */
+  svst1_scatter_index (pg, s32_ptr, s32, s32, 0); /* { dg-error {too many arguments to function 'svst1_scatter_index'} } */
+  svst1_scatter_index (0, s32_ptr, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svst1_scatter_index', which expects 'svbool_t'} } */
+  svst1_scatter_index (pg, 0, s32, s32);
+  svst1_scatter_index (pg, (int *) 0, s32, s32);
+  svst1_scatter_index (pg, void_ptr, s32, s32);
+  svst1_scatter_index (pg, s_ptr, s32, s32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32index_s32' from incompatible pointer type" } */
+  svst1_scatter_index (pg, f32_ptr, s32, s32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32index_s32' from incompatible pointer type" } */
+  svst1_scatter_index (pg, f32_ptr, s32, f32);
+  svst1_scatter_index (pg, cf32_ptr, s32, f32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32index_f32' from incompatible pointer type" } */
+  svst1_scatter_index (pg, s, s32, s32); /* { dg-error {passing 'struct s' to argument 2 of 'svst1_scatter_index', which expects a vector or pointer base address} } */
+
+  svst1_scatter_index (pg, u32, void_ptr, s32); /* { dg-warning "passing argument 3 of 'svst1_scatter_u32base_index_s32' makes integer from pointer without a cast" } */
+  svst1_scatter_index (pg, u32, pg, s32); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_scatter_index', which expects 'int64_t'} } */
+  svst1_scatter_index (pg, u32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_index', which expects 'int64_t'} } */
+
+  svst1_scatter_index (pg, void_ptr, u32, pg); /* { dg-error {passing 'svbool_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+
+  svst1_scatter_index (pg, s8_ptr, u32, s8); /* { dg-error {passing 'svint8_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+  svst1_scatter_index (pg, s8_ptr, u32, u8); /* { dg-error {passing 'svuint8_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+
+  svst1_scatter_index (pg, s16_ptr, u32, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+  svst1_scatter_index (pg, s16_ptr, u32, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+  svst1_scatter_index (pg, s16_ptr, u32, f16); /* { dg-error {passing 'svfloat16_t' to argument 4 of 'svst1_scatter_index', which expects a vector of 32-bit or 64-bit elements} } */
+
+  svst1_scatter_index (pg, u32, 0, s32);
+  svst1_scatter_index (pg, s32, 0, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint32_t'} } */
+
+  svst1_scatter_index (pg, u32, 0, u32);
+  svst1_scatter_index (pg, s32, 0, u32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint32_t'} } */
+
+  svst1_scatter_index (pg, u32, 0, f32);
+  svst1_scatter_index (pg, s32, 0, f32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint32_t'} } */
+
+  svst1_scatter_index (pg, u64, 0, s64);
+  svst1_scatter_index (pg, s64, 0, s64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint64_t'} } */
+
+  svst1_scatter_index (pg, u64, 0, u64);
+  svst1_scatter_index (pg, s64, 0, u64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint64_t'} } */
+
+  svst1_scatter_index (pg, u64, 0, f64);
+  svst1_scatter_index (pg, s64, 0, f64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_index', which expects 'svuint64_t'} } */
+
+  svst1_scatter_index (pg, s32_ptr, s32, s32);
+  svst1_scatter_index (pg, s32_ptr, u32, s32);
+  svst1_scatter_index (pg, s32_ptr, f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_index (pg, s32_ptr, s64, s32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_index (pg, s32_ptr, u64, s32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_index (pg, s32_ptr, f64, s32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+
+  svst1_scatter_index (pg, u32_ptr, s32, u32);
+  svst1_scatter_index (pg, u32_ptr, u32, u32);
+  svst1_scatter_index (pg, u32_ptr, f32, u32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_index (pg, u32_ptr, s64, u32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_index (pg, u32_ptr, u64, u32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_index (pg, u32_ptr, f64, u32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+
+  svst1_scatter_index (pg, f32_ptr, s32, f32);
+  svst1_scatter_index (pg, f32_ptr, u32, f32);
+  svst1_scatter_index (pg, f32_ptr, f32, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_index (pg, f32_ptr, s64, f32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_index (pg, f32_ptr, u64, f32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_index (pg, f32_ptr, f64, f32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+
+  svst1_scatter_index (pg, s64_ptr, s32, s64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_index (pg, s64_ptr, u32, s64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_index (pg, s64_ptr, f32, s64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_index (pg, s64_ptr, s64, s64);
+  svst1_scatter_index (pg, s64_ptr, u64, s64);
+  svst1_scatter_index (pg, s64_ptr, f64, s64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+
+  svst1_scatter_index (pg, u64_ptr, s32, u64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_index (pg, u64_ptr, u32, u64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_index (pg, u64_ptr, f32, u64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_index (pg, u64_ptr, s64, u64);
+  svst1_scatter_index (pg, u64_ptr, u64, u64);
+  svst1_scatter_index (pg, u64_ptr, f64, u64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+
+  svst1_scatter_index (pg, f64_ptr, s32, f64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_index (pg, f64_ptr, u32, f64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_index (pg, f64_ptr, f32, f64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_index (pg, f64_ptr, s64, f64);
+  svst1_scatter_index (pg, f64_ptr, u64, f64);
+  svst1_scatter_index (pg, f64_ptr, f64, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_index', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_1.c
new file mode 100644 (file)
index 0000000..10abf75
--- /dev/null
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+    svfloat16_t f16, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64)
+{
+  svst1_scatter (pg, u32); /* { dg-error {too few arguments to function 'svst1_scatter'} } */
+  svst1_scatter (pg, u32, u32, 0); /* { dg-error {too many arguments to function 'svst1_scatter'} } */
+  svst1_scatter (0, u32, u32); /* { dg-error {passing 'int' to argument 1 of 'svst1_scatter', which expects 'svbool_t'} } */
+  svst1_scatter (pg, 0, u32); /* { dg-error {passing 'int' to argument 2 of 'svst1_scatter', which expects an SVE vector type} } */
+  svst1_scatter (pg, u32, 0); /* { dg-error {passing 'int' to argument 3 of 'svst1_scatter', which expects an SVE vector type} } */
+
+  svst1_scatter (pg, u32, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+
+  svst1_scatter (pg, u32, s8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+  svst1_scatter (pg, u32, u8); /* { dg-error {passing 'svuint8_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+
+  svst1_scatter (pg, u32, s16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+  svst1_scatter (pg, u32, u16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+  svst1_scatter (pg, u32, f16); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svst1_scatter', which expects a vector of 32-bit or 64-bit elements} } */
+
+  svst1_scatter (pg, u32, s32);
+  svst1_scatter (pg, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter', which expects 'svuint32_t'} } */
+
+  svst1_scatter (pg, u32, u32);
+  svst1_scatter (pg, s32, u32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter', which expects 'svuint32_t'} } */
+
+  svst1_scatter (pg, u32, f32);
+  svst1_scatter (pg, s32, f32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter', which expects 'svuint32_t'} } */
+
+  svst1_scatter (pg, u64, s64);
+  svst1_scatter (pg, s64, s64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter', which expects 'svuint64_t'} } */
+
+  svst1_scatter (pg, u64, u64);
+  svst1_scatter (pg, s64, u64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter', which expects 'svuint64_t'} } */
+
+  svst1_scatter (pg, u64, f64);
+  svst1_scatter (pg, s64, f64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter', which expects 'svuint64_t'} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/store_scatter_offset_2.c
new file mode 100644 (file)
index 0000000..8ee8129
--- /dev/null
@@ -0,0 +1,101 @@
+/* { dg-do compile } */
+/* { dg-options "-std=c99" } */
+
+#include <arm_sve.h>
+
+struct s { signed char x; };
+
+svuint32_t
+f1 (svbool_t pg, signed char *s8_ptr, short *s16_ptr,
+    int32_t *s32_ptr, uint32_t *u32_ptr, float *f32_ptr,
+    int64_t *s64_ptr, uint64_t *u64_ptr, double *f64_ptr,
+    void *void_ptr, struct s *s_ptr, _Complex float *cf32_ptr,
+    svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16, svfloat16_t f16,
+    svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64, svfloat64_t f64, struct s s)
+{
+  svst1_scatter_offset (pg, s32_ptr, s32); /* { dg-error {too few arguments to function 'svst1_scatter_offset'} } */
+  svst1_scatter_offset (pg, s32_ptr, s32, s32, 0); /* { dg-error {too many arguments to function 'svst1_scatter_offset'} } */
+  svst1_scatter_offset (0, s32_ptr, s32, s32); /* { dg-error {passing 'int' to argument 1 of 'svst1_scatter_offset', which expects 'svbool_t'} } */
+  svst1_scatter_offset (pg, 0, s32, s32);
+  svst1_scatter_offset (pg, (int *) 0, s32, s32);
+  svst1_scatter_offset (pg, void_ptr, s32, s32);
+  svst1_scatter_offset (pg, s_ptr, s32, s32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32offset_s32' from incompatible pointer type" } */
+  svst1_scatter_offset (pg, f32_ptr, s32, s32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32offset_s32' from incompatible pointer type" } */
+  svst1_scatter_offset (pg, f32_ptr, s32, f32);
+  svst1_scatter_offset (pg, cf32_ptr, s32, f32); /* { dg-warning "passing argument 2 of 'svst1_scatter_s32offset_f32' from incompatible pointer type" } */
+  svst1_scatter_offset (pg, s, s32, s32); /* { dg-error {passing 'struct s' to argument 2 of 'svst1_scatter_offset', which expects a vector or pointer base address} } */
+
+  svst1_scatter_offset (pg, u32, void_ptr, s32); /* { dg-warning "passing argument 3 of 'svst1_scatter_u32base_offset_s32' makes integer from pointer without a cast" } */
+  svst1_scatter_offset (pg, u32, pg, s32); /* { dg-error {passing 'svbool_t' to argument 3 of 'svst1_scatter_offset', which expects 'int64_t'} } */
+  svst1_scatter_offset (pg, u32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_offset', which expects 'int64_t'} } */
+
+  svst1_scatter_offset (pg, void_ptr, u32, pg); /* { dg-error {passing 'svbool_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+
+  svst1_scatter_offset (pg, s8_ptr, u32, s8); /* { dg-error {passing 'svint8_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+  svst1_scatter_offset (pg, s8_ptr, u32, u8); /* { dg-error {passing 'svuint8_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+
+  svst1_scatter_offset (pg, s16_ptr, u32, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+  svst1_scatter_offset (pg, s16_ptr, u32, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+  svst1_scatter_offset (pg, s16_ptr, u32, f16); /* { dg-error {passing 'svfloat16_t' to argument 4 of 'svst1_scatter_offset', which expects a vector of 32-bit or 64-bit elements} } */
+
+  svst1_scatter_offset (pg, u32, 0, s32);
+  svst1_scatter_offset (pg, s32, 0, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint32_t'} } */
+
+  svst1_scatter_offset (pg, u32, 0, u32);
+  svst1_scatter_offset (pg, s32, 0, u32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint32_t'} } */
+
+  svst1_scatter_offset (pg, u32, 0, f32);
+  svst1_scatter_offset (pg, s32, 0, f32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint32_t'} } */
+
+  svst1_scatter_offset (pg, u64, 0, s64);
+  svst1_scatter_offset (pg, s64, 0, s64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint64_t'} } */
+
+  svst1_scatter_offset (pg, u64, 0, u64);
+  svst1_scatter_offset (pg, s64, 0, u64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint64_t'} } */
+
+  svst1_scatter_offset (pg, u64, 0, f64);
+  svst1_scatter_offset (pg, s64, 0, f64); /* { dg-error {passing 'svint64_t' to argument 2 of 'svst1_scatter_offset', which expects 'svuint64_t'} } */
+
+  svst1_scatter_offset (pg, s32_ptr, s32, s32);
+  svst1_scatter_offset (pg, s32_ptr, u32, s32);
+  svst1_scatter_offset (pg, s32_ptr, f32, s32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_offset (pg, s32_ptr, s64, s32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_offset (pg, s32_ptr, u64, s32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_offset (pg, s32_ptr, f64, s32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint32_t' expects a vector of 32-bit integers} } */
+
+  svst1_scatter_offset (pg, u32_ptr, s32, u32);
+  svst1_scatter_offset (pg, u32_ptr, u32, u32);
+  svst1_scatter_offset (pg, u32_ptr, f32, u32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_offset (pg, u32_ptr, s64, u32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_offset (pg, u32_ptr, u64, u32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_offset (pg, u32_ptr, f64, u32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint32_t' expects a vector of 32-bit integers} } */
+
+  svst1_scatter_offset (pg, f32_ptr, s32, f32);
+  svst1_scatter_offset (pg, f32_ptr, u32, f32);
+  svst1_scatter_offset (pg, f32_ptr, f32, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_offset (pg, f32_ptr, s64, f32); /* { dg-error {passing 'svint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_offset (pg, f32_ptr, u64, f32); /* { dg-error {passing 'svuint64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+  svst1_scatter_offset (pg, f32_ptr, f64, f32); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat32_t' expects a vector of 32-bit integers} } */
+
+  svst1_scatter_offset (pg, s64_ptr, s32, s64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_offset (pg, s64_ptr, u32, s64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_offset (pg, s64_ptr, f32, s64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_offset (pg, s64_ptr, s64, s64);
+  svst1_scatter_offset (pg, s64_ptr, u64, s64);
+  svst1_scatter_offset (pg, s64_ptr, f64, s64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svint64_t' expects a vector of 64-bit integers} } */
+
+  svst1_scatter_offset (pg, u64_ptr, s32, u64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_offset (pg, u64_ptr, u32, u64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_offset (pg, u64_ptr, f32, u64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_offset (pg, u64_ptr, s64, u64);
+  svst1_scatter_offset (pg, u64_ptr, u64, u64);
+  svst1_scatter_offset (pg, u64_ptr, f64, u64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svuint64_t' expects a vector of 64-bit integers} } */
+
+  svst1_scatter_offset (pg, f64_ptr, s32, f64); /* { dg-error {passing 'svint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_offset (pg, f64_ptr, u32, f64); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_offset (pg, f64_ptr, f32, f64); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+  svst1_scatter_offset (pg, f64_ptr, s64, f64);
+  svst1_scatter_offset (pg, f64_ptr, u64, f64);
+  svst1_scatter_offset (pg, f64_ptr, f64, f64); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svst1_scatter_offset', which when storing 'svfloat64_t' expects a vector of 64-bit integers} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_1.c
new file mode 100644 (file)
index 0000000..bbd1f91
--- /dev/null
@@ -0,0 +1,35 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+    svint32_t s32, int i)
+{
+  svmla_lane (f32, f32, f32); /* { dg-error {too few arguments to function 'svmla_lane'} } */
+  svmla_lane (f32, f32, f32, 0, 0); /* { dg-error {too many arguments to function 'svmla_lane'} } */
+  svmla_lane (pg, pg, pg, 0); /* { dg-error {'svmla_lane' has no form that takes 'svbool_t' arguments} } */
+  svmla_lane (s32, s32, s32, 0); /* { dg-error {'svmla_lane' has no form that takes 'svint32_t' arguments} } */
+  svmla_lane (1, f32, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svmla_lane', which expects an SVE vector type} } */
+  svmla_lane (f32, 1, f32, 0); /* { dg-error {passing 'int' to argument 2 of 'svmla_lane', which expects an SVE vector type} } */
+  svmla_lane (f32, f32, 1, 0); /* { dg-error {passing 'int' to argument 3 of 'svmla_lane', which expects an SVE vector type} } */
+  svmla_lane (f32, f64, f32, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svmla_lane', but previous arguments had type 'svfloat32_t'} } */
+  svmla_lane (f32, f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svmla_lane', but previous arguments had type 'svfloat32_t'} } */
+  svmla_lane (f32, f32, f32, s32); /* { dg-error {argument 4 of 'svmla_lane' must be an integer constant expression} } */
+  svmla_lane (f32, f32, f32, i); /* { dg-error {argument 4 of 'svmla_lane' must be an integer constant expression} } */
+
+  svmla_lane (f16, f16, f16, 0);
+  svmla_lane (f16, f16, f16, 7);
+  svmla_lane (f16, f16, f16, 8); /* { dg-error {passing 8 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 7\]} } */
+  svmla_lane (f16, f16, f16, -1); /* { dg-error {passing -1 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 7\]} } */
+
+  svmla_lane (f32, f32, f32, 0);
+  svmla_lane (f32, f32, f32, 3);
+  svmla_lane (f32, f32, f32, 4); /* { dg-error {passing 4 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 3\]} } */
+  svmla_lane (f32, f32, f32, -1); /* { dg-error {passing -1 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 3\]} } */
+
+  svmla_lane (f64, f64, f64, 0);
+  svmla_lane (f64, f64, f64, 1);
+  svmla_lane (f64, f64, f64, 2); /* { dg-error {passing 2 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 1\]} } */
+  svmla_lane (f64, f64, f64, -1); /* { dg-error {passing -1 to argument 4 of 'svmla_lane', which expects a value in the range \[0, 1\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_lane_rotate_1.c
new file mode 100644 (file)
index 0000000..bccc6c7
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat16_t f16, svfloat32_t f32, svfloat64_t f64,
+    svint32_t s32, int i)
+{
+  svcmla_lane (f32, f32, f32, 0); /* { dg-error {too few arguments to function 'svcmla_lane'} } */
+  svcmla_lane (f32, f32, f32, 0, 90, 90); /* { dg-error {too many arguments to function 'svcmla_lane'} } */
+  svcmla_lane (pg, pg, pg, 0, 90); /* { dg-error {'svcmla_lane' has no form that takes 'svbool_t' arguments} } */
+  svcmla_lane (s32, s32, s32, 0, 90); /* { dg-error {'svcmla_lane' has no form that takes 'svint32_t' arguments} } */
+  svcmla_lane (f64, f64, f64, 0, 90); /* { dg-error {'svcmla_lane' has no form that takes 'svfloat64_t' arguments} } */
+  svcmla_lane (1, f32, f32, 0, 90); /* { dg-error {passing 'int' to argument 1 of 'svcmla_lane', which expects an SVE vector type} } */
+  svcmla_lane (f32, 1, f32, 0, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_lane', which expects an SVE vector type} } */
+  svcmla_lane (f32, f32, 1, 0, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_lane', which expects an SVE vector type} } */
+  svcmla_lane (f32, f64, f32, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svcmla_lane', but previous arguments had type 'svfloat32_t'} } */
+  svcmla_lane (f32, f32, f64, 0, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_lane', but previous arguments had type 'svfloat32_t'} } */
+  svcmla_lane (f32, f32, f32, s32, 0); /* { dg-error {argument 4 of 'svcmla_lane' must be an integer constant expression} } */
+  svcmla_lane (f32, f32, f32, i, 0); /* { dg-error {argument 4 of 'svcmla_lane' must be an integer constant expression} } */
+
+  svcmla_lane (f16, f16, f16, 0, 0);
+  svcmla_lane (f16, f16, f16, 3, 0);
+  svcmla_lane (f16, f16, f16, 4, 0); /* { dg-error {passing 4 to argument 4 of 'svcmla_lane', which expects a value in the range \[0, 3\]} } */
+  svcmla_lane (f16, f16, f16, -1, 0); /* { dg-error {passing -1 to argument 4 of 'svcmla_lane', which expects a value in the range \[0, 3\]} } */
+
+  svcmla_lane (f32, f32, f32, 0, 0);
+  svcmla_lane (f32, f32, f32, 1, 0);
+  svcmla_lane (f32, f32, f32, 2, 0); /* { dg-error {passing 2 to argument 4 of 'svcmla_lane', which expects a value in the range \[0, 1\]} } */
+  svcmla_lane (f32, f32, f32, -1, 0); /* { dg-error {passing -1 to argument 4 of 'svcmla_lane', which expects a value in the range \[0, 1\]} } */
+
+  svcmla_lane (f32, f32, f32, 0, -90); /* { dg-error {passing -90 to argument 5 of 'svcmla_lane', which expects 0, 90, 180 or 270} } */
+  svcmla_lane (f32, f32, f32, 0, 0);
+  svcmla_lane (f32, f32, f32, 0, 1); /* { dg-error {passing 1 to argument 5 of 'svcmla_lane', which expects 0, 90, 180 or 270} } */
+  svcmla_lane (f32, f32, f32, 0, 90);
+  svcmla_lane (f32, f32, f32, 0, 180);
+  svcmla_lane (f32, f32, f32, 0, 270);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_opt_n_1.c
new file mode 100644 (file)
index 0000000..c4a80e9
--- /dev/null
@@ -0,0 +1,34 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+    svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+  svmla_x (pg, u8, u8); /* { dg-error {too few arguments to function 'svmla_x'} } */
+  svmla_x (pg, u8, u8, u8, u8); /* { dg-error {too many arguments to function 'svmla_x'} } */
+  svmla_x (u8, u8, u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svmla_x', which expects 'svbool_t'} } */
+  svmla_x (pg, pg, pg, pg); /* { dg-error {'svmla_x' has no form that takes 'svbool_t' arguments} } */
+  svmla_x (pg, 1, u8, u8); /* { dg-error {passing 'int' to argument 2 of 'svmla_x', which expects an SVE vector type} } */
+  svmla_x (pg, u8, s8, u8); /* { dg-error {passing 'svint8_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, u8, u8);
+  svmla_x (pg, u8, s16, u8); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, u16, u8); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, f16, u8); /* { dg-error {passing 'svfloat16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, pg, u8); /* { dg-error {passing 'svbool_t' to argument 3 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, 0, u8); /* { dg-error {passing 'int' to argument 3 of 'svmla_x', which expects an SVE vector type} } */
+  svmla_x (pg, u8, u8, s8); /* { dg-error {passing 'svint8_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, u8, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, u8, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, u8, f16); /* { dg-error {passing 'svfloat16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, u8, pg); /* { dg-error {passing 'svbool_t' to argument 4 of 'svmla_x', but previous arguments had type 'svuint8_t'} } */
+  svmla_x (pg, u8, u8, 0);
+
+  svmla_x (pg, f16, s16, f16); /* { dg-error {passing 'svint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+  svmla_x (pg, f16, u16, f16); /* { dg-error {passing 'svuint16_t' to argument 3 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+  svmla_x (pg, f16, f16, s16); /* { dg-error {passing 'svint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+  svmla_x (pg, f16, f16, u16); /* { dg-error {passing 'svuint16_t' to argument 4 of 'svmla_x', but previous arguments had type 'svfloat16_t'} } */
+  svmla_x (pg, f16, f16, f16);
+  svmla_x (pg, f16, f16, 1);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_lane_1.c
new file mode 100644 (file)
index 0000000..e81552b
--- /dev/null
@@ -0,0 +1,63 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svint16_t s16, svuint16_t u16,
+    svint32_t s32, svuint32_t u32, svint64_t s64, svuint64_t u64,
+    svfloat32_t f32, int i)
+{
+  svdot_lane (u32, u8, u8); /* { dg-error {too few arguments to function 'svdot_lane'} } */
+  svdot_lane (u32, u8, u8, 0, 0); /* { dg-error {too many arguments to function 'svdot_lane'} } */
+  svdot_lane (0, u8, u8, 0); /* { dg-error {passing 'int' to argument 1 of 'svdot_lane', which expects an SVE vector type} } */
+  svdot_lane (pg, u8, u8, 0); /* { dg-error {'svdot_lane' has no form that takes 'svbool_t' arguments} } */
+  svdot_lane (u8, u8, u8, 0); /* { dg-error {'svdot_lane' has no form that takes 'svuint8_t' arguments} } */
+  svdot_lane (f32, u8, u8, 0); /* { dg-error {'svdot_lane' has no form that takes 'svfloat32_t' arguments} } */
+  svdot_lane (u32, u8, u8, 0);
+  svdot_lane (u32, 0, u8, 0); /* { dg-error {passing 'int' to argument 2 of 'svdot_lane', which expects an SVE vector type} } */
+  svdot_lane (u32, u8, 0, 0); /* { dg-error {passing 'int' to argument 3 of 'svdot_lane', which expects an SVE vector type} } */
+
+  svdot_lane (s32, s8, s8, 0);
+  svdot_lane (s32, u8, s8, 0); /* { dg-error {arguments 1 and 2 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svint32_t' and 'svuint8_t' respectively} } */
+  svdot_lane (s32, s8, u8, 0); /* { dg-error {arguments 1 and 3 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svint32_t' and 'svuint8_t' respectively} } */
+  svdot_lane (s32, s32, s32, 0); /* { dg-error {passing 'svint32_t' instead of the expected 'svint8_t' to argument 2 of 'svdot_lane', after passing 'svint32_t' to argument 1} } */
+
+  svdot_lane (u32, u8, u8, 0);
+  svdot_lane (u32, s8, u8, 0); /* { dg-error {arguments 1 and 2 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+  svdot_lane (u32, u8, s8, 0); /* { dg-error {arguments 1 and 3 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+  svdot_lane (u32, u32, u32, 0); /* { dg-error {passing 'svuint32_t' instead of the expected 'svuint8_t' to argument 2 of 'svdot_lane', after passing 'svuint32_t' to argument 1} } */
+
+  svdot_lane (s64, s16, s16, 0);
+  svdot_lane (s64, u16, s16, 0); /* { dg-error {arguments 1 and 2 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svint64_t' and 'svuint16_t' respectively} } */
+  svdot_lane (s64, s16, u16, 0); /* { dg-error {arguments 1 and 3 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svint64_t' and 'svuint16_t' respectively} } */
+  svdot_lane (s64, s64, s64, 0); /* { dg-error {passing 'svint64_t' instead of the expected 'svint16_t' to argument 2 of 'svdot_lane', after passing 'svint64_t' to argument 1} } */
+
+  svdot_lane (u64, u16, u16, 0);
+  svdot_lane (u64, s16, u16, 0); /* { dg-error {arguments 1 and 2 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svuint64_t' and 'svint16_t' respectively} } */
+  svdot_lane (u64, u16, s16, 0); /* { dg-error {arguments 1 and 3 of 'svdot_lane' must have the same signedness, but the values passed here have type 'svuint64_t' and 'svint16_t' respectively} } */
+  svdot_lane (u64, u64, u64, 0); /* { dg-error {passing 'svuint64_t' instead of the expected 'svuint16_t' to argument 2 of 'svdot_lane', after passing 'svuint64_t' to argument 1} } */
+
+  svdot_lane (s32, s8, s8, i); /* { dg-error {argument 4 of 'svdot_lane' must be an integer constant expression} } */
+  svdot_lane (s32, s8, s8, 0);
+  svdot_lane (s32, s8, s8, 3);
+  svdot_lane (s32, s8, s8, 4);  /* { dg-error {passing 4 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 3\]} } */
+  svdot_lane (s32, s8, s8, -1);  /* { dg-error {passing -1 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 3\]} } */
+
+  svdot_lane (u32, u8, u8, i); /* { dg-error {argument 4 of 'svdot_lane' must be an integer constant expression} } */
+  svdot_lane (u32, u8, u8, 0);
+  svdot_lane (u32, u8, u8, 3);
+  svdot_lane (u32, u8, u8, 4);  /* { dg-error {passing 4 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 3\]} } */
+  svdot_lane (u32, u8, u8, -1);  /* { dg-error {passing -1 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 3\]} } */
+
+  svdot_lane (s64, s16, s16, i); /* { dg-error {argument 4 of 'svdot_lane' must be an integer constant expression} } */
+  svdot_lane (s64, s16, s16, 0);
+  svdot_lane (s64, s16, s16, 1);
+  svdot_lane (s64, s16, s16, 2);  /* { dg-error {passing 2 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 1\]} } */
+  svdot_lane (s64, s16, s16, -1);  /* { dg-error {passing -1 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 1\]} } */
+
+  svdot_lane (u64, u16, u16, i); /* { dg-error {argument 4 of 'svdot_lane' must be an integer constant expression} } */
+  svdot_lane (u64, u16, u16, 0);
+  svdot_lane (u64, u16, u16, 1);
+  svdot_lane (u64, u16, u16, 2);  /* { dg-error {passing 2 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 1\]} } */
+  svdot_lane (u64, u16, u16, -1);  /* { dg-error {passing -1 to argument 4 of 'svdot_lane', which expects a value in the range \[0, 1\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_1.c
new file mode 100644 (file)
index 0000000..b41e6fc
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+svint32_t
+f1 (svuint32_t u32, svuint8_t u8, svint8_t s8)
+{
+  svdot_u32 (u32); /* { dg-error {too few arguments to function 'svdot_u32'} } */
+  svdot_u32 (u32, u8, u8, u32); /* { dg-error {too many arguments to function 'svdot_u32'} } */
+  svdot_u32 (u32, u32, u8); /* { dg-error {incompatible type for argument 2 of 'svdot_u32'} } */
+  svdot_u32 (u32, s8, u8); /* { dg-error {incompatible type for argument 2 of 'svdot_u32'} } */
+  svdot_u32 (u32, u8, u32); /* { dg-error {incompatible type for argument 3 of 'svdot_u32'} } */
+  svdot_u32 (u32, u8, s8); /* { dg-error {incompatible type for argument 3 of 'svdot_u32'} } */
+  return svdot_u32 (u32, u8, u8); /* { dg-error {incompatible types when returning type 'svuint32_t' but 'svint32_t' was expected} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_qq_opt_n_2.c
new file mode 100644 (file)
index 0000000..fee4096
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8, svuint32_t u32,
+    svfloat32_t f32)
+{
+  svdot (u32, u8); /* { dg-error {too few arguments to function 'svdot'} } */
+  svdot (u32, u8, u8, u8); /* { dg-error {too many arguments to function 'svdot'} } */
+  svdot (0, u8, u8); /* { dg-error {passing 'int' to argument 1 of 'svdot', which expects an SVE vector type} } */
+  svdot (pg, u8, u8); /* { dg-error {'svdot' has no form that takes 'svbool_t' arguments} } */
+  svdot (u8, u8, u8); /* { dg-error {'svdot' has no form that takes 'svuint8_t' arguments} } */
+  svdot (f32, u8, u8); /* { dg-error {'svdot' has no form that takes 'svfloat32_t' arguments} } */
+  svdot (u32, u8, u8);
+  svdot (u32, 0, u8); /* { dg-error {passing 'int' to argument 2 of 'svdot', which expects an SVE vector type} } */
+  svdot (u32, s8, u8); /* { dg-error {arguments 1 and 2 of 'svdot' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+  svdot (u32, u8, 0);
+  svdot (u32, u8, s8); /* { dg-error {arguments 1 and 3 of 'svdot' must have the same signedness, but the values passed here have type 'svuint32_t' and 'svint8_t' respectively} } */
+  svdot (u32, u32, u32); /* { dg-error {passing 'svuint32_t' instead of the expected 'svuint8_t' to argument 2 of 'svdot', after passing 'svuint32_t' to argument 1} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/ternary_rotate_1.c
new file mode 100644 (file)
index 0000000..f340e3d
--- /dev/null
@@ -0,0 +1,26 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+{
+  svcmla_x (pg, f32, f32, f32); /* { dg-error {too few arguments to function 'svcmla_x'} } */
+  svcmla_x (pg, f32, f32, f32, 90, 90); /* { dg-error {too many arguments to function 'svcmla_x'} } */
+  svcmla_x (f32, f32, f32, f32, 90); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svcmla_x', which expects 'svbool_t'} } */
+  svcmla_x (pg, pg, pg, pg, 90); /* { dg-error {'svcmla_x' has no form that takes 'svbool_t' arguments} } */
+  svcmla_x (pg, s32, s32, s32, 90); /* { dg-error {'svcmla_x' has no form that takes 'svint32_t' arguments} } */
+  svcmla_x (pg, 1, f32, f32, 90); /* { dg-error {passing 'int' to argument 2 of 'svcmla_x', which expects an SVE vector type} } */
+  svcmla_x (pg, f32, 1, f32, 90); /* { dg-error {passing 'int' to argument 3 of 'svcmla_x', which expects an SVE vector type} } */
+  svcmla_x (pg, f32, f32, 1, 90); /* { dg-error {passing 'int' to argument 4 of 'svcmla_x', which expects an SVE vector type} } */
+  svcmla_x (pg, f32, f64, f32, 90); /* { dg-error {passing 'svfloat64_t' to argument 3 of 'svcmla_x', but previous arguments had type 'svfloat32_t'} } */
+  svcmla_x (pg, f32, f32, f64, 90); /* { dg-error {passing 'svfloat64_t' to argument 4 of 'svcmla_x', but previous arguments had type 'svfloat32_t'} } */
+  svcmla_x (pg, f32, f32, f32, s32); /* { dg-error {argument 5 of 'svcmla_x' must be an integer constant expression} } */
+  svcmla_x (pg, f32, f32, f32, i); /* { dg-error {argument 5 of 'svcmla_x' must be an integer constant expression} } */
+  svcmla_x (pg, f32, f32, f32, -90); /* { dg-error {passing -90 to argument 5 of 'svcmla_x', which expects 0, 90, 180 or 270} } */
+  svcmla_x (pg, f32, f32, f32, 0);
+  svcmla_x (pg, f32, f32, f32, 1); /* { dg-error {passing 1 to argument 5 of 'svcmla_x', which expects 0, 90, 180 or 270} } */
+  svcmla_x (pg, f32, f32, f32, 90);
+  svcmla_x (pg, f32, f32, f32, 180);
+  svcmla_x (pg, f32, f32, f32, 270);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/tmad_1.c
new file mode 100644 (file)
index 0000000..8b98fc2
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svfloat32_t f32, svfloat64_t f64, svint32_t s32, int i)
+{
+  svtmad (f32, f32); /* { dg-error {too few arguments to function 'svtmad'} } */
+  svtmad (f32, f32, 0, 0); /* { dg-error {too many arguments to function 'svtmad'} } */
+  svtmad (pg, pg, 0); /* { dg-error {'svtmad' has no form that takes 'svbool_t' arguments} } */
+  svtmad (s32, s32, 0); /* { dg-error {'svtmad' has no form that takes 'svint32_t' arguments} } */
+  svtmad (1, f32, 0); /* { dg-error {passing 'int' to argument 1 of 'svtmad', which expects an SVE vector type} } */
+  svtmad (f32, 1, 0); /* { dg-error {passing 'int' to argument 2 of 'svtmad', which expects an SVE vector type} } */
+  svtmad (f32, f64, 0); /* { dg-error {passing 'svfloat64_t' to argument 2 of 'svtmad', but previous arguments had type 'svfloat32_t'} } */
+  svtmad (f32, f32, s32); /* { dg-error {argument 3 of 'svtmad' must be an integer constant expression} } */
+  svtmad (f32, f32, i); /* { dg-error {argument 3 of 'svtmad' must be an integer constant expression} } */
+  svtmad (f32, f32, -1); /* { dg-error {passing -1 to argument 3 of 'svtmad', which expects a value in the range \[0, 7\]} } */
+  svtmad (f32, f32, 0);
+  svtmad (f32, f32, 1);
+  svtmad (f32, f32, 7);
+  svtmad (f32, f32, 8); /* { dg-error {passing 8 to argument 3 of 'svtmad', which expects a value in the range \[0, 7\]} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_1.c
new file mode 100644 (file)
index 0000000..70b2d9d
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svbool_t; /* { dg-message "note: previous declaration of 'svbool_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'svbool_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_10.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_10.c
new file mode 100644 (file)
index 0000000..8278c1c
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+typedef struct svint8x2_t svint8x2_t; /* { dg-message "note: previous declaration of 'svint8x2_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {conflicting types for 'svint8x2_t'} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_11.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_11.c
new file mode 100644 (file)
index 0000000..2147df7
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+/* This isn't explicitly allowed or disallowed, but mustn't ICE.  */
+struct svint8x2_t;
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void
+f (svint8x2_t *a, struct svint8x2_t *b)
+{
+  *a = *b; /* { dg-error {dereferencing pointer to incomplete type} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_12.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_12.c
new file mode 100644 (file)
index 0000000..1a6ccbd
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-do compile } */
+
+/* This isn't explicitly allowed or disallowed, but mustn't ICE.  */
+struct svint8x2_t { int x; };
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void
+f (svint8x2_t *a, struct svint8x2_t *b)
+{
+  *a = *b; /* { dg-error {incompatible types} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_13.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_13.c
new file mode 100644 (file)
index 0000000..62bab1f
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-message "note: previous declaration of 'svint8x2_t' was here" } */
+
+int svint8x2_t;  /* { dg-error {'svint8x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_14.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_14.c
new file mode 100644 (file)
index 0000000..0f00db1
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+enum svpattern { FOO }; /* { dg-message "note: originally defined here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {redeclaration of 'enum svpattern'} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_15.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_15.c
new file mode 100644 (file)
index 0000000..ea97217
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-message "note: originally defined here" } */
+
+enum svpattern { FOO }; /* { dg-error {redeclaration of 'enum svpattern'} } */
+enum foo { SV_ALL }; /* { dg-error {redeclaration of enumerator 'SV_ALL'} } */
+typedef int SV_POW2; /* { dg-error {'SV_POW2' redeclared as different kind of symbol} } */
+int SV_VL3; /* { dg-error {'SV_VL3' redeclared as different kind of symbol} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_16.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_16.c
new file mode 100644 (file)
index 0000000..a59dabc
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+struct svpattern { int x; };
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {'svpattern' defined as wrong kind of tag} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_17.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_17.c
new file mode 100644 (file)
index 0000000..027fdb2
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+struct svpattern { int x; }; /* { dg-error {'svpattern' defined as wrong kind of tag} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_18.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_18.c
new file mode 100644 (file)
index 0000000..b670615
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svpattern; /* OK in C.  */
+
+#pragma GCC aarch64 "arm_sve.h"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_19.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_19.c
new file mode 100644 (file)
index 0000000..c6379f7
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+int svpattern; /* OK in C.  */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_2.c
new file mode 100644 (file)
index 0000000..ffd86ae
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svint8_t; /* { dg-message "note: previous declaration of 'svint8_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'svint8_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_20.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_20.c
new file mode 100644 (file)
index 0000000..3d770a9
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do compile } */
+
+enum foo { SV_VL4 };
+typedef int SV_POW2;
+int SV_ALL;
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {redeclaration of enumerator 'SV_VL4'} } */
+/* { dg-error {'SV_POW2' redeclared as different kind of symbol} "" { target *-*-* } .-1 } */
+/* { dg-error {'SV_ALL' redeclared as different kind of symbol} "" { target *-*-* } .-2 } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_3.c
new file mode 100644 (file)
index 0000000..f42dd96
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svuint16_t; /* { dg-message "note: previous declaration of 'svuint16_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'svuint16_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_4.c
new file mode 100644 (file)
index 0000000..91c95a1
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svfloat32_t; /* { dg-message "note: previous declaration of 'svfloat32_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'svfloat32_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_5.c
new file mode 100644 (file)
index 0000000..3cb6b8a
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+typedef int svbool_t; /* { dg-message "note: previous declaration of 'svbool_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {conflicting types for 'svbool_t'} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_6.c
new file mode 100644 (file)
index 0000000..c051897
--- /dev/null
@@ -0,0 +1,6 @@
+/* { dg-do compile } */
+
+typedef __SVBool_t svbool_t; /* { dg-message "note: previous declaration of 'svbool_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error {redefinition of typedef 'svbool_t'} } */
+
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_7.c
new file mode 100644 (file)
index 0000000..fd40631
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "-std=gnu90" } */
+
+typedef __SVBool_t svbool_t;
+
+/* Without -pedantic-errors this should compile.  */
+#pragma GCC aarch64 "arm_sve.h"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_8.c
new file mode 100644 (file)
index 0000000..41614a3
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+int svint8x2_t; /* { dg-message "note: previous declaration of 'svint8x2_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {'svint8x2_t' redeclared} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_9.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/type_redef_9.c
new file mode 100644 (file)
index 0000000..83b6855
--- /dev/null
@@ -0,0 +1,5 @@
+/* { dg-do compile } */
+
+typedef int svint8x2_t; /* { dg-message "note: previous declaration of 'svint8x2_t' was here" } */
+
+#pragma GCC aarch64 "arm_sve.h"  /* { dg-error {conflicting types for 'svint8x2_t'} } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_1.c
new file mode 100644 (file)
index 0000000..eef85a0
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32)
+{
+  svabs_m (s32, pg); /* { dg-error {too few arguments to function 'svabs_m'} } */
+  svabs_m (s32, pg, s32, s32); /* { dg-error {too many arguments to function 'svabs_m'} } */
+  svabs_m (0, pg, s32); /* { dg-error {passing 'int' to argument 1 of 'svabs_m', which expects an SVE vector type} } */
+  svabs_m (s32, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svabs_m', which expects 'svbool_t'} } */
+  svabs_m (s32, 0, s32); /* { dg-error {passing 'int' to argument 2 of 'svabs_m', which expects 'svbool_t'} } */
+  svabs_m (s32, pg, s32);
+  svabs_m (u32, pg, u32); /* { dg-error {'svabs_m' has no form that takes 'svuint32_t' arguments} } */
+  svabs_m (f32, pg, f32);
+  svabs_m (s32, pg, u32); /* { dg-error {passing 'svuint32_t' to argument 3 of 'svabs_m', but previous arguments had type 'svint32_t'} } */
+  svabs_m (s32, pg, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svabs_m', but previous arguments had type 'svint32_t'} } */
+  svabs_m (s32, pg, pg); /* { dg-error {passing 'svbool_t' to argument 3 of 'svabs_m', but previous arguments had type 'svint32_t'} } */
+  svabs_m (pg, pg, s32); /* { dg-error {passing 'svint32_t' to argument 3 of 'svabs_m', but previous arguments had type 'svbool_t'} } */
+  svabs_m (pg, pg, pg); /* { dg-error {'svabs_m' has no form that takes 'svbool_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_2.c
new file mode 100644 (file)
index 0000000..e94673a
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8)
+{
+  svabs_x (pg); /* { dg-error {too few arguments to function 'svabs_x'} } */
+  svabs_x (pg, s8, s8); /* { dg-error {too many arguments to function 'svabs_x'} } */
+  svabs_x (s8, s8); /* { dg-error {passing 'svint8_t' to argument 1 of 'svabs_x', which expects 'svbool_t'} } */
+  svabs_x (pg, pg); /* { dg-error {'svabs_x' has no form that takes 'svbool_t' arguments} } */
+  svabs_x (pg, 1); /* { dg-error {passing 'int' to argument 2 of 'svabs_x', which expects an SVE vector type} } */
+  svabs_x (pg, s8);
+  svabs_x (pg, u8); /* { dg-error {'svabs_x' has no form that takes 'svuint8_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_1.c
new file mode 100644 (file)
index 0000000..caa4e62
--- /dev/null
@@ -0,0 +1,73 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, svfloat16_t f16, svfloat32_t f32,
+      svfloat64_t f64)
+{
+  svcvt_f64_x (pg); /* { dg-error {too few arguments to function 'svcvt_f64_x'} } */
+  svcvt_f64_x (pg, s32, 0); /* { dg-error {too many arguments to function 'svcvt_f64_x'} } */
+  svcvt_f64_x (s32, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svcvt_f64_x', which expects 'svbool_t'} } */
+  svcvt_f64_x (pg, 0); /* { dg-error {passing 'int' to argument 2 of 'svcvt_f64_x', which expects an SVE vector type} } */
+
+  svcvt_f64_x (pg, s8); /* { dg-error {'svcvt_f64_x' has no form that takes 'svint8_t' arguments} } */
+  svcvt_f64_x (pg, s16); /* { dg-error {'svcvt_f64_x' has no form that takes 'svint16_t' arguments} } */
+  svcvt_f64_x (pg, s32);
+  svcvt_f64_x (pg, s64);
+  svcvt_f64_x (pg, u8); /* { dg-error {'svcvt_f64_x' has no form that takes 'svuint8_t' arguments} } */
+  svcvt_f64_x (pg, u16); /* { dg-error {'svcvt_f64_x' has no form that takes 'svuint16_t' arguments} } */
+  svcvt_f64_x (pg, u32);
+  svcvt_f64_x (pg, u64);
+  svcvt_f64_x (pg, f16);
+  svcvt_f64_x (pg, f32);
+  svcvt_f64_x (pg, f64); /* { dg-error {'svcvt_f64_x' has no form that takes 'svfloat64_t' arguments} } */
+
+  svcvt_f32_x (pg, s8); /* { dg-error {'svcvt_f32_x' has no form that takes 'svint8_t' arguments} } */
+  svcvt_f32_x (pg, s16); /* { dg-error {'svcvt_f32_x' has no form that takes 'svint16_t' arguments} } */
+  svcvt_f32_x (pg, s32);
+  svcvt_f32_x (pg, s64);
+  svcvt_f32_x (pg, u8); /* { dg-error {'svcvt_f32_x' has no form that takes 'svuint8_t' arguments} } */
+  svcvt_f32_x (pg, u16); /* { dg-error {'svcvt_f32_x' has no form that takes 'svuint16_t' arguments} } */
+  svcvt_f32_x (pg, u32);
+  svcvt_f32_x (pg, u64);
+  svcvt_f32_x (pg, f16);
+  svcvt_f32_x (pg, f32); /* { dg-error {'svcvt_f32_x' has no form that takes 'svfloat32_t' arguments} } */
+  svcvt_f32_x (pg, f64);
+
+  svcvt_f16_x (pg, s8); /* { dg-error {'svcvt_f16_x' has no form that takes 'svint8_t' arguments} } */
+  svcvt_f16_x (pg, s16);
+  svcvt_f16_x (pg, s32);
+  svcvt_f16_x (pg, s64);
+  svcvt_f16_x (pg, u8); /* { dg-error {'svcvt_f16_x' has no form that takes 'svuint8_t' arguments} } */
+  svcvt_f16_x (pg, u16);
+  svcvt_f16_x (pg, u32);
+  svcvt_f16_x (pg, u64);
+  svcvt_f16_x (pg, f16); /* { dg-error {'svcvt_f16_x' has no form that takes 'svfloat16_t' arguments} } */
+  svcvt_f16_x (pg, f32);
+  svcvt_f16_x (pg, f64);
+
+  svcvt_s64_x (pg, f16);
+  svcvt_s64_x (pg, f32);
+  svcvt_s64_x (pg, f64);
+
+  svcvt_s32_x (pg, f16);
+  svcvt_s32_x (pg, f32);
+  svcvt_s32_x (pg, f64);
+
+  svcvt_s16_x (pg, f16);
+  svcvt_s16_x (pg, f32); /* { dg-error {'svcvt_s16_x' has no form that takes 'svfloat32_t' arguments} } */
+  svcvt_s16_x (pg, f64); /* { dg-error {'svcvt_s16_x' has no form that takes 'svfloat64_t' arguments} } */
+
+  svcvt_u64_x (pg, f16);
+  svcvt_u64_x (pg, f32);
+  svcvt_u64_x (pg, f64);
+
+  svcvt_u32_x (pg, f16);
+  svcvt_u32_x (pg, f32);
+  svcvt_u32_x (pg, f64);
+
+  svcvt_u16_x (pg, f16);
+  svcvt_u16_x (pg, f32); /* { dg-error {'svcvt_u16_x' has no form that takes 'svfloat32_t' arguments} } */
+  svcvt_u16_x (pg, f64); /* { dg-error {'svcvt_u16_x' has no form that takes 'svfloat64_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_convert_2.c
new file mode 100644 (file)
index 0000000..ddbd93b
--- /dev/null
@@ -0,0 +1,76 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svint32_t s32, svuint32_t u32,
+      svint64_t s64, svuint64_t u64, svfloat16_t f16, svfloat32_t f32,
+      svfloat64_t f64)
+{
+  svcvt_f64_m (f64, pg); /* { dg-error {too few arguments to function 'svcvt_f64_m'} } */
+  svcvt_f64_m (f64, pg, s32, 0); /* { dg-error {too many arguments to function 'svcvt_f64_m'} } */
+  svcvt_f64_m (f32, pg, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svcvt_f64_m', which expects 'svfloat64_t'} } */
+  svcvt_f64_m (0, pg, s32); /* { dg-error {passing 'int' to argument 1 of 'svcvt_f64_m', which expects 'svfloat64_t'} } */
+  svcvt_f64_m (pg, pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svcvt_f64_m', which expects 'svfloat64_t'} } */
+  svcvt_f64_m (f64, s32, s32); /* { dg-error {passing 'svint32_t' to argument 2 of 'svcvt_f64_m', which expects 'svbool_t'} } */
+  svcvt_f64_m (f64, pg, 0); /* { dg-error {passing 'int' to argument 3 of 'svcvt_f64_m', which expects an SVE vector type} } */
+
+  svcvt_f64_m (f64, pg, s8); /* { dg-error {'svcvt_f64_m' has no form that takes 'svint8_t' arguments} } */
+  svcvt_f64_m (f64, pg, s16); /* { dg-error {'svcvt_f64_m' has no form that takes 'svint16_t' arguments} } */
+  svcvt_f64_m (f64, pg, s32);
+  svcvt_f64_m (f64, pg, s64);
+  svcvt_f64_m (f64, pg, u8); /* { dg-error {'svcvt_f64_m' has no form that takes 'svuint8_t' arguments} } */
+  svcvt_f64_m (f64, pg, u16); /* { dg-error {'svcvt_f64_m' has no form that takes 'svuint16_t' arguments} } */
+  svcvt_f64_m (f64, pg, u32);
+  svcvt_f64_m (f64, pg, u64);
+  svcvt_f64_m (f64, pg, f16);
+  svcvt_f64_m (f64, pg, f32);
+  svcvt_f64_m (f64, pg, f64); /* { dg-error {'svcvt_f64_m' has no form that takes 'svfloat64_t' arguments} } */
+
+  svcvt_f32_m (f32, pg, s8); /* { dg-error {'svcvt_f32_m' has no form that takes 'svint8_t' arguments} } */
+  svcvt_f32_m (f32, pg, s16); /* { dg-error {'svcvt_f32_m' has no form that takes 'svint16_t' arguments} } */
+  svcvt_f32_m (f32, pg, s32);
+  svcvt_f32_m (f32, pg, s64);
+  svcvt_f32_m (f32, pg, u8); /* { dg-error {'svcvt_f32_m' has no form that takes 'svuint8_t' arguments} } */
+  svcvt_f32_m (f32, pg, u16); /* { dg-error {'svcvt_f32_m' has no form that takes 'svuint16_t' arguments} } */
+  svcvt_f32_m (f32, pg, u32);
+  svcvt_f32_m (f32, pg, u64);
+  svcvt_f32_m (f32, pg, f16);
+  svcvt_f32_m (f32, pg, f32); /* { dg-error {'svcvt_f32_m' has no form that takes 'svfloat32_t' arguments} } */
+  svcvt_f32_m (f32, pg, f64);
+
+  svcvt_f16_m (f16, pg, s8); /* { dg-error {'svcvt_f16_m' has no form that takes 'svint8_t' arguments} } */
+  svcvt_f16_m (f16, pg, s16);
+  svcvt_f16_m (f16, pg, s32);
+  svcvt_f16_m (f16, pg, s64);
+  svcvt_f16_m (f16, pg, u8); /* { dg-error {'svcvt_f16_m' has no form that takes 'svuint8_t' arguments} } */
+  svcvt_f16_m (f16, pg, u16);
+  svcvt_f16_m (f16, pg, u32);
+  svcvt_f16_m (f16, pg, u64);
+  svcvt_f16_m (f16, pg, f16); /* { dg-error {'svcvt_f16_m' has no form that takes 'svfloat16_t' arguments} } */
+  svcvt_f16_m (f16, pg, f32);
+  svcvt_f16_m (f16, pg, f64);
+
+  svcvt_s64_m (s64, pg, f16);
+  svcvt_s64_m (s64, pg, f32);
+  svcvt_s64_m (s64, pg, f64);
+
+  svcvt_s32_m (s32, pg, f16);
+  svcvt_s32_m (s32, pg, f32);
+  svcvt_s32_m (s32, pg, f64);
+
+  svcvt_s16_m (s16, pg, f16);
+  svcvt_s16_m (s16, pg, f32); /* { dg-error {'svcvt_s16_m' has no form that takes 'svfloat32_t' arguments} } */
+  svcvt_s16_m (s16, pg, f64); /* { dg-error {'svcvt_s16_m' has no form that takes 'svfloat64_t' arguments} } */
+
+  svcvt_u64_m (u64, pg, f16);
+  svcvt_u64_m (u64, pg, f32);
+  svcvt_u64_m (u64, pg, f64);
+
+  svcvt_u32_m (u32, pg, f16);
+  svcvt_u32_m (u32, pg, f32);
+  svcvt_u32_m (u32, pg, f64);
+
+  svcvt_u16_m (u16, pg, f16);
+  svcvt_u16_m (u16, pg, f32); /* { dg-error {'svcvt_u16_m' has no form that takes 'svfloat32_t' arguments} } */
+  svcvt_u16_m (u16, pg, f64); /* { dg-error {'svcvt_u16_m' has no form that takes 'svfloat64_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_count_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_count_1.c
new file mode 100644 (file)
index 0000000..888b525
--- /dev/null
@@ -0,0 +1,24 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64)
+{
+  svclz_m (u32, pg); /* { dg-error {too few arguments to function 'svclz_m'} } */
+  svclz_m (u32, pg, s32, s32); /* { dg-error {too many arguments to function 'svclz_m'} } */
+  svclz_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svclz_m', which expects an SVE vector type} } */
+  svclz_m (u32, u32, f32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+  svclz_m (u32, 0, f32); /* { dg-error {passing 'int' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+  svclz_m (u32, pg, s32);
+  svclz_m (u32, pg, u32);
+  svclz_m (u32, pg, f32); /* { dg-error {'svclz_m' has no form that takes 'svfloat32_t' arguments} } */
+  svclz_m (u32, pg, pg); /* { dg-error {'svclz_m' has no form that takes 'svbool_t' arguments} } */
+
+  svclz_m (pg, pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+  svclz_m (s32, pg, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+  svclz_m (f32, pg, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+  svclz_m (s64, pg, s32); /* { dg-error {passing 'svint64_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+  svclz_m (u64, pg, s32); /* { dg-error {arguments 1 and 3 of 'svclz_m' must have the same element size, but the values passed here have type 'svuint64_t' and 'svint32_t' respectively} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_count_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_count_2.c
new file mode 100644 (file)
index 0000000..233e847
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-flax-vector-conversions" } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint32_t s32, svuint32_t u32, svfloat32_t f32,
+    svint64_t s64, svuint64_t u64)
+{
+  svclz_m (u32, pg); /* { dg-error {too few arguments to function 'svclz_m'} } */
+  svclz_m (u32, pg, s32, s32); /* { dg-error {too many arguments to function 'svclz_m'} } */
+  svclz_m (0, pg, f32); /* { dg-error {passing 'int' to argument 1 of 'svclz_m', which expects an SVE vector type} } */
+  svclz_m (u32, u32, f32); /* { dg-error {passing 'svuint32_t' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+  svclz_m (u32, 0, f32); /* { dg-error {passing 'int' to argument 2 of 'svclz_m', which expects 'svbool_t'} } */
+  svclz_m (u32, pg, s32);
+  svclz_m (u32, pg, u32);
+  svclz_m (u32, pg, f32); /* { dg-error {'svclz_m' has no form that takes 'svfloat32_t' arguments} } */
+  svclz_m (u32, pg, pg); /* { dg-error {'svclz_m' has no form that takes 'svbool_t' arguments} } */
+
+  svclz_m (pg, pg, s32); /* { dg-error {passing 'svbool_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+  svclz_m (s32, pg, s32); /* { dg-error {passing 'svint32_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+  svclz_m (f32, pg, s32); /* { dg-error {passing 'svfloat32_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+  svclz_m (s64, pg, s32); /* { dg-error {passing 'svint64_t' to argument 1 of 'svclz_m', which expects a vector of unsigned integers} } */
+  svclz_m (u64, pg, s32); /* { dg-error {arguments 1 and 3 of 'svclz_m' must have the same element size, but the values passed here have type 'svuint64_t' and 'svint32_t' respectively} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_count_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_count_3.c
new file mode 100644 (file)
index 0000000..da57b07
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svuint8_t u8)
+{
+  svcnt_x (pg); /* { dg-error {too few arguments to function 'svcnt_x'} } */
+  svcnt_x (pg, u8, u8); /* { dg-error {too many arguments to function 'svcnt_x'} } */
+  svcnt_x (u8, u8); /* { dg-error {passing 'svuint8_t' to argument 1 of 'svcnt_x', which expects 'svbool_t'} } */
+  svcnt_x (pg, pg); /* { dg-error {'svcnt_x' has no form that takes 'svbool_t' arguments} } */
+  svcnt_x (pg, 1); /* { dg-error {passing 'int' to argument 2 of 'svcnt_x', which expects an SVE vector type} } */
+  svcnt_x (pg, u8);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_uint_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_uint_1.c
new file mode 100644 (file)
index 0000000..9c8acdf
--- /dev/null
@@ -0,0 +1,19 @@
+/* { dg-do compile } */
+
+#include <arm_sve.h>
+
+void
+f1 (svbool_t pg, svint8_t s8, svuint8_t u8,
+    svint16_t s16, svuint16_t u16, svfloat16_t f16)
+{
+  svexpa (); /* { dg-error {too few arguments to function 'svexpa'} } */
+  svexpa (u16, u16); /* { dg-error {too many arguments to function 'svexpa'} } */
+  svexpa (1); /* { dg-error {passing 'int' to argument 1 of 'svexpa', which expects an SVE vector type} } */
+  svexpa (pg); /* { dg-error {passing 'svbool_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+  svexpa (s8); /* { dg-error {passing 'svint8_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+  svexpa (s16); /* { dg-error {passing 'svint16_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+  svexpa (f16); /* { dg-error {passing 'svfloat16_t' to argument 1 of 'svexpa', which expects a vector of unsigned integers} } */
+
+  svexpa (u8); /* { dg-error {'svexpa' has no form that takes 'svuint8_t' arguments} } */
+  svexpa (u16);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_widen_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/unary_widen_1.c
new file mode 100644 (file)
index 0000000..95a97a7
--- /dev/null
@@ -0,0 +1,25 @@
+#include <arm_sve.h>
+
+void
+test (svbool_t pg, svint8_t s8, svuint8_t u8,
+      svint16_t s16, svuint16_t u16, svfloat16_t f16,
+      svint32_t s32, svuint32_t u32, svfloat32_t f32,
+      svint64_t s64, svuint64_t u64, svfloat64_t f64, float f, int i)
+{
+  svunpklo (); /* { dg-error {too few arguments to function 'svunpklo'} } */
+  svunpklo (pg, s8); /* { dg-error {too many arguments to function 'svunpklo'} } */
+  svunpklo (i); /* { dg-error {passing 'int' to argument 1 of 'svunpklo', which expects an SVE vector type} } */
+  svunpklo (f); /* { dg-error {passing 'float' to argument 1 of 'svunpklo', which expects an SVE vector type} } */
+  svunpklo (pg);
+  svunpklo (s8);
+  svunpklo (s16);
+  svunpklo (s32);
+  svunpklo (s64); /* { dg-error {'svunpklo' has no form that takes 'svint64_t' arguments} } */
+  svunpklo (u8);
+  svunpklo (u16);
+  svunpklo (u32);
+  svunpklo (u64); /* { dg-error {'svunpklo' has no form that takes 'svuint64_t' arguments} } */
+  svunpklo (f16); /* { dg-error {'svunpklo' has no form that takes 'svfloat16_t' arguments} } */
+  svunpklo (f32); /* { dg-error {'svunpklo' has no form that takes 'svfloat32_t' arguments} } */
+  svunpklo (f64); /* { dg-error {'svunpklo' has no form that takes 'svfloat64_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_1.c
new file mode 100644 (file)
index 0000000..37524c2
--- /dev/null
@@ -0,0 +1,17 @@
+#include <arm_sve.h>
+
+void
+f (svint8_t s8, svuint16_t u16, svfloat32_t f32,
+   svint16x2_t s16x2, svuint32x3_t u32x3, svfloat64x4_t f64x4,
+   svbool_t pg)
+{
+  s8 = no_ret_s8 (); /* { dg-error {incompatible types when assigning to type 'svint8_t' from type 'int'} } */
+  u16 = no_ret_u16 (); /* { dg-error {incompatible types when assigning to type 'svuint16_t' from type 'int'} } */
+  f32 = no_ret_f32 (); /* { dg-error {incompatible types when assigning to type 'svfloat32_t' from type 'int'} } */
+  s16x2 = no_ret_s16x2 (); /* { dg-error {incompatible types when assigning to type 'svint16x2_t' from type 'int'} } */
+  u32x3 = no_ret_u32x3 (); /* { dg-error {incompatible types when assigning to type 'svuint32x3_t' from type 'int'} } */
+  f64x4 = no_ret_f64x4 (); /* { dg-error {incompatible types when assigning to type 'svfloat64x4_t' from type 'int'} } */
+  pg = no_ret_pg (); /* { dg-error {incompatible types when assigning to type 'svbool_t' from type 'int'} } */
+
+  no_pass_args (pg, u16, f32, s16x2, u32x3, f64x4, pg);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general-c/undeclared_2.c
new file mode 100644 (file)
index 0000000..7e869bd
--- /dev/null
@@ -0,0 +1,15 @@
+#include <arm_sve.h>
+
+void
+f (svint8_t s8, svuint16_t u16, svfloat32_t f32,
+   svint16x2_t s16x2, svuint32x3_t u32x3, svfloat64x4_t f64x4,
+   svbool_t pg)
+{
+  s8 = svlsr_x (pg, s8, 1); /* { dg-error {'svlsr_x' has no form that takes 'svint8_t' arguments} } */
+  u16 = svneg_x (pg, u16); /* { dg-error {'svneg_x' has no form that takes 'svuint16_t' arguments} } */
+  f32 = svclz_x (pg, f32); /* { dg-error {'svclz_x' has no form that takes 'svfloat32_t' arguments} } */
+  s16x2 = svcreate2 (s8); /* { dg-error {too few arguments to function 'svcreate2'} } */
+  u32x3 = svcreate3 (u16, u16, f32); /* { dg-error {passing 'svfloat32_t' to argument 3 of 'svcreate3', but previous arguments had type 'svuint16_t'} } */
+  f64x4 = svcreate4 (f32, f32, f32, f32, f32); /* { dg-error {too many arguments to function 'svcreate4'} } */
+  pg = svadd_x (pg, pg, pg); /* { dg-error {'svadd_x' has no form that takes 'svbool_t' arguments} } */
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/add_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/add_1.c
new file mode 100644 (file)
index 0000000..f5c6285
--- /dev/null
@@ -0,0 +1,13 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-optimized" } */
+
+#include <arm_sve.h>
+
+void
+foo (svint8_t *res1, svint8_t *res2, svbool_t pg, svint8_t a, svint8_t b)
+{
+  *res1 = svadd_m (pg, a, b);
+  *res2 = svadd_m (pg, a, b);
+}
+
+/* { dg-final { scan-tree-dump-times {svadd_s8_m|svadd_m} 1 "optimized" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/and_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/and_1.c
new file mode 100644 (file)
index 0000000..59348ce
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svand_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svand_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tands\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tand\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/bic_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/bic_1.c
new file mode 100644 (file)
index 0000000..e1c4849
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svbic_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svbic_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbics\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tbic\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brka_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brka_1.c
new file mode 100644 (file)
index 0000000..24aa8f3
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svbrka_m (x, pg, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svbrka_m (x, pg, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkas\tp[0-9]+\.b, p[0-9]+/m,} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrka\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brka_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brka_2.c
new file mode 100644 (file)
index 0000000..8aa3388
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, int *any, svbool_t *ptr)
+{
+  svbool_t res = svbrka_z (pg, x);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, int *any)
+{
+  svbool_t res = svbrka_z (pg, x);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkas\tp[0-9]+\.b, p[0-9]+/z,} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrka\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkb_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkb_1.c
new file mode 100644 (file)
index 0000000..07e3622
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svbrkb_m (x, pg, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svbrkb_m (x, pg, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkbs\tp[0-9]+\.b, p[0-9]+/m,} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkb\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkb_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkb_2.c
new file mode 100644 (file)
index 0000000..ee677ce
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, int *any, svbool_t *ptr)
+{
+  svbool_t res = svbrkb_z (pg, x);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, int *any)
+{
+  svbool_t res = svbrkb_z (pg, x);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkbs\tp[0-9]+\.b, p[0-9]+/z,} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkb\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkn_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkn_1.c
new file mode 100644 (file)
index 0000000..7fd9318
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svbrkn_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svbrkn_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkns\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkn\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkpa_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkpa_1.c
new file mode 100644 (file)
index 0000000..18cca37
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svbrkpa_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svbrkpa_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkpas\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkpa\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkpb_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/brkpb_1.c
new file mode 100644 (file)
index 0000000..73eb709
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svbrkpb_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svbrkpb_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tbrkpbs\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tbrkpb\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_1.c
new file mode 100644 (file)
index 0000000..dd8f6c4
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint64_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svcmpeq_wide (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint64_t y, int *any)
+{
+  svbool_t res = svcmpeq_wide (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpeq\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_2.c
new file mode 100644 (file)
index 0000000..028d375
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svint8_t x, svint8_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svcmpeq (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svint8_t x, svint8_t y, int *any)
+{
+  svbool_t res = svcmpeq (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svint8_t x, int *any, svbool_t *ptr)
+{
+  svbool_t res = svcmpeq (pg, x, 10);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svint8_t x, int *any)
+{
+  svbool_t res = svcmpeq (pg, x, 10);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tcmpeq\t} 4 } } */
+/* { dg-final { scan-assembler-times {\tcmpeq\t[^\n]*, #10} 2 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cmpeq_3.c
new file mode 100644 (file)
index 0000000..115b26c
--- /dev/null
@@ -0,0 +1,38 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svfloat32_t x, svfloat32_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svcmpeq (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svfloat32_t x, svfloat32_t y, int *any)
+{
+  svbool_t res = svcmpeq (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+void
+test3 (svbool_t pg, svfloat32_t x, int *any, svbool_t *ptr)
+{
+  svbool_t res = svcmpeq (pg, x, 0.0);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svfloat32_t x, int *any)
+{
+  svbool_t res = svcmpeq (pg, x, 0.0);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tfcmeq\t} 4 } } */
+/* { dg-final { scan-assembler-times {\tfcmeq\t[^\n]*, #0\.0} 2 } } */
+/* { dg-final { scan-assembler-times {\tptest\t} 4 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntb_pat_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntb_pat_1.c
new file mode 100644 (file)
index 0000000..d57a75c
--- /dev/null
@@ -0,0 +1,132 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O -msve-vector-bits=256" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** cntb_pow2:
+**     mov     x0, #?32
+**     ret
+*/
+uint64_t cntb_pow2 () { return svcntb_pat (SV_POW2); }
+
+/*
+** cntb_vl1:
+**     mov     x0, #?1
+**     ret
+*/
+uint64_t cntb_vl1 () { return svcntb_pat (SV_VL1); }
+
+/*
+** cntb_vl2:
+**     mov     x0, #?2
+**     ret
+*/
+uint64_t cntb_vl2 () { return svcntb_pat (SV_VL2); }
+
+/*
+** cntb_vl3:
+**     mov     x0, #?3
+**     ret
+*/
+uint64_t cntb_vl3 () { return svcntb_pat (SV_VL3); }
+
+/*
+** cntb_vl4:
+**     mov     x0, #?4
+**     ret
+*/
+uint64_t cntb_vl4 () { return svcntb_pat (SV_VL4); }
+
+/*
+** cntb_vl5:
+**     mov     x0, #?5
+**     ret
+*/
+uint64_t cntb_vl5 () { return svcntb_pat (SV_VL5); }
+
+/*
+** cntb_vl6:
+**     mov     x0, #?6
+**     ret
+*/
+uint64_t cntb_vl6 () { return svcntb_pat (SV_VL6); }
+
+/*
+** cntb_vl7:
+**     mov     x0, #?7
+**     ret
+*/
+uint64_t cntb_vl7 () { return svcntb_pat (SV_VL7); }
+
+/*
+** cntb_vl8:
+**     mov     x0, #?8
+**     ret
+*/
+uint64_t cntb_vl8 () { return svcntb_pat (SV_VL8); }
+
+/*
+** cntb_vl16:
+**     mov     x0, #?16
+**     ret
+*/
+uint64_t cntb_vl16 () { return svcntb_pat (SV_VL16); }
+
+/*
+** cntb_vl32:
+**     mov     x0, #?32
+**     ret
+*/
+uint64_t cntb_vl32 () { return svcntb_pat (SV_VL32); }
+
+/*
+** cntb_vl64:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntb_vl64 () { return svcntb_pat (SV_VL64); }
+
+/*
+** cntb_vl128:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntb_vl128 () { return svcntb_pat (SV_VL128); }
+
+/*
+** cntb_vl256:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntb_vl256 () { return svcntb_pat (SV_VL256); }
+
+/*
+** cntb_mul3:
+**     mov     x0, #?30
+**     ret
+*/
+uint64_t cntb_mul3 () { return svcntb_pat (SV_MUL3); }
+
+/*
+** cntb_mul4:
+**     mov     x0, #?32
+**     ret
+*/
+uint64_t cntb_mul4 () { return svcntb_pat (SV_MUL4); }
+
+/*
+** cntb_all:
+**     mov     x0, #?32
+**     ret
+*/
+uint64_t cntb_all () { return svcntb_pat (SV_ALL); }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntd_pat_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntd_pat_1.c
new file mode 100644 (file)
index 0000000..d93a320
--- /dev/null
@@ -0,0 +1,132 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O -msve-vector-bits=256" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** cntd_pow2:
+**     mov     x0, #?4
+**     ret
+*/
+uint64_t cntd_pow2 () { return svcntd_pat (SV_POW2); }
+
+/*
+** cntd_vl1:
+**     mov     x0, #?1
+**     ret
+*/
+uint64_t cntd_vl1 () { return svcntd_pat (SV_VL1); }
+
+/*
+** cntd_vl2:
+**     mov     x0, #?2
+**     ret
+*/
+uint64_t cntd_vl2 () { return svcntd_pat (SV_VL2); }
+
+/*
+** cntd_vl3:
+**     mov     x0, #?3
+**     ret
+*/
+uint64_t cntd_vl3 () { return svcntd_pat (SV_VL3); }
+
+/*
+** cntd_vl4:
+**     mov     x0, #?4
+**     ret
+*/
+uint64_t cntd_vl4 () { return svcntd_pat (SV_VL4); }
+
+/*
+** cntd_vl5:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntd_vl5 () { return svcntd_pat (SV_VL5); }
+
+/*
+** cntd_vl6:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntd_vl6 () { return svcntd_pat (SV_VL6); }
+
+/*
+** cntd_vl7:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntd_vl7 () { return svcntd_pat (SV_VL7); }
+
+/*
+** cntd_vl8:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntd_vl8 () { return svcntd_pat (SV_VL8); }
+
+/*
+** cntd_vl16:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntd_vl16 () { return svcntd_pat (SV_VL16); }
+
+/*
+** cntd_vl32:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntd_vl32 () { return svcntd_pat (SV_VL32); }
+
+/*
+** cntd_vl64:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntd_vl64 () { return svcntd_pat (SV_VL64); }
+
+/*
+** cntd_vl128:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntd_vl128 () { return svcntd_pat (SV_VL128); }
+
+/*
+** cntd_vl256:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntd_vl256 () { return svcntd_pat (SV_VL256); }
+
+/*
+** cntd_mul3:
+**     mov     x0, #?3
+**     ret
+*/
+uint64_t cntd_mul3 () { return svcntd_pat (SV_MUL3); }
+
+/*
+** cntd_mul4:
+**     mov     x0, #?4
+**     ret
+*/
+uint64_t cntd_mul4 () { return svcntd_pat (SV_MUL4); }
+
+/*
+** cntd_all:
+**     mov     x0, #?4
+**     ret
+*/
+uint64_t cntd_all () { return svcntd_pat (SV_ALL); }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cnth_pat_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cnth_pat_1.c
new file mode 100644 (file)
index 0000000..bd988f5
--- /dev/null
@@ -0,0 +1,132 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O -msve-vector-bits=256" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** cnth_pow2:
+**     mov     x0, #?16
+**     ret
+*/
+uint64_t cnth_pow2 () { return svcnth_pat (SV_POW2); }
+
+/*
+** cnth_vl1:
+**     mov     x0, #?1
+**     ret
+*/
+uint64_t cnth_vl1 () { return svcnth_pat (SV_VL1); }
+
+/*
+** cnth_vl2:
+**     mov     x0, #?2
+**     ret
+*/
+uint64_t cnth_vl2 () { return svcnth_pat (SV_VL2); }
+
+/*
+** cnth_vl3:
+**     mov     x0, #?3
+**     ret
+*/
+uint64_t cnth_vl3 () { return svcnth_pat (SV_VL3); }
+
+/*
+** cnth_vl4:
+**     mov     x0, #?4
+**     ret
+*/
+uint64_t cnth_vl4 () { return svcnth_pat (SV_VL4); }
+
+/*
+** cnth_vl5:
+**     mov     x0, #?5
+**     ret
+*/
+uint64_t cnth_vl5 () { return svcnth_pat (SV_VL5); }
+
+/*
+** cnth_vl6:
+**     mov     x0, #?6
+**     ret
+*/
+uint64_t cnth_vl6 () { return svcnth_pat (SV_VL6); }
+
+/*
+** cnth_vl7:
+**     mov     x0, #?7
+**     ret
+*/
+uint64_t cnth_vl7 () { return svcnth_pat (SV_VL7); }
+
+/*
+** cnth_vl8:
+**     mov     x0, #?8
+**     ret
+*/
+uint64_t cnth_vl8 () { return svcnth_pat (SV_VL8); }
+
+/*
+** cnth_vl16:
+**     mov     x0, #?16
+**     ret
+*/
+uint64_t cnth_vl16 () { return svcnth_pat (SV_VL16); }
+
+/*
+** cnth_vl32:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cnth_vl32 () { return svcnth_pat (SV_VL32); }
+
+/*
+** cnth_vl64:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cnth_vl64 () { return svcnth_pat (SV_VL64); }
+
+/*
+** cnth_vl128:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cnth_vl128 () { return svcnth_pat (SV_VL128); }
+
+/*
+** cnth_vl256:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cnth_vl256 () { return svcnth_pat (SV_VL256); }
+
+/*
+** cnth_mul3:
+**     mov     x0, #?15
+**     ret
+*/
+uint64_t cnth_mul3 () { return svcnth_pat (SV_MUL3); }
+
+/*
+** cnth_mul4:
+**     mov     x0, #?16
+**     ret
+*/
+uint64_t cnth_mul4 () { return svcnth_pat (SV_MUL4); }
+
+/*
+** cnth_all:
+**     mov     x0, #?16
+**     ret
+*/
+uint64_t cnth_all () { return svcnth_pat (SV_ALL); }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntw_pat_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/cntw_pat_1.c
new file mode 100644 (file)
index 0000000..53c8435
--- /dev/null
@@ -0,0 +1,132 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O -msve-vector-bits=256" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** cntw_pow2:
+**     mov     x0, #?8
+**     ret
+*/
+uint64_t cntw_pow2 () { return svcntw_pat (SV_POW2); }
+
+/*
+** cntw_vl1:
+**     mov     x0, #?1
+**     ret
+*/
+uint64_t cntw_vl1 () { return svcntw_pat (SV_VL1); }
+
+/*
+** cntw_vl2:
+**     mov     x0, #?2
+**     ret
+*/
+uint64_t cntw_vl2 () { return svcntw_pat (SV_VL2); }
+
+/*
+** cntw_vl3:
+**     mov     x0, #?3
+**     ret
+*/
+uint64_t cntw_vl3 () { return svcntw_pat (SV_VL3); }
+
+/*
+** cntw_vl4:
+**     mov     x0, #?4
+**     ret
+*/
+uint64_t cntw_vl4 () { return svcntw_pat (SV_VL4); }
+
+/*
+** cntw_vl5:
+**     mov     x0, #?5
+**     ret
+*/
+uint64_t cntw_vl5 () { return svcntw_pat (SV_VL5); }
+
+/*
+** cntw_vl6:
+**     mov     x0, #?6
+**     ret
+*/
+uint64_t cntw_vl6 () { return svcntw_pat (SV_VL6); }
+
+/*
+** cntw_vl7:
+**     mov     x0, #?7
+**     ret
+*/
+uint64_t cntw_vl7 () { return svcntw_pat (SV_VL7); }
+
+/*
+** cntw_vl8:
+**     mov     x0, #?8
+**     ret
+*/
+uint64_t cntw_vl8 () { return svcntw_pat (SV_VL8); }
+
+/*
+** cntw_vl16:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntw_vl16 () { return svcntw_pat (SV_VL16); }
+
+/*
+** cntw_vl32:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntw_vl32 () { return svcntw_pat (SV_VL32); }
+
+/*
+** cntw_vl64:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntw_vl64 () { return svcntw_pat (SV_VL64); }
+
+/*
+** cntw_vl128:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntw_vl128 () { return svcntw_pat (SV_VL128); }
+
+/*
+** cntw_vl256:
+**     mov     x0, #?0
+**     ret
+*/
+uint64_t cntw_vl256 () { return svcntw_pat (SV_VL256); }
+
+/*
+** cntw_mul3:
+**     mov     x0, #?6
+**     ret
+*/
+uint64_t cntw_mul3 () { return svcntw_pat (SV_MUL3); }
+
+/*
+** cntw_mul4:
+**     mov     x0, #?8
+**     ret
+*/
+uint64_t cntw_mul4 () { return svcntw_pat (SV_MUL4); }
+
+/*
+** cntw_all:
+**     mov     x0, #?8
+**     ret
+*/
+uint64_t cntw_all () { return svcntw_pat (SV_ALL); }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/debug_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/debug_1.c
new file mode 100644 (file)
index 0000000..0442efe
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-options "-g" } */
+
+#include <arm_sve.h>
+
+svbool_t f_b (svbool_t x) { return x; }
+svint8_t f_s8 (svint8_t x) { return x; }
+svuint8_t f_u8 (svuint8_t x) { return x; }
+svint16_t f_s16 (svint16_t x) { return x; }
+svuint16_t f_u16 (svuint16_t x) { return x; }
+svfloat16_t f_f16 (svfloat16_t x) { return x; }
+svint32_t f_s32 (svint32_t x) { return x; }
+svuint32_t f_u32 (svuint32_t x) { return x; }
+svfloat32_t f_f32 (svfloat32_t x) { return x; }
+svint64_t f_s64 (svint64_t x) { return x; }
+svuint64_t f_u64 (svuint64_t x) { return x; }
+svfloat64_t f_f64 (svfloat64_t x) { return x; }
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/debug_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/debug_2.c
new file mode 100644 (file)
index 0000000..63a26d2
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-options "-g" } */
+
+#include <arm_sve.h>
+
+svbool_t f_b (svbool_t x) { return svptrue_b32 (); }
+svint8_t f_s8 (svint8_t x) { return svdup_s8 (0); }
+svuint8_t f_u8 (svuint8_t x) { return svdup_u8 (1); }
+svint16_t f_s16 (svint16_t x) { return svdup_s16 (2); }
+svuint16_t f_u16 (svuint16_t x) { return svdup_u16 (3); }
+svfloat16_t f_f16 (svfloat16_t x) { return svdup_f16 (4); }
+svint32_t f_s32 (svint32_t x) { return svdup_s32 (5); }
+svuint32_t f_u32 (svuint32_t x) { return svdup_u32 (6); }
+svfloat32_t f_f32 (svfloat32_t x) { return svdup_f32 (7); }
+svint64_t f_s64 (svint64_t x) { return svdup_s64 (8); }
+svuint64_t f_u64 (svuint64_t x) { return svdup_u64 (9); }
+svfloat64_t f_f64 (svfloat64_t x) { return svdup_f64 (10); }
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/debug_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/debug_3.c
new file mode 100644 (file)
index 0000000..ac151e4
--- /dev/null
@@ -0,0 +1,39 @@
+/* { dg-options "-g" } */
+
+#include <arm_sve.h>
+
+svint8x2_t f2_s8 (svint8x2_t x) { return x; }
+svuint8x2_t f2_u8 (svuint8x2_t x) { return x; }
+svint16x2_t f2_s16 (svint16x2_t x) { return x; }
+svuint16x2_t f2_u16 (svuint16x2_t x) { return x; }
+svfloat16x2_t f2_f16 (svfloat16x2_t x) { return x; }
+svint32x2_t f2_s32 (svint32x2_t x) { return x; }
+svuint32x2_t f2_u32 (svuint32x2_t x) { return x; }
+svfloat32x2_t f2_f32 (svfloat32x2_t x) { return x; }
+svint64x2_t f2_s64 (svint64x2_t x) { return x; }
+svuint64x2_t f2_u64 (svuint64x2_t x) { return x; }
+svfloat64x2_t f2_f64 (svfloat64x2_t x) { return x; }
+
+svint8x3_t f3_s8 (svint8x3_t x) { return x; }
+svuint8x3_t f3_u8 (svuint8x3_t x) { return x; }
+svint16x3_t f3_s16 (svint16x3_t x) { return x; }
+svuint16x3_t f3_u16 (svuint16x3_t x) { return x; }
+svfloat16x3_t f3_f16 (svfloat16x3_t x) { return x; }
+svint32x3_t f3_s32 (svint32x3_t x) { return x; }
+svuint32x3_t f3_u32 (svuint32x3_t x) { return x; }
+svfloat32x3_t f3_f32 (svfloat32x3_t x) { return x; }
+svint64x3_t f3_s64 (svint64x3_t x) { return x; }
+svuint64x3_t f3_u64 (svuint64x3_t x) { return x; }
+svfloat64x3_t f3_f64 (svfloat64x3_t x) { return x; }
+
+svint8x4_t f4_s8 (svint8x4_t x) { return x; }
+svuint8x4_t f4_u8 (svuint8x4_t x) { return x; }
+svint16x4_t f4_s16 (svint16x4_t x) { return x; }
+svuint16x4_t f4_u16 (svuint16x4_t x) { return x; }
+svfloat16x4_t f4_f16 (svfloat16x4_t x) { return x; }
+svint32x4_t f4_s32 (svint32x4_t x) { return x; }
+svuint32x4_t f4_u32 (svuint32x4_t x) { return x; }
+svfloat32x4_t f4_f42 (svfloat32x4_t x) { return x; }
+svint64x4_t f4_s64 (svint64x4_t x) { return x; }
+svuint64x4_t f4_u64 (svuint64x4_t x) { return x; }
+svfloat64x4_t f4_f64 (svfloat64x4_t x) { return x; }
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/double_pragma_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/double_pragma_1.c
new file mode 100644 (file)
index 0000000..9b3c369
--- /dev/null
@@ -0,0 +1,7 @@
+/* { dg-do compile } */
+/* { dg-options "" } */
+
+/* It doesn't really matter if this produces errors about redefinitions,
+   but it mustn't trigger an ICE.  */
+#pragma GCC aarch64 "arm_sve.h"
+#pragma GCC aarch64 "arm_sve.h" /* { dg-error "duplicate definition of 'arm_sve.h'" } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_1.c
new file mode 100644 (file)
index 0000000..d71507b
--- /dev/null
@@ -0,0 +1,15 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlittle-endian" } */
+
+#include <arm_sve.h>
+
+svint32_t
+dupq (int x)
+{
+  return svdupq_s32 (x, 1, 2, 3);
+}
+
+/* { dg-final { scan-assembler {\tldr\tq[0-9]+,} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[0\], w0\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
+/* { dg-final { scan-assembler {\t\.word\t1\n\t\.word\t2\n\t\.word\t3\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_10.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_10.c
new file mode 100644 (file)
index 0000000..f8f797c
--- /dev/null
@@ -0,0 +1,66 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svbool_t __attribute__ ((noipa))
+make_b8 (int8_t x0, int8_t x1, int8_t x2, int8_t x3,
+        int8_t x4, int8_t x5, int8_t x6, int8_t x7,
+        int8_t x8, int8_t x9, int8_t xa, int8_t xb,
+        int8_t xc, int8_t xd, int8_t xe, int8_t xf)
+{
+  return svdupq_b8 (x0, x1, x2, x3, x4, x5, x6, x7,
+                   x8, x9, xa, xb, xc, xd, xe, xf);
+}
+
+svbool_t __attribute__ ((noipa))
+make_b16 (int16_t x0, int16_t x1, int16_t x2, int16_t x3,
+         int16_t x4, int16_t x5, int16_t x6, int16_t x7)
+{
+  return svdupq_b16 (x0, x1, x2, x3, x4, x5, x6, x7);
+}
+
+svbool_t __attribute__ ((noipa))
+make_b32 (int32_t x0, int32_t x1, int32_t x2, int32_t x3)
+{
+  return svdupq_b32 (x0, x1, x2, x3);
+}
+
+svbool_t __attribute__ ((noipa))
+make_b64 (int64_t x0, int64_t x1)
+{
+  return svdupq_b64 (x0, x1);
+}
+
+int8_t a[16] = { 1, 0, 0, -3, 0, 9, 11, 0, 0, 1, 0, -4, 9, 9, 0, 0 };
+
+int
+main ()
+{
+  svbool_t pg = svptrue_pat_b8 (SV_VL16);
+  svbool_t b8 = make_b8 (a[0], a[1], a[2], a[3],
+                        a[4], a[5], a[6], a[7],
+                        a[8], a[9], a[10], a[11],
+                        a[12], a[13], a[14], a[15]);
+  if (svptest_any (svptrue_b8 (),
+                  sveor_z (pg, b8, svcmpne (pg, svld1 (pg, a), 0))))
+    __builtin_abort ();
+
+  svbool_t b16 = make_b16 (a[0], a[1], a[2], a[3],
+                          a[4], a[5], a[6], a[7]);
+  if (svptest_any (svptrue_b16 (),
+                  sveor_z (pg, b16, svcmpne (pg, svld1sb_u16 (pg, a), 0))))
+    __builtin_abort ();
+
+  svbool_t b32 = make_b32 (a[0], a[1], a[2], a[3]);
+  if (svptest_any (svptrue_b32 (),
+                  sveor_z (pg, b32, svcmpne (pg, svld1sb_u32 (pg, a), 0))))
+    __builtin_abort ();
+
+  svbool_t b64 = make_b64 (a[0], a[1]);
+  if (svptest_any (svptrue_b64 (),
+                  sveor_z (pg, b64, svcmpne (pg, svld1sb_u64 (pg, a), 0))))
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_2.c
new file mode 100644 (file)
index 0000000..d494943
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbig-endian" } */
+
+/* To avoid needing big-endian header files.  */
+#pragma GCC aarch64 "arm_sve.h"
+
+svint32_t
+dupq (int x)
+{
+  return svdupq_s32 (x, 1, 2, 3);
+}
+
+/* { dg-final { scan-assembler {\tldr\tq[0-9]+,} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[0\], w0\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
+/* { dg-final { scan-assembler {\t\.word\t3\n\t\.word\t2\n\t\.word\t1\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_3.c
new file mode 100644 (file)
index 0000000..4bc8259
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlittle-endian" } */
+
+/* To avoid needing big-endian header files.  */
+#pragma GCC aarch64 "arm_sve.h"
+
+svint32_t
+dupq (int x)
+{
+  return svdupq_s32 (0, 1, x, 3);
+}
+
+/* { dg-final { scan-assembler {\tldr\tq[0-9]+,} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w0\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
+/* { dg-final { scan-assembler {\t\.word\t0\n\t\.word\t1\n\t\.word\t[^\n]*\n\t\.word\t3\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_4.c
new file mode 100644 (file)
index 0000000..6f9f9f2
--- /dev/null
@@ -0,0 +1,16 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbig-endian" } */
+
+/* To avoid needing big-endian header files.  */
+#pragma GCC aarch64 "arm_sve.h"
+
+svint32_t
+dupq (int x)
+{
+  return svdupq_s32 (0, 1, x, 3);
+}
+
+/* { dg-final { scan-assembler {\tldr\tq[0-9]+,} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w0\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
+/* { dg-final { scan-assembler {\t\.word\t3\n\t\.word\t[^\n]*\n\t\.word\t1\n\t\.word\t0\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_5.c
new file mode 100644 (file)
index 0000000..53426c9
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mlittle-endian" } */
+
+#include <arm_sve.h>
+
+svint32_t
+dupq (int x1, int x2, int x3, int x4)
+{
+  return svdupq_s32 (x1, x2, x3, x4);
+}
+
+/* { dg-final { scan-assembler-not {\tldr\t} } } */
+/* { dg-final { scan-assembler {, [wx]0\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[1\], w1\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w2\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[3\], w3\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_6.c
new file mode 100644 (file)
index 0000000..dfce5e7
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2 -mbig-endian" } */
+
+/* To avoid needing big-endian header files.  */
+#pragma GCC aarch64 "arm_sve.h"
+
+svint32_t
+dupq (int x1, int x2, int x3, int x4)
+{
+  return svdupq_s32 (x1, x2, x3, x4);
+}
+
+/* { dg-final { scan-assembler-not {\tldr\t} } } */
+/* { dg-final { scan-assembler {, [wx]0\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[1\], w1\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[2\], w2\n} } } */
+/* { dg-final { scan-assembler {\tins\tv[0-9]+\.s\[3\], w3\n} } } */
+/* { dg-final { scan-assembler {\tdup\tz[0-9]+\.q, z[0-9]+\.q\[0\]\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_7.c
new file mode 100644 (file)
index 0000000..08decb5
--- /dev/null
@@ -0,0 +1,66 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svint8_t __attribute__ ((noipa))
+make_s8 (int8_t x0, int8_t x1, int8_t x2, int8_t x3,
+        int8_t x4, int8_t x5, int8_t x6, int8_t x7,
+        int8_t x8, int8_t x9, int8_t xa, int8_t xb,
+        int8_t xc, int8_t xd, int8_t xe, int8_t xf)
+{
+  return svdupq_s8 (x0, x1, x2, x3, x4, x5, x6, x7,
+                   x8, x9, xa, xb, xc, xd, xe, xf);
+}
+
+svint16_t __attribute__ ((noipa))
+make_s16 (int16_t x0, int16_t x1, int16_t x2, int16_t x3,
+         int16_t x4, int16_t x5, int16_t x6, int16_t x7)
+{
+  return svdupq_s16 (x0, x1, x2, x3, x4, x5, x6, x7);
+}
+
+svint32_t __attribute__ ((noipa))
+make_s32 (int32_t x0, int32_t x1, int32_t x2, int32_t x3)
+{
+  return svdupq_s32 (x0, x1, x2, x3);
+}
+
+svint64_t __attribute__ ((noipa))
+make_s64 (int64_t x0, int64_t x1)
+{
+  return svdupq_s64 (x0, x1);
+}
+
+int8_t a[16] = { 1, -44, 91, -24, 101, -55, 77, 83,
+                -30, 69, 121, -128, -1, 13, 127, 26 };
+int16_t b[8] = { -716, -10288, 30604, -19258, -9418, -10435, -16001, 7300 };
+int32_t c[4] = { 1268374995, -1023602831, -891830021, -1793452959 };
+int64_t d[2] = { 0x123456789abcdefLL, -0x123456789abcdefLL };
+
+int
+main ()
+{
+  svbool_t pg = svptrue_pat_b8 (SV_VL16);
+  svint8_t s8 = make_s8 (a[0], a[1], a[2], a[3],
+                        a[4], a[5], a[6], a[7],
+                        a[8], a[9], a[10], a[11],
+                        a[12], a[13], a[14], a[15]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, s8, svld1 (pg, a))))
+    __builtin_abort ();
+
+  svint16_t s16 = make_s16 (b[0], b[1], b[2], b[3],
+                           b[4], b[5], b[6], b[7]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, s16, svld1 (pg, b))))
+    __builtin_abort ();
+
+  svint32_t s32 = make_s32 (c[0], c[1], c[2], c[3]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, s32, svld1 (pg, c))))
+    __builtin_abort ();
+
+  svint64_t s64 = make_s64 (d[0], d[1]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, s64, svld1 (pg, d))))
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_8.c
new file mode 100644 (file)
index 0000000..c20fb73
--- /dev/null
@@ -0,0 +1,66 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svuint8_t __attribute__ ((noipa))
+make_u8 (uint8_t x0, uint8_t x1, uint8_t x2, uint8_t x3,
+        uint8_t x4, uint8_t x5, uint8_t x6, uint8_t x7,
+        uint8_t x8, uint8_t x9, uint8_t xa, uint8_t xb,
+        uint8_t xc, uint8_t xd, uint8_t xe, uint8_t xf)
+{
+  return svdupq_u8 (x0, x1, x2, x3, x4, x5, x6, x7,
+                   x8, x9, xa, xb, xc, xd, xe, xf);
+}
+
+svuint16_t __attribute__ ((noipa))
+make_u16 (uint16_t x0, uint16_t x1, uint16_t x2, uint16_t x3,
+         uint16_t x4, uint16_t x5, uint16_t x6, uint16_t x7)
+{
+  return svdupq_u16 (x0, x1, x2, x3, x4, x5, x6, x7);
+}
+
+svuint32_t __attribute__ ((noipa))
+make_u32 (uint32_t x0, uint32_t x1, uint32_t x2, uint32_t x3)
+{
+  return svdupq_u32 (x0, x1, x2, x3);
+}
+
+svuint64_t __attribute__ ((noipa))
+make_u64 (uint64_t x0, uint64_t x1)
+{
+  return svdupq_u64 (x0, x1);
+}
+
+uint8_t a[16] = { 1, 212, 91, 232, 101, 201, 77, 83,
+                 226, 69, 121, 128, 255, 13, 127, 26 };
+uint16_t b[8] = { 64820, 55248, 30604, 46278, 56118, 55101, 49535, 7300 };
+uint32_t c[4] = { 1268374995, 3271364465, 3403137275, 2501514337 };
+uint64_t d[2] = { 0x123456789abcdefULL, 0xfedcba9876543210ULL };
+
+int
+main ()
+{
+  svbool_t pg = svptrue_pat_b8 (SV_VL16);
+  svuint8_t u8 = make_u8 (a[0], a[1], a[2], a[3],
+                         a[4], a[5], a[6], a[7],
+                         a[8], a[9], a[10], a[11],
+                         a[12], a[13], a[14], a[15]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, u8, svld1 (pg, a))))
+    __builtin_abort ();
+
+  svuint16_t u16 = make_u16 (b[0], b[1], b[2], b[3],
+                            b[4], b[5], b[6], b[7]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, u16, svld1 (pg, b))))
+    __builtin_abort ();
+
+  svuint32_t u32 = make_u32 (c[0], c[1], c[2], c[3]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, u32, svld1 (pg, c))))
+    __builtin_abort ();
+
+  svuint64_t u64 = make_u64 (d[0], d[1]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, u64, svld1 (pg, d))))
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_9.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_9.c
new file mode 100644 (file)
index 0000000..b29aa94
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+svfloat16_t __attribute__ ((noipa))
+make_f16 (float16_t x0, float16_t x1, float16_t x2, float16_t x3,
+         float16_t x4, float16_t x5, float16_t x6, float16_t x7)
+{
+  return svdupq_f16 (x0, x1, x2, x3, x4, x5, x6, x7);
+}
+
+svfloat32_t __attribute__ ((noipa))
+make_f32 (float32_t x0, float32_t x1, float32_t x2, float32_t x3)
+{
+  return svdupq_f32 (x0, x1, x2, x3);
+}
+
+svfloat64_t __attribute__ ((noipa))
+make_f64 (float64_t x0, float64_t x1)
+{
+  return svdupq_f64 (x0, x1);
+}
+
+float16_t a[8] = { 1.0, -4.25, 9.75, 6.5, -2.125, 5.5, -3.75, 7.625 };
+float32_t b[4] = { 1.0, -90.25, -11.75, 141.5 };
+float64_t c[2] = { 9221.5, -4491.25 };
+
+int
+main ()
+{
+  svbool_t pg = svptrue_pat_b8 (SV_VL16);
+  svfloat16_t f16 = make_f16 (a[0], a[1], a[2], a[3],
+                             a[4], a[5], a[6], a[7]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, f16, svld1 (pg, a))))
+    __builtin_abort ();
+
+  svfloat32_t f32 = make_f32 (b[0], b[1], b[2], b[3]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, f32, svld1 (pg, b))))
+    __builtin_abort ();
+
+  svfloat64_t f64 = make_f64 (c[0], c[1]);
+  if (svptest_any (svptrue_b8 (), svcmpne (pg, f64, svld1 (pg, c))))
+    __builtin_abort ();
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_1.c
new file mode 100644 (file)
index 0000000..32ccb08
--- /dev/null
@@ -0,0 +1,87 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+#ifndef TYPE
+#define TYPE svint8_t
+#define DUPQ svdupq_lane_s8
+#define INDEX svindex_s8
+#define COUNT 16
+#endif
+
+#define BASE 42
+
+TYPE __attribute__ ((noipa))
+dupq_var (TYPE x, uint64_t y)
+{
+  return DUPQ (x, y);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_0 (TYPE x)
+{
+  return DUPQ (x, 0);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_1 (TYPE x)
+{
+  return DUPQ (x, 1);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_2 (TYPE x)
+{
+  return DUPQ (x, 2);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_3 (TYPE x)
+{
+  return DUPQ (x, 3);
+}
+
+TYPE __attribute__ ((noipa))
+dupq_4 (TYPE x)
+{
+  return DUPQ (x, 4);
+}
+
+void __attribute__ ((noipa))
+check (TYPE x, uint64_t y)
+{
+  svbool_t pg = svptrue_b8 ();
+  if (y * 2 >= svcntd ())
+    {
+      if (svptest_any (pg, svcmpne (pg, x, 0)))
+       __builtin_abort ();
+    }
+  else
+    {
+      TYPE repeat = svand_x (pg, INDEX (0, 1), COUNT - 1);
+      TYPE expected = svadd_x (pg, repeat, BASE + y * COUNT);
+      if (svptest_any (pg, svcmpne (pg, x, expected)))
+       __builtin_abort ();
+    }
+}
+
+int
+main ()
+{
+  TYPE x = INDEX (BASE, 1);
+
+  check (dupq_0 (x), 0);
+  check (dupq_1 (x), 1);
+  check (dupq_2 (x), 2);
+  check (dupq_3 (x), 3);
+  check (dupq_4 (x), 4);
+
+  for (int i = 0; i < 63; ++i)
+    {
+      check (dupq_var (x, i), i);
+      check (dupq_var (x, (uint64_t) 1 << i), (uint64_t) 1 << i);
+    }
+
+  return 0;
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_2.c
new file mode 100644 (file)
index 0000000..40de1c7
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svuint8_t
+#define DUPQ svdupq_lane_u8
+#define INDEX svindex_u8
+#define COUNT 16
+
+#include "dupq_lane_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_3.c
new file mode 100644 (file)
index 0000000..4ebe895
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svint16_t
+#define DUPQ svdupq_lane_s16
+#define INDEX svindex_s16
+#define COUNT 8
+
+#include "dupq_lane_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_4.c
new file mode 100644 (file)
index 0000000..1be20c8
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svuint16_t
+#define DUPQ svdupq_lane_u16
+#define INDEX svindex_u16
+#define COUNT 8
+
+#include "dupq_lane_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_5.c
new file mode 100644 (file)
index 0000000..67554d0
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svint32_t
+#define DUPQ svdupq_lane_s32
+#define INDEX svindex_s32
+#define COUNT 4
+
+#include "dupq_lane_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_6.c
new file mode 100644 (file)
index 0000000..1914d23
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svuint32_t
+#define DUPQ svdupq_lane_u32
+#define INDEX svindex_u32
+#define COUNT 4
+
+#include "dupq_lane_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_7.c
new file mode 100644 (file)
index 0000000..d7a8e52
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svint64_t
+#define DUPQ svdupq_lane_s64
+#define INDEX svindex_s64
+#define COUNT 2
+
+#include "dupq_lane_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_8.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/dupq_lane_8.c
new file mode 100644 (file)
index 0000000..68655fe
--- /dev/null
@@ -0,0 +1,9 @@
+/* { dg-do run { target aarch64_sve_hw } } */
+/* { dg-options "-O2" } */
+
+#define TYPE svuint64_t
+#define DUPQ svdupq_lane_u64
+#define INDEX svindex_u64
+#define COUNT 2
+
+#include "dupq_lane_1.c"
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/eor_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/eor_1.c
new file mode 100644 (file)
index 0000000..357b0bf
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = sveor_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = sveor_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\teors\t} 2 } } */
+/* { dg-final { scan-assembler-not {\teor\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ld1_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ld1_1.c
new file mode 100644 (file)
index 0000000..c68a9ed
--- /dev/null
@@ -0,0 +1,25 @@
+/* { dg-do compile } */
+/* { dg-options "-O" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** nop1:
+**     ret
+*/
+void nop1 (int8_t *s) { svld1 (svptrue_b8 (), s); }
+
+/*
+** nop2:
+**     ret
+*/
+void nop2 (svbool_t pg, int16_t *s) { svld1 (pg, s); }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_1.c
new file mode 100644 (file)
index 0000000..79f8bee
--- /dev/null
@@ -0,0 +1,18 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that SETFFR comes first, however high the priority of the
+   LDFF1 is.  */
+svint8_t
+foo (svbool_t pg, int8_t *ptr)
+{
+  svsetffr ();
+  svint8_t x = svldff1 (pg, ptr);
+  x = svadd_x (pg, x, x);
+  x = svmul_x (pg, x, x);
+  return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_2.c
new file mode 100644 (file)
index 0000000..7c3c8d8
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that RDFFR comes after the LDFF1 and that the RDFFRs can
+   be CSEd.  */
+svint8_t
+foo (svbool_t pg, int8_t *__restrict ptr,
+     svbool_t *__restrict *__restrict preds)
+{
+  svsetffr ();
+  svint8_t x = svldff1 (pg, ptr);
+  *preds[0] = svrdffr ();
+  *preds[1] = svrdffr ();
+  return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffr\t} } } */
+/* { dg-final { scan-assembler-times {\trdffr\t} 1 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_3.c
new file mode 100644 (file)
index 0000000..41ad0bc
--- /dev/null
@@ -0,0 +1,21 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that LDFF1s can be reordered.  The load of x should come due
+   to its longer dependence chain.  */
+svint8_t
+foo (int8_t *ptr1, int8_t *ptr2)
+{
+  svsetffr ();
+  svbool_t pg = svptrue_b8 ();
+  svint8_t y = svldff1 (pg, ptr2);
+  svint8_t x = svldff1 (pg, ptr1);
+  x = svadd_x (pg, x, x);
+  x = svmul_x (pg, x, x);
+  x = svadd_x (pg, x, y);
+  return x;
+}
+
+/* { dg-final { scan-assembler {\tldff1b\tz[0-9]+\.b, p[0-7]/z, \[x0\]\n.*\tldff1b\tz[0-9]+\.b, p[0-7]/z, \[x1\]\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_4.c
new file mode 100644 (file)
index 0000000..c273021
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that we can use RDFFRS to test for a fault.  */
+svint8_t
+foo (svbool_t pg, int8_t *ptr, int *fault)
+{
+  svsetffr ();
+  svint8_t x = svldff1 (pg, ptr);
+  *fault = svptest_any (pg, svrdffr_z (pg));
+  return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffrs\t} } } */
+/* { dg-final { scan-assembler-not {\trdffr\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_5.c
new file mode 100644 (file)
index 0000000..76e7ab8
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that we can use RDFFRS to read the FFR while testing for a
+   fault.  */
+svint8_t
+foo (svbool_t pg, int8_t *ptr, svbool_t *pred, int *fault)
+{
+  svsetffr ();
+  svint8_t x = svldff1 (pg, ptr);
+  svbool_t ffr = svrdffr_z (pg);
+  *fault = svptest_any (pg, ffr);
+  *pred = ffr;
+  return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffrs\t} } } */
+/* { dg-final { scan-assembler-not {\trdffr\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_6.c
new file mode 100644 (file)
index 0000000..7110e5f
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that we can use RDFFRS to test for a fault.  */
+svint8_t
+foo (svbool_t pg, int8_t *ptr, int *fault)
+{
+  svsetffr ();
+  svint8_t x = svldff1 (pg, ptr);
+  *fault = svptest_any (svptrue_b8 (), svrdffr ());
+  return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffrs\t} } } */
+/* { dg-final { scan-assembler-not {\trdffr\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ldff1_7.c
new file mode 100644 (file)
index 0000000..355fe91
--- /dev/null
@@ -0,0 +1,20 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* Make sure that we can use RDFFRS to read the FFR while testing for a
+   fault.  */
+svint8_t
+foo (svbool_t pg, int8_t *ptr, svbool_t *pred, int *fault)
+{
+  svsetffr ();
+  svint8_t x = svldff1 (pg, ptr);
+  svbool_t ffr = svrdffr ();
+  *fault = svptest_any (svptrue_b8 (), ffr);
+  *pred = ffr;
+  return x;
+}
+
+/* { dg-final { scan-assembler {\tsetffr\n.*\tldff1b\t.*\trdffrs\t} } } */
+/* { dg-final { scan-assembler-not {\trdffr\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nand_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nand_1.c
new file mode 100644 (file)
index 0000000..0bc54c0
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svnand_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svnand_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tnands\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tnand\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nor_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nor_1.c
new file mode 100644 (file)
index 0000000..7973294
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svnor_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svnor_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tnors\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tnor\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_1.c
new file mode 100644 (file)
index 0000000..09dfacd
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-options "-march=armv8-a" } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void
+f (svbool_t *x, svint8_t *y)
+{
+  *x = svptrue_b8 (); /* { dg-error {ACLE function '(svbool_t svptrue_b8\(\)|svptrue_b8)' requires ISA extension 'sve'} } */
+  /* { dg-message {note: you can enable 'sve' using the command-line option '-march', or by using the 'target' attribute or pragma} "" { target *-*-* } .-1 } */
+  *x = svptrue_b8 ();
+  *x = svptrue_b8 ();
+  *x = svptrue_b8 ();
+  *x = svptrue_b8 ();
+  *x = svptrue_b8 ();
+  *x = svptrue_b8 ();
+  *y = svadd_m (*x, *y, 1);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_2.c
new file mode 100644 (file)
index 0000000..594be1c
--- /dev/null
@@ -0,0 +1,14 @@
+/* { dg-options "-march=armv8-a" } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+#pragma GCC target "+sve"
+
+void
+f (svbool_t *x, svint8_t *y)
+{
+  *x = svptrue_b8 ();
+  *y = svadd_m (*x, *y, 1);
+}
+
+/* { dg-final { scan-assembler {\tadd\tz[0-9]+\.b, p[0-7]/m, z[0-9]+\.b, z[0-9]+\.b\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/nosve_3.c
new file mode 100644 (file)
index 0000000..85f4eb3
--- /dev/null
@@ -0,0 +1,12 @@
+/* { dg-options "-march=armv8-a" } */
+
+#pragma GCC aarch64 "arm_sve.h"
+
+void __attribute__ ((target("+sve")))
+f (svbool_t *x, svint8_t *y)
+{
+  *x = svptrue_b8 ();
+  *y = svadd_m (*x, *y, 1);
+}
+
+/* { dg-final { scan-assembler {\tadd\tz[0-9]+\.b, p[0-7]/m, z[0-9]+\.b, z[0-9]+\.b\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/orn_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/orn_1.c
new file mode 100644 (file)
index 0000000..c3ed1eb
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svorn_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svorn_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\torns\t} 2 } } */
+/* { dg-final { scan-assembler-not {\torn\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/orr_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/orr_1.c
new file mode 100644 (file)
index 0000000..4456fa6
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t x, svbool_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svorr_z (pg, x, y);
+  *any = svptest_any (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t x, svbool_t y, int *any)
+{
+  svbool_t res = svorr_z (pg, x, y);
+  return svptest_any (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\torrs\t} 2 } } */
+/* { dg-final { scan-assembler-not {\torr\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pfirst_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pfirst_1.c
new file mode 100644 (file)
index 0000000..de1ff69
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, int *last, svbool_t *ptr)
+{
+  svbool_t res = svpfirst (pg, svpfalse ());
+  *last = svptest_last (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg)
+{
+  svbool_t res = svpfirst (pg, svpfalse ());
+  return svptest_last (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tpfirst\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_1.c
new file mode 100644 (file)
index 0000000..bf59cb9
--- /dev/null
@@ -0,0 +1,22 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t prev, int *last, svbool_t *ptr)
+{
+  svbool_t res = svpnext_b8 (pg, prev);
+  *last = svptest_last (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t prev)
+{
+  svbool_t res = svpnext_b8 (pg, prev);
+  return svptest_last (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tpnext\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/pnext_2.c
new file mode 100644 (file)
index 0000000..9926a2b
--- /dev/null
@@ -0,0 +1,52 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (svbool_t pg, svbool_t prev, int *last, svbool_t *ptr)
+{
+  svbool_t res = svpnext_b16 (pg, prev);
+  *last = svptest_last (pg, res);
+  *ptr = res;
+}
+
+int
+test2 (svbool_t pg, svbool_t prev)
+{
+  svbool_t res = svpnext_b16 (pg, prev);
+  return svptest_last (pg, res);
+}
+
+void
+test3 (svbool_t pg, svbool_t prev, int *last, svbool_t *ptr)
+{
+  svbool_t res = svpnext_b32 (pg, prev);
+  *last = svptest_last (pg, res);
+  *ptr = res;
+}
+
+int
+test4 (svbool_t pg, svbool_t prev)
+{
+  svbool_t res = svpnext_b32 (pg, prev);
+  return svptest_last (pg, res);
+}
+
+void
+test5 (svbool_t pg, svbool_t prev, int *last, svbool_t *ptr)
+{
+  svbool_t res = svpnext_b64 (pg, prev);
+  *last = svptest_last (pg, res);
+  *ptr = res;
+}
+
+int
+test6 (svbool_t pg, svbool_t prev)
+{
+  svbool_t res = svpnext_b64 (pg, prev);
+  return svptest_last (pg, res);
+}
+
+/* { dg-final { scan-assembler-times {\tpnext\t} 6 } } */
+/* { dg-final { scan-assembler-times {\tptest\t} 6 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_1.c
new file mode 100644 (file)
index 0000000..69bbb1e
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int *last, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b8 (SV_VL32);
+  *last = svptest_last (svptrue_b8 (), res);
+  *ptr = res;
+}
+
+int
+test2 ()
+{
+  svbool_t res = svptrue_pat_b8 (SV_VL32);
+  return svptest_last (svptrue_b8 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\tptrues\tp[0-9]+\.b, vl32\n} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_2.c
new file mode 100644 (file)
index 0000000..ede8340
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int *last, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b16 (SV_VL16);
+  *last = svptest_last (svptrue_b16 (), res);
+  *ptr = res;
+}
+
+int
+test2 ()
+{
+  svbool_t res = svptrue_pat_b16 (SV_VL16);
+  return svptest_last (svptrue_b16 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\tptrues\tp[0-9]+\.h, vl16\n} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_3.c
new file mode 100644 (file)
index 0000000..d2eb3fc
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int *last, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b32 (SV_VL16);
+  *last = svptest_last (svptrue_b32 (), res);
+  *ptr = res;
+}
+
+int
+test2 ()
+{
+  svbool_t res = svptrue_pat_b32 (SV_VL16);
+  return svptest_last (svptrue_b32 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\tptrues\tp[0-9]+\.s, vl16\n} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_4.c
new file mode 100644 (file)
index 0000000..59a21da
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b64 (SV_VL7);
+  *any = svptest_any (svptrue_b64 (), res);
+  *ptr = res;
+}
+
+int
+test2 ()
+{
+  svbool_t res = svptrue_pat_b64 (SV_VL7);
+  return svptest_any (svptrue_b64 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\tptrues\tp[0-9]+\.d, vl7\n} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} { xfail *-*-* } } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/ptrue_pat_5.c
new file mode 100644 (file)
index 0000000..c8f6d8a
--- /dev/null
@@ -0,0 +1,188 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+b8_b16_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b8 (SV_VL64);
+  *any = svptest_any (svptrue_b16 (), res);
+  *ptr = res;
+}
+
+int
+b8_b16_2 ()
+{
+  svbool_t res = svptrue_pat_b8 (SV_VL64);
+  return svptest_any (svptrue_b16 (), res);
+}
+
+void
+b8_b32_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b8 (SV_VL32);
+  *any = svptest_any (svptrue_b32 (), res);
+  *ptr = res;
+}
+
+int
+b8_b32_2 ()
+{
+  svbool_t res = svptrue_pat_b8 (SV_VL32);
+  return svptest_any (svptrue_b32 (), res);
+}
+
+void
+b8_b64_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b8 (SV_VL128);
+  *any = svptest_any (svptrue_b64 (), res);
+  *ptr = res;
+}
+
+int
+b8_b64_2 ()
+{
+  svbool_t res = svptrue_pat_b8 (SV_VL128);
+  return svptest_any (svptrue_b64 (), res);
+}
+
+void
+b16_b8_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b16 (SV_VL32);
+  *any = svptest_any (svptrue_b8 (), res);
+  *ptr = res;
+}
+
+int
+b16_b8_2 ()
+{
+  svbool_t res = svptrue_pat_b16 (SV_VL32);
+  return svptest_any (svptrue_b8 (), res);
+}
+
+void
+b16_b32_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b16 (SV_VL16);
+  *any = svptest_any (svptrue_b32 (), res);
+  *ptr = res;
+}
+
+int
+b16_b32_2 ()
+{
+  svbool_t res = svptrue_pat_b16 (SV_VL16);
+  return svptest_any (svptrue_b32 (), res);
+}
+
+void
+b16_b64_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b16 (SV_VL64);
+  *any = svptest_any (svptrue_b64 (), res);
+  *ptr = res;
+}
+
+int
+b16_b64_2 ()
+{
+  svbool_t res = svptrue_pat_b16 (SV_VL64);
+  return svptest_any (svptrue_b64 (), res);
+}
+
+void
+b32_b8_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b32 (SV_VL16);
+  *any = svptest_any (svptrue_b8 (), res);
+  *ptr = res;
+}
+
+int
+b32_b8_2 ()
+{
+  svbool_t res = svptrue_pat_b32 (SV_VL16);
+  return svptest_any (svptrue_b8 (), res);
+}
+
+void
+b32_b16_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b32 (SV_VL6);
+  *any = svptest_any (svptrue_b16 (), res);
+  *ptr = res;
+}
+
+int
+b32_b16_2 ()
+{
+  svbool_t res = svptrue_pat_b32 (SV_VL6);
+  return svptest_any (svptrue_b16 (), res);
+}
+
+void
+b32_b64_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b32 (SV_VL32);
+  *any = svptest_any (svptrue_b64 (), res);
+  *ptr = res;
+}
+
+int
+b32_b64_2 ()
+{
+  svbool_t res = svptrue_pat_b32 (SV_VL32);
+  return svptest_any (svptrue_b64 (), res);
+}
+
+void
+b64_b8_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b64 (SV_VL7);
+  *any = svptest_any (svptrue_b8 (), res);
+  *ptr = res;
+}
+
+int
+b64_b8_2 ()
+{
+  svbool_t res = svptrue_pat_b64 (SV_VL7);
+  return svptest_any (svptrue_b8 (), res);
+}
+
+void
+b64_b16_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b64 (SV_VL16);
+  *any = svptest_any (svptrue_b16 (), res);
+  *ptr = res;
+}
+
+int
+b64_b16_2 ()
+{
+  svbool_t res = svptrue_pat_b64 (SV_VL16);
+  return svptest_any (svptrue_b16 (), res);
+}
+
+void
+b64_b32_1 (int *any, svbool_t *ptr)
+{
+  svbool_t res = svptrue_pat_b64 (SV_VL32);
+  *any = svptest_any (svptrue_b32 (), res);
+  *ptr = res;
+}
+
+int
+b64_b32_2 ()
+{
+  svbool_t res = svptrue_pat_b64 (SV_VL32);
+  return svptest_any (svptrue_b32 (), res);
+}
+
+/* { dg-final { scan-assembler-not {\tptrues\n} } } */
+/* { dg-final { scan-assembler-times {\tptrue\t} 48 } } */
+/* { dg-final { scan-assembler-times {\tptest\t} 24 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/qincb_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/qincb_1.c
new file mode 100644 (file)
index 0000000..ba512f4
--- /dev/null
@@ -0,0 +1,43 @@
+/* { dg-do compile } */
+/* { dg-additional-options "-O" } */
+/* { dg-final { check-function-bodies "**" "" } } */
+
+#include <arm_sve.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+** qincb_s32_s:
+**     sqincb  x0, w0, all, mul #15
+**     ret
+*/
+uint64_t qincb_s32_s (int32_t x) { return svqincb (x, 15); }
+
+/*
+** qincb_s32_z:
+**     sqincb  x([0-9]+), w0, all, mul #15
+**     uxtw    x0, w\1
+**     ret
+*/
+uint64_t qincb_s32_z (int32_t x) { return (uint32_t) svqincb (x, 15); }
+
+/*
+** qincb_u32_s:
+**     uqincb  (w[0-9]+), all, mul #15
+**     sxtw    x0, \1
+**     ret
+*/
+uint64_t qincb_u32_s (uint32_t x) { return (int32_t) svqincb (x, 15); }
+
+/*
+** qincb_u32_z:
+**     uqincb  w0, all, mul #15
+**     ret
+*/
+uint64_t qincb_u32_z (uint32_t x) { return svqincb (x, 15); }
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/struct_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/struct_1.c
new file mode 100644 (file)
index 0000000..50892c8
--- /dev/null
@@ -0,0 +1,16 @@
+#include <arm_sve.h>
+
+void
+f (svint8x2_t *a, svint8x2_t *b)
+{
+  svint8_t *ptr;
+  svint8x2_t x = *a;
+  *a = *b;
+  a = &x;
+  (void) (a == b);
+  (void) (a != b);
+  (void) (a < b);
+  (void) (a > b);
+  (void) (a <= b);
+  (void) (a >= b);
+}
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_1.c
new file mode 100644 (file)
index 0000000..1d5523e
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int32_t x, int32_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svwhilele_b8 (x, y);
+  *any = svptest_last (svptrue_b8 (), res);
+  *ptr = res;
+}
+
+int
+test2 (int32_t x, int32_t y)
+{
+  svbool_t res = svwhilele_b8 (x, y);
+  return svptest_last (svptrue_b8 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\twhilele\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_10.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_10.c
new file mode 100644 (file)
index 0000000..ca339c4
--- /dev/null
@@ -0,0 +1,28 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b32_u32 (-1, 0);
+}
+
+void
+test2 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b16_u64 (0x80000000, 0);
+}
+
+void
+test3 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b8_u64 (0x8000000000000001ULL, 0x7ffffffffffffffeULL);
+}
+
+/* { dg-final { scan-assembler-times {\tpfalse\tp[0-7]\.b\n} 3 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_2.c
new file mode 100644 (file)
index 0000000..0208460
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int32_t x, int32_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svwhilele_b16 (x, y);
+  *any = svptest_last (svptrue_b16 (), res);
+  *ptr = res;
+}
+
+int
+test2 (int32_t x, int32_t y)
+{
+  svbool_t res = svwhilele_b16 (x, y);
+  return svptest_last (svptrue_b16 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\twhilele\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_3.c
new file mode 100644 (file)
index 0000000..4a1045c
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int32_t x, int32_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svwhilele_b32 (x, y);
+  *any = svptest_last (svptrue_b32 (), res);
+  *ptr = res;
+}
+
+int
+test2 (int32_t x, int32_t y)
+{
+  svbool_t res = svwhilele_b32 (x, y);
+  return svptest_last (svptrue_b32 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\twhilele\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_4.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_4.c
new file mode 100644 (file)
index 0000000..f6fb0d0
--- /dev/null
@@ -0,0 +1,23 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+void
+test1 (int32_t x, int32_t y, int *any, svbool_t *ptr)
+{
+  svbool_t res = svwhilele_b64 (x, y);
+  *any = svptest_last (svptrue_b64 (), res);
+  *ptr = res;
+}
+
+int
+test2 (int32_t x, int32_t y)
+{
+  svbool_t res = svwhilele_b64 (x, y);
+  return svptest_last (svptrue_b64 (), res);
+}
+
+/* { dg-final { scan-assembler-times {\twhilele\t} 2 } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+/* { dg-final { scan-assembler-not {\tptest\t} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_5.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_5.c
new file mode 100644 (file)
index 0000000..ada958b
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b32_s32 (-8, -8);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.[bhsd], vl1\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b16_s64 (-1, 1);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl3\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b16_s32 (0x7ffffffb, 0x7fffffff);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl5\n} } } */
+
+void
+test4 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b8_s64 (svcntb (), svcntb () + 6);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, vl7\n} } } */
+
+void
+test5 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b64_s64 (0, 1);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.d, vl2\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_6.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_6.c
new file mode 100644 (file)
index 0000000..00d92ba
--- /dev/null
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b32_s32 (-8, -9);
+}
+
+void
+test2 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b16_s64 (50, -1);
+}
+
+void
+test3 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b16_s32 (0x7ffffffb, 0x80000000);
+}
+
+void
+test4 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b8_s64 (svcntb (), 15);
+}
+
+void
+test5 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b8_s64 (svcntb (), svcntw ());
+}
+
+/* { dg-final { scan-assembler-times {\tpfalse\tp[0-7]\.b\n} 5 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_7.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_7.c
new file mode 100644 (file)
index 0000000..92488f5
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilel[et]\t} } } */
+/* { dg-final { scan-assembler-not {\tpfalse\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b8_s32 (-svcnth (), svcnth () - 1);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, all\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b16_s64 (1, svcntw () * 2);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, all\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b32_s32 (svcntd (), svcntw () + svcntd () - 1);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.s, all\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_9.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilele_9.c
new file mode 100644 (file)
index 0000000..e7f81a8
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b32_u32 (1, 3);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.s, vl3\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b16_u64 (svcntd (), svcntd () + 5);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl6\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+  *ptr = svwhilele_b8_u32 (0x7ffffffb, 0x80000002);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, vl8\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_1.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_1.c
new file mode 100644 (file)
index 0000000..5c8f97e
--- /dev/null
@@ -0,0 +1,47 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b32_s32 (-8, -7);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.[bhsd], vl1\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b16_s64 (-1, 2);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl3\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b16_s32 (0x7ffffffa, 0x7fffffff);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, vl5\n} } } */
+
+void
+test4 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b8_s64 (svcntb (), svcntb () + 7);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, vl7\n} } } */
+
+void
+test5 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b64_s64 (0, 2);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.d, vl2\n} } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_2.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_2.c
new file mode 100644 (file)
index 0000000..2be3a5b
--- /dev/null
@@ -0,0 +1,40 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilele\t} } } */
+/* { dg-final { scan-assembler-not {\twhilelt\t} } } */
+/* { dg-final { scan-assembler-not {\tptrue\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b32_s32 (0, 0);
+}
+
+void
+test2 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b16_s64 (50, -1);
+}
+
+void
+test3 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b16_s32 (0x7ffffffb, 0x80000000);
+}
+
+void
+test4 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b8_s64 (svcntb (), svcntb ());
+}
+
+void
+test5 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b8_s64 (svcntb (), svcntw ());
+}
+
+/* { dg-final { scan-assembler-times {\tpfalse\tp[0-7]\.b\n} 5 } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_3.c b/gcc/testsuite/gcc.target/aarch64/sve/acle/general/whilelt_3.c
new file mode 100644 (file)
index 0000000..650b265
--- /dev/null
@@ -0,0 +1,31 @@
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+#include <arm_sve.h>
+
+/* { dg-final { scan-assembler-not {\twhilel[et]\t} } } */
+/* { dg-final { scan-assembler-not {\tpfalse\t} } } */
+
+void
+test1 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b8_s32 (-svcnth (), svcnth ());
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.b, all\n} } } */
+
+void
+test2 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b16_s64 (0, svcntw () * 2);
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.h, all\n} } } */
+
+void
+test3 (svbool_t *ptr)
+{
+  *ptr = svwhilelt_b32_s32 (svcntd (), svcntw () + svcntd ());
+}
+
+/* { dg-final { scan-assembler {\tptrue\tp[0-7]\.s, all\n} } } */